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

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

Issue 2787123005: Block data URL navigations with RenderFrameImpl::DecidePolicyForNavigation (Closed)
Patch Set: Attempt another fix 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 top-level navigate to resource:*";
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 // data URL form of the file at content/test/data/data_url_navigations.html
449 GURL data_url() const { return data_url_; }
450
451 private:
452 base::ScopedTempDir downloads_directory_;
453
454 #if BUILDFLAG(ENABLE_PLUGINS)
455 ScopedPluginRegister scoped_plugin_register_;
456 #endif // BUILDFLAG(ENABLE_PLUGINS)
457
458 GURL data_url_;
459
460 DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationBrowserTest);
461 };
462
463 ////////////////////////////////////////////////////////////////////////////////
464 // data URLs with HTML mimetype
465 //
466 // Tests that a browser initiated navigation to a data URL doesn't show a
467 // console warning and is not blocked.
468 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, BrowserInitiated_Allow) {
469 DataURLWarningConsoleObserverDelegate console_delegate(
470 shell()->web_contents(), NAVIGATION_ALLOWED);
471 shell()->web_contents()->SetDelegate(&console_delegate);
472
473 NavigateToURL(shell(), GURL("data:text/"
474 "html,<html><script>console.log('NAVIGATION_"
475 "SUCCESSFUL');</script>"));
476 console_delegate.Wait();
477 shell()->web_contents()->SetDelegate(nullptr);
478
479 EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
480 url::kDataScheme));
481 }
482
483 // Tests that a content initiated navigation to a data URL is blocked.
484 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_Navigation_Block) {
485 NavigateToURL(shell(),
486 embedded_test_server()->GetURL("/data_url_navigations.html"));
487 ExecuteScriptAndCheckNavigation(
488 shell()->web_contents()->GetMainFrame(),
489 "document.getElementById('navigate-top-frame-to-html').click()",
490 NAVIGATION_BLOCKED);
491 }
492
493 // Tests that a content initiated navigation to a data URL is allowed if
494 // blocking is disabled with a feature flag.
495 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
496 HTML_Navigation_Allow_FeatureFlag) {
497 base::test::ScopedFeatureList feature_list;
498 feature_list.InitAndEnableFeature(
499 features::kAllowContentInitiatedDataUrlNavigations);
500 NavigateToURL(shell(),
501 embedded_test_server()->GetURL("/data_url_navigations.html"));
502 ExecuteScriptAndCheckNavigation(
503 shell()->web_contents()->GetMainFrame(),
504 "document.getElementById('navigate-top-frame-to-html').click()",
505 NAVIGATION_ALLOWED);
506 }
507
508 // Tests that a window.open to a data URL with HTML mime type is blocked.
509 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_WindowOpen_Block) {
510 NavigateToURL(shell(),
511 embedded_test_server()->GetURL("/data_url_navigations.html"));
512 ExecuteScriptAndCheckWindowOpen(
513 shell()->web_contents()->GetMainFrame(),
514 "document.getElementById('window-open-html').click()",
515 NAVIGATION_BLOCKED);
516 }
517
518 // Tests that a form post to a data URL with HTML mime type is blocked.
519 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_FormPost_Block) {
520 NavigateToURL(shell(),
521 embedded_test_server()->GetURL("/data_url_navigations.html"));
522 ExecuteScriptAndCheckNavigation(
523 shell()->web_contents()->GetMainFrame(),
524 "document.getElementById('form-post-to-html').click()",
525 NAVIGATION_BLOCKED);
526 }
527
528 // Tests that navigating the main frame to a data URL with HTML mimetype from a
529 // subframe is blocked.
530 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
531 HTML_NavigationFromFrame_Block) {
532 // This test fails and is disabled in site-per-process + no plznavigate mode.
533 // request->originDocument is null in FrameLoader::prepareForRequest,
534 // allowing the navigation by default. See https://crbug.com/647839
535 if (AreAllSitesIsolatedForTesting() && !IsBrowserSideNavigationEnabled()) {
536 return;
537 }
538
539 NavigateToURL(shell(),
540 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
541 AddIFrame(
542 shell()->web_contents()->GetMainFrame(),
543 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
544
545 TestNavigationFromFrame(
546 "document.getElementById('navigate-top-frame-to-html').click()",
547 NAVIGATION_BLOCKED);
548 }
549
550 // Tests that opening a new data URL window from a subframe is blocked.
551 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
552 HTML_WindowOpenFromFrame_Block) {
553 NavigateToURL(shell(),
554 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
555 AddIFrame(
556 shell()->web_contents()->GetMainFrame(),
557 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
558
559 TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
560 NAVIGATION_BLOCKED);
561 }
562
563 // Tests that navigation to a data URL is blocked even if the top frame is
564 // already a data URL.
565 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
566 HTML_Navigation_DataToData_Block) {
567 NavigateToURL(shell(), data_url());
568 ExecuteScriptAndCheckNavigation(
569 shell()->web_contents()->GetMainFrame(),
570 "document.getElementById('navigate-top-frame-to-html').click()",
571 NAVIGATION_BLOCKED);
572 }
573
574 // Tests that a form post to a data URL with HTML mime type is blocked even if
575 // the top frame is already a data URL.
576 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
577 HTML_FormPost_DataToData_Block) {
578 NavigateToURL(shell(), data_url());
579 ExecuteScriptAndCheckNavigation(
580 shell()->web_contents()->GetMainFrame(),
581 "document.getElementById('form-post-to-html').click()",
582 NAVIGATION_BLOCKED);
583 }
584
585 // Tests that navigating the top frame to a data URL with HTML mimetype is
586 // blocked even if the top frame is already a data URL.
587 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
588 HTML_NavigationFromFrame_TopFrameIsDataURL_Block) {
589 // This test fails and is disabled in site-per-process + no plznavigate mode.
590 // request->originDocument is null in FrameLoader::prepareForRequest,
591 // allowing the navigation by default. See https://crbug.com/647839
592 if (AreAllSitesIsolatedForTesting() && !IsBrowserSideNavigationEnabled()) {
593 return;
594 }
595
596 const GURL top_url(
597 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
598 embedded_test_server()
599 ->GetURL("/data_url_navigations.html")
600 .spec()
601 .c_str()));
602 NavigateToURL(shell(), top_url);
603
604 TestNavigationFromFrame(
605 "document.getElementById('navigate-top-frame-to-html').click()",
606 NAVIGATION_BLOCKED);
607 }
608
609 // Tests that opening a new window with a data URL with HTML mimetype is blocked
610 // even if the top frame is already a data URL.
611 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
612 HTML_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
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 TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
622 NAVIGATION_BLOCKED);
623 }
624
625 ////////////////////////////////////////////////////////////////////////////////
626 // data URLs with octet-stream mimetype (binary)
627 //
628 // Test that window.open to a data URL results in a download if the URL has a
629 // binary mime type.
630 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
631 OctetStream_WindowOpen_Download) {
632 NavigateToURL(shell(),
633 embedded_test_server()->GetURL("/data_url_navigations.html"));
634 ExecuteScriptAndCheckWindowOpenDownload(
635 shell()->web_contents()->GetMainFrame(),
636 "document.getElementById('window-open-octetstream').click()");
637 }
638
639 // Test that a navigation to a data URL results in a download if the URL has a
640 // binary mime type.
641 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
642 OctetStream_Navigation_Download) {
643 NavigateToURL(shell(),
644 embedded_test_server()->GetURL("/data_url_navigations.html"));
645 ExecuteScriptAndCheckNavigationDownload(
646 shell()->web_contents()->GetMainFrame(),
647 "document.getElementById('navigate-top-frame-to-octetstream').click()");
648 }
649
650 // Test that a form post to a data URL results in a download if the URL has a
651 // binary mime type.
652 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
653 OctetStream_FormPost_Download) {
654 NavigateToURL(shell(),
655 embedded_test_server()->GetURL("/data_url_navigations.html"));
656 ExecuteScriptAndCheckNavigationDownload(
657 shell()->web_contents()->GetMainFrame(),
658 "document.getElementById('form-post-to-octetstream').click()");
659 }
660
661 // Tests that navigating the main frame from a subframe results in a download
662 // if the URL has a binary mimetype.
663 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
664 OctetStream_NavigationFromFrame_Download) {
665 NavigateToURL(shell(),
666 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
667 AddIFrame(
668 shell()->web_contents()->GetMainFrame(),
669 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
670
671 TestDownloadFromFrame(
672 "document.getElementById('navigate-top-frame-to-octetstream').click()");
673 }
674
675 ////////////////////////////////////////////////////////////////////////////////
676 // data URLs with unknown mimetype
677 //
678 // Test that window.open to a data URL results in a download if the URL has an
679 // unknown mime type.
680 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
681 UnknownMimeType_WindowOpen_Download) {
682 NavigateToURL(shell(),
683 embedded_test_server()->GetURL("/data_url_navigations.html"));
684 ExecuteScriptAndCheckWindowOpenDownload(
685 shell()->web_contents()->GetMainFrame(),
686 "document.getElementById('window-open-unknown-mimetype').click()");
687 }
688
689 // Test that a navigation to a data URL results in a download if the URL has an
690 // unknown mime type.
691 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
692 UnknownMimeType_Navigation_Download) {
693 NavigateToURL(shell(),
694 embedded_test_server()->GetURL("/data_url_navigations.html"));
695 ExecuteScriptAndCheckNavigationDownload(
696 shell()->web_contents()->GetMainFrame(),
697 "document.getElementById('navigate-top-"
698 "frame-to-unknown-mimetype').click()");
699 }
700
701 // Test that a form post to a data URL results in a download if the URL has an
702 // unknown mime type.
703 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
704 UnknownMimeType_FormPost_Download) {
705 NavigateToURL(shell(),
706 embedded_test_server()->GetURL("/data_url_navigations.html"));
707 ExecuteScriptAndCheckNavigationDownload(
708 shell()->web_contents()->GetMainFrame(),
709 "document.getElementById('form-post-to-unknown-mimetype').click()");
710 }
711
712 // Tests that navigating the main frame from a subframe results in a download
713 // if the URL has an unknown mimetype.
714 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
715 UnknownMimeType_NavigationFromFrame_Download) {
716 NavigateToURL(shell(),
717 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
718 AddIFrame(
719 shell()->web_contents()->GetMainFrame(),
720 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
721
722 TestDownloadFromFrame(
723 "document.getElementById('navigate-top-frame-to-unknown-mimetype').click("
724 ")");
725 }
726
727 ////////////////////////////////////////////////////////////////////////////////
728 // data URLs with PDF mimetype
729 //
730 // Tests that a browser initiated navigation to a data URL with PDF mime type is
731 // allowed.
732 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
733 PDF_BrowserInitiatedNavigation_Allow) {
734 TestNavigationObserver observer(shell()->web_contents());
735 NavigateToURL(shell(), GURL(kPdfUrl));
736 EXPECT_EQ(GURL(kPdfUrl), observer.last_navigation_url());
737 EXPECT_TRUE(observer.last_navigation_succeeded());
738 EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
739 url::kDataScheme));
740 }
741
742 // Tests that a window.open to a data URL is blocked if the data URL has a
743 // mime type that will be handled by a plugin (PDF in this case).
744 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_WindowOpen_Block) {
745 NavigateToURL(shell(),
746 embedded_test_server()->GetURL("/data_url_navigations.html"));
747 ExecuteScriptAndCheckWindowOpen(
748 shell()->web_contents()->GetMainFrame(),
749 "document.getElementById('window-open-pdf').click()", NAVIGATION_BLOCKED);
750 }
751
752 // Test that a navigation to a data URL is blocked if the data URL has a mime
753 // type that will be handled by a plugin (PDF in this case).
754 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_Navigation_Block) {
755 NavigateToURL(shell(),
756 embedded_test_server()->GetURL("/data_url_navigations.html"));
757 ExecuteScriptAndCheckPDFNavigation(
758 shell()->web_contents()->GetMainFrame(),
759 "document.getElementById('navigate-top-frame-to-pdf').click()",
760 NAVIGATION_BLOCKED);
761 }
762
763 // Test that a form post to a data URL is blocked if the data URL has a mime
764 // type that will be handled by a plugin (PDF in this case).
765 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_FormPost_Block) {
766 NavigateToURL(shell(),
767 embedded_test_server()->GetURL("/data_url_navigations.html"));
768 ExecuteScriptAndCheckPDFNavigation(
769 shell()->web_contents()->GetMainFrame(),
770 "document.getElementById('form-post-to-pdf').click()",
771 NAVIGATION_BLOCKED);
772 }
773
774 // Tests that navigating the main frame to a data URL with PDF mimetype from a
775 // subframe is blocked.
776 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
777 PDF_NavigationFromFrame_Block) {
778 NavigateToURL(shell(),
779 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
780 AddIFrame(
781 shell()->web_contents()->GetMainFrame(),
782 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
783
784 TestPDFNavigationFromFrame(
785 "document.getElementById('navigate-top-frame-to-pdf').click()",
786 NAVIGATION_BLOCKED);
787 }
788
789 // Tests that opening a window with a data URL with PDF mimetype from a
790 // subframe is blocked.
791 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
792 PDF_WindowOpenFromFrame_Block) {
793 NavigateToURL(shell(),
794 embedded_test_server()->GetURL("a.com", "/simple_page.html"));
795 AddIFrame(
796 shell()->web_contents()->GetMainFrame(),
797 embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
798
799 TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
800 NAVIGATION_BLOCKED);
801 }
802
803 // Tests that navigating the top frame to a data URL with PDF mimetype from a
804 // subframe is blocked even if the top frame is already a data URL.
805 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
806 PDF_NavigationFromFrame_TopFrameIsDataURL_Block) {
807 const GURL top_url(
808 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
809 embedded_test_server()
810 ->GetURL("/data_url_navigations.html")
811 .spec()
812 .c_str()));
813 NavigateToURL(shell(), top_url);
814
815 TestPDFNavigationFromFrame(
816 "document.getElementById('navigate-top-frame-to-pdf').click()",
817 NAVIGATION_BLOCKED);
818 }
819
820 // Tests that opening a window with a data URL with PDF mimetype from a
821 // subframe is blocked even if the top frame is already a data URL.
822 IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
823 PDF_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
824 const GURL top_url(
825 base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
826 embedded_test_server()
827 ->GetURL("/data_url_navigations.html")
828 .spec()
829 .c_str()));
830 NavigateToURL(shell(), top_url);
831
832 TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
833 NAVIGATION_BLOCKED);
834 }
835
836 } // 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