| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "chrome/browser/extensions/extension_apitest.h" | 14 #include "chrome/browser/extensions/extension_apitest.h" |
| 15 #include "chrome/browser/extensions/test_extension_dir.h" | 15 #include "chrome/browser/extensions/test_extension_dir.h" |
| 16 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 17 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
| 18 #include "chrome/test/base/ui_test_utils.h" | 19 #include "chrome/test/base/ui_test_utils.h" |
| 19 #include "components/crx_file/id_util.h" | 20 #include "components/crx_file/id_util.h" |
| 20 #include "content/public/test/browser_test_utils.h" | 21 #include "content/public/test/browser_test_utils.h" |
| 21 #include "extensions/common/extension_builder.h" | 22 #include "extensions/common/extension_builder.h" |
| 22 #include "extensions/common/manifest_handlers/content_capabilities_handler.h" | 23 #include "extensions/common/manifest_handlers/content_capabilities_handler.h" |
| 23 #include "extensions/common/switches.h" | 24 #include "extensions/common/switches.h" |
| 24 #include "extensions/common/url_pattern.h" | 25 #include "extensions/common/url_pattern.h" |
| 25 #include "net/dns/mock_host_resolver.h" | 26 #include "net/dns/mock_host_resolver.h" |
| 26 #include "net/test/embedded_test_server/embedded_test_server.h" | 27 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 28 #include "storage/browser/quota/special_storage_policy.h" |
| 27 | 29 |
| 28 using extensions::DictionaryBuilder; | 30 using extensions::DictionaryBuilder; |
| 29 using extensions::Extension; | 31 using extensions::Extension; |
| 30 using extensions::ExtensionBuilder; | 32 using extensions::ExtensionBuilder; |
| 31 using extensions::ListBuilder; | 33 using extensions::ListBuilder; |
| 32 | 34 |
| 33 class ContentCapabilitiesTest : public ExtensionApiTest { | 35 class ContentCapabilitiesTest : public ExtensionApiTest { |
| 34 protected: | 36 protected: |
| 35 void SetUpCommandLine(base::CommandLine* command_line) override { | 37 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 36 ExtensionApiTest::SetUpCommandLine(command_line); | 38 ExtensionApiTest::SetUpCommandLine(command_line); |
| 37 command_line->AppendSwitchASCII( | 39 command_line->AppendSwitchASCII( |
| 38 extensions::switches::kWhitelistedExtensionID, | 40 extensions::switches::kWhitelistedExtensionID, |
| 39 crx_file::id_util::GenerateIdForPath( | 41 crx_file::id_util::GenerateIdForPath( |
| 40 base::MakeAbsoluteFilePath(test_extension_dir_.unpacked_path()))); | 42 base::MakeAbsoluteFilePath(test_extension_dir_.unpacked_path()))); |
| 41 } | 43 } |
| 42 | 44 |
| 43 // Builds an extension manifest with the given content_capabilities matches | 45 // Builds an extension manifest with the given content_capabilities matches |
| 44 // and permissions. The extension always has the same (whitelisted) ID. | 46 // and permissions. The extension always has the same (whitelisted) ID. |
| 45 scoped_refptr<const Extension> LoadExtensionWithCapabilities( | 47 scoped_refptr<const Extension> LoadExtensionWithCapabilities( |
| 46 const std::string& matches, | 48 const std::string& matches, |
| 47 const std::string& permissions) { | 49 const std::string& permissions, |
| 50 const std::string& extension_permissions = "[]") { |
| 48 std::string manifest = base::StringPrintf( | 51 std::string manifest = base::StringPrintf( |
| 49 "{\n" | 52 "{\n" |
| 50 " \"name\": \"content_capabilities test extensions\",\n" | 53 " \"name\": \"content_capabilities test extensions\",\n" |
| 51 " \"version\": \"1\",\n" | 54 " \"version\": \"1\",\n" |
| 52 " \"manifest_version\": 2,\n" | 55 " \"manifest_version\": 2,\n" |
| 53 " \"content_capabilities\": {\n" | 56 " \"content_capabilities\": {\n" |
| 54 " \"matches\": %s,\n" | 57 " \"matches\": %s,\n" |
| 55 " \"permissions\": %s\n" | 58 " \"permissions\": %s\n" |
| 56 " }\n" | 59 " },\n" |
| 60 " \"permissions\": %s\n" |
| 57 "}\n", | 61 "}\n", |
| 58 matches.c_str(), permissions.c_str()); | 62 matches.c_str(), permissions.c_str(), extension_permissions.c_str()); |
| 59 test_extension_dir_.WriteManifest(manifest); | 63 test_extension_dir_.WriteManifest(manifest); |
| 60 return LoadExtension(test_extension_dir_.unpacked_path()); | 64 return LoadExtension(test_extension_dir_.unpacked_path()); |
| 61 } | 65 } |
| 62 | 66 |
| 63 std::string MakeJSONList(const std::string& s0 = "", | 67 std::string MakeJSONList(const std::string& s0 = "", |
| 64 const std::string& s1 = "", | 68 const std::string& s1 = "", |
| 65 const std::string& s2 = "") { | 69 const std::string& s2 = "") { |
| 66 std::vector<std::string> v; | 70 std::vector<std::string> v; |
| 67 if (!s0.empty()) | 71 if (!s0.empty()) |
| 68 v.push_back(s0); | 72 v.push_back(s0); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 96 embedded_test_server()->ServeFilesFromDirectory( | 100 embedded_test_server()->ServeFilesFromDirectory( |
| 97 test_data.AppendASCII("extensions/content_capabilities")); | 101 test_data.AppendASCII("extensions/content_capabilities")); |
| 98 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); | 102 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| 99 host_resolver()->AddRule("*", embedded_test_server()->base_url().host()); | 103 host_resolver()->AddRule("*", embedded_test_server()->base_url().host()); |
| 100 } | 104 } |
| 101 | 105 |
| 102 // Run some script in the context of the given origin and in the presence of | 106 // Run some script in the context of the given origin and in the presence of |
| 103 // the given extension. This is used to wrap calls into the JS test functions | 107 // the given extension. This is used to wrap calls into the JS test functions |
| 104 // defined by | 108 // defined by |
| 105 // $(DIR_TEST_DATA)/extensions/content_capabilities/capability_tests.js. | 109 // $(DIR_TEST_DATA)/extensions/content_capabilities/capability_tests.js. |
| 106 bool TestContentCapability(const Extension* extension, | 110 testing::AssertionResult TestScriptResult(const Extension* extension, |
| 107 const char* origin, | 111 const GURL& url, |
| 108 const char* code) { | 112 const char* code) { |
| 109 ui_test_utils::NavigateToURL(browser(), GetTestURLFor(origin)); | 113 ui_test_utils::NavigateToURL(browser(), url); |
| 110 bool result = false; | 114 bool result = false; |
| 111 CHECK(content::ExecuteScriptAndExtractBool(web_contents(), code, &result)); | 115 if (!content::ExecuteScriptAndExtractBool(web_contents(), code, &result)) |
| 112 return result; | 116 return testing::AssertionFailure() << "Could not execute test script."; |
| 117 if (!result) |
| 118 return testing::AssertionFailure(); |
| 119 return testing::AssertionSuccess(); |
| 113 } | 120 } |
| 114 | 121 |
| 115 bool CanReadClipboard(const Extension* extension, const char* origin) { | 122 testing::AssertionResult CanReadClipboard(const Extension* extension, |
| 116 return TestContentCapability(extension, origin, "tests.canReadClipboard()"); | 123 const GURL& url) { |
| 124 return TestScriptResult(extension, url, "tests.canReadClipboard()"); |
| 117 } | 125 } |
| 118 | 126 |
| 119 bool CanWriteClipboard(const Extension* extension, const char* origin) { | 127 testing::AssertionResult CanWriteClipboard(const Extension* extension, |
| 120 return TestContentCapability(extension, origin, | 128 const GURL& url) { |
| 121 "tests.canWriteClipboard()"); | 129 return TestScriptResult(extension, url, "tests.canWriteClipboard()"); |
| 130 } |
| 131 |
| 132 testing::AssertionResult HasUnlimitedStorage(const Extension* extension, |
| 133 const GURL& url) { |
| 134 if (profile()->GetSpecialStoragePolicy()->IsStorageUnlimited(url)) |
| 135 return testing::AssertionSuccess(); |
| 136 return testing::AssertionFailure(); |
| 122 } | 137 } |
| 123 | 138 |
| 124 private: | 139 private: |
| 125 extensions::TestExtensionDir test_extension_dir_; | 140 extensions::TestExtensionDir test_extension_dir_; |
| 126 }; | 141 }; |
| 127 | 142 |
| 128 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, NoCapabilities) { | 143 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, NoCapabilities) { |
| 129 InitializeTestServer(); | 144 InitializeTestServer(); |
| 130 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( | 145 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( |
| 131 MakeJSONList("http://foo.example.com/*"), MakeJSONList()); | 146 MakeJSONList("http://foo.example.com/*"), MakeJSONList()); |
| 132 EXPECT_FALSE(CanReadClipboard(extension.get(), "foo.example.com")); | 147 EXPECT_FALSE( |
| 133 EXPECT_FALSE(CanWriteClipboard(extension.get(), "foo.example.com")); | 148 CanReadClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 149 EXPECT_FALSE( |
| 150 CanWriteClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 151 EXPECT_FALSE( |
| 152 HasUnlimitedStorage(extension.get(), GetTestURLFor("foo.example.com"))); |
| 134 } | 153 } |
| 135 | 154 |
| 136 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, ClipboardRead) { | 155 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, ClipboardRead) { |
| 137 InitializeTestServer(); | 156 InitializeTestServer(); |
| 138 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( | 157 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( |
| 139 MakeJSONList("http://foo.example.com/*"), MakeJSONList("clipboardRead")); | 158 MakeJSONList("http://foo.example.com/*"), MakeJSONList("clipboardRead")); |
| 140 EXPECT_TRUE(CanReadClipboard(extension.get(), "foo.example.com")); | 159 EXPECT_TRUE( |
| 141 EXPECT_FALSE(CanReadClipboard(extension.get(), "bar.example.com")); | 160 CanReadClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 142 EXPECT_FALSE(CanWriteClipboard(extension.get(), "foo.example.com")); | 161 EXPECT_FALSE( |
| 162 CanReadClipboard(extension.get(), GetTestURLFor("bar.example.com"))); |
| 163 EXPECT_FALSE( |
| 164 CanWriteClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 143 } | 165 } |
| 144 | 166 |
| 145 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, ClipboardWrite) { | 167 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, ClipboardWrite) { |
| 146 InitializeTestServer(); | 168 InitializeTestServer(); |
| 147 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( | 169 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( |
| 148 MakeJSONList("http://foo.example.com/*"), MakeJSONList("clipboardWrite")); | 170 MakeJSONList("http://foo.example.com/*"), MakeJSONList("clipboardWrite")); |
| 149 EXPECT_TRUE(CanWriteClipboard(extension.get(), "foo.example.com")); | 171 EXPECT_TRUE( |
| 150 EXPECT_FALSE(CanWriteClipboard(extension.get(), "bar.example.com")); | 172 CanWriteClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 151 EXPECT_FALSE(CanReadClipboard(extension.get(), "foo.example.com")); | 173 EXPECT_FALSE( |
| 174 CanWriteClipboard(extension.get(), GetTestURLFor("bar.example.com"))); |
| 175 EXPECT_FALSE( |
| 176 CanReadClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 152 } | 177 } |
| 153 | 178 |
| 154 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, ClipboardReadWrite) { | 179 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, ClipboardReadWrite) { |
| 155 InitializeTestServer(); | 180 InitializeTestServer(); |
| 156 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( | 181 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( |
| 157 MakeJSONList("http://foo.example.com/*"), | 182 MakeJSONList("http://foo.example.com/*"), |
| 158 MakeJSONList("clipboardRead", "clipboardWrite")); | 183 MakeJSONList("clipboardRead", "clipboardWrite")); |
| 159 EXPECT_TRUE(CanReadClipboard(extension.get(), "foo.example.com")); | 184 EXPECT_TRUE( |
| 160 EXPECT_TRUE(CanWriteClipboard(extension.get(), "foo.example.com")); | 185 CanReadClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 161 EXPECT_FALSE(CanReadClipboard(extension.get(), "bar.example.com")); | 186 EXPECT_TRUE( |
| 162 EXPECT_FALSE(CanWriteClipboard(extension.get(), "bar.example.com")); | 187 CanWriteClipboard(extension.get(), GetTestURLFor("foo.example.com"))); |
| 188 EXPECT_FALSE( |
| 189 CanReadClipboard(extension.get(), GetTestURLFor("bar.example.com"))); |
| 190 EXPECT_FALSE( |
| 191 CanWriteClipboard(extension.get(), GetTestURLFor("bar.example.com"))); |
| 163 } | 192 } |
| 193 |
| 194 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, UnlimitedStorage) { |
| 195 InitializeTestServer(); |
| 196 scoped_refptr<const Extension> extension = |
| 197 LoadExtensionWithCapabilities(MakeJSONList("http://foo.example.com/*"), |
| 198 MakeJSONList("unlimitedStorage")); |
| 199 EXPECT_TRUE( |
| 200 HasUnlimitedStorage(extension.get(), GetTestURLFor("foo.example.com"))); |
| 201 EXPECT_FALSE( |
| 202 HasUnlimitedStorage(extension.get(), GetTestURLFor("bar.example.com"))); |
| 203 } |
| 204 |
| 205 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, WebUnlimitedStorageIsIsolated) { |
| 206 InitializeTestServer(); |
| 207 // This extension grants unlimited storage to bar.example.com but does not |
| 208 // have unlimitedStorage itself. |
| 209 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( |
| 210 MakeJSONList("http://bar.example.com/*"), |
| 211 MakeJSONList("unlimitedStorage"), MakeJSONList("storage")); |
| 212 EXPECT_FALSE( |
| 213 HasUnlimitedStorage(extension.get(), extension->GetResourceURL(""))); |
| 214 EXPECT_TRUE( |
| 215 HasUnlimitedStorage(extension.get(), GetTestURLFor("bar.example.com"))); |
| 216 } |
| 217 |
| 218 IN_PROC_BROWSER_TEST_F(ContentCapabilitiesTest, |
| 219 ExtensionUnlimitedStorageIsIsolated) { |
| 220 InitializeTestServer(); |
| 221 // This extension has unlimitedStorage but doesn't grant it to foo.example.com |
| 222 scoped_refptr<const Extension> extension = LoadExtensionWithCapabilities( |
| 223 MakeJSONList("http://foo.example.com/*"), MakeJSONList("clipboardRead"), |
| 224 MakeJSONList("unlimitedStorage")); |
| 225 |
| 226 EXPECT_TRUE( |
| 227 HasUnlimitedStorage(extension.get(), extension->GetResourceURL(""))); |
| 228 EXPECT_FALSE( |
| 229 HasUnlimitedStorage(extension.get(), GetTestURLFor("foo.example.com"))); |
| 230 } |
| OLD | NEW |