| Index: content/browser/frame_host/data_url_navigation_browsertest.cc
|
| diff --git a/content/browser/frame_host/data_url_navigation_browsertest.cc b/content/browser/frame_host/data_url_navigation_browsertest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3091dff963d926ae1e4b32bf500b1d7c427712c9
|
| --- /dev/null
|
| +++ b/content/browser/frame_host/data_url_navigation_browsertest.cc
|
| @@ -0,0 +1,836 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/files/file_util.h"
|
| +#include "base/files/scoped_temp_dir.h"
|
| +#include "base/macros.h"
|
| +#include "base/path_service.h"
|
| +#include "base/strings/pattern.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "base/test/scoped_feature_list.h"
|
| +#include "build/build_config.h"
|
| +#include "build/buildflag.h"
|
| +#include "content/browser/site_per_process_browsertest.h"
|
| +#include "content/public/browser/browser_context.h"
|
| +#include "content/public/browser/navigation_entry.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/browser_side_navigation_policy.h"
|
| +#include "content/public/common/content_features.h"
|
| +#include "content/public/common/content_paths.h"
|
| +#include "content/public/common/content_switches.h"
|
| +#include "content/public/test/browser_test_utils.h"
|
| +#include "content/public/test/content_browser_test.h"
|
| +#include "content/public/test/content_browser_test_utils.h"
|
| +#include "content/public/test/download_test_observer.h"
|
| +#include "content/public/test/test_navigation_observer.h"
|
| +#include "content/shell/browser/shell.h"
|
| +#include "content/shell/browser/shell_download_manager_delegate.h"
|
| +#include "net/base/escape.h"
|
| +#include "net/dns/mock_host_resolver.h"
|
| +#include "net/test/embedded_test_server/embedded_test_server.h"
|
| +#include "ppapi/features/features.h"
|
| +
|
| +#if BUILDFLAG(ENABLE_PLUGINS)
|
| +#include "content/public/browser/plugin_service.h"
|
| +#include "content/public/common/webplugininfo.h"
|
| +#endif
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +// The pattern to catch messages printed by the browser when a data URL
|
| +// navigation is blocked.
|
| +const char kDataUrlBlockedPattern[] =
|
| + "Not allowed to top-level navigate to resource:*";
|
| +
|
| +// The message printed by the data URL when it successfully navigates.
|
| +const char kDataUrlSuccessfulMessage[] = "NAVIGATION_SUCCESSFUL";
|
| +
|
| +// A "Hello World" PDF encoded as a data URL. Source of this PDF:
|
| +// -------------------------
|
| +// %PDF-1.7
|
| +// 1 0 obj << /Type /Page /Parent 3 0 R /Resources 5 0 R /Contents 2 0 R >>
|
| +// endobj
|
| +// 2 0 obj << /Length 51 >>
|
| +// stream BT
|
| +// /F1 12 Tf
|
| +// 1 0 0 1 100 20 Tm
|
| +// (Hello World)Tj
|
| +// ET
|
| +// endstream
|
| +// endobj
|
| +// 3 0 obj << /Type /Pages /Kids [ 1 0 R ] /Count 1 /MediaBox [ 0 0 300 50] >>
|
| +// endobj
|
| +// 4 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont/Arial >>
|
| +// endobj
|
| +// 5 0 obj << /ProcSet[/PDF/Text] /Font <</F1 4 0 R >> >>
|
| +// endobj
|
| +// 6 0 obj << /Type /Catalog /Pages 3 0 R >>
|
| +// endobj
|
| +// trailer << /Root 6 0 R >>
|
| +// -------------------------
|
| +const char kPdfUrl[] =
|
| + "data:application/pdf;base64,JVBERi0xLjcKMSAwIG9iaiA8PCAvVHlwZSAvUGFnZSAvUG"
|
| + "FyZW50IDMgMCBSIC9SZXNvdXJjZXMgNSAwIFIgL0NvbnRlbnRzIDIgMCBSID4+CmVuZG9iagoy"
|
| + "IDAgb2JqIDw8IC9MZW5ndGggNTEgPj4KIHN0cmVhbSBCVAogL0YxIDEyIFRmCiAxIDAgMCAxID"
|
| + "EwMCAyMCBUbQogKEhlbGxvIFdvcmxkKVRqCiBFVAogZW5kc3RyZWFtCmVuZG9iagozIDAgb2Jq"
|
| + "IDw8IC9UeXBlIC9QYWdlcyAvS2lkcyBbIDEgMCBSIF0gL0NvdW50IDEgL01lZGlhQm94IFsgMC"
|
| + "AwIDMwMCA1MF0gPj4KZW5kb2JqCjQgMCBvYmogPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1R5"
|
| + "cGUxIC9OYW1lIC9GMSAvQmFzZUZvbnQvQXJpYWwgPj4KZW5kb2JqCjUgMCBvYmogPDwgL1Byb2"
|
| + "NTZXRbL1BERi9UZXh0XSAvRm9udCA8PC9GMSA0IDAgUiA+PiA+PgplbmRvYmoKNiAwIG9iaiA8"
|
| + "PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMyAwIFIgPj4KZW5kb2JqCnRyYWlsZXIgPDwgL1Jvb3"
|
| + "QgNiAwIFIgPj4K";
|
| +
|
| +enum ExpectedNavigationStatus { NAVIGATION_BLOCKED, NAVIGATION_ALLOWED };
|
| +
|
| +// This class is similar to ConsoleObserverDelegate in that it listens and waits
|
| +// for specific console messages. The difference from ConsoleObserverDelegate is
|
| +// that this class immediately stops waiting if it sees a message matching
|
| +// fail_pattern, instead of waiting for a message matching success_pattern.
|
| +class DataURLWarningConsoleObserverDelegate : public WebContentsDelegate {
|
| + public:
|
| + DataURLWarningConsoleObserverDelegate(
|
| + WebContents* web_contents,
|
| + ExpectedNavigationStatus expected_navigation_status)
|
| + : web_contents_(web_contents),
|
| + success_filter_(expected_navigation_status == NAVIGATION_ALLOWED
|
| + ? kDataUrlSuccessfulMessage
|
| + : kDataUrlBlockedPattern),
|
| + fail_filter_(expected_navigation_status == NAVIGATION_ALLOWED
|
| + ? kDataUrlBlockedPattern
|
| + : kDataUrlSuccessfulMessage),
|
| + message_loop_runner_(
|
| + new MessageLoopRunner(MessageLoopRunner::QuitMode::IMMEDIATE)),
|
| + saw_failure_message_(false) {}
|
| + ~DataURLWarningConsoleObserverDelegate() override {}
|
| +
|
| + void Wait() { message_loop_runner_->Run(); }
|
| +
|
| + // WebContentsDelegate method:
|
| + bool DidAddMessageToConsole(WebContents* source,
|
| + int32_t level,
|
| + const base::string16& message,
|
| + int32_t line_no,
|
| + const base::string16& source_id) override {
|
| + DCHECK(source == web_contents_);
|
| + const std::string ascii_message = base::UTF16ToASCII(message);
|
| + if (base::MatchPattern(ascii_message, fail_filter_)) {
|
| + saw_failure_message_ = true;
|
| + message_loop_runner_->Quit();
|
| + }
|
| + if (base::MatchPattern(ascii_message, success_filter_)) {
|
| + message_loop_runner_->Quit();
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + // Returns true if the observer encountered a message that matches
|
| + // |fail_filter_|.
|
| + bool saw_failure_message() const { return saw_failure_message_; }
|
| +
|
| + private:
|
| + WebContents* web_contents_;
|
| + const std::string success_filter_;
|
| + const std::string fail_filter_;
|
| + scoped_refptr<MessageLoopRunner> message_loop_runner_;
|
| + bool saw_failure_message_;
|
| +};
|
| +
|
| +#if BUILDFLAG(ENABLE_PLUGINS)
|
| +// This class registers a fake PDF plugin handler so that data URL navigations
|
| +// with a PDF mime type end up with a navigation and don't simply download the
|
| +// file.
|
| +class ScopedPluginRegister {
|
| + public:
|
| + ScopedPluginRegister(content::PluginService* plugin_service)
|
| + : plugin_service_(plugin_service) {
|
| + const char kPluginName[] = "PDF";
|
| + const char kPdfMimeType[] = "application/pdf";
|
| + const char kPdfFileType[] = "pdf";
|
| + WebPluginInfo plugin_info;
|
| + plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
|
| + plugin_info.name = base::ASCIIToUTF16(kPluginName);
|
| + plugin_info.mime_types.push_back(
|
| + WebPluginMimeType(kPdfMimeType, kPdfFileType, std::string()));
|
| + plugin_service_->RegisterInternalPlugin(plugin_info, false);
|
| + plugin_service_->RefreshPlugins();
|
| + }
|
| +
|
| + ~ScopedPluginRegister() {
|
| + std::vector<WebPluginInfo> plugins;
|
| + plugin_service_->GetInternalPlugins(&plugins);
|
| + EXPECT_EQ(1u, plugins.size());
|
| + plugin_service_->UnregisterInternalPlugin(plugins[0].path);
|
| + plugin_service_->RefreshPlugins();
|
| +
|
| + plugins.clear();
|
| + plugin_service_->GetInternalPlugins(&plugins);
|
| + EXPECT_TRUE(plugins.empty());
|
| + }
|
| +
|
| + private:
|
| + content::PluginService* plugin_service_;
|
| +};
|
| +#endif // BUILDFLAG(ENABLE_PLUGINS)
|
| +
|
| +} // namespace
|
| +
|
| +class DataUrlNavigationBrowserTest : public ContentBrowserTest {
|
| + public:
|
| +#if BUILDFLAG(ENABLE_PLUGINS)
|
| + DataUrlNavigationBrowserTest()
|
| + : scoped_plugin_register_(PluginService::GetInstance()) {}
|
| +#else
|
| + DataUrlNavigationBrowserTest() {}
|
| +#endif // BUILDFLAG(ENABLE_PLUGINS)
|
| +
|
| + protected:
|
| + void SetUpOnMainThread() override {
|
| + host_resolver()->AddRule("*", "127.0.0.1");
|
| + ASSERT_TRUE(embedded_test_server()->Start());
|
| +
|
| + base::FilePath path;
|
| + ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &path));
|
| + path = path.AppendASCII("data_url_navigations.html");
|
| + ASSERT_TRUE(base::PathExists(path));
|
| +
|
| + std::string contents;
|
| + ASSERT_TRUE(base::ReadFileToString(path, &contents));
|
| + data_url_ = GURL(std::string("data:text/html,") + contents);
|
| +
|
| + ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
|
| + ShellDownloadManagerDelegate* delegate =
|
| + static_cast<ShellDownloadManagerDelegate*>(
|
| + shell()
|
| + ->web_contents()
|
| + ->GetBrowserContext()
|
| + ->GetDownloadManagerDelegate());
|
| + delegate->SetDownloadBehaviorForTesting(downloads_directory_.GetPath());
|
| + }
|
| +
|
| + // Adds an iframe to |rfh| pointing to |url|.
|
| + void AddIFrame(RenderFrameHost* rfh, const GURL& url) {
|
| + const std::string javascript = base::StringPrintf(
|
| + "f = document.createElement('iframe'); f.src = '%s';"
|
| + "document.body.appendChild(f);",
|
| + url.spec().c_str());
|
| + TestNavigationObserver observer(shell()->web_contents());
|
| + EXPECT_TRUE(ExecuteScript(rfh, javascript));
|
| + observer.Wait();
|
| + }
|
| +
|
| + // Runs |javascript| on the first child frame and checks for a navigation.
|
| + void TestNavigationFromFrame(
|
| + const std::string& javascript,
|
| + ExpectedNavigationStatus expected_navigation_status) {
|
| + RenderFrameHost* child =
|
| + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
|
| + ASSERT_TRUE(child);
|
| + if (AreAllSitesIsolatedForTesting()) {
|
| + ASSERT_TRUE(child->IsCrossProcessSubframe());
|
| + }
|
| + ExecuteScriptAndCheckNavigation(child, javascript,
|
| + expected_navigation_status);
|
| + }
|
| +
|
| + // Runs |javascript| on the first child frame and expects a download to occur.
|
| + void TestDownloadFromFrame(const std::string& javascript) {
|
| + RenderFrameHost* child =
|
| + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
|
| + ASSERT_TRUE(child);
|
| + if (AreAllSitesIsolatedForTesting()) {
|
| + ASSERT_TRUE(child->IsCrossProcessSubframe());
|
| + }
|
| + ExecuteScriptAndCheckNavigationDownload(child, javascript);
|
| + }
|
| +
|
| + // Runs |javascript| on the first child frame and checks for a navigation to
|
| + // the PDF file pointed by the test case.
|
| + void TestPDFNavigationFromFrame(
|
| + const std::string& javascript,
|
| + ExpectedNavigationStatus expected_navigation_status) {
|
| + RenderFrameHost* child =
|
| + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
|
| + ASSERT_TRUE(child);
|
| + if (AreAllSitesIsolatedForTesting()) {
|
| + ASSERT_TRUE(child->IsCrossProcessSubframe());
|
| + }
|
| + ExecuteScriptAndCheckPDFNavigation(child, javascript,
|
| + expected_navigation_status);
|
| + }
|
| +
|
| + // Same as TestNavigationFromFrame, but instead of navigating, the child frame
|
| + // tries to open a new window with a data URL.
|
| + void TestWindowOpenFromFrame(
|
| + const std::string& javascript,
|
| + ExpectedNavigationStatus expected_navigation_status) {
|
| + RenderFrameHost* child =
|
| + ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
|
| + if (AreAllSitesIsolatedForTesting()) {
|
| + ASSERT_TRUE(child->IsCrossProcessSubframe());
|
| + }
|
| + ExecuteScriptAndCheckWindowOpen(child, javascript,
|
| + expected_navigation_status);
|
| + }
|
| +
|
| + // Executes |javascript| on |rfh| and waits for a console message based on
|
| + // |expected_navigation_status|.
|
| + // - Blocked navigations should print kDataUrlBlockedPattern.
|
| + // - Allowed navigations should print kDataUrlSuccessfulMessage.
|
| + void ExecuteScriptAndCheckNavigation(
|
| + RenderFrameHost* rfh,
|
| + const std::string& javascript,
|
| + ExpectedNavigationStatus expected_navigation_status) {
|
| + const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
|
| + const std::string expected_message;
|
| +
|
| + DataURLWarningConsoleObserverDelegate console_delegate(
|
| + shell()->web_contents(), expected_navigation_status);
|
| + shell()->web_contents()->SetDelegate(&console_delegate);
|
| +
|
| + TestNavigationObserver navigation_observer(shell()->web_contents());
|
| + EXPECT_TRUE(ExecuteScript(rfh, javascript));
|
| + console_delegate.Wait();
|
| + EXPECT_FALSE(console_delegate.saw_failure_message());
|
| + shell()->web_contents()->SetDelegate(nullptr);
|
| +
|
| + switch (expected_navigation_status) {
|
| + case NAVIGATION_ALLOWED:
|
| + navigation_observer.Wait();
|
| + // The new page should have a data URL.
|
| + EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
|
| + url::kDataScheme));
|
| + EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(
|
| + url::kDataScheme));
|
| + EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
|
| + break;
|
| +
|
| + case NAVIGATION_BLOCKED:
|
| + // Original page shouldn't navigate away.
|
| + EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
|
| + EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + // Similar to ExecuteScriptAndCheckNavigation(), but doesn't wait for a
|
| + // console message if the navigation is expected to be allowed (this is
|
| + // because PDF files can't print to the console).
|
| + void ExecuteScriptAndCheckPDFNavigation(
|
| + RenderFrameHost* rfh,
|
| + const std::string& javascript,
|
| + ExpectedNavigationStatus expected_navigation_status) {
|
| + const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
|
| +
|
| + const std::string expected_message =
|
| + (expected_navigation_status == NAVIGATION_ALLOWED)
|
| + ? std::string()
|
| + : kDataUrlBlockedPattern;
|
| +
|
| + std::unique_ptr<ConsoleObserverDelegate> console_delegate;
|
| + if (!expected_message.empty()) {
|
| + console_delegate.reset(new ConsoleObserverDelegate(
|
| + shell()->web_contents(), expected_message));
|
| + shell()->web_contents()->SetDelegate(console_delegate.get());
|
| + }
|
| +
|
| + TestNavigationObserver navigation_observer(shell()->web_contents());
|
| + EXPECT_TRUE(ExecuteScript(rfh, javascript));
|
| +
|
| + if (console_delegate) {
|
| + console_delegate->Wait();
|
| + shell()->web_contents()->SetDelegate(nullptr);
|
| + }
|
| +
|
| + switch (expected_navigation_status) {
|
| + case NAVIGATION_ALLOWED:
|
| + navigation_observer.Wait();
|
| + // The new page should have a data URL.
|
| + EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
|
| + url::kDataScheme));
|
| + EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(
|
| + url::kDataScheme));
|
| + EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
|
| + break;
|
| +
|
| + case NAVIGATION_BLOCKED:
|
| + // Original page shouldn't navigate away.
|
| + EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
|
| + EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + // Executes |javascript| on |rfh| and waits for a new window to be opened.
|
| + // Does not check for console messages (it's currently not possible to
|
| + // concurrently wait for a new shell to be created and a console message to be
|
| + // printed on that new shell).
|
| + void ExecuteScriptAndCheckWindowOpen(
|
| + RenderFrameHost* rfh,
|
| + const std::string& javascript,
|
| + ExpectedNavigationStatus expected_navigation_status) {
|
| + ShellAddedObserver new_shell_observer;
|
| + EXPECT_TRUE(ExecuteScript(rfh, javascript));
|
| +
|
| + Shell* new_shell = new_shell_observer.GetShell();
|
| + WaitForLoadStop(new_shell->web_contents());
|
| +
|
| + switch (expected_navigation_status) {
|
| + case NAVIGATION_ALLOWED:
|
| + EXPECT_TRUE(new_shell->web_contents()->GetLastCommittedURL().SchemeIs(
|
| + url::kDataScheme));
|
| + break;
|
| +
|
| + case NAVIGATION_BLOCKED:
|
| + EXPECT_TRUE(
|
| + new_shell->web_contents()->GetLastCommittedURL().is_empty());
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + // Executes |javascript| on |rfh| and waits for a download to be started by
|
| + // a window.open call.
|
| + void ExecuteScriptAndCheckWindowOpenDownload(RenderFrameHost* rfh,
|
| + const std::string& javascript) {
|
| + const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
|
| + ShellAddedObserver new_shell_observer;
|
| + DownloadManager* download_manager = BrowserContext::GetDownloadManager(
|
| + shell()->web_contents()->GetBrowserContext());
|
| +
|
| + EXPECT_TRUE(ExecuteScript(rfh, javascript));
|
| + Shell* new_shell = new_shell_observer.GetShell();
|
| +
|
| + DownloadTestObserverTerminal download_observer(
|
| + download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
|
| +
|
| + WaitForLoadStop(new_shell->web_contents());
|
| + // If no download happens, this will timeout.
|
| + download_observer.WaitForFinished();
|
| +
|
| + EXPECT_TRUE(
|
| + new_shell->web_contents()->GetLastCommittedURL().spec().empty());
|
| + // No navigation should commit.
|
| + EXPECT_FALSE(
|
| + new_shell->web_contents()->GetController().GetLastCommittedEntry());
|
| + // Original page shouldn't navigate away.
|
| + EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
|
| + }
|
| +
|
| + // Executes |javascript| on |rfh| and waits for a download to be started.
|
| + void ExecuteScriptAndCheckNavigationDownload(RenderFrameHost* rfh,
|
| + const std::string& javascript) {
|
| + const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
|
| + DownloadManager* download_manager = BrowserContext::GetDownloadManager(
|
| + shell()->web_contents()->GetBrowserContext());
|
| + DownloadTestObserverTerminal download_observer(
|
| + download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
|
| +
|
| + EXPECT_TRUE(ExecuteScript(rfh, javascript));
|
| + // If no download happens, this will timeout.
|
| + download_observer.WaitForFinished();
|
| +
|
| + // Original page shouldn't navigate away.
|
| + EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
|
| + }
|
| +
|
| + // data URL form of the file at content/test/data/data_url_navigations.html
|
| + GURL data_url() const { return data_url_; }
|
| +
|
| + private:
|
| + base::ScopedTempDir downloads_directory_;
|
| +
|
| +#if BUILDFLAG(ENABLE_PLUGINS)
|
| + ScopedPluginRegister scoped_plugin_register_;
|
| +#endif // BUILDFLAG(ENABLE_PLUGINS)
|
| +
|
| + GURL data_url_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationBrowserTest);
|
| +};
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// data URLs with HTML mimetype
|
| +//
|
| +// Tests that a browser initiated navigation to a data URL doesn't show a
|
| +// console warning and is not blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, BrowserInitiated_Allow) {
|
| + DataURLWarningConsoleObserverDelegate console_delegate(
|
| + shell()->web_contents(), NAVIGATION_ALLOWED);
|
| + shell()->web_contents()->SetDelegate(&console_delegate);
|
| +
|
| + NavigateToURL(shell(), GURL("data:text/"
|
| + "html,<html><script>console.log('NAVIGATION_"
|
| + "SUCCESSFUL');</script>"));
|
| + console_delegate.Wait();
|
| + shell()->web_contents()->SetDelegate(nullptr);
|
| +
|
| + EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
|
| + url::kDataScheme));
|
| +}
|
| +
|
| +// Tests that a content initiated navigation to a data URL is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_Navigation_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('navigate-top-frame-to-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that a content initiated navigation to a data URL is allowed if
|
| +// blocking is disabled with a feature flag.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_Navigation_Allow_FeatureFlag) {
|
| + base::test::ScopedFeatureList feature_list;
|
| + feature_list.InitAndEnableFeature(
|
| + features::kAllowContentInitiatedDataUrlNavigations);
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('navigate-top-frame-to-html').click()",
|
| + NAVIGATION_ALLOWED);
|
| +}
|
| +
|
| +// Tests that a window.open to a data URL with HTML mime type is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_WindowOpen_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckWindowOpen(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('window-open-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that a form post to a data URL with HTML mime type is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_FormPost_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('form-post-to-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that navigating the main frame to a data URL with HTML mimetype from a
|
| +// subframe is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_NavigationFromFrame_Block) {
|
| + // This test fails and is disabled in site-per-process + no plznavigate mode.
|
| + // request->originDocument is null in FrameLoader::prepareForRequest,
|
| + // allowing the navigation by default. See https://crbug.com/647839
|
| + if (AreAllSitesIsolatedForTesting() && !IsBrowserSideNavigationEnabled()) {
|
| + return;
|
| + }
|
| +
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("a.com", "/simple_page.html"));
|
| + AddIFrame(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
|
| +
|
| + TestNavigationFromFrame(
|
| + "document.getElementById('navigate-top-frame-to-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that opening a new data URL window from a subframe is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_WindowOpenFromFrame_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("a.com", "/simple_page.html"));
|
| + AddIFrame(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
|
| +
|
| + TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that navigation to a data URL is blocked even if the top frame is
|
| +// already a data URL.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_Navigation_DataToData_Block) {
|
| + NavigateToURL(shell(), data_url());
|
| + ExecuteScriptAndCheckNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('navigate-top-frame-to-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that a form post to a data URL with HTML mime type is blocked even if
|
| +// the top frame is already a data URL.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_FormPost_DataToData_Block) {
|
| + NavigateToURL(shell(), data_url());
|
| + ExecuteScriptAndCheckNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('form-post-to-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that navigating the top frame to a data URL with HTML mimetype is
|
| +// blocked even if the top frame is already a data URL.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_NavigationFromFrame_TopFrameIsDataURL_Block) {
|
| + // This test fails and is disabled in site-per-process + no plznavigate mode.
|
| + // request->originDocument is null in FrameLoader::prepareForRequest,
|
| + // allowing the navigation by default. See https://crbug.com/647839
|
| + if (AreAllSitesIsolatedForTesting() && !IsBrowserSideNavigationEnabled()) {
|
| + return;
|
| + }
|
| +
|
| + const GURL top_url(
|
| + base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
|
| + embedded_test_server()
|
| + ->GetURL("/data_url_navigations.html")
|
| + .spec()
|
| + .c_str()));
|
| + NavigateToURL(shell(), top_url);
|
| +
|
| + TestNavigationFromFrame(
|
| + "document.getElementById('navigate-top-frame-to-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that opening a new window with a data URL with HTML mimetype is blocked
|
| +// even if the top frame is already a data URL.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + HTML_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
|
| + const GURL top_url(
|
| + base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
|
| + embedded_test_server()
|
| + ->GetURL("/data_url_navigations.html")
|
| + .spec()
|
| + .c_str()));
|
| + NavigateToURL(shell(), top_url);
|
| +
|
| + TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// data URLs with octet-stream mimetype (binary)
|
| +//
|
| +// Test that window.open to a data URL results in a download if the URL has a
|
| +// binary mime type.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + OctetStream_WindowOpen_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckWindowOpenDownload(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('window-open-octetstream').click()");
|
| +}
|
| +
|
| +// Test that a navigation to a data URL results in a download if the URL has a
|
| +// binary mime type.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + OctetStream_Navigation_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigationDownload(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('navigate-top-frame-to-octetstream').click()");
|
| +}
|
| +
|
| +// Test that a form post to a data URL results in a download if the URL has a
|
| +// binary mime type.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + OctetStream_FormPost_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigationDownload(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('form-post-to-octetstream').click()");
|
| +}
|
| +
|
| +// Tests that navigating the main frame from a subframe results in a download
|
| +// if the URL has a binary mimetype.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + OctetStream_NavigationFromFrame_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("a.com", "/simple_page.html"));
|
| + AddIFrame(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
|
| +
|
| + TestDownloadFromFrame(
|
| + "document.getElementById('navigate-top-frame-to-octetstream').click()");
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// data URLs with unknown mimetype
|
| +//
|
| +// Test that window.open to a data URL results in a download if the URL has an
|
| +// unknown mime type.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + UnknownMimeType_WindowOpen_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckWindowOpenDownload(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('window-open-unknown-mimetype').click()");
|
| +}
|
| +
|
| +// Test that a navigation to a data URL results in a download if the URL has an
|
| +// unknown mime type.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + UnknownMimeType_Navigation_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigationDownload(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('navigate-top-"
|
| + "frame-to-unknown-mimetype').click()");
|
| +}
|
| +
|
| +// Test that a form post to a data URL results in a download if the URL has an
|
| +// unknown mime type.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + UnknownMimeType_FormPost_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckNavigationDownload(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('form-post-to-unknown-mimetype').click()");
|
| +}
|
| +
|
| +// Tests that navigating the main frame from a subframe results in a download
|
| +// if the URL has an unknown mimetype.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + UnknownMimeType_NavigationFromFrame_Download) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("a.com", "/simple_page.html"));
|
| + AddIFrame(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
|
| +
|
| + TestDownloadFromFrame(
|
| + "document.getElementById('navigate-top-frame-to-unknown-mimetype').click("
|
| + ")");
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// data URLs with PDF mimetype
|
| +//
|
| +// Tests that a browser initiated navigation to a data URL with PDF mime type is
|
| +// allowed.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + PDF_BrowserInitiatedNavigation_Allow) {
|
| + TestNavigationObserver observer(shell()->web_contents());
|
| + NavigateToURL(shell(), GURL(kPdfUrl));
|
| + EXPECT_EQ(GURL(kPdfUrl), observer.last_navigation_url());
|
| + EXPECT_TRUE(observer.last_navigation_succeeded());
|
| + EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
|
| + url::kDataScheme));
|
| +}
|
| +
|
| +// Tests that a window.open to a data URL is blocked if the data URL has a
|
| +// mime type that will be handled by a plugin (PDF in this case).
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_WindowOpen_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckWindowOpen(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('window-open-pdf').click()", NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Test that a navigation to a data URL is blocked if the data URL has a mime
|
| +// type that will be handled by a plugin (PDF in this case).
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_Navigation_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckPDFNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('navigate-top-frame-to-pdf').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Test that a form post to a data URL is blocked if the data URL has a mime
|
| +// type that will be handled by a plugin (PDF in this case).
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_FormPost_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("/data_url_navigations.html"));
|
| + ExecuteScriptAndCheckPDFNavigation(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + "document.getElementById('form-post-to-pdf').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that navigating the main frame to a data URL with PDF mimetype from a
|
| +// subframe is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + PDF_NavigationFromFrame_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("a.com", "/simple_page.html"));
|
| + AddIFrame(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
|
| +
|
| + TestPDFNavigationFromFrame(
|
| + "document.getElementById('navigate-top-frame-to-pdf').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that opening a window with a data URL with PDF mimetype from a
|
| +// subframe is blocked.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + PDF_WindowOpenFromFrame_Block) {
|
| + NavigateToURL(shell(),
|
| + embedded_test_server()->GetURL("a.com", "/simple_page.html"));
|
| + AddIFrame(
|
| + shell()->web_contents()->GetMainFrame(),
|
| + embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
|
| +
|
| + TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that navigating the top frame to a data URL with PDF mimetype from a
|
| +// subframe is blocked even if the top frame is already a data URL.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + PDF_NavigationFromFrame_TopFrameIsDataURL_Block) {
|
| + const GURL top_url(
|
| + base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
|
| + embedded_test_server()
|
| + ->GetURL("/data_url_navigations.html")
|
| + .spec()
|
| + .c_str()));
|
| + NavigateToURL(shell(), top_url);
|
| +
|
| + TestPDFNavigationFromFrame(
|
| + "document.getElementById('navigate-top-frame-to-pdf').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +// Tests that opening a window with a data URL with PDF mimetype from a
|
| +// subframe is blocked even if the top frame is already a data URL.
|
| +IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
|
| + PDF_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
|
| + const GURL top_url(
|
| + base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
|
| + embedded_test_server()
|
| + ->GetURL("/data_url_navigations.html")
|
| + .spec()
|
| + .c_str()));
|
| + NavigateToURL(shell(), top_url);
|
| +
|
| + TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
|
| + NAVIGATION_BLOCKED);
|
| +}
|
| +
|
| +} // content
|
|
|