Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: content/browser/frame_host/data_url_navigation_browsertest.cc

Issue 2702503002: Block renderer-initiated main frame navigations to data URLs (Closed)
Patch Set: Fix Android PDF tests where PDFs should be downloaded Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/BUILD.gn ('k') | content/browser/frame_host/data_url_navigation_throttle.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/macros.h"
9 #include "base/path_service.h"
10 #include "base/strings/pattern.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/test/scoped_feature_list.h"
13 #include "build/build_config.h"
14 #include "build/buildflag.h"
15 #include "content/browser/site_per_process_browsertest.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/browser_side_navigation_policy.h"
20 #include "content/public/common/content_features.h"
21 #include "content/public/common/content_paths.h"
22 #include "content/public/common/content_switches.h"
23 #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_utils.h"
26 #include "content/public/test/download_test_observer.h"
27 #include "content/public/test/test_navigation_observer.h"
28 #include "content/shell/browser/shell.h"
29 #include "content/shell/browser/shell_download_manager_delegate.h"
30 #include "net/base/escape.h"
31 #include "net/dns/mock_host_resolver.h"
32 #include "net/test/embedded_test_server/embedded_test_server.h"
33 #include "ppapi/features/features.h"
34
35 #if BUILDFLAG(ENABLE_PLUGINS)
36 #include "content/public/browser/plugin_service.h"
37 #include "content/public/common/webplugininfo.h"
38 #endif
39
40 namespace content {
41
42 namespace {
43
44 // The pattern to catch messages printed by the browser when a data URL
45 // navigation is blocked.
46 const char kDataUrlBlockedPattern[] =
47 "Not allowed to navigate top frame to data URL:*";
48
49 // The message printed by the data URL when it successfully navigates.
50 const char kDataUrlSuccessfulMessage[] = "NAVIGATION_SUCCESSFUL";
51
52 // A "Hello World" PDF encoded as a data URL. Source of this PDF:
53 // -------------------------
54 // %PDF-1.7
55 // 1 0 obj << /Type /Page /Parent 3 0 R /Resources 5 0 R /Contents 2 0 R >>
56 // endobj
57 // 2 0 obj << /Length 51 >>
58 // stream BT
59 // /F1 12 Tf
60 // 1 0 0 1 100 20 Tm
61 // (Hello World)Tj
62 // ET
63 // endstream
64 // endobj
65 // 3 0 obj << /Type /Pages /Kids [ 1 0 R ] /Count 1 /MediaBox [ 0 0 300 50] >>
66 // endobj
67 // 4 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont/Arial >>
68 // endobj
69 // 5 0 obj << /ProcSet[/PDF/Text] /Font <</F1 4 0 R >> >>
70 // endobj
71 // 6 0 obj << /Type /Catalog /Pages 3 0 R >>
72 // endobj
73 // trailer << /Root 6 0 R >>
74 // -------------------------
75 const char kPdfUrl[] =
76 "data:application/pdf;base64,JVBERi0xLjcKMSAwIG9iaiA8PCAvVHlwZSAvUGFnZSAvUG"
77 "FyZW50IDMgMCBSIC9SZXNvdXJjZXMgNSAwIFIgL0NvbnRlbnRzIDIgMCBSID4+CmVuZG9iagoy"
78 "IDAgb2JqIDw8IC9MZW5ndGggNTEgPj4KIHN0cmVhbSBCVAogL0YxIDEyIFRmCiAxIDAgMCAxID"
79 "EwMCAyMCBUbQogKEhlbGxvIFdvcmxkKVRqCiBFVAogZW5kc3RyZWFtCmVuZG9iagozIDAgb2Jq"
80 "IDw8IC9UeXBlIC9QYWdlcyAvS2lkcyBbIDEgMCBSIF0gL0NvdW50IDEgL01lZGlhQm94IFsgMC"
81 "AwIDMwMCA1MF0gPj4KZW5kb2JqCjQgMCBvYmogPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1R5"
82 "cGUxIC9OYW1lIC9GMSAvQmFzZUZvbnQvQXJpYWwgPj4KZW5kb2JqCjUgMCBvYmogPDwgL1Byb2"
83 "NTZXRbL1BERi9UZXh0XSAvRm9udCA8PC9GMSA0IDAgUiA+PiA+PgplbmRvYmoKNiAwIG9iaiA8"
84 "PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMyAwIFIgPj4KZW5kb2JqCnRyYWlsZXIgPDwgL1Jvb3"
85 "QgNiAwIFIgPj4K";
86
87 enum ExpectedNavigationStatus { NAVIGATION_BLOCKED, NAVIGATION_ALLOWED };
88
89 // This class is similar to ConsoleObserverDelegate in that it listens and waits
90 // for specific console messages. The difference from ConsoleObserverDelegate is
91 // that this class immediately stops waiting if it sees a message matching
92 // fail_pattern, instead of waiting for a message matching success_pattern.
93 class DataURLWarningConsoleObserverDelegate : public WebContentsDelegate {
94 public:
95 DataURLWarningConsoleObserverDelegate(
96 WebContents* web_contents,
97 ExpectedNavigationStatus expected_navigation_status)
98 : web_contents_(web_contents),
99 success_filter_(expected_navigation_status == NAVIGATION_ALLOWED
100 ? kDataUrlSuccessfulMessage
101 : kDataUrlBlockedPattern),
102 fail_filter_(expected_navigation_status == NAVIGATION_ALLOWED
103 ? kDataUrlBlockedPattern
104 : kDataUrlSuccessfulMessage),
105 message_loop_runner_(
106 new MessageLoopRunner(MessageLoopRunner::QuitMode::IMMEDIATE)),
107 saw_failure_message_(false) {}
108 ~DataURLWarningConsoleObserverDelegate() override {}
109
110 void Wait() { message_loop_runner_->Run(); }
111
112 // WebContentsDelegate method:
113 bool DidAddMessageToConsole(WebContents* source,
114 int32_t level,
115 const base::string16& message,
116 int32_t line_no,
117 const base::string16& source_id) override {
118 DCHECK(source == web_contents_);
119 const std::string ascii_message = base::UTF16ToASCII(message);
120 if (base::MatchPattern(ascii_message, fail_filter_)) {
121 saw_failure_message_ = true;
122 message_loop_runner_->Quit();
123 }
124 if (base::MatchPattern(ascii_message, success_filter_)) {
125 message_loop_runner_->Quit();
126 }
127 return false;
128 }
129
130 // Returns true if the observer encountered a message that matches
131 // |fail_filter_|.
132 bool saw_failure_message() const { return saw_failure_message_; }
133
134 private:
135 WebContents* web_contents_;
136 const std::string success_filter_;
137 const std::string fail_filter_;
138 scoped_refptr<MessageLoopRunner> message_loop_runner_;
139 bool saw_failure_message_;
140 };
141
142 #if BUILDFLAG(ENABLE_PLUGINS)
143 // This class registers a fake PDF plugin handler so that data URL navigations
144 // with a PDF mime type end up with a navigation and don't simply download the
145 // file.
146 class ScopedPluginRegister {
147 public:
148 ScopedPluginRegister(content::PluginService* plugin_service)
149 : plugin_service_(plugin_service) {
150 const char kPluginName[] = "PDF";
151 const char kPdfMimeType[] = "application/pdf";
152 const char kPdfFileType[] = "pdf";
153 WebPluginInfo plugin_info;
154 plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
155 plugin_info.name = base::ASCIIToUTF16(kPluginName);
156 plugin_info.mime_types.push_back(
157 WebPluginMimeType(kPdfMimeType, kPdfFileType, std::string()));
158 plugin_service_->RegisterInternalPlugin(plugin_info, false);
159 plugin_service_->RefreshPlugins();
160 }
161
162 ~ScopedPluginRegister() {
163 std::vector<WebPluginInfo> plugins;
164 plugin_service_->GetInternalPlugins(&plugins);
165 EXPECT_EQ(1u, plugins.size());
166 plugin_service_->UnregisterInternalPlugin(plugins[0].path);
167 plugin_service_->RefreshPlugins();
168
169 plugins.clear();
170 plugin_service_->GetInternalPlugins(&plugins);
171 EXPECT_TRUE(plugins.empty());
172 }
173
174 private:
175 content::PluginService* plugin_service_;
176 };
177 #endif // BUILDFLAG(ENABLE_PLUGINS)
178
179 } // namespace
180
181 class DataUrlNavigationBrowserTest : public ContentBrowserTest {
182 public:
183 #if BUILDFLAG(ENABLE_PLUGINS)
184 DataUrlNavigationBrowserTest()
185 : scoped_plugin_register_(PluginService::GetInstance()) {}
186 #else
187 DataUrlNavigationBrowserTest() {}
188 #endif // BUILDFLAG(ENABLE_PLUGINS)
189
190 protected:
191 void SetUpOnMainThread() override {
192 host_resolver()->AddRule("*", "127.0.0.1");
193 ASSERT_TRUE(embedded_test_server()->Start());
194
195 base::FilePath path;
196 ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &path));
197 path = path.AppendASCII("data_url_navigations.html");
198 ASSERT_TRUE(base::PathExists(path));
199
200 std::string contents;
201 ASSERT_TRUE(base::ReadFileToString(path, &contents));
202 data_url_ = GURL(std::string("data:text/html,") + contents);
203
204 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
205 ShellDownloadManagerDelegate* delegate =
206 static_cast<ShellDownloadManagerDelegate*>(
207 shell()
208 ->web_contents()
209 ->GetBrowserContext()
210 ->GetDownloadManagerDelegate());
211 delegate->SetDownloadBehaviorForTesting(downloads_directory_.GetPath());
212 }
213
214 // Adds an iframe to |rfh| pointing to |url|.
215 void AddIFrame(RenderFrameHost* rfh, const GURL& url) {
216 const std::string javascript = base::StringPrintf(
217 "f = document.createElement('iframe'); f.src = '%s';"
218 "document.body.appendChild(f);",
219 url.spec().c_str());
220 TestNavigationObserver observer(shell()->web_contents());
221 EXPECT_TRUE(ExecuteScript(rfh, javascript));
222 observer.Wait();
223 }
224
225 // Runs |javascript| on the first child frame and checks for a navigation.
226 void TestNavigationFromFrame(
227 const std::string& javascript,
228 ExpectedNavigationStatus expected_navigation_status) {
229 RenderFrameHost* child =
230 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
231 ASSERT_TRUE(child);
232 if (AreAllSitesIsolatedForTesting()) {
233 ASSERT_TRUE(child->IsCrossProcessSubframe());
234 }
235 ExecuteScriptAndCheckNavigation(child, javascript,
236 expected_navigation_status);
237 }
238
239 // Runs |javascript| on the first child frame and expects a download to occur.
240 void TestDownloadFromFrame(const std::string& javascript) {
241 RenderFrameHost* child =
242 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
243 ASSERT_TRUE(child);
244 if (AreAllSitesIsolatedForTesting()) {
245 ASSERT_TRUE(child->IsCrossProcessSubframe());
246 }
247 ExecuteScriptAndCheckNavigationDownload(child, javascript);
248 }
249
250 // Runs |javascript| on the first child frame and checks for a navigation to
251 // the PDF file pointed by the test case.
252 void TestPDFNavigationFromFrame(
253 const std::string& javascript,
254 ExpectedNavigationStatus expected_navigation_status) {
255 RenderFrameHost* child =
256 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
257 ASSERT_TRUE(child);
258 if (AreAllSitesIsolatedForTesting()) {
259 ASSERT_TRUE(child->IsCrossProcessSubframe());
260 }
261 ExecuteScriptAndCheckPDFNavigation(child, javascript,
262 expected_navigation_status);
263 }
264
265 // Same as TestNavigationFromFrame, but instead of navigating, the child frame
266 // tries to open a new window with a data URL.
267 void TestWindowOpenFromFrame(
268 const std::string& javascript,
269 ExpectedNavigationStatus expected_navigation_status) {
270 RenderFrameHost* child =
271 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
272 if (AreAllSitesIsolatedForTesting()) {
273 ASSERT_TRUE(child->IsCrossProcessSubframe());
274 }
275 ExecuteScriptAndCheckWindowOpen(child, javascript,
276 expected_navigation_status);
277 }
278
279 // Executes |javascript| on |rfh| and waits for a console message based on
280 // |expected_navigation_status|.
281 // - Blocked navigations should print kDataUrlBlockedPattern.
282 // - Allowed navigations should print kDataUrlSuccessfulMessage.
283 void ExecuteScriptAndCheckNavigation(
284 RenderFrameHost* rfh,
285 const std::string& javascript,
286 ExpectedNavigationStatus expected_navigation_status) {
287 const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
288 const std::string expected_message;
289
290 DataURLWarningConsoleObserverDelegate console_delegate(
291 shell()->web_contents(), expected_navigation_status);
292 shell()->web_contents()->SetDelegate(&console_delegate);
293
294 TestNavigationObserver navigation_observer(shell()->web_contents());
295 EXPECT_TRUE(ExecuteScript(rfh, javascript));
296 console_delegate.Wait();
297 EXPECT_FALSE(console_delegate.saw_failure_message());
298 shell()->web_contents()->SetDelegate(nullptr);
299
300 switch (expected_navigation_status) {
301 case NAVIGATION_ALLOWED:
302 navigation_observer.Wait();
303 // The new page should have a data URL.
304 EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
305 url::kDataScheme));
306 EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(
307 url::kDataScheme));
308 EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
309 break;
310
311 case NAVIGATION_BLOCKED:
312 // Original page shouldn't navigate away.
313 EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
314 EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
315 break;
316
317 default:
318 NOTREACHED();
319 }
320 }
321
322 // Similar to ExecuteScriptAndCheckNavigation(), but doesn't wait for a
323 // console message if the navigation is expected to be allowed (this is
324 // because PDF files can't print to the console).
325 void ExecuteScriptAndCheckPDFNavigation(
326 RenderFrameHost* rfh,
327 const std::string& javascript,
328 ExpectedNavigationStatus expected_navigation_status) {
329 const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
330
331 const std::string expected_message =
332 (expected_navigation_status == NAVIGATION_ALLOWED)
333 ? std::string()
334 : kDataUrlBlockedPattern;
335
336 std::unique_ptr<ConsoleObserverDelegate> console_delegate;
337 if (!expected_message.empty()) {
338 console_delegate.reset(new ConsoleObserverDelegate(
339 shell()->web_contents(), expected_message));
340 shell()->web_contents()->SetDelegate(console_delegate.get());
341 }
342
343 TestNavigationObserver navigation_observer(shell()->web_contents());
344 EXPECT_TRUE(ExecuteScript(rfh, javascript));
345
346 if (console_delegate) {
347 console_delegate->Wait();
348 shell()->web_contents()->SetDelegate(nullptr);
349 }
350
351 switch (expected_navigation_status) {
352 case NAVIGATION_ALLOWED:
353 navigation_observer.Wait();
354 // The new page should have a data URL.
355 EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
356 url::kDataScheme));
357 EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(
358 url::kDataScheme));
359 EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
360 break;
361
362 case NAVIGATION_BLOCKED:
363 // Original page shouldn't navigate away.
364 EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
365 EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
366 break;
367
368 default:
369 NOTREACHED();
370 }
371 }
372
373 // Executes |javascript| on |rfh| and waits for a new window to be opened.
374 // Does not check for console messages (it's currently not possible to
375 // concurrently wait for a new shell to be created and a console message to be
376 // printed on that new shell).
377 void ExecuteScriptAndCheckWindowOpen(
378 RenderFrameHost* rfh,
379 const std::string& javascript,
380 ExpectedNavigationStatus expected_navigation_status) {
381 ShellAddedObserver new_shell_observer;
382 EXPECT_TRUE(ExecuteScript(rfh, javascript));
383
384 Shell* new_shell = new_shell_observer.GetShell();
385 WaitForLoadStop(new_shell->web_contents());
386
387 switch (expected_navigation_status) {
388 case NAVIGATION_ALLOWED:
389 EXPECT_TRUE(new_shell->web_contents()->GetLastCommittedURL().SchemeIs(
390 url::kDataScheme));
391 break;
392
393 case NAVIGATION_BLOCKED:
394 EXPECT_TRUE(
395 new_shell->web_contents()->GetLastCommittedURL().is_empty());
396 break;
397
398 default:
399 NOTREACHED();
400 }
401 }
402
403 // Executes |javascript| on |rfh| and waits for a download to be started by
404 // a window.open call.
405 void ExecuteScriptAndCheckWindowOpenDownload(RenderFrameHost* rfh,
406 const std::string& javascript) {
407 const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
408 ShellAddedObserver new_shell_observer;
409 DownloadManager* download_manager = BrowserContext::GetDownloadManager(
410 shell()->web_contents()->GetBrowserContext());
411
412 EXPECT_TRUE(ExecuteScript(rfh, javascript));
413 Shell* new_shell = new_shell_observer.GetShell();
414
415 DownloadTestObserverTerminal download_observer(
416 download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
417
418 WaitForLoadStop(new_shell->web_contents());
419 // If no download happens, this will timeout.
420 download_observer.WaitForFinished();
421
422 EXPECT_TRUE(
423 new_shell->web_contents()->GetLastCommittedURL().spec().empty());
424 // No navigation should commit.
425 EXPECT_FALSE(
426 new_shell->web_contents()->GetController().GetLastCommittedEntry());
427 // Original page shouldn't navigate away.
428 EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
429 }
430
431 // Executes |javascript| on |rfh| and waits for a download to be started.
432 void ExecuteScriptAndCheckNavigationDownload(RenderFrameHost* rfh,
433 const std::string& javascript) {
434 const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
435 DownloadManager* download_manager = BrowserContext::GetDownloadManager(
436 shell()->web_contents()->GetBrowserContext());
437 DownloadTestObserverTerminal download_observer(
438 download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
439
440 EXPECT_TRUE(ExecuteScript(rfh, javascript));
441 // If no download happens, this will timeout.
442 download_observer.WaitForFinished();
443
444 // Original page shouldn't navigate away.
445 EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
446 }
447
448 // Initiates a browser initiated navigation to |url| and waits for a download
449 // to be started.
450 void NavigateAndCheckDownload(const GURL& url) {
451 const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
452 DownloadManager* download_manager = BrowserContext::GetDownloadManager(
453 shell()->web_contents()->GetBrowserContext());
454 DownloadTestObserverTerminal download_observer(
455 download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
456 NavigateToURL(shell(), url);
457
458 // If no download happens, this will timeout.
459 download_observer.WaitForFinished();
460
461 // Original page shouldn't navigate away.
462 EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
463 }
464
465 // data URL form of the file at content/test/data/data_url_navigations.html
466 GURL data_url() const { return data_url_; }
467
468 private:
469 base::ScopedTempDir downloads_directory_;
470
471 #if BUILDFLAG(ENABLE_PLUGINS)
472 ScopedPluginRegister scoped_plugin_register_;
473 #endif // BUILDFLAG(ENABLE_PLUGINS)
474
475 GURL data_url_;
476
477 DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationBrowserTest);
478 };
479
480 ////////////////////////////////////////////////////////////////////////////////
481 // data URLs with HTML mimetype
482 //
483 // Tests that a browser initiated navigation to a data URL doesn't show a
484 // console warning and is not blocked.
485 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, BrowserInitiated_Allow) {
486 DataURLWarningConsoleObserverDelegate console_delegate(
487 shell()->web_contents(), NAVIGATION_ALLOWED);
488 shell()->web_contents()->SetDelegate(&console_delegate);
489
490 NavigateToURL(shell(), GURL("data:text/"
491 "html,<html><script>console.log('NAVIGATION_"
492 "SUCCESSFUL');</script>"));
493 console_delegate.Wait();
494 shell()->web_contents()->SetDelegate(nullptr);
495
496 EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
497 url::kDataScheme));
498 }
499
500 // Tests that a content initiated navigation to a data URL is blocked.
501 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_Navigation_Block) {
502 NavigateToURL(shell(),
503 embedded_test_server()->GetURL("/data_url_navigations.html"));
504 ExecuteScriptAndCheckNavigation(
505 shell()->web_contents()->GetMainFrame(),
506 "document.getElementById('navigate-top-frame-to-html').click()",
507 NAVIGATION_BLOCKED);
508 }
509
510 // Tests that a content initiated navigation to a data URL is allowed if
511 // blocking is disabled with a feature flag.
512 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
513 HTML_Navigation_Allow_FeatureFlag) {
514 base::test::ScopedFeatureList feature_list;
515 feature_list.InitAndEnableFeature(
516 features::kAllowContentInitiatedDataUrlNavigations);
517 NavigateToURL(shell(),
518 embedded_test_server()->GetURL("/data_url_navigations.html"));
519 ExecuteScriptAndCheckNavigation(
520 shell()->web_contents()->GetMainFrame(),
521 "document.getElementById('navigate-top-frame-to-html').click()",
522 NAVIGATION_ALLOWED);
523 }
524
525 // Tests that a window.open to a data URL with HTML mime type is blocked.
526 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_WindowOpen_Block) {
527 NavigateToURL(shell(),
528 embedded_test_server()->GetURL("/data_url_navigations.html"));
529 ExecuteScriptAndCheckWindowOpen(
530 shell()->web_contents()->GetMainFrame(),
531 "document.getElementById('window-open-html').click()",
532 NAVIGATION_BLOCKED);
533 }
534
535 // Tests that a form post to a data URL with HTML mime type is blocked.
536 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_FormPost_Block) {
537 NavigateToURL(shell(),
538 embedded_test_server()->GetURL("/data_url_navigations.html"));
539 ExecuteScriptAndCheckNavigation(
540 shell()->web_contents()->GetMainFrame(),
541 "document.getElementById('form-post-to-html').click()",
542 NAVIGATION_BLOCKED);
543 }
544
545 // Tests that navigating the main frame to a data URL with HTML mimetype from a
546 // subframe is blocked.
547 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
548 HTML_NavigationFromFrame_Block) {
549 // This test fails and is disabled in site-per-process + no plznavigate mode.
550 // request->originDocument is null in FrameLoader::prepareForRequest,
551 // allowing the navigation by default. See https://crbug.com/647839
552 if (AreAllSitesIsolatedForTesting() && !IsBrowserSideNavigationEnabled()) {
553 return;
554 }
555
556 NavigateToURL(shell(),
557 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
558 AddIFrame(
559 shell()->web_contents()->GetMainFrame(),
560 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
561
562 TestNavigationFromFrame(
563 "document.getElementById('navigate-top-frame-to-html').click()",
564 NAVIGATION_BLOCKED);
565 }
566
567 // Tests that opening a new data URL window from a subframe is blocked.
568 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
569 HTML_WindowOpenFromFrame_Block) {
570 NavigateToURL(shell(),
571 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
572 AddIFrame(
573 shell()->web_contents()->GetMainFrame(),
574 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
575
576 TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
577 NAVIGATION_BLOCKED);
578 }
579
580 // Tests that navigation to a data URL is blocked even if the top frame is
581 // already a data URL.
582 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
583 HTML_Navigation_DataToData_Block) {
584 NavigateToURL(shell(), data_url());
585 ExecuteScriptAndCheckNavigation(
586 shell()->web_contents()->GetMainFrame(),
587 "document.getElementById('navigate-top-frame-to-html').click()",
588 NAVIGATION_BLOCKED);
589 }
590
591 // Tests that a form post to a data URL with HTML mime type is blocked even if
592 // the top frame is already a data URL.
593 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
594 HTML_FormPost_DataToData_Block) {
595 NavigateToURL(shell(), data_url());
596 ExecuteScriptAndCheckNavigation(
597 shell()->web_contents()->GetMainFrame(),
598 "document.getElementById('form-post-to-html').click()",
599 NAVIGATION_BLOCKED);
600 }
601
602 // Tests that navigating the top frame to a data URL with HTML mimetype is
603 // blocked even if the top frame is already a data URL.
604 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
605 HTML_NavigationFromFrame_TopFrameIsDataURL_Block) {
606 // This test fails and is disabled in site-per-process + no plznavigate mode.
607 // request->originDocument is null in FrameLoader::prepareForRequest,
608 // allowing the navigation by default. See https://crbug.com/647839
609 if (AreAllSitesIsolatedForTesting() && !IsBrowserSideNavigationEnabled()) {
610 return;
611 }
612
613 const GURL top_url(
614 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
615 embedded_test_server()
616 ->GetURL("/data_url_navigations.html")
617 .spec()
618 .c_str()));
619 NavigateToURL(shell(), top_url);
620
621 TestNavigationFromFrame(
622 "document.getElementById('navigate-top-frame-to-html').click()",
623 NAVIGATION_BLOCKED);
624 }
625
626 // Tests that opening a new window with a data URL with HTML mimetype is blocked
627 // even if the top frame is already a data URL.
628 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
629 HTML_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
630 const GURL top_url(
631 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
632 embedded_test_server()
633 ->GetURL("/data_url_navigations.html")
634 .spec()
635 .c_str()));
636 NavigateToURL(shell(), top_url);
637
638 TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
639 NAVIGATION_BLOCKED);
640 }
641
642 ////////////////////////////////////////////////////////////////////////////////
643 // data URLs with octet-stream mimetype (binary)
644 //
645 // Test that a direct navigation to a binary mime type initiates a download.
646 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
647 OctetStream_BrowserInitiated_Download) {
648 NavigateAndCheckDownload(GURL("data:application/octet-stream,test"));
649 }
650
651 // Test that window.open to a data URL results in a download if the URL has a
652 // binary mime type.
653 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
654 OctetStream_WindowOpen_Download) {
655 NavigateToURL(shell(),
656 embedded_test_server()->GetURL("/data_url_navigations.html"));
657 ExecuteScriptAndCheckWindowOpenDownload(
658 shell()->web_contents()->GetMainFrame(),
659 "document.getElementById('window-open-octetstream').click()");
660 }
661
662 // Test that a navigation to a data URL results in a download if the URL has a
663 // binary mime type.
664 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
665 OctetStream_Navigation_Download) {
666 NavigateToURL(shell(),
667 embedded_test_server()->GetURL("/data_url_navigations.html"));
668 ExecuteScriptAndCheckNavigationDownload(
669 shell()->web_contents()->GetMainFrame(),
670 "document.getElementById('navigate-top-frame-to-octetstream').click()");
671 }
672
673 // Test that a form post to a data URL results in a download if the URL has a
674 // binary mime type.
675 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
676 OctetStream_FormPost_Download) {
677 NavigateToURL(shell(),
678 embedded_test_server()->GetURL("/data_url_navigations.html"));
679 ExecuteScriptAndCheckNavigationDownload(
680 shell()->web_contents()->GetMainFrame(),
681 "document.getElementById('form-post-to-octetstream').click()");
682 }
683
684 // Tests that navigating the main frame from a subframe results in a download
685 // if the URL has a binary mimetype.
686 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
687 OctetStream_NavigationFromFrame_Download) {
688 NavigateToURL(shell(),
689 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
690 AddIFrame(
691 shell()->web_contents()->GetMainFrame(),
692 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
693
694 TestDownloadFromFrame(
695 "document.getElementById('navigate-top-frame-to-octetstream').click()");
696 }
697
698 ////////////////////////////////////////////////////////////////////////////////
699 // data URLs with unknown mimetype
700 //
701 // Test that a direct navigation to an unknown mime type initiates a download.
702 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
703 UnknownMimeType_BrowserInitiated_Download) {
704 NavigateAndCheckDownload(GURL("data:unknown/mimetype,test"));
705 }
706
707 // Test that window.open to a data URL results in a download if the URL has an
708 // unknown mime type.
709 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
710 UnknownMimeType_WindowOpen_Download) {
711 NavigateToURL(shell(),
712 embedded_test_server()->GetURL("/data_url_navigations.html"));
713 ExecuteScriptAndCheckWindowOpenDownload(
714 shell()->web_contents()->GetMainFrame(),
715 "document.getElementById('window-open-unknown-mimetype').click()");
716 }
717
718 // Test that a navigation to a data URL results in a download if the URL has an
719 // unknown mime type.
720 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
721 UnknownMimeType_Navigation_Download) {
722 NavigateToURL(shell(),
723 embedded_test_server()->GetURL("/data_url_navigations.html"));
724 ExecuteScriptAndCheckNavigationDownload(
725 shell()->web_contents()->GetMainFrame(),
726 "document.getElementById('navigate-top-"
727 "frame-to-unknown-mimetype').click()");
728 }
729
730 // Test that a form post to a data URL results in a download if the URL has an
731 // unknown mime type.
732 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
733 UnknownMimeType_FormPost_Download) {
734 NavigateToURL(shell(),
735 embedded_test_server()->GetURL("/data_url_navigations.html"));
736 ExecuteScriptAndCheckNavigationDownload(
737 shell()->web_contents()->GetMainFrame(),
738 "document.getElementById('form-post-to-unknown-mimetype').click()");
739 }
740
741 // Tests that navigating the main frame from a subframe results in a download
742 // if the URL has an unknown mimetype.
743 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
744 UnknownMimeType_NavigationFromFrame_Download) {
745 NavigateToURL(shell(),
746 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
747 AddIFrame(
748 shell()->web_contents()->GetMainFrame(),
749 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
750
751 TestDownloadFromFrame(
752 "document.getElementById('navigate-top-frame-to-unknown-mimetype').click("
753 ")");
754 }
755
756 ////////////////////////////////////////////////////////////////////////////////
757 // data URLs with PDF mimetype
758 //
759 // Tests that a browser initiated navigation to a data URL with PDF mime type is
760 // allowed, or initiates a download on Android.
761 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
762 PDF_BrowserInitiatedNavigation_Allow) {
763 #if !defined(OS_ANDROID)
764 TestNavigationObserver observer(shell()->web_contents());
765 NavigateToURL(shell(), GURL(kPdfUrl));
766 EXPECT_EQ(GURL(kPdfUrl), observer.last_navigation_url());
767 EXPECT_TRUE(observer.last_navigation_succeeded());
768 EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
769 url::kDataScheme));
770 #else
771 // On Android, PDFs are downloaded upon navigation.
772 NavigateAndCheckDownload(GURL(kPdfUrl));
773 #endif
774 }
775
776 // Tests that a window.open to a data URL is blocked if the data URL has a
777 // mime type that will be handled by a plugin (PDF in this case).
778 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_WindowOpen_Block) {
779 NavigateToURL(shell(),
780 embedded_test_server()->GetURL("/data_url_navigations.html"));
781
782 #if !defined(OS_ANDROID)
783 ExecuteScriptAndCheckWindowOpen(
784 shell()->web_contents()->GetMainFrame(),
785 "document.getElementById('window-open-pdf').click()", NAVIGATION_BLOCKED);
786 #else
787 // On Android, PDFs are downloaded upon navigation.
788 ExecuteScriptAndCheckNavigationDownload(
789 shell()->web_contents()->GetMainFrame(),
790 "document.getElementById('window-open-pdf').click()");
791 #endif
792 }
793
794 // Test that a navigation to a data URL is blocked if the data URL has a mime
795 // type that will be handled by a plugin (PDF in this case).
796 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_Navigation_Block) {
797 NavigateToURL(shell(),
798 embedded_test_server()->GetURL("/data_url_navigations.html"));
799
800 #if !defined(OS_ANDROID)
801 ExecuteScriptAndCheckPDFNavigation(
802 shell()->web_contents()->GetMainFrame(),
803 "document.getElementById('navigate-top-frame-to-pdf').click()",
804 NAVIGATION_BLOCKED);
805 #else
806 // On Android, PDFs are downloaded upon navigation.
807 ExecuteScriptAndCheckNavigationDownload(
808 shell()->web_contents()->GetMainFrame(),
809 "document.getElementById('navigate-top-frame-to-pdf').click()");
810 #endif
811 }
812
813 // Test that a form post to a data URL is blocked if the data URL has a mime
814 // type that will be handled by a plugin (PDF in this case).
815 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_FormPost_Block) {
816 NavigateToURL(shell(),
817 embedded_test_server()->GetURL("/data_url_navigations.html"));
818
819 #if !defined(OS_ANDROID)
820 ExecuteScriptAndCheckPDFNavigation(
821 shell()->web_contents()->GetMainFrame(),
822 "document.getElementById('form-post-to-pdf').click()",
823 NAVIGATION_BLOCKED);
824 #else
825 // On Android, PDFs are downloaded upon navigation.
826 ExecuteScriptAndCheckNavigationDownload(
827 shell()->web_contents()->GetMainFrame(),
828 "document.getElementById('form-post-to-pdf').click()");
829 #endif
830 }
831
832 // Tests that navigating the main frame to a data URL with PDF mimetype from a
833 // subframe is blocked.
834 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
835 PDF_NavigationFromFrame_Block) {
836 NavigateToURL(shell(),
837 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
838 AddIFrame(
839 shell()->web_contents()->GetMainFrame(),
840 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
841
842 #if !defined(OS_ANDROID)
843 TestPDFNavigationFromFrame(
844 "document.getElementById('navigate-top-frame-to-pdf').click()",
845 NAVIGATION_BLOCKED);
846 #else
847 // On Android, PDFs are downloaded upon navigation.
848 RenderFrameHost* child =
849 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
850 ASSERT_TRUE(child);
851 if (AreAllSitesIsolatedForTesting()) {
852 ASSERT_TRUE(child->IsCrossProcessSubframe());
853 }
854 ExecuteScriptAndCheckNavigationDownload(
855 child, "document.getElementById('navigate-top-frame-to-pdf').click()");
856 #endif
857 }
858
859 // Tests that opening a window with a data URL with PDF mimetype from a
860 // subframe is blocked.
861 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
862 PDF_WindowOpenFromFrame_Block) {
863 NavigateToURL(shell(),
864 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
865 AddIFrame(
866 shell()->web_contents()->GetMainFrame(),
867 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
868
869 #if !defined(OS_ANDROID)
870 TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
871 NAVIGATION_BLOCKED);
872 #else
873 // On Android, PDFs are downloaded upon navigation.
874 RenderFrameHost* child =
875 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
876 ASSERT_TRUE(child);
877 if (AreAllSitesIsolatedForTesting()) {
878 ASSERT_TRUE(child->IsCrossProcessSubframe());
879 }
880 ExecuteScriptAndCheckNavigationDownload(
881 child, "document.getElementById('window-open-pdf').click()");
882 #endif
883 }
884
885 // Tests that navigating the top frame to a data URL with PDF mimetype from a
886 // subframe is blocked even if the top frame is already a data URL.
887 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
888 PDF_NavigationFromFrame_TopFrameIsDataURL_Block) {
889 const GURL top_url(
890 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
891 embedded_test_server()
892 ->GetURL("/data_url_navigations.html")
893 .spec()
894 .c_str()));
895 NavigateToURL(shell(), top_url);
896
897 #if !defined(OS_ANDROID)
898 TestPDFNavigationFromFrame(
899 "document.getElementById('navigate-top-frame-to-pdf').click()",
900 NAVIGATION_BLOCKED);
901 #else
902 // On Android, PDFs are downloaded upon navigation.
903 RenderFrameHost* child =
904 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
905 ASSERT_TRUE(child);
906 if (AreAllSitesIsolatedForTesting()) {
907 ASSERT_TRUE(child->IsCrossProcessSubframe());
908 }
909 ExecuteScriptAndCheckNavigationDownload(
910 child, "document.getElementById('navigate-top-frame-to-pdf').click()");
911 #endif
912 }
913
914 // Tests that opening a window with a data URL with PDF mimetype from a
915 // subframe is blocked even if the top frame is already a data URL.
916 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
917 PDF_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
918 const GURL top_url(
919 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
920 embedded_test_server()
921 ->GetURL("/data_url_navigations.html")
922 .spec()
923 .c_str()));
924 NavigateToURL(shell(), top_url);
925
926 #if !defined(OS_ANDROID)
927 TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
928 NAVIGATION_BLOCKED);
929 #else
930 // On Android, PDFs are downloaded upon navigation.
931 RenderFrameHost* child =
932 ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
933 ASSERT_TRUE(child);
934 if (AreAllSitesIsolatedForTesting()) {
935 ASSERT_TRUE(child->IsCrossProcessSubframe());
936 }
937 ExecuteScriptAndCheckNavigationDownload(
938 child, "document.getElementById('window-open-pdf').click()");
939 #endif
940 }
941
942 } // content
OLDNEW
« no previous file with comments | « content/browser/BUILD.gn ('k') | content/browser/frame_host/data_url_navigation_throttle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698