blob: 1e0a8b5881cb302c0dface648b37ce3ca1cfcf81 [file] [log] [blame]
[email protected]1791e6c92014-04-11 08:29:011// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]5e212ed2012-03-21 23:29:152// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stddef.h>
6
dchengc963c7142016-04-08 03:55:227#include <memory>
[email protected]5e212ed2012-03-21 23:29:158#include <string>
vabr9984ea62017-04-10 11:33:499#include <utility>
[email protected]5e212ed2012-03-21 23:29:1510
lazyboyd6dbb262017-03-30 00:57:3011#include "base/command_line.h"
thestigc9e38a22014-09-13 01:02:1112#include "base/files/file_util.h"
Clark DuVallc7e3b4692019-06-13 22:07:1113#include "base/path_service.h"
fdoraycb32419d2016-06-23 15:52:5514#include "base/run_loop.h"
Avi Drissman5f0fb8c2018-12-25 23:20:4915#include "base/stl_util.h"
[email protected]774cebd2013-09-26 04:55:0116#include "base/strings/string_number_conversions.h"
[email protected]00e7bef2013-06-10 20:35:1717#include "base/strings/string_util.h"
Karandeep Bhatiaab489a4d2018-11-28 21:56:0618#include "base/test/power_monitor_test_base.h"
lazyboyd6dbb262017-03-30 00:57:3019#include "base/test/test_file_util.h"
Devlin Croninc3f88072018-01-30 02:10:1120#include "base/test/values_test_util.h"
[email protected]06492ed2013-03-24 22:13:1421#include "base/values.h"
Kevin Marshall4cab5af2019-01-14 20:27:1422#include "build/build_config.h"
lazyboyd6dbb262017-03-30 00:57:3023#include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
[email protected]93ac047a2012-12-13 02:53:4924#include "chrome/common/chrome_paths.h"
lazyboyd6dbb262017-03-30 00:57:3025#include "chrome/common/chrome_switches.h"
26#include "chrome/test/base/testing_profile.h"
27#include "components/crx_file/id_util.h"
Matt Falkenhagenae65b292018-04-25 16:03:2728#include "content/public/browser/render_process_host.h"
megjabloncaf312f2017-01-12 18:47:4929#include "content/public/common/previews_state.h"
Gabriel Charettec7108742019-08-23 03:31:4030#include "content/public/test/browser_task_environment.h"
Chris Mumford8f812662018-02-22 00:27:5731#include "content/public/test/test_renderer_host.h"
lazyboyd6dbb262017-03-30 00:57:3032#include "content/public/test/test_utils.h"
Chris Mumford8f812662018-02-22 00:27:5733#include "content/public/test/web_contents_tester.h"
lazyboyd6dbb262017-03-30 00:57:3034#include "extensions/browser/content_verifier.h"
Istiaque Ahmed72816eaa2018-01-30 22:37:0635#include "extensions/browser/content_verifier/test_utils.h"
Chris Mumford8f812662018-02-22 00:27:5736#include "extensions/browser/extension_prefs.h"
[email protected]1791e6c92014-04-11 08:29:0137#include "extensions/browser/extension_protocols.h"
Chris Mumford8f812662018-02-22 00:27:5738#include "extensions/browser/extension_registry.h"
John Abd-El-Malekea006302018-05-10 05:50:4639#include "extensions/browser/extension_system.h"
[email protected]38427a12013-11-09 17:34:2040#include "extensions/browser/info_map.h"
Devlin Croninc9c4efe2020-01-07 21:04:0541#include "extensions/browser/unloaded_extension_reason.h"
[email protected]885c0e92012-11-13 20:27:4242#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4143#include "extensions/common/extension.h"
lazyboyd6dbb262017-03-30 00:57:3044#include "extensions/common/extension_builder.h"
Istiaque Ahmed72816eaa2018-01-30 22:37:0645#include "extensions/common/extension_paths.h"
asargenta093ec32016-02-13 01:36:4346#include "extensions/common/file_util.h"
Devlin Cronin1fa235b62018-04-12 14:04:0747#include "extensions/common/value_builder.h"
Devlin Croninc3f88072018-01-30 02:10:1148#include "extensions/test/test_extension_dir.h"
Julie Jeongeun Kim917c197902019-11-26 03:36:1449#include "mojo/public/cpp/bindings/pending_remote.h"
rhalavati04b93382017-04-07 19:00:5450#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Chris Mumford8f812662018-02-22 00:27:5751#include "services/network/test/test_url_loader_client.h"
[email protected]5e212ed2012-03-21 23:29:1552#include "testing/gtest/include/gtest/gtest.h"
Minggang Wangee5af392020-02-05 02:55:2853#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
[email protected]5e212ed2012-03-21 23:29:1554
Minggang Wangee5af392020-02-05 02:55:2855using blink::mojom::ResourceType;
Chris Mumford8f812662018-02-22 00:27:5756using extensions::ExtensionRegistry;
57using network::mojom::URLLoader;
[email protected]7491ad02014-07-05 19:10:0758
[email protected]702d8b42013-02-27 20:55:5059namespace extensions {
jamescook8816ae52014-09-05 17:02:3760namespace {
[email protected]5e212ed2012-03-21 23:29:1561
asargenta093ec32016-02-13 01:36:4362base::FilePath GetTestPath(const std::string& name) {
63 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:5264 EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &path));
asargenta093ec32016-02-13 01:36:4365 return path.AppendASCII("extensions").AppendASCII(name);
66}
67
Istiaque Ahmed72816eaa2018-01-30 22:37:0668base::FilePath GetContentVerifierTestPath() {
69 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:5270 EXPECT_TRUE(base::PathService::Get(extensions::DIR_TEST_DATA, &path));
Istiaque Ahmed72816eaa2018-01-30 22:37:0671 return path.AppendASCII("content_hash_fetcher")
72 .AppendASCII("different_sized_files");
lazyboyd6dbb262017-03-30 00:57:3073}
74
[email protected]5e212ed2012-03-21 23:29:1575scoped_refptr<Extension> CreateTestExtension(const std::string& name,
76 bool incognito_split_mode) {
[email protected]023b3d12013-12-23 18:46:4977 base::DictionaryValue manifest;
[email protected]5e212ed2012-03-21 23:29:1578 manifest.SetString("name", name);
79 manifest.SetString("version", "1");
[email protected]b109bdd2013-11-04 18:08:4380 manifest.SetInteger("manifest_version", 2);
[email protected]5e212ed2012-03-21 23:29:1581 manifest.SetString("incognito", incognito_split_mode ? "split" : "spanning");
82
asargenta093ec32016-02-13 01:36:4383 base::FilePath path = GetTestPath("response_headers");
[email protected]5e212ed2012-03-21 23:29:1584
85 std::string error;
86 scoped_refptr<Extension> extension(
[email protected]1d5e58b2013-01-31 08:41:4087 Extension::Create(path, Manifest::INTERNAL, manifest,
[email protected]ed3b9b12012-05-31 18:37:5188 Extension::NO_FLAGS, &error));
[email protected]5e212ed2012-03-21 23:29:1589 EXPECT_TRUE(extension.get()) << error;
90 return extension;
91}
92
[email protected]93ac047a2012-12-13 02:53:4993scoped_refptr<Extension> CreateWebStoreExtension() {
Devlin Croninf43c3312018-03-27 19:54:1794 std::unique_ptr<base::DictionaryValue> manifest =
95 DictionaryBuilder()
96 .Set("name", "WebStore")
97 .Set("version", "1")
98 .Set("manifest_version", 2)
99 .Set("icons",
100 DictionaryBuilder().Set("16", "webstore_icon_16.png").Build())
101 .Set("web_accessible_resources",
102 ListBuilder().Append("webstore_icon_16.png").Build())
103 .Build();
[email protected]93ac047a2012-12-13 02:53:49104
[email protected]650b2d52013-02-10 03:41:45105 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:52106 EXPECT_TRUE(base::PathService::Get(chrome::DIR_RESOURCES, &path));
[email protected]93ac047a2012-12-13 02:53:49107 path = path.AppendASCII("web_store");
108
109 std::string error;
Devlin Croninf43c3312018-03-27 19:54:17110 scoped_refptr<Extension> extension(Extension::Create(
111 path, Manifest::COMPONENT, *manifest, Extension::NO_FLAGS, &error));
[email protected]93ac047a2012-12-13 02:53:49112 EXPECT_TRUE(extension.get()) << error;
113 return extension;
114}
115
Devlin Cronin8e5892f2018-10-04 00:13:43116scoped_refptr<const Extension> CreateTestResponseHeaderExtension() {
Devlin Cronin1fa235b62018-04-12 14:04:07117 return ExtensionBuilder("An extension with web-accessible resources")
Devlin Cronin98cd6582018-05-08 19:18:12118 .SetManifestKey("web_accessible_resources",
119 ListBuilder().Append("test.dat").Build())
Devlin Cronin1fa235b62018-04-12 14:04:07120 .SetPath(GetTestPath("response_headers"))
121 .Build();
[email protected]6f7d7062013-06-04 03:49:33122}
123
Chris Mumford8f812662018-02-22 00:27:57124// Helper function to create a |ResourceRequest| for testing purposes.
125network::ResourceRequest CreateResourceRequest(const std::string& method,
126 ResourceType resource_type,
127 const GURL& url) {
128 network::ResourceRequest request;
129 request.method = method;
130 request.url = url;
Maks Orlovich5d02d9e02019-12-15 22:14:10131 request.site_for_cookies =
132 net::SiteForCookies::FromUrl(url); // bypass third-party cookie blocking.
Chris Mumford8f812662018-02-22 00:27:57133 request.request_initiator =
134 url::Origin::Create(url); // ensure initiator set.
135 request.referrer_policy = content::Referrer::GetDefaultReferrerPolicy();
Daniel Cheng57541be2019-05-07 07:51:07136 request.resource_type = static_cast<int>(resource_type);
Minggang Wangee5af392020-02-05 02:55:28137 request.is_main_frame =
138 resource_type == blink::mojom::ResourceType::kMainFrame;
Chris Mumford8f812662018-02-22 00:27:57139 return request;
140}
141
142// The result of either a URLRequest of a URLLoader response (but not both)
143// depending on the on test type.
144class GetResult {
145 public:
Lucas Furukawa Gadani06902602019-09-27 20:44:27146 GetResult(network::mojom::URLResponseHeadPtr response, int result)
147 : response_(std::move(response)), result_(result) {}
Clark DuVallc7e3b4692019-06-13 22:07:11148 GetResult(GetResult&& other) : result_(other.result_) {}
Chris Mumford8f812662018-02-22 00:27:57149 ~GetResult() = default;
150
151 std::string GetResponseHeaderByName(const std::string& name) const {
152 std::string value;
Lucas Furukawa Gadani06902602019-09-27 20:44:27153 if (response_ && response_->headers)
154 response_->headers->GetNormalizedHeader(name, &value);
Chris Mumford8f812662018-02-22 00:27:57155 return value;
156 }
157
158 int result() const { return result_; }
159
160 private:
Lucas Furukawa Gadani06902602019-09-27 20:44:27161 network::mojom::URLResponseHeadPtr response_;
Chris Mumford8f812662018-02-22 00:27:57162 int result_;
163
164 DISALLOW_COPY_AND_ASSIGN(GetResult);
165};
166
jamescook8816ae52014-09-05 17:02:37167} // namespace
168
169// This test lives in src/chrome instead of src/extensions because it tests
170// functionality delegated back to Chrome via ChromeExtensionsBrowserClient.
lfg048201a2014-09-16 19:09:36171// See chrome/browser/extensions/chrome_url_request_util.cc.
Clark DuVallc7e3b4692019-06-13 22:07:11172class ExtensionProtocolsTestBase : public testing::Test {
[email protected]5e212ed2012-03-21 23:29:15173 public:
Alexey Baskakovf0f9d8f2019-01-19 02:31:54174 explicit ExtensionProtocolsTestBase(bool force_incognito)
Gabriel Charette798fde72019-08-20 22:24:04175 : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
Chris Mumford8f812662018-02-22 00:27:57176 rvh_test_enabler_(new content::RenderViewHostTestEnabler()),
Alexey Baskakovf0f9d8f2019-01-19 02:31:54177 force_incognito_(force_incognito) {}
[email protected]5e212ed2012-03-21 23:29:15178
dcheng72191812014-10-28 20:49:56179 void SetUp() override {
[email protected]06492ed2013-03-24 22:13:14180 testing::Test::SetUp();
lazyboyd6dbb262017-03-30 00:57:30181 testing_profile_ = TestingProfile::Builder().Build();
Erik Chen5bab4992018-05-05 15:19:53182 contents_ = CreateTestWebContents();
lazyboyd6dbb262017-03-30 00:57:30183
184 // Set up content verification.
185 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
186 command_line->AppendSwitchASCII(
187 switches::kExtensionContentVerification,
188 switches::kExtensionContentVerificationEnforce);
189 content_verifier_ = new ContentVerifier(
Chris Mumford8f812662018-02-22 00:27:57190 browser_context(),
191 std::make_unique<ChromeContentVerifierDelegate>(browser_context()));
John Abd-El-Malekea006302018-05-10 05:50:46192 info_map()->SetContentVerifier(content_verifier_.get());
[email protected]5e212ed2012-03-21 23:29:15193 }
194
dcheng72191812014-10-28 20:49:56195 void TearDown() override {
Chris Mumford8f812662018-02-22 00:27:57196 loader_factory_.reset();
lazyboyd6dbb262017-03-30 00:57:30197 content_verifier_->Shutdown();
Matt Menkedb9fc40b2019-06-19 17:57:35198 // Shut down the PowerMonitor if initialized.
199 base::PowerMonitor::ShutdownForTesting();
[email protected]5e212ed2012-03-21 23:29:15200 }
201
[email protected]1791e6c92014-04-11 08:29:01202 void SetProtocolHandler(bool is_incognito) {
Clark DuVallc7e3b4692019-06-13 22:07:11203 loader_factory_ = extensions::CreateExtensionNavigationURLLoaderFactory(
204 browser_context(), false);
[email protected]93ac047a2012-12-13 02:53:49205 }
206
Chris Mumford8f812662018-02-22 00:27:57207 GetResult RequestOrLoad(const GURL& url, ResourceType resource_type) {
Clark DuVallc7e3b4692019-06-13 22:07:11208 return LoadURL(url, resource_type);
Chris Mumford8f812662018-02-22 00:27:57209 }
210
211 void AddExtension(const scoped_refptr<const Extension>& extension,
212 bool incognito_enabled,
213 bool notifications_disabled) {
John Abd-El-Malekea006302018-05-10 05:50:46214 info_map()->AddExtension(extension.get(), base::Time::Now(),
215 incognito_enabled, notifications_disabled);
Clark DuVallc7e3b4692019-06-13 22:07:11216 EXPECT_TRUE(extension_registry()->AddEnabled(extension));
217 ExtensionPrefs::Get(browser_context())
218 ->SetIsIncognitoEnabled(extension->id(), incognito_enabled);
Chris Mumford8f812662018-02-22 00:27:57219 }
220
221 void RemoveExtension(const scoped_refptr<const Extension>& extension,
222 const UnloadedExtensionReason reason) {
John Abd-El-Malekea006302018-05-10 05:50:46223 info_map()->RemoveExtension(extension->id(), reason);
Clark DuVallc7e3b4692019-06-13 22:07:11224 EXPECT_TRUE(extension_registry()->RemoveEnabled(extension->id()));
225 if (reason == UnloadedExtensionReason::DISABLE)
226 EXPECT_TRUE(extension_registry()->AddDisabled(extension));
Chris Mumford8f812662018-02-22 00:27:57227 }
228
229 // Helper method to create a URL request/loader, call RequestOrLoad on it, and
230 // return the result. If |extension| hasn't already been added to
John Abd-El-Malekea006302018-05-10 05:50:46231 // info_map(), this will add it.
Chris Mumford8f812662018-02-22 00:27:57232 GetResult DoRequestOrLoad(const scoped_refptr<Extension> extension,
233 const std::string& relative_path) {
John Abd-El-Malekea006302018-05-10 05:50:46234 if (!info_map()->extensions().Contains(extension->id())) {
Chris Mumford8f812662018-02-22 00:27:57235 AddExtension(extension.get(),
236 /*incognito_enabled=*/false,
237 /*notifications_disabled=*/false);
238 }
239 return RequestOrLoad(extension->GetResourceURL(relative_path),
Minggang Wangee5af392020-02-05 02:55:28240 blink::mojom::ResourceType::kMainFrame);
Chris Mumford8f812662018-02-22 00:27:57241 }
242
243 ExtensionRegistry* extension_registry() {
244 return ExtensionRegistry::Get(browser_context());
245 }
246
John Abd-El-Malekea006302018-05-10 05:50:46247 InfoMap* info_map() {
248 return ExtensionSystem::Get(browser_context())->info_map();
249 }
250
Alexey Baskakovf0f9d8f2019-01-19 02:31:54251 content::BrowserContext* browser_context() {
252 return force_incognito_ ? testing_profile_->GetOffTheRecordProfile()
253 : testing_profile_.get();
254 }
Chris Mumford8f812662018-02-22 00:27:57255
Karandeep Bhatiaab489a4d2018-11-28 21:56:06256 void SimulateSystemSuspendForRequests() {
257 power_monitor_source_ = new base::PowerMonitorTestSource();
Matt Menkedb9fc40b2019-06-19 17:57:35258 base::PowerMonitor::Initialize(
Karandeep Bhatiaab489a4d2018-11-28 21:56:06259 std::unique_ptr<base::PowerMonitorSource>(power_monitor_source_));
260 }
261
Chris Mumford8f812662018-02-22 00:27:57262 protected:
263 scoped_refptr<ContentVerifier> content_verifier_;
264
265 private:
266 GetResult LoadURL(const GURL& url, ResourceType resource_type) {
267 constexpr int32_t kRoutingId = 81;
268 constexpr int32_t kRequestId = 28;
269
Julie Jeongeun Kim917c197902019-11-26 03:36:14270 mojo::PendingRemote<network::mojom::URLLoader> loader;
Chris Mumford8f812662018-02-22 00:27:57271 network::TestURLLoaderClient client;
272 loader_factory_->CreateLoaderAndStart(
Julie Jeongeun Kim917c197902019-11-26 03:36:14273 loader.InitWithNewPipeAndPassReceiver(), kRoutingId, kRequestId,
Chris Mumford8f812662018-02-22 00:27:57274 network::mojom::kURLLoadOptionNone,
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:30275 CreateResourceRequest("GET", resource_type, url), client.CreateRemote(),
Chris Mumford8f812662018-02-22 00:27:57276 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
277
Karandeep Bhatiaab489a4d2018-11-28 21:56:06278 if (power_monitor_source_) {
279 power_monitor_source_->GenerateSuspendEvent();
280 power_monitor_source_->GenerateResumeEvent();
281 }
282
Chris Mumford8f812662018-02-22 00:27:57283 client.RunUntilComplete();
Lucas Furukawa Gadani06902602019-09-27 20:44:27284 return GetResult(client.response_head().Clone(),
Chris Mumford8f812662018-02-22 00:27:57285 client.completion_status().error_code);
286 }
287
Erik Chen5bab4992018-05-05 15:19:53288 std::unique_ptr<content::WebContents> CreateTestWebContents() {
Chris Mumford8f812662018-02-22 00:27:57289 auto site_instance = content::SiteInstance::Create(browser_context());
290 return content::WebContentsTester::CreateTestWebContents(
291 browser_context(), std::move(site_instance));
asargenta093ec32016-02-13 01:36:43292 }
293
Chris Mumford8f812662018-02-22 00:27:57294 content::WebContents* web_contents() { return contents_.get(); }
295
296 content::RenderFrameHost* main_rfh() {
297 return web_contents()->GetMainFrame();
298 }
299
Gabriel Charette798fde72019-08-20 22:24:04300 content::BrowserTaskEnvironment task_environment_;
Chris Mumford8f812662018-02-22 00:27:57301 std::unique_ptr<content::RenderViewHostTestEnabler> rvh_test_enabler_;
Chris Mumford8f812662018-02-22 00:27:57302 std::unique_ptr<network::mojom::URLLoaderFactory> loader_factory_;
lazyboyd6dbb262017-03-30 00:57:30303 std::unique_ptr<TestingProfile> testing_profile_;
Chris Mumford8f812662018-02-22 00:27:57304 std::unique_ptr<content::WebContents> contents_;
Alexey Baskakovf0f9d8f2019-01-19 02:31:54305 const bool force_incognito_;
Karandeep Bhatiaab489a4d2018-11-28 21:56:06306
Matt Menkedb9fc40b2019-06-19 17:57:35307 // |power_monitor_source_| is owned by the global PowerMonitor.
Karandeep Bhatiaab489a4d2018-11-28 21:56:06308 base::PowerMonitorTestSource* power_monitor_source_ = nullptr;
[email protected]5e212ed2012-03-21 23:29:15309};
310
Alexey Baskakovf0f9d8f2019-01-19 02:31:54311class ExtensionProtocolsTest : public ExtensionProtocolsTestBase {
312 public:
313 ExtensionProtocolsTest()
314 : ExtensionProtocolsTestBase(false /*force_incognito*/) {}
315};
316
317class ExtensionProtocolsIncognitoTest : public ExtensionProtocolsTestBase {
318 public:
319 ExtensionProtocolsIncognitoTest()
320 : ExtensionProtocolsTestBase(true /*force_incognito*/) {}
321};
322
[email protected]5e212ed2012-03-21 23:29:15323// Tests that making a chrome-extension request in an incognito context is
324// only allowed under the right circumstances (if the extension is allowed
325// in incognito, and it's either a non-main-frame request or a split-mode
326// extension).
Clark DuVallc7e3b4692019-06-13 22:07:11327TEST_F(ExtensionProtocolsIncognitoTest, IncognitoRequest) {
[email protected]93ac047a2012-12-13 02:53:49328 // Register an incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01329 SetProtocolHandler(true);
[email protected]93ac047a2012-12-13 02:53:49330
[email protected]5e212ed2012-03-21 23:29:15331 struct TestCase {
332 // Inputs.
333 std::string name;
334 bool incognito_split_mode;
335 bool incognito_enabled;
336
337 // Expected results.
338 bool should_allow_main_frame_load;
339 bool should_allow_sub_frame_load;
340 } cases[] = {
341 {"spanning disabled", false, false, false, false},
342 {"split disabled", true, false, false, false},
nasko5cf9d452016-06-01 05:34:56343 {"spanning enabled", false, true, false, false},
344 {"split enabled", true, true, true, false},
[email protected]5e212ed2012-03-21 23:29:15345 };
346
Avi Drissman5f0fb8c2018-12-25 23:20:49347 for (size_t i = 0; i < base::size(cases); ++i) {
[email protected]5e212ed2012-03-21 23:29:15348 scoped_refptr<Extension> extension =
349 CreateTestExtension(cases[i].name, cases[i].incognito_split_mode);
Chris Mumford8f812662018-02-22 00:27:57350 AddExtension(extension, cases[i].incognito_enabled, false);
[email protected]5e212ed2012-03-21 23:29:15351
352 // First test a main frame request.
353 {
354 // It doesn't matter that the resource doesn't exist. If the resource
naskob9164c42016-06-07 01:21:35355 // is blocked, we should see BLOCKED_BY_CLIENT. Otherwise, the request
[email protected]5e212ed2012-03-21 23:29:15356 // should just fail because the file doesn't exist.
Chris Mumford8f812662018-02-22 00:27:57357 auto get_result = RequestOrLoad(extension->GetResourceURL("404.html"),
Minggang Wangee5af392020-02-05 02:55:28358 blink::mojom::ResourceType::kMainFrame);
[email protected]5e212ed2012-03-21 23:29:15359
360 if (cases[i].should_allow_main_frame_load) {
Chris Mumford8f812662018-02-22 00:27:57361 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, get_result.result())
maksim.sisov1b83bb72016-10-07 06:07:23362 << cases[i].name;
[email protected]5e212ed2012-03-21 23:29:15363 } else {
Chris Mumford8f812662018-02-22 00:27:57364 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, get_result.result())
naskob9164c42016-06-07 01:21:35365 << cases[i].name;
[email protected]5e212ed2012-03-21 23:29:15366 }
367 }
368
John Abd-El-Malek2305cdc2018-02-14 20:26:28369 // Subframe navigation requests are blocked in ExtensionNavigationThrottle
370 // which isn't added in this unit test. This is tested in an integration
371 // test in ExtensionResourceRequestPolicyTest.IframeNavigateToInaccessible.
Chris Mumford8f812662018-02-22 00:27:57372 RemoveExtension(extension, UnloadedExtensionReason::UNINSTALL);
[email protected]5e212ed2012-03-21 23:29:15373 }
374}
375
Chris Mumford8f812662018-02-22 00:27:57376void CheckForContentLengthHeader(const GetResult& get_result) {
377 std::string content_length = get_result.GetResponseHeaderByName(
378 net::HttpRequestHeaders::kContentLength);
379
[email protected]774cebd2013-09-26 04:55:01380 EXPECT_FALSE(content_length.empty());
381 int length_value = 0;
382 EXPECT_TRUE(base::StringToInt(content_length, &length_value));
383 EXPECT_GT(length_value, 0);
384}
385
dstockwell944d18882019-04-09 04:25:58386#if defined(OS_CHROMEOS)
387// Tests getting a resource for a component extension works correctly where
388// there is no mime type. Such a resource currently only exists for Chrome OS
389// build.
Clark DuVallc7e3b4692019-06-13 22:07:11390TEST_F(ExtensionProtocolsTest, ComponentResourceRequestNoMimeType) {
dstockwell944d18882019-04-09 04:25:58391 SetProtocolHandler(false);
392 std::unique_ptr<base::DictionaryValue> manifest =
393 DictionaryBuilder()
394 .Set("name", "pdf")
395 .Set("version", "1")
396 .Set("manifest_version", 2)
397 .Set("web_accessible_resources",
398 // Registered by chrome_component_extension_resource_manager.cc
399 ListBuilder().Append("ink/glcore_base.js.mem").Build())
400 .Build();
401
402 base::FilePath path;
403 EXPECT_TRUE(base::PathService::Get(chrome::DIR_RESOURCES, &path));
404 path = path.AppendASCII("pdf");
405
406 std::string error;
407 scoped_refptr<Extension> extension(Extension::Create(
408 path, Manifest::COMPONENT, *manifest, Extension::NO_FLAGS, &error));
409 EXPECT_TRUE(extension.get()) << error;
410 AddExtension(extension, false, false);
411
412 auto get_result =
413 RequestOrLoad(extension->GetResourceURL("ink/glcore_base.js.mem"),
Minggang Wangee5af392020-02-05 02:55:28414 blink::mojom::ResourceType::kXhr);
dstockwell944d18882019-04-09 04:25:58415 EXPECT_EQ(net::OK, get_result.result());
416 CheckForContentLengthHeader(get_result);
417 EXPECT_EQ("", get_result.GetResponseHeaderByName(
418 net::HttpRequestHeaders::kContentType));
419}
420#endif
421
[email protected]93ac047a2012-12-13 02:53:49422// Tests getting a resource for a component extension works correctly, both when
423// the extension is enabled and when it is disabled.
Clark DuVallc7e3b4692019-06-13 22:07:11424TEST_F(ExtensionProtocolsTest, ComponentResourceRequest) {
[email protected]93ac047a2012-12-13 02:53:49425 // Register a non-incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01426 SetProtocolHandler(false);
[email protected]93ac047a2012-12-13 02:53:49427
428 scoped_refptr<Extension> extension = CreateWebStoreExtension();
Chris Mumford8f812662018-02-22 00:27:57429 AddExtension(extension, false, false);
[email protected]93ac047a2012-12-13 02:53:49430
431 // First test it with the extension enabled.
432 {
Chris Mumford8f812662018-02-22 00:27:57433 auto get_result =
434 RequestOrLoad(extension->GetResourceURL("webstore_icon_16.png"),
Minggang Wangee5af392020-02-05 02:55:28435 blink::mojom::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57436 EXPECT_EQ(net::OK, get_result.result());
437 CheckForContentLengthHeader(get_result);
438 EXPECT_EQ("image/png", get_result.GetResponseHeaderByName(
439 net::HttpRequestHeaders::kContentType));
[email protected]93ac047a2012-12-13 02:53:49440 }
441
442 // And then test it with the extension disabled.
Chris Mumford8f812662018-02-22 00:27:57443 RemoveExtension(extension, UnloadedExtensionReason::DISABLE);
[email protected]93ac047a2012-12-13 02:53:49444 {
Chris Mumford8f812662018-02-22 00:27:57445 auto get_result =
446 RequestOrLoad(extension->GetResourceURL("webstore_icon_16.png"),
Minggang Wangee5af392020-02-05 02:55:28447 blink::mojom::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57448 EXPECT_EQ(net::OK, get_result.result());
449 CheckForContentLengthHeader(get_result);
450 EXPECT_EQ("image/png", get_result.GetResponseHeaderByName(
451 net::HttpRequestHeaders::kContentType));
[email protected]93ac047a2012-12-13 02:53:49452 }
453}
454
[email protected]6f7d7062013-06-04 03:49:33455// Tests that a URL request for resource from an extension returns a few
456// expected response headers.
Clark DuVallc7e3b4692019-06-13 22:07:11457TEST_F(ExtensionProtocolsTest, ResourceRequestResponseHeaders) {
[email protected]6f7d7062013-06-04 03:49:33458 // Register a non-incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01459 SetProtocolHandler(false);
[email protected]6f7d7062013-06-04 03:49:33460
Devlin Cronin8e5892f2018-10-04 00:13:43461 scoped_refptr<const Extension> extension =
462 CreateTestResponseHeaderExtension();
Chris Mumford8f812662018-02-22 00:27:57463 AddExtension(extension, false, false);
[email protected]6f7d7062013-06-04 03:49:33464
465 {
Chris Mumford8f812662018-02-22 00:27:57466 auto get_result = RequestOrLoad(extension->GetResourceURL("test.dat"),
Minggang Wangee5af392020-02-05 02:55:28467 blink::mojom::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57468 EXPECT_EQ(net::OK, get_result.result());
[email protected]6f7d7062013-06-04 03:49:33469
470 // Check that cache-related headers are set.
Chris Mumford8f812662018-02-22 00:27:57471 std::string etag = get_result.GetResponseHeaderByName("ETag");
brettw66d1b81b2015-07-06 19:29:40472 EXPECT_TRUE(base::StartsWith(etag, "\"", base::CompareCase::SENSITIVE));
473 EXPECT_TRUE(base::EndsWith(etag, "\"", base::CompareCase::SENSITIVE));
[email protected]6f7d7062013-06-04 03:49:33474
Chris Mumford8f812662018-02-22 00:27:57475 std::string revalidation_header =
476 get_result.GetResponseHeaderByName("cache-control");
[email protected]6f7d7062013-06-04 03:49:33477 EXPECT_EQ("no-cache", revalidation_header);
478
479 // We set test.dat as web-accessible, so it should have a CORS header.
Chris Mumford8f812662018-02-22 00:27:57480 std::string access_control =
481 get_result.GetResponseHeaderByName("Access-Control-Allow-Origin");
[email protected]6f7d7062013-06-04 03:49:33482 EXPECT_EQ("*", access_control);
483 }
484}
485
[email protected]b109bdd2013-11-04 18:08:43486// Tests that a URL request for main frame or subframe from an extension
487// succeeds, but subresources fail. See http://crbug.com/312269.
Clark DuVallc7e3b4692019-06-13 22:07:11488TEST_F(ExtensionProtocolsTest, AllowFrameRequests) {
[email protected]b109bdd2013-11-04 18:08:43489 // Register a non-incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01490 SetProtocolHandler(false);
[email protected]b109bdd2013-11-04 18:08:43491
492 scoped_refptr<Extension> extension = CreateTestExtension("foo", false);
Chris Mumford8f812662018-02-22 00:27:57493 AddExtension(extension, false, false);
[email protected]b109bdd2013-11-04 18:08:43494
nasko5cf9d452016-06-01 05:34:56495 // All MAIN_FRAME requests should succeed. SUB_FRAME requests that are not
Chris Mumford8f812662018-02-22 00:27:57496 // explicitly listed in web_accessible_resources or same-origin to the parent
nasko5cf9d452016-06-01 05:34:56497 // should not succeed.
[email protected]b109bdd2013-11-04 18:08:43498 {
Chris Mumford8f812662018-02-22 00:27:57499 auto get_result = RequestOrLoad(extension->GetResourceURL("test.dat"),
Minggang Wangee5af392020-02-05 02:55:28500 blink::mojom::ResourceType::kMainFrame);
Chris Mumford8f812662018-02-22 00:27:57501 EXPECT_EQ(net::OK, get_result.result());
[email protected]b109bdd2013-11-04 18:08:43502 }
John Abd-El-Malek2305cdc2018-02-14 20:26:28503
504 // Subframe navigation requests are blocked in ExtensionNavigationThrottle
505 // which isn't added in this unit test. This is tested in an integration test
506 // in ExtensionResourceRequestPolicyTest.IframeNavigateToInaccessible.
[email protected]b109bdd2013-11-04 18:08:43507
508 // And subresource types, such as media, should fail.
509 {
Chris Mumford8f812662018-02-22 00:27:57510 auto get_result = RequestOrLoad(extension->GetResourceURL("test.dat"),
Minggang Wangee5af392020-02-05 02:55:28511 blink::mojom::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57512 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, get_result.result());
[email protected]b109bdd2013-11-04 18:08:43513 }
514}
515
Clark DuVallc7e3b4692019-06-13 22:07:11516TEST_F(ExtensionProtocolsTest, MetadataFolder) {
asargenta093ec32016-02-13 01:36:43517 SetProtocolHandler(false);
518
519 base::FilePath extension_dir = GetTestPath("metadata_folder");
520 std::string error;
521 scoped_refptr<Extension> extension =
522 file_util::LoadExtension(extension_dir, Manifest::INTERNAL,
523 Extension::NO_FLAGS, &error);
524 ASSERT_NE(extension.get(), nullptr) << "error: " << error;
525
526 // Loading "/test.html" should succeed.
Chris Mumford8f812662018-02-22 00:27:57527 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, "test.html").result());
asargenta093ec32016-02-13 01:36:43528
529 // Loading "/_metadata/verified_contents.json" should fail.
530 base::FilePath relative_path =
531 base::FilePath(kMetadataFolder).Append(kVerifiedContentsFilename);
532 EXPECT_TRUE(base::PathExists(extension_dir.Append(relative_path)));
Chris Mumford8f812662018-02-22 00:27:57533 EXPECT_NE(net::OK,
534 DoRequestOrLoad(extension, relative_path.AsUTF8Unsafe()).result());
asargenta093ec32016-02-13 01:36:43535
536 // Loading "/_metadata/a.txt" should also fail.
537 relative_path = base::FilePath(kMetadataFolder).AppendASCII("a.txt");
538 EXPECT_TRUE(base::PathExists(extension_dir.Append(relative_path)));
Chris Mumford8f812662018-02-22 00:27:57539 EXPECT_NE(net::OK,
540 DoRequestOrLoad(extension, relative_path.AsUTF8Unsafe()).result());
asargenta093ec32016-02-13 01:36:43541}
542
lazyboyd6dbb262017-03-30 00:57:30543// Tests that unreadable files and deleted files correctly go through
544// ContentVerifyJob.
Clark DuVallc7e3b4692019-06-13 22:07:11545TEST_F(ExtensionProtocolsTest, VerificationSeenForFileAccessErrors) {
lazyboyd6dbb262017-03-30 00:57:30546 SetProtocolHandler(false);
547
Istiaque Ahmed72816eaa2018-01-30 22:37:06548 // Unzip extension containing verification hashes to a temporary directory.
lazyboyd6dbb262017-03-30 00:57:30549 base::ScopedTempDir temp_dir;
550 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Istiaque Ahmed72816eaa2018-01-30 22:37:06551 base::FilePath unzipped_path = temp_dir.GetPath();
552 scoped_refptr<Extension> extension =
553 content_verifier_test_utils::UnzipToDirAndLoadExtension(
554 GetContentVerifierTestPath().AppendASCII("source.zip"),
555 unzipped_path);
lazyboyd6dbb262017-03-30 00:57:30556 ASSERT_TRUE(extension.get());
Istiaque Ahmed72816eaa2018-01-30 22:37:06557 ExtensionId extension_id = extension->id();
lazyboyd6dbb262017-03-30 00:57:30558
Istiaque Ahmed72816eaa2018-01-30 22:37:06559 const std::string kJs("1024.js");
560 base::FilePath kRelativePath(FILE_PATH_LITERAL("1024.js"));
lazyboyd6dbb262017-03-30 00:57:30561
Istiaque Ahmed72816eaa2018-01-30 22:37:06562 // Valid and readable 1024.js.
563 {
Istiaque Ahmed584fe142018-03-13 09:19:04564 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
lazyboyd6dbb262017-03-30 00:57:30565
Chris Mumford8f812662018-02-22 00:27:57566 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
Istiaque Ahmed72816eaa2018-01-30 22:37:06567 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
568 content::RunAllPendingInMessageLoop();
569
Chris Mumford8f812662018-02-22 00:27:57570 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36571 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06572 }
573
574 // chmod -r 1024.js.
575 {
Oleg Davydovb7559452020-02-07 15:01:25576 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06577 base::FilePath file_path = unzipped_path.AppendASCII(kJs);
578 ASSERT_TRUE(base::MakeFileUnreadable(file_path));
Chris Mumford8f812662018-02-22 00:27:57579 EXPECT_EQ(net::ERR_ACCESS_DENIED, DoRequestOrLoad(extension, kJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36580 EXPECT_EQ(ContentVerifyJob::HASH_MISMATCH, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06581 // NOTE: In production, hash mismatch would have disabled |extension|, but
582 // since UnzipToDirAndLoadExtension() doesn't add the extension to
583 // ExtensionRegistry, ChromeContentVerifierDelegate won't disable it.
584 // TODO(lazyboy): We may want to update this to more closely reflect the
585 // real flow.
586 }
587
588 // Delete 1024.js.
589 {
Istiaque Ahmed584fe142018-03-13 09:19:04590 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06591 base::FilePath file_path = unzipped_path.AppendASCII(kJs);
592 ASSERT_TRUE(base::DieFileDie(file_path, false));
Chris Mumford8f812662018-02-22 00:27:57593 EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
594 DoRequestOrLoad(extension, kJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36595 EXPECT_EQ(ContentVerifyJob::HASH_MISMATCH, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06596 }
lazyboyd6dbb262017-03-30 00:57:30597}
598
lazyboye83ab9c62017-03-30 03:18:26599// Tests that zero byte files correctly go through ContentVerifyJob.
Clark DuVallc7e3b4692019-06-13 22:07:11600TEST_F(ExtensionProtocolsTest, VerificationSeenForZeroByteFile) {
lazyboye83ab9c62017-03-30 03:18:26601 SetProtocolHandler(false);
602
Istiaque Ahmed72816eaa2018-01-30 22:37:06603 const std::string kEmptyJs("empty.js");
lazyboye83ab9c62017-03-30 03:18:26604 base::ScopedTempDir temp_dir;
605 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Istiaque Ahmed72816eaa2018-01-30 22:37:06606 base::FilePath unzipped_path = temp_dir.GetPath();
lazyboye83ab9c62017-03-30 03:18:26607
Istiaque Ahmed72816eaa2018-01-30 22:37:06608 scoped_refptr<Extension> extension =
609 content_verifier_test_utils::UnzipToDirAndLoadExtension(
610 GetContentVerifierTestPath().AppendASCII("source.zip"),
611 unzipped_path);
612 ASSERT_TRUE(extension.get());
613
614 base::FilePath kRelativePath(FILE_PATH_LITERAL("empty.js"));
615 ExtensionId extension_id = extension->id();
616
617 // Sanity check empty.js.
618 base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
lazyboye83ab9c62017-03-30 03:18:26619 int64_t foo_file_size = -1;
Istiaque Ahmed72816eaa2018-01-30 22:37:06620 ASSERT_TRUE(base::GetFileSize(file_path, &foo_file_size));
lazyboye83ab9c62017-03-30 03:18:26621 ASSERT_EQ(0, foo_file_size);
622
Istiaque Ahmed72816eaa2018-01-30 22:37:06623 // Request empty.js.
624 {
Istiaque Ahmed584fe142018-03-13 09:19:04625 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
lazyboye83ab9c62017-03-30 03:18:26626
Chris Mumford8f812662018-02-22 00:27:57627 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
Istiaque Ahmed72816eaa2018-01-30 22:37:06628 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
629 content::RunAllPendingInMessageLoop();
lazyboye83ab9c62017-03-30 03:18:26630
Chris Mumford8f812662018-02-22 00:27:57631 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kEmptyJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36632 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06633 }
634
635 // chmod -r empty.js.
636 // Unreadable empty file doesn't generate hash mismatch. Note that this is the
637 // current behavior of ContentVerifyJob.
638 // TODO(lazyboy): The behavior is probably incorrect.
639 {
Oleg Davydovb7559452020-02-07 15:01:25640 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06641 base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
642 ASSERT_TRUE(base::MakeFileUnreadable(file_path));
Chris Mumford8f812662018-02-22 00:27:57643 EXPECT_EQ(net::ERR_ACCESS_DENIED,
644 DoRequestOrLoad(extension, kEmptyJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36645 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06646 }
647
648 // rm empty.js.
649 // Deleted empty file doesn't generate hash mismatch. Note that this is the
650 // current behavior of ContentVerifyJob.
651 // TODO(lazyboy): The behavior is probably incorrect.
652 {
Istiaque Ahmed584fe142018-03-13 09:19:04653 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06654 base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
655 ASSERT_TRUE(base::DieFileDie(file_path, false));
Chris Mumford8f812662018-02-22 00:27:57656 EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
657 DoRequestOrLoad(extension, kEmptyJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36658 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06659 }
lazyboye83ab9c62017-03-30 03:18:26660}
661
Clark DuVallc7e3b4692019-06-13 22:07:11662TEST_F(ExtensionProtocolsTest, VerifyScriptListedAsIcon) {
proberge4f9644c2018-03-27 23:01:54663 SetProtocolHandler(false);
664
665 const std::string kBackgroundJs("background.js");
666 base::ScopedTempDir temp_dir;
667 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
668 base::FilePath unzipped_path = temp_dir.GetPath();
669
670 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:52671 EXPECT_TRUE(base::PathService::Get(extensions::DIR_TEST_DATA, &path));
proberge4f9644c2018-03-27 23:01:54672
673 scoped_refptr<Extension> extension =
674 content_verifier_test_utils::UnzipToDirAndLoadExtension(
675 path.AppendASCII("content_hash_fetcher")
676 .AppendASCII("manifest_mislabeled_script")
677 .AppendASCII("source.zip"),
678 unzipped_path);
679 ASSERT_TRUE(extension.get());
680
681 base::FilePath kRelativePath(FILE_PATH_LITERAL("background.js"));
682 ExtensionId extension_id = extension->id();
683
684 // Request background.js.
685 {
686 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
687
688 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
689 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
690 base::RunLoop().RunUntilIdle();
691
692 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kBackgroundJs).result());
693 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
694 }
695
696 // Modify background.js and request it.
697 {
698 base::FilePath file_path = unzipped_path.AppendASCII("background.js");
699 const std::string content = "new content";
Lei Zhanga5bd23f12020-05-07 05:50:15700 EXPECT_TRUE(base::WriteFile(file_path, content));
proberge4f9644c2018-03-27 23:01:54701 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
702
703 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
704 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
705 base::RunLoop().RunUntilIdle();
706
707 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kBackgroundJs).result());
708 EXPECT_EQ(ContentVerifyJob::HASH_MISMATCH, observer.WaitForJobFinished());
709 }
710}
711
Devlin Croninc3f88072018-01-30 02:10:11712// Tests that mime types are properly set for returned extension resources.
Clark DuVallc7e3b4692019-06-13 22:07:11713TEST_F(ExtensionProtocolsTest, MimeTypesForKnownFiles) {
Devlin Croninc3f88072018-01-30 02:10:11714 // Register a non-incognito extension protocol handler.
715 SetProtocolHandler(false);
716
717 TestExtensionDir test_dir;
718 constexpr char kManifest[] = R"(
719 {
720 "name": "Test Ext",
721 "description": "A test extension",
722 "manifest_version": 2,
723 "version": "0.1",
724 "web_accessible_resources": ["*"]
725 })";
726 test_dir.WriteManifest(kManifest);
727 std::unique_ptr<base::DictionaryValue> manifest =
Lei Zhang9b9d5792019-02-20 07:24:42728 base::DictionaryValue::From(base::test::ParseJsonDeprecated(kManifest));
Devlin Croninc3f88072018-01-30 02:10:11729 ASSERT_TRUE(manifest);
730
731 test_dir.WriteFile(FILE_PATH_LITERAL("json_file.json"), "{}");
732 test_dir.WriteFile(FILE_PATH_LITERAL("js_file.js"), "function() {}");
733
734 base::FilePath unpacked_path = test_dir.UnpackedPath();
735 ASSERT_TRUE(base::PathExists(unpacked_path.AppendASCII("json_file.json")));
736 std::string error;
737 scoped_refptr<const Extension> extension =
738 ExtensionBuilder()
739 .SetManifest(std::move(manifest))
740 .SetPath(unpacked_path)
741 .SetLocation(Manifest::INTERNAL)
742 .Build();
743 ASSERT_TRUE(extension);
744
Chris Mumford8f812662018-02-22 00:27:57745 AddExtension(extension.get(), false, false);
Devlin Croninc3f88072018-01-30 02:10:11746
747 struct {
748 const char* file_name;
749 const char* expected_mime_type;
750 } test_cases[] = {
dstockwell00677932019-04-09 02:12:08751 {"json_file.json", "application/json"},
752 {"js_file.js", "text/javascript"},
753 {"mem_file.mem", ""},
Devlin Croninc3f88072018-01-30 02:10:11754 };
755
756 for (const auto& test_case : test_cases) {
757 SCOPED_TRACE(test_case.file_name);
Chris Mumford8f812662018-02-22 00:27:57758 auto result = RequestOrLoad(extension->GetResourceURL(test_case.file_name),
Minggang Wangee5af392020-02-05 02:55:28759 blink::mojom::ResourceType::kSubResource);
Chris Mumford8f812662018-02-22 00:27:57760 EXPECT_EQ(
761 test_case.expected_mime_type,
762 result.GetResponseHeaderByName(net::HttpRequestHeaders::kContentType));
Devlin Croninc3f88072018-01-30 02:10:11763 }
764}
765
Kevin Marshall4cab5af2019-01-14 20:27:14766#if defined(OS_WIN)
767#define MAYBE_ExtensionRequestsNotAborted DISABLED_ExtensionRequestsNotAborted
768#else
769#define MAYBE_ExtensionRequestsNotAborted ExtensionRequestsNotAborted
770#endif
Karandeep Bhatiaab489a4d2018-11-28 21:56:06771// Tests that requests for extension resources (including the generated
772// background page) are not aborted on system suspend.
Kevin Marshall4cab5af2019-01-14 20:27:14773//
774// Flaky on Windows.
775// TODO(https://crbug.com/921687): Investigate and fix.
Clark DuVallc7e3b4692019-06-13 22:07:11776TEST_F(ExtensionProtocolsTest, MAYBE_ExtensionRequestsNotAborted) {
Karandeep Bhatiaab489a4d2018-11-28 21:56:06777 // Register a non-incognito extension protocol handler.
778 SetProtocolHandler(false);
779
780 base::FilePath extension_dir =
781 GetTestPath("common").AppendASCII("background_script");
782 std::string error;
783 scoped_refptr<Extension> extension = file_util::LoadExtension(
784 extension_dir, Manifest::INTERNAL, Extension::NO_FLAGS, &error);
785 ASSERT_TRUE(extension.get()) << error;
786
787 SimulateSystemSuspendForRequests();
788
789 // Request the generated background page. Ensure the request completes
790 // successfully.
791 EXPECT_EQ(net::OK,
792 DoRequestOrLoad(extension.get(), kGeneratedBackgroundPageFilename)
793 .result());
794
795 // Request the background.js file. Ensure the request completes successfully.
796 EXPECT_EQ(net::OK, DoRequestOrLoad(extension.get(), "background.js").result());
797}
798
[email protected]702d8b42013-02-27 20:55:50799} // namespace extensions