OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 #include <memory> | 6 #include <memory> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
12 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
13 #include "base/macros.h" | 13 #include "base/macros.h" |
14 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
16 #include "base/test/histogram_tester.h" | 16 #include "base/test/histogram_tester.h" |
17 #include "base/threading/thread_restrictions.h" | 17 #include "base/threading/thread_restrictions.h" |
18 #include "content/browser/frame_host/frame_tree_node.h" | |
18 #include "content/browser/renderer_host/render_process_host_impl.h" | 19 #include "content/browser/renderer_host/render_process_host_impl.h" |
20 #include "content/browser/web_contents/web_contents_impl.h" | |
19 #include "content/common/frame_messages.h" | 21 #include "content/common/frame_messages.h" |
20 #include "content/public/browser/render_process_host.h" | 22 #include "content/public/browser/render_process_host.h" |
21 #include "content/public/browser/web_contents.h" | |
22 #include "content/public/common/mhtml_generation_params.h" | 23 #include "content/public/common/mhtml_generation_params.h" |
23 #include "content/public/test/browser_test_utils.h" | 24 #include "content/public/test/browser_test_utils.h" |
24 #include "content/public/test/content_browser_test.h" | 25 #include "content/public/test/content_browser_test.h" |
25 #include "content/public/test/content_browser_test_utils.h" | 26 #include "content/public/test/content_browser_test_utils.h" |
26 #include "content/public/test/test_utils.h" | 27 #include "content/public/test/test_utils.h" |
27 #include "content/shell/browser/shell.h" | 28 #include "content/shell/browser/shell.h" |
28 #include "net/base/filename_util.h" | 29 #include "net/base/filename_util.h" |
29 #include "net/dns/mock_host_resolver.h" | 30 #include "net/dns/mock_host_resolver.h" |
30 #include "net/test/embedded_test_server/embedded_test_server.h" | 31 #include "net/test/embedded_test_server/embedded_test_server.h" |
31 #include "testing/gmock/include/gmock/gmock.h" | 32 #include "testing/gmock/include/gmock/gmock.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 | 216 |
216 // Tests that generating a MHTML does create contents. | 217 // Tests that generating a MHTML does create contents. |
217 // Note that the actual content of the file is not tested, the purpose of this | 218 // Note that the actual content of the file is not tested, the purpose of this |
218 // test is to ensure we were successful in creating the MHTML data from the | 219 // test is to ensure we were successful in creating the MHTML data from the |
219 // renderer. | 220 // renderer. |
220 IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) { | 221 IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) { |
221 base::FilePath path(temp_dir_.GetPath()); | 222 base::FilePath path(temp_dir_.GetPath()); |
222 path = path.Append(FILE_PATH_LITERAL("test.mht")); | 223 path = path.Append(FILE_PATH_LITERAL("test.mht")); |
223 | 224 |
224 GenerateMHTML(path, embedded_test_server()->GetURL("/simple_page.html")); | 225 GenerateMHTML(path, embedded_test_server()->GetURL("/simple_page.html")); |
226 | |
227 // Checks that no other test failure was detected so far. | |
225 ASSERT_FALSE(HasFailure()); | 228 ASSERT_FALSE(HasFailure()); |
226 | 229 |
227 // Make sure the actual generated file has some contents. | 230 // Make sure the actual generated file has some contents. |
228 EXPECT_GT(file_size(), 0); // Verify the size reported by the callback. | 231 EXPECT_GT(file_size(), 0); // Verify the size reported by the callback. |
229 EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size. | 232 EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size. |
230 | 233 |
231 { | 234 { |
232 base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification; | 235 base::ThreadRestrictions::ScopedAllowIO allow_io_for_content_verification; |
233 std::string mhtml; | 236 std::string mhtml; |
234 ASSERT_TRUE(base::ReadFileToString(path, &mhtml)); | 237 ASSERT_TRUE(base::ReadFileToString(path, &mhtml)); |
235 EXPECT_THAT(mhtml, | 238 EXPECT_THAT(mhtml, |
236 HasSubstr("Content-Transfer-Encoding: quoted-printable")); | 239 HasSubstr("Content-Transfer-Encoding: quoted-printable")); |
237 } | 240 } |
238 | 241 |
239 // Checks that the final status reported to UMA is correct. | 242 // Checks that the final status reported to UMA is correct. |
240 histogram_tester()->ExpectUniqueSample( | 243 histogram_tester()->ExpectUniqueSample( |
241 "PageSerialization.MhtmlGeneration.FinalSaveStatus", | 244 "PageSerialization.MhtmlGeneration.FinalSaveStatus", |
242 static_cast<int>(MhtmlSaveStatus::SUCCESS), 1); | 245 static_cast<int>(MhtmlSaveStatus::SUCCESS), 1); |
243 } | 246 } |
244 | 247 |
248 // Removes all children of the root tree node once the first MHTML serialization | |
249 // response (regarding the main frame) is received from the renderer but before | |
250 // that message is actually handled by the browser UI thread. | |
251 class ChildFrameRemoverFilter : public BrowserMessageFilter { | |
252 public: | |
253 ChildFrameRemoverFilter(WebContentsImpl* web_contents) | |
254 : BrowserMessageFilter(FrameMsgStart), web_contents_(web_contents) {} | |
Łukasz Anforowicz
2016/11/28 22:15:37
nit: DCHECK(web_contents_) ?
carlosk
2016/11/29 02:11:20
Done.
| |
255 | |
256 protected: | |
257 ~ChildFrameRemoverFilter() override {} | |
258 | |
259 private: | |
260 bool OnMessageReceived(const IPC::Message& message) override { | |
Łukasz Anforowicz
2016/11/28 22:15:37
nit: DCHECK_CURRENTLY_ON(BrowserThread::IO) ?
carlosk
2016/11/29 02:11:20
Done.
| |
261 if (message.type() == FrameHostMsg_SerializeAsMHTMLResponse::ID) { | |
262 if (!already_received_response_) { | |
263 already_received_response_ = true; | |
264 BrowserThread::PostTask( | |
265 BrowserThread::UI, FROM_HERE, | |
266 base::Bind(&ChildFrameRemoverFilter::RemoveAllChildFrames, | |
267 base::Unretained(this))); | |
268 } else { | |
269 ADD_FAILURE() | |
270 << "Should not receive another MHTML serialization response"; | |
271 } | |
272 } | |
273 return false; | |
274 } | |
275 | |
276 void RemoveAllChildFrames() { | |
Łukasz Anforowicz
2016/11/28 22:15:37
nit: DCHECK_CURRENTLY_ON(BrowserThread::UI) ?
(th
carlosk
2016/11/29 02:11:20
Agreed and done. Also added these checks to the ot
| |
277 int tree_node_count = 1; | |
278 for (auto tree_node : web_contents_->GetFrameTree()->Nodes()) | |
279 tree_node_count += tree_node->child_count(); | |
280 // Note: at least 2 children nodes are needed to test all code paths. | |
281 ASSERT_GE(tree_node_count, 3); | |
282 FrameTreeNode* root = web_contents_->GetFrameTree()->root(); | |
283 while (root->child_count()) | |
284 root->RemoveChild(root->child_at(root->child_count() - 1)); | |
Łukasz Anforowicz
2016/11/28 22:15:37
Is it okay to instead call root->RemoveChild(0)?
carlosk
2016/11/29 02:11:20
This was just my ODD of always removing vector ele
Łukasz Anforowicz
2016/11/29 19:18:13
Thanks.
I see now that the simpler code might be
| |
285 ASSERT_EQ(0u, root->child_count()); | |
286 } | |
287 | |
288 WebContentsImpl* web_contents_; | |
289 bool already_received_response_ = false; | |
290 | |
291 DISALLOW_COPY_AND_ASSIGN(ChildFrameRemoverFilter); | |
292 }; | |
293 | |
294 // Tests that if child frames are removed while saving a MHTML page the | |
295 // operation fails by default. | |
296 IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, FailDueToMissingIframe) { | |
297 NavigateToURL(shell(), | |
Łukasz Anforowicz
2016/11/28 22:15:37
nit: ASSERT_TRUE(NavigateToURL(...)
(this will al
carlosk
2016/11/29 02:11:20
Done for all calls of this function.
| |
298 embedded_test_server()->GetURL("/site_per_process_main.html")); | |
299 | |
300 scoped_refptr<BrowserMessageFilter> filter = new ChildFrameRemoverFilter( | |
301 static_cast<WebContentsImpl*>(shell()->web_contents())); | |
302 shell()->web_contents()->GetRenderProcessHost()->AddFilter(filter.get()); | |
303 | |
304 base::FilePath path(temp_dir_.GetPath()); | |
305 path = path.Append(FILE_PATH_LITERAL("test.mht")); | |
306 | |
307 MHTMLGenerationParams params(path); | |
308 | |
309 // Verifies the default is to not ignore missing iframes. | |
310 ASSERT_FALSE(params.ignore_missing_frames); | |
311 | |
312 GenerateMHTMLForCurrentPage(params); | |
313 | |
314 // Checks that no other test failure was detected so far. | |
315 ASSERT_FALSE(HasFailure()); | |
316 | |
317 // Verify the size reported by the callback is negative (an error happened). | |
318 EXPECT_LT(file_size(), 0); | |
319 | |
320 // Checks that the final status reported to UMA is correct. | |
321 histogram_tester()->ExpectUniqueSample( | |
322 "PageSerialization.MhtmlGeneration.FinalSaveStatus", | |
323 static_cast<int>(MhtmlSaveStatus::FRAME_NO_LONGER_EXISTS), 1); | |
324 } | |
325 | |
326 // Tests that a MHTML save operation does not fail when frames are removed if | |
327 // the caller configures it to ignore missing frames. | |
328 IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, SucceedIgnoringMissingIframe) { | |
329 NavigateToURL(shell(), | |
Łukasz Anforowicz
2016/11/28 22:15:37
nit: ASSERT_TRUE(NavigateToURL(...)
carlosk
2016/11/29 02:11:20
Done.
| |
330 embedded_test_server()->GetURL("/site_per_process_main.html")); | |
331 | |
332 scoped_refptr<BrowserMessageFilter> filter = new ChildFrameRemoverFilter( | |
333 static_cast<WebContentsImpl*>(shell()->web_contents())); | |
334 shell()->web_contents()->GetRenderProcessHost()->AddFilter(filter.get()); | |
335 | |
336 base::FilePath path(temp_dir_.GetPath()); | |
337 path = path.Append(FILE_PATH_LITERAL("test.mht")); | |
338 | |
339 MHTMLGenerationParams params(path); | |
340 | |
341 // Enables the ignoring of missing iframes. | |
342 params.ignore_missing_frames = true; | |
343 | |
344 GenerateMHTMLForCurrentPage(params); | |
345 | |
346 // Checks that no other test failure was detected so far. | |
347 ASSERT_FALSE(HasFailure()); | |
348 | |
349 // Verify the size reported by the callback is positive. | |
350 EXPECT_GT(file_size(), 0); | |
351 | |
352 // Checks that the final status reported to UMA is correct. | |
353 histogram_tester()->ExpectUniqueSample( | |
354 "PageSerialization.MhtmlGeneration.FinalSaveStatus", | |
355 static_cast<int>(MhtmlSaveStatus::SUCCESS), 1); | |
356 } | |
357 | |
245 class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter { | 358 class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter { |
246 public: | 359 public: |
247 GenerateMHTMLAndExitRendererMessageFilter( | 360 GenerateMHTMLAndExitRendererMessageFilter( |
248 RenderProcessHostImpl* render_process_host) | 361 RenderProcessHostImpl* render_process_host) |
249 : BrowserMessageFilter(FrameMsgStart), | 362 : BrowserMessageFilter(FrameMsgStart), |
250 render_process_host_(render_process_host) {} | 363 render_process_host_(render_process_host) {} |
251 | 364 |
252 protected: | 365 protected: |
253 ~GenerateMHTMLAndExitRendererMessageFilter() override {} | 366 ~GenerateMHTMLAndExitRendererMessageFilter() override {} |
254 | 367 |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
644 | 757 |
645 // Make sure that URLs of both frames are present | 758 // Make sure that URLs of both frames are present |
646 // (note that these are single-line regexes). | 759 // (note that these are single-line regexes). |
647 EXPECT_THAT( | 760 EXPECT_THAT( |
648 mhtml, | 761 mhtml, |
649 ContainsRegex("Content-Location:.*/frame_tree/page_with_one_frame.html")); | 762 ContainsRegex("Content-Location:.*/frame_tree/page_with_one_frame.html")); |
650 EXPECT_THAT(mhtml, ContainsRegex("Content-Location:.*/title1.html")); | 763 EXPECT_THAT(mhtml, ContainsRegex("Content-Location:.*/title1.html")); |
651 } | 764 } |
652 | 765 |
653 } // namespace content | 766 } // namespace content |
OLD | NEW |