blob: 8997d24f0f40d91ed3d9b0a7da9ff0871b2e1273 [file] [log] [blame]
Rob Wu956801d12018-01-10 17:06:311// Copyright (c) 2018 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/strings/stringprintf.h"
6#include "chrome/browser/extensions/extension_browsertest.h"
Rob Wu956801d12018-01-10 17:06:317#include "chrome/browser/ui/tabs/tab_strip_model.h"
8#include "chrome/common/url_constants.h"
9#include "chrome/test/base/ui_test_utils.h"
10#include "content/public/browser/render_frame_host.h"
11#include "content/public/browser/web_contents.h"
12#include "content/public/test/browser_test_utils.h"
13#include "extensions/common/value_builder.h"
Devlin Cronin4f455a22018-01-25 01:36:4514#include "extensions/test/test_extension_dir.h"
Rob Wu956801d12018-01-10 17:06:3115
16namespace extensions {
17
18namespace {
19
20class ExtensionCSPBypassTest : public ExtensionBrowserTest {
21 public:
22 ExtensionCSPBypassTest() {}
23
24 void SetUpOnMainThread() override {
25 ExtensionBrowserTest::SetUpOnMainThread();
26 ASSERT_TRUE(embedded_test_server()->Start());
27 }
28
29 protected:
30 const Extension* AddExtension(bool is_component, bool all_urls_permission) {
31 auto dir = std::make_unique<TestExtensionDir>();
32
33 std::string unique_name = base::StringPrintf(
34 "component=%d, all_urls=%d", is_component, all_urls_permission);
35 DictionaryBuilder manifest;
36 manifest.Set("name", unique_name)
37 .Set("version", "1")
38 .Set("manifest_version", 2)
39 .Set("web_accessible_resources", ListBuilder().Append("*").Build());
40
41 if (all_urls_permission) {
42 manifest.Set("permissions", ListBuilder().Append("<all_urls>").Build());
43 }
44 if (is_component) {
45 // LoadExtensionAsComponent requires the manifest to contain a key.
46 std::string key;
47 EXPECT_TRUE(Extension::ProducePEM(unique_name, &key));
48 manifest.Set("key", key);
49 }
50
51 dir->WriteFile(FILE_PATH_LITERAL("script.js"), "");
52 dir->WriteManifest(manifest.ToJSON());
53
54 const Extension* extension = nullptr;
55 if (is_component) {
56 extension = LoadExtensionAsComponent(dir->UnpackedPath());
57 } else {
58 extension = LoadExtension(dir->UnpackedPath());
59 }
60 CHECK(extension);
61 temp_dirs_.push_back(std::move(dir));
62 return extension;
63 }
64
65 bool CanLoadScript(const Extension* extension) {
66 content::RenderFrameHost* rfh =
67 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
68 std::string code = base::StringPrintf(
69 R"(
70 var s = document.createElement('script');
71 s.src = '%s';
72 s.onload = function() {
73 // Not blocked by CSP.
74 window.domAutomationController.send(true);
75 };
76 s.onerror = function() {
77 // Blocked by CSP.
78 window.domAutomationController.send(false);
79 };
80 document.body.appendChild(s);)",
81 extension->GetResourceURL("script.js").spec().c_str());
82 bool script_loaded = false;
83 EXPECT_TRUE(ExecuteScriptAndExtractBool(rfh, code, &script_loaded));
84 return script_loaded;
85 }
86
87 private:
88 std::vector<std::unique_ptr<TestExtensionDir>> temp_dirs_;
89
90 DISALLOW_COPY_AND_ASSIGN(ExtensionCSPBypassTest);
91};
92
93} // namespace
94
95IN_PROC_BROWSER_TEST_F(ExtensionCSPBypassTest, LoadWebAccessibleScript) {
96 const Extension* component_ext_with_permission = AddExtension(true, true);
97 const Extension* component_ext_without_permission = AddExtension(true, false);
98 const Extension* ext_with_permission = AddExtension(false, true);
99 const Extension* ext_without_permission = AddExtension(false, false);
100
101 // chrome-extension:-URLs can always bypass CSP in normal pages.
102 GURL non_webui_url(embedded_test_server()->GetURL("/empty.html"));
103 ui_test_utils::NavigateToURL(browser(), non_webui_url);
104
105 EXPECT_TRUE(CanLoadScript(component_ext_with_permission));
106 EXPECT_TRUE(CanLoadScript(component_ext_without_permission));
107 EXPECT_TRUE(CanLoadScript(ext_with_permission));
108 EXPECT_TRUE(CanLoadScript(ext_without_permission));
109
110 // chrome-extension:-URLs can never bypass CSP in WebUI.
111 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
112
113 EXPECT_FALSE(CanLoadScript(component_ext_with_permission));
114 EXPECT_FALSE(CanLoadScript(component_ext_without_permission));
115 EXPECT_FALSE(CanLoadScript(ext_with_permission));
116 EXPECT_FALSE(CanLoadScript(ext_without_permission));
117}
118
119} // namespace extensions