blob: 64e6c6dc42f3899b614393e607bddfcd5cbc38cd [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"
[email protected]885c0e92012-11-13 20:27:4241#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4142#include "extensions/common/extension.h"
lazyboyd6dbb262017-03-30 00:57:3043#include "extensions/common/extension_builder.h"
Istiaque Ahmed72816eaa2018-01-30 22:37:0644#include "extensions/common/extension_paths.h"
asargenta093ec32016-02-13 01:36:4345#include "extensions/common/file_util.h"
Devlin Cronin1fa235b62018-04-12 14:04:0746#include "extensions/common/value_builder.h"
Devlin Croninc3f88072018-01-30 02:10:1147#include "extensions/test/test_extension_dir.h"
Julie Jeongeun Kim917c197902019-11-26 03:36:1448#include "mojo/public/cpp/bindings/pending_remote.h"
rhalavati04b93382017-04-07 19:00:5449#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Chris Mumford8f812662018-02-22 00:27:5750#include "services/network/test/test_url_loader_client.h"
[email protected]5e212ed2012-03-21 23:29:1551#include "testing/gtest/include/gtest/gtest.h"
52
[email protected]7491ad02014-07-05 19:10:0753using content::ResourceType;
Chris Mumford8f812662018-02-22 00:27:5754using extensions::ExtensionRegistry;
55using network::mojom::URLLoader;
[email protected]7491ad02014-07-05 19:10:0756
[email protected]702d8b42013-02-27 20:55:5057namespace extensions {
jamescook8816ae52014-09-05 17:02:3758namespace {
[email protected]5e212ed2012-03-21 23:29:1559
asargenta093ec32016-02-13 01:36:4360base::FilePath GetTestPath(const std::string& name) {
61 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:5262 EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &path));
asargenta093ec32016-02-13 01:36:4363 return path.AppendASCII("extensions").AppendASCII(name);
64}
65
Istiaque Ahmed72816eaa2018-01-30 22:37:0666base::FilePath GetContentVerifierTestPath() {
67 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:5268 EXPECT_TRUE(base::PathService::Get(extensions::DIR_TEST_DATA, &path));
Istiaque Ahmed72816eaa2018-01-30 22:37:0669 return path.AppendASCII("content_hash_fetcher")
70 .AppendASCII("different_sized_files");
lazyboyd6dbb262017-03-30 00:57:3071}
72
[email protected]5e212ed2012-03-21 23:29:1573scoped_refptr<Extension> CreateTestExtension(const std::string& name,
74 bool incognito_split_mode) {
[email protected]023b3d12013-12-23 18:46:4975 base::DictionaryValue manifest;
[email protected]5e212ed2012-03-21 23:29:1576 manifest.SetString("name", name);
77 manifest.SetString("version", "1");
[email protected]b109bdd2013-11-04 18:08:4378 manifest.SetInteger("manifest_version", 2);
[email protected]5e212ed2012-03-21 23:29:1579 manifest.SetString("incognito", incognito_split_mode ? "split" : "spanning");
80
asargenta093ec32016-02-13 01:36:4381 base::FilePath path = GetTestPath("response_headers");
[email protected]5e212ed2012-03-21 23:29:1582
83 std::string error;
84 scoped_refptr<Extension> extension(
[email protected]1d5e58b2013-01-31 08:41:4085 Extension::Create(path, Manifest::INTERNAL, manifest,
[email protected]ed3b9b12012-05-31 18:37:5186 Extension::NO_FLAGS, &error));
[email protected]5e212ed2012-03-21 23:29:1587 EXPECT_TRUE(extension.get()) << error;
88 return extension;
89}
90
[email protected]93ac047a2012-12-13 02:53:4991scoped_refptr<Extension> CreateWebStoreExtension() {
Devlin Croninf43c3312018-03-27 19:54:1792 std::unique_ptr<base::DictionaryValue> manifest =
93 DictionaryBuilder()
94 .Set("name", "WebStore")
95 .Set("version", "1")
96 .Set("manifest_version", 2)
97 .Set("icons",
98 DictionaryBuilder().Set("16", "webstore_icon_16.png").Build())
99 .Set("web_accessible_resources",
100 ListBuilder().Append("webstore_icon_16.png").Build())
101 .Build();
[email protected]93ac047a2012-12-13 02:53:49102
[email protected]650b2d52013-02-10 03:41:45103 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:52104 EXPECT_TRUE(base::PathService::Get(chrome::DIR_RESOURCES, &path));
[email protected]93ac047a2012-12-13 02:53:49105 path = path.AppendASCII("web_store");
106
107 std::string error;
Devlin Croninf43c3312018-03-27 19:54:17108 scoped_refptr<Extension> extension(Extension::Create(
109 path, Manifest::COMPONENT, *manifest, Extension::NO_FLAGS, &error));
[email protected]93ac047a2012-12-13 02:53:49110 EXPECT_TRUE(extension.get()) << error;
111 return extension;
112}
113
Devlin Cronin8e5892f2018-10-04 00:13:43114scoped_refptr<const Extension> CreateTestResponseHeaderExtension() {
Devlin Cronin1fa235b62018-04-12 14:04:07115 return ExtensionBuilder("An extension with web-accessible resources")
Devlin Cronin98cd6582018-05-08 19:18:12116 .SetManifestKey("web_accessible_resources",
117 ListBuilder().Append("test.dat").Build())
Devlin Cronin1fa235b62018-04-12 14:04:07118 .SetPath(GetTestPath("response_headers"))
119 .Build();
[email protected]6f7d7062013-06-04 03:49:33120}
121
Chris Mumford8f812662018-02-22 00:27:57122// Helper function to create a |ResourceRequest| for testing purposes.
123network::ResourceRequest CreateResourceRequest(const std::string& method,
124 ResourceType resource_type,
125 const GURL& url) {
126 network::ResourceRequest request;
127 request.method = method;
128 request.url = url;
129 request.site_for_cookies = url; // bypass third-party cookie blocking.
130 request.request_initiator =
131 url::Origin::Create(url); // ensure initiator set.
132 request.referrer_policy = content::Referrer::GetDefaultReferrerPolicy();
Daniel Cheng57541be2019-05-07 07:51:07133 request.resource_type = static_cast<int>(resource_type);
Daniel Chengaee5c0312019-04-18 23:49:05134 request.is_main_frame = resource_type == content::ResourceType::kMainFrame;
Chris Mumford8f812662018-02-22 00:27:57135 return request;
136}
137
138// The result of either a URLRequest of a URLLoader response (but not both)
139// depending on the on test type.
140class GetResult {
141 public:
Lucas Furukawa Gadani06902602019-09-27 20:44:27142 GetResult(network::mojom::URLResponseHeadPtr response, int result)
143 : response_(std::move(response)), result_(result) {}
Clark DuVallc7e3b4692019-06-13 22:07:11144 GetResult(GetResult&& other) : result_(other.result_) {}
Chris Mumford8f812662018-02-22 00:27:57145 ~GetResult() = default;
146
147 std::string GetResponseHeaderByName(const std::string& name) const {
148 std::string value;
Lucas Furukawa Gadani06902602019-09-27 20:44:27149 if (response_ && response_->headers)
150 response_->headers->GetNormalizedHeader(name, &value);
Chris Mumford8f812662018-02-22 00:27:57151 return value;
152 }
153
154 int result() const { return result_; }
155
156 private:
Lucas Furukawa Gadani06902602019-09-27 20:44:27157 network::mojom::URLResponseHeadPtr response_;
Chris Mumford8f812662018-02-22 00:27:57158 int result_;
159
160 DISALLOW_COPY_AND_ASSIGN(GetResult);
161};
162
jamescook8816ae52014-09-05 17:02:37163} // namespace
164
165// This test lives in src/chrome instead of src/extensions because it tests
166// functionality delegated back to Chrome via ChromeExtensionsBrowserClient.
lfg048201a2014-09-16 19:09:36167// See chrome/browser/extensions/chrome_url_request_util.cc.
Clark DuVallc7e3b4692019-06-13 22:07:11168class ExtensionProtocolsTestBase : public testing::Test {
[email protected]5e212ed2012-03-21 23:29:15169 public:
Alexey Baskakovf0f9d8f2019-01-19 02:31:54170 explicit ExtensionProtocolsTestBase(bool force_incognito)
Gabriel Charette798fde72019-08-20 22:24:04171 : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
Chris Mumford8f812662018-02-22 00:27:57172 rvh_test_enabler_(new content::RenderViewHostTestEnabler()),
Alexey Baskakovf0f9d8f2019-01-19 02:31:54173 force_incognito_(force_incognito) {}
[email protected]5e212ed2012-03-21 23:29:15174
dcheng72191812014-10-28 20:49:56175 void SetUp() override {
[email protected]06492ed2013-03-24 22:13:14176 testing::Test::SetUp();
lazyboyd6dbb262017-03-30 00:57:30177 testing_profile_ = TestingProfile::Builder().Build();
Erik Chen5bab4992018-05-05 15:19:53178 contents_ = CreateTestWebContents();
lazyboyd6dbb262017-03-30 00:57:30179
180 // Set up content verification.
181 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
182 command_line->AppendSwitchASCII(
183 switches::kExtensionContentVerification,
184 switches::kExtensionContentVerificationEnforce);
185 content_verifier_ = new ContentVerifier(
Chris Mumford8f812662018-02-22 00:27:57186 browser_context(),
187 std::make_unique<ChromeContentVerifierDelegate>(browser_context()));
John Abd-El-Malekea006302018-05-10 05:50:46188 info_map()->SetContentVerifier(content_verifier_.get());
[email protected]5e212ed2012-03-21 23:29:15189 }
190
dcheng72191812014-10-28 20:49:56191 void TearDown() override {
Chris Mumford8f812662018-02-22 00:27:57192 loader_factory_.reset();
lazyboyd6dbb262017-03-30 00:57:30193 content_verifier_->Shutdown();
Matt Menkedb9fc40b2019-06-19 17:57:35194 // Shut down the PowerMonitor if initialized.
195 base::PowerMonitor::ShutdownForTesting();
[email protected]5e212ed2012-03-21 23:29:15196 }
197
[email protected]1791e6c92014-04-11 08:29:01198 void SetProtocolHandler(bool is_incognito) {
Clark DuVallc7e3b4692019-06-13 22:07:11199 loader_factory_ = extensions::CreateExtensionNavigationURLLoaderFactory(
200 browser_context(), false);
[email protected]93ac047a2012-12-13 02:53:49201 }
202
Chris Mumford8f812662018-02-22 00:27:57203 GetResult RequestOrLoad(const GURL& url, ResourceType resource_type) {
Clark DuVallc7e3b4692019-06-13 22:07:11204 return LoadURL(url, resource_type);
Chris Mumford8f812662018-02-22 00:27:57205 }
206
207 void AddExtension(const scoped_refptr<const Extension>& extension,
208 bool incognito_enabled,
209 bool notifications_disabled) {
John Abd-El-Malekea006302018-05-10 05:50:46210 info_map()->AddExtension(extension.get(), base::Time::Now(),
211 incognito_enabled, notifications_disabled);
Clark DuVallc7e3b4692019-06-13 22:07:11212 EXPECT_TRUE(extension_registry()->AddEnabled(extension));
213 ExtensionPrefs::Get(browser_context())
214 ->SetIsIncognitoEnabled(extension->id(), incognito_enabled);
Chris Mumford8f812662018-02-22 00:27:57215 }
216
217 void RemoveExtension(const scoped_refptr<const Extension>& extension,
218 const UnloadedExtensionReason reason) {
John Abd-El-Malekea006302018-05-10 05:50:46219 info_map()->RemoveExtension(extension->id(), reason);
Clark DuVallc7e3b4692019-06-13 22:07:11220 EXPECT_TRUE(extension_registry()->RemoveEnabled(extension->id()));
221 if (reason == UnloadedExtensionReason::DISABLE)
222 EXPECT_TRUE(extension_registry()->AddDisabled(extension));
Chris Mumford8f812662018-02-22 00:27:57223 }
224
225 // Helper method to create a URL request/loader, call RequestOrLoad on it, and
226 // return the result. If |extension| hasn't already been added to
John Abd-El-Malekea006302018-05-10 05:50:46227 // info_map(), this will add it.
Chris Mumford8f812662018-02-22 00:27:57228 GetResult DoRequestOrLoad(const scoped_refptr<Extension> extension,
229 const std::string& relative_path) {
John Abd-El-Malekea006302018-05-10 05:50:46230 if (!info_map()->extensions().Contains(extension->id())) {
Chris Mumford8f812662018-02-22 00:27:57231 AddExtension(extension.get(),
232 /*incognito_enabled=*/false,
233 /*notifications_disabled=*/false);
234 }
235 return RequestOrLoad(extension->GetResourceURL(relative_path),
Daniel Chengaee5c0312019-04-18 23:49:05236 content::ResourceType::kMainFrame);
Chris Mumford8f812662018-02-22 00:27:57237 }
238
239 ExtensionRegistry* extension_registry() {
240 return ExtensionRegistry::Get(browser_context());
241 }
242
John Abd-El-Malekea006302018-05-10 05:50:46243 InfoMap* info_map() {
244 return ExtensionSystem::Get(browser_context())->info_map();
245 }
246
Alexey Baskakovf0f9d8f2019-01-19 02:31:54247 content::BrowserContext* browser_context() {
248 return force_incognito_ ? testing_profile_->GetOffTheRecordProfile()
249 : testing_profile_.get();
250 }
Chris Mumford8f812662018-02-22 00:27:57251
Karandeep Bhatiaab489a4d2018-11-28 21:56:06252 void SimulateSystemSuspendForRequests() {
253 power_monitor_source_ = new base::PowerMonitorTestSource();
Matt Menkedb9fc40b2019-06-19 17:57:35254 base::PowerMonitor::Initialize(
Karandeep Bhatiaab489a4d2018-11-28 21:56:06255 std::unique_ptr<base::PowerMonitorSource>(power_monitor_source_));
256 }
257
Chris Mumford8f812662018-02-22 00:27:57258 protected:
259 scoped_refptr<ContentVerifier> content_verifier_;
260
261 private:
262 GetResult LoadURL(const GURL& url, ResourceType resource_type) {
263 constexpr int32_t kRoutingId = 81;
264 constexpr int32_t kRequestId = 28;
265
Julie Jeongeun Kim917c197902019-11-26 03:36:14266 mojo::PendingRemote<network::mojom::URLLoader> loader;
Chris Mumford8f812662018-02-22 00:27:57267 network::TestURLLoaderClient client;
268 loader_factory_->CreateLoaderAndStart(
Julie Jeongeun Kim917c197902019-11-26 03:36:14269 loader.InitWithNewPipeAndPassReceiver(), kRoutingId, kRequestId,
Chris Mumford8f812662018-02-22 00:27:57270 network::mojom::kURLLoadOptionNone,
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:30271 CreateResourceRequest("GET", resource_type, url), client.CreateRemote(),
Chris Mumford8f812662018-02-22 00:27:57272 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
273
Karandeep Bhatiaab489a4d2018-11-28 21:56:06274 if (power_monitor_source_) {
275 power_monitor_source_->GenerateSuspendEvent();
276 power_monitor_source_->GenerateResumeEvent();
277 }
278
Chris Mumford8f812662018-02-22 00:27:57279 client.RunUntilComplete();
Lucas Furukawa Gadani06902602019-09-27 20:44:27280 return GetResult(client.response_head().Clone(),
Chris Mumford8f812662018-02-22 00:27:57281 client.completion_status().error_code);
282 }
283
Erik Chen5bab4992018-05-05 15:19:53284 std::unique_ptr<content::WebContents> CreateTestWebContents() {
Chris Mumford8f812662018-02-22 00:27:57285 auto site_instance = content::SiteInstance::Create(browser_context());
286 return content::WebContentsTester::CreateTestWebContents(
287 browser_context(), std::move(site_instance));
asargenta093ec32016-02-13 01:36:43288 }
289
Chris Mumford8f812662018-02-22 00:27:57290 content::WebContents* web_contents() { return contents_.get(); }
291
292 content::RenderFrameHost* main_rfh() {
293 return web_contents()->GetMainFrame();
294 }
295
Gabriel Charette798fde72019-08-20 22:24:04296 content::BrowserTaskEnvironment task_environment_;
Chris Mumford8f812662018-02-22 00:27:57297 std::unique_ptr<content::RenderViewHostTestEnabler> rvh_test_enabler_;
Chris Mumford8f812662018-02-22 00:27:57298 std::unique_ptr<network::mojom::URLLoaderFactory> loader_factory_;
lazyboyd6dbb262017-03-30 00:57:30299 std::unique_ptr<TestingProfile> testing_profile_;
Chris Mumford8f812662018-02-22 00:27:57300 std::unique_ptr<content::WebContents> contents_;
Alexey Baskakovf0f9d8f2019-01-19 02:31:54301 const bool force_incognito_;
Karandeep Bhatiaab489a4d2018-11-28 21:56:06302
Matt Menkedb9fc40b2019-06-19 17:57:35303 // |power_monitor_source_| is owned by the global PowerMonitor.
Karandeep Bhatiaab489a4d2018-11-28 21:56:06304 base::PowerMonitorTestSource* power_monitor_source_ = nullptr;
[email protected]5e212ed2012-03-21 23:29:15305};
306
Alexey Baskakovf0f9d8f2019-01-19 02:31:54307class ExtensionProtocolsTest : public ExtensionProtocolsTestBase {
308 public:
309 ExtensionProtocolsTest()
310 : ExtensionProtocolsTestBase(false /*force_incognito*/) {}
311};
312
313class ExtensionProtocolsIncognitoTest : public ExtensionProtocolsTestBase {
314 public:
315 ExtensionProtocolsIncognitoTest()
316 : ExtensionProtocolsTestBase(true /*force_incognito*/) {}
317};
318
[email protected]5e212ed2012-03-21 23:29:15319// Tests that making a chrome-extension request in an incognito context is
320// only allowed under the right circumstances (if the extension is allowed
321// in incognito, and it's either a non-main-frame request or a split-mode
322// extension).
Clark DuVallc7e3b4692019-06-13 22:07:11323TEST_F(ExtensionProtocolsIncognitoTest, IncognitoRequest) {
[email protected]93ac047a2012-12-13 02:53:49324 // Register an incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01325 SetProtocolHandler(true);
[email protected]93ac047a2012-12-13 02:53:49326
[email protected]5e212ed2012-03-21 23:29:15327 struct TestCase {
328 // Inputs.
329 std::string name;
330 bool incognito_split_mode;
331 bool incognito_enabled;
332
333 // Expected results.
334 bool should_allow_main_frame_load;
335 bool should_allow_sub_frame_load;
336 } cases[] = {
337 {"spanning disabled", false, false, false, false},
338 {"split disabled", true, false, false, false},
nasko5cf9d452016-06-01 05:34:56339 {"spanning enabled", false, true, false, false},
340 {"split enabled", true, true, true, false},
[email protected]5e212ed2012-03-21 23:29:15341 };
342
Avi Drissman5f0fb8c2018-12-25 23:20:49343 for (size_t i = 0; i < base::size(cases); ++i) {
[email protected]5e212ed2012-03-21 23:29:15344 scoped_refptr<Extension> extension =
345 CreateTestExtension(cases[i].name, cases[i].incognito_split_mode);
Chris Mumford8f812662018-02-22 00:27:57346 AddExtension(extension, cases[i].incognito_enabled, false);
[email protected]5e212ed2012-03-21 23:29:15347
348 // First test a main frame request.
349 {
350 // It doesn't matter that the resource doesn't exist. If the resource
naskob9164c42016-06-07 01:21:35351 // is blocked, we should see BLOCKED_BY_CLIENT. Otherwise, the request
[email protected]5e212ed2012-03-21 23:29:15352 // should just fail because the file doesn't exist.
Chris Mumford8f812662018-02-22 00:27:57353 auto get_result = RequestOrLoad(extension->GetResourceURL("404.html"),
Daniel Chengaee5c0312019-04-18 23:49:05354 content::ResourceType::kMainFrame);
[email protected]5e212ed2012-03-21 23:29:15355
356 if (cases[i].should_allow_main_frame_load) {
Chris Mumford8f812662018-02-22 00:27:57357 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, get_result.result())
maksim.sisov1b83bb72016-10-07 06:07:23358 << cases[i].name;
[email protected]5e212ed2012-03-21 23:29:15359 } else {
Chris Mumford8f812662018-02-22 00:27:57360 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, get_result.result())
naskob9164c42016-06-07 01:21:35361 << cases[i].name;
[email protected]5e212ed2012-03-21 23:29:15362 }
363 }
364
John Abd-El-Malek2305cdc2018-02-14 20:26:28365 // Subframe navigation requests are blocked in ExtensionNavigationThrottle
366 // which isn't added in this unit test. This is tested in an integration
367 // test in ExtensionResourceRequestPolicyTest.IframeNavigateToInaccessible.
Chris Mumford8f812662018-02-22 00:27:57368 RemoveExtension(extension, UnloadedExtensionReason::UNINSTALL);
[email protected]5e212ed2012-03-21 23:29:15369 }
370}
371
Chris Mumford8f812662018-02-22 00:27:57372void CheckForContentLengthHeader(const GetResult& get_result) {
373 std::string content_length = get_result.GetResponseHeaderByName(
374 net::HttpRequestHeaders::kContentLength);
375
[email protected]774cebd2013-09-26 04:55:01376 EXPECT_FALSE(content_length.empty());
377 int length_value = 0;
378 EXPECT_TRUE(base::StringToInt(content_length, &length_value));
379 EXPECT_GT(length_value, 0);
380}
381
dstockwell944d18882019-04-09 04:25:58382#if defined(OS_CHROMEOS)
383// Tests getting a resource for a component extension works correctly where
384// there is no mime type. Such a resource currently only exists for Chrome OS
385// build.
Clark DuVallc7e3b4692019-06-13 22:07:11386TEST_F(ExtensionProtocolsTest, ComponentResourceRequestNoMimeType) {
dstockwell944d18882019-04-09 04:25:58387 SetProtocolHandler(false);
388 std::unique_ptr<base::DictionaryValue> manifest =
389 DictionaryBuilder()
390 .Set("name", "pdf")
391 .Set("version", "1")
392 .Set("manifest_version", 2)
393 .Set("web_accessible_resources",
394 // Registered by chrome_component_extension_resource_manager.cc
395 ListBuilder().Append("ink/glcore_base.js.mem").Build())
396 .Build();
397
398 base::FilePath path;
399 EXPECT_TRUE(base::PathService::Get(chrome::DIR_RESOURCES, &path));
400 path = path.AppendASCII("pdf");
401
402 std::string error;
403 scoped_refptr<Extension> extension(Extension::Create(
404 path, Manifest::COMPONENT, *manifest, Extension::NO_FLAGS, &error));
405 EXPECT_TRUE(extension.get()) << error;
406 AddExtension(extension, false, false);
407
408 auto get_result =
409 RequestOrLoad(extension->GetResourceURL("ink/glcore_base.js.mem"),
Daniel Chengaee5c0312019-04-18 23:49:05410 content::ResourceType::kXhr);
dstockwell944d18882019-04-09 04:25:58411 EXPECT_EQ(net::OK, get_result.result());
412 CheckForContentLengthHeader(get_result);
413 EXPECT_EQ("", get_result.GetResponseHeaderByName(
414 net::HttpRequestHeaders::kContentType));
415}
416#endif
417
[email protected]93ac047a2012-12-13 02:53:49418// Tests getting a resource for a component extension works correctly, both when
419// the extension is enabled and when it is disabled.
Clark DuVallc7e3b4692019-06-13 22:07:11420TEST_F(ExtensionProtocolsTest, ComponentResourceRequest) {
[email protected]93ac047a2012-12-13 02:53:49421 // Register a non-incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01422 SetProtocolHandler(false);
[email protected]93ac047a2012-12-13 02:53:49423
424 scoped_refptr<Extension> extension = CreateWebStoreExtension();
Chris Mumford8f812662018-02-22 00:27:57425 AddExtension(extension, false, false);
[email protected]93ac047a2012-12-13 02:53:49426
427 // First test it with the extension enabled.
428 {
Chris Mumford8f812662018-02-22 00:27:57429 auto get_result =
430 RequestOrLoad(extension->GetResourceURL("webstore_icon_16.png"),
Daniel Chengaee5c0312019-04-18 23:49:05431 content::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57432 EXPECT_EQ(net::OK, get_result.result());
433 CheckForContentLengthHeader(get_result);
434 EXPECT_EQ("image/png", get_result.GetResponseHeaderByName(
435 net::HttpRequestHeaders::kContentType));
[email protected]93ac047a2012-12-13 02:53:49436 }
437
438 // And then test it with the extension disabled.
Chris Mumford8f812662018-02-22 00:27:57439 RemoveExtension(extension, UnloadedExtensionReason::DISABLE);
[email protected]93ac047a2012-12-13 02:53:49440 {
Chris Mumford8f812662018-02-22 00:27:57441 auto get_result =
442 RequestOrLoad(extension->GetResourceURL("webstore_icon_16.png"),
Daniel Chengaee5c0312019-04-18 23:49:05443 content::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57444 EXPECT_EQ(net::OK, get_result.result());
445 CheckForContentLengthHeader(get_result);
446 EXPECT_EQ("image/png", get_result.GetResponseHeaderByName(
447 net::HttpRequestHeaders::kContentType));
[email protected]93ac047a2012-12-13 02:53:49448 }
449}
450
[email protected]6f7d7062013-06-04 03:49:33451// Tests that a URL request for resource from an extension returns a few
452// expected response headers.
Clark DuVallc7e3b4692019-06-13 22:07:11453TEST_F(ExtensionProtocolsTest, ResourceRequestResponseHeaders) {
[email protected]6f7d7062013-06-04 03:49:33454 // Register a non-incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01455 SetProtocolHandler(false);
[email protected]6f7d7062013-06-04 03:49:33456
Devlin Cronin8e5892f2018-10-04 00:13:43457 scoped_refptr<const Extension> extension =
458 CreateTestResponseHeaderExtension();
Chris Mumford8f812662018-02-22 00:27:57459 AddExtension(extension, false, false);
[email protected]6f7d7062013-06-04 03:49:33460
461 {
Chris Mumford8f812662018-02-22 00:27:57462 auto get_result = RequestOrLoad(extension->GetResourceURL("test.dat"),
Daniel Chengaee5c0312019-04-18 23:49:05463 content::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57464 EXPECT_EQ(net::OK, get_result.result());
[email protected]6f7d7062013-06-04 03:49:33465
466 // Check that cache-related headers are set.
Chris Mumford8f812662018-02-22 00:27:57467 std::string etag = get_result.GetResponseHeaderByName("ETag");
brettw66d1b81b2015-07-06 19:29:40468 EXPECT_TRUE(base::StartsWith(etag, "\"", base::CompareCase::SENSITIVE));
469 EXPECT_TRUE(base::EndsWith(etag, "\"", base::CompareCase::SENSITIVE));
[email protected]6f7d7062013-06-04 03:49:33470
Chris Mumford8f812662018-02-22 00:27:57471 std::string revalidation_header =
472 get_result.GetResponseHeaderByName("cache-control");
[email protected]6f7d7062013-06-04 03:49:33473 EXPECT_EQ("no-cache", revalidation_header);
474
475 // We set test.dat as web-accessible, so it should have a CORS header.
Chris Mumford8f812662018-02-22 00:27:57476 std::string access_control =
477 get_result.GetResponseHeaderByName("Access-Control-Allow-Origin");
[email protected]6f7d7062013-06-04 03:49:33478 EXPECT_EQ("*", access_control);
479 }
480}
481
[email protected]b109bdd2013-11-04 18:08:43482// Tests that a URL request for main frame or subframe from an extension
483// succeeds, but subresources fail. See http://crbug.com/312269.
Clark DuVallc7e3b4692019-06-13 22:07:11484TEST_F(ExtensionProtocolsTest, AllowFrameRequests) {
[email protected]b109bdd2013-11-04 18:08:43485 // Register a non-incognito extension protocol handler.
[email protected]1791e6c92014-04-11 08:29:01486 SetProtocolHandler(false);
[email protected]b109bdd2013-11-04 18:08:43487
488 scoped_refptr<Extension> extension = CreateTestExtension("foo", false);
Chris Mumford8f812662018-02-22 00:27:57489 AddExtension(extension, false, false);
[email protected]b109bdd2013-11-04 18:08:43490
nasko5cf9d452016-06-01 05:34:56491 // All MAIN_FRAME requests should succeed. SUB_FRAME requests that are not
Chris Mumford8f812662018-02-22 00:27:57492 // explicitly listed in web_accessible_resources or same-origin to the parent
nasko5cf9d452016-06-01 05:34:56493 // should not succeed.
[email protected]b109bdd2013-11-04 18:08:43494 {
Chris Mumford8f812662018-02-22 00:27:57495 auto get_result = RequestOrLoad(extension->GetResourceURL("test.dat"),
Daniel Chengaee5c0312019-04-18 23:49:05496 content::ResourceType::kMainFrame);
Chris Mumford8f812662018-02-22 00:27:57497 EXPECT_EQ(net::OK, get_result.result());
[email protected]b109bdd2013-11-04 18:08:43498 }
John Abd-El-Malek2305cdc2018-02-14 20:26:28499
500 // Subframe navigation requests are blocked in ExtensionNavigationThrottle
501 // which isn't added in this unit test. This is tested in an integration test
502 // in ExtensionResourceRequestPolicyTest.IframeNavigateToInaccessible.
[email protected]b109bdd2013-11-04 18:08:43503
504 // And subresource types, such as media, should fail.
505 {
Chris Mumford8f812662018-02-22 00:27:57506 auto get_result = RequestOrLoad(extension->GetResourceURL("test.dat"),
Daniel Chengaee5c0312019-04-18 23:49:05507 content::ResourceType::kMedia);
Chris Mumford8f812662018-02-22 00:27:57508 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, get_result.result());
[email protected]b109bdd2013-11-04 18:08:43509 }
510}
511
Clark DuVallc7e3b4692019-06-13 22:07:11512TEST_F(ExtensionProtocolsTest, MetadataFolder) {
asargenta093ec32016-02-13 01:36:43513 SetProtocolHandler(false);
514
515 base::FilePath extension_dir = GetTestPath("metadata_folder");
516 std::string error;
517 scoped_refptr<Extension> extension =
518 file_util::LoadExtension(extension_dir, Manifest::INTERNAL,
519 Extension::NO_FLAGS, &error);
520 ASSERT_NE(extension.get(), nullptr) << "error: " << error;
521
522 // Loading "/test.html" should succeed.
Chris Mumford8f812662018-02-22 00:27:57523 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, "test.html").result());
asargenta093ec32016-02-13 01:36:43524
525 // Loading "/_metadata/verified_contents.json" should fail.
526 base::FilePath relative_path =
527 base::FilePath(kMetadataFolder).Append(kVerifiedContentsFilename);
528 EXPECT_TRUE(base::PathExists(extension_dir.Append(relative_path)));
Chris Mumford8f812662018-02-22 00:27:57529 EXPECT_NE(net::OK,
530 DoRequestOrLoad(extension, relative_path.AsUTF8Unsafe()).result());
asargenta093ec32016-02-13 01:36:43531
532 // Loading "/_metadata/a.txt" should also fail.
533 relative_path = base::FilePath(kMetadataFolder).AppendASCII("a.txt");
534 EXPECT_TRUE(base::PathExists(extension_dir.Append(relative_path)));
Chris Mumford8f812662018-02-22 00:27:57535 EXPECT_NE(net::OK,
536 DoRequestOrLoad(extension, relative_path.AsUTF8Unsafe()).result());
asargenta093ec32016-02-13 01:36:43537}
538
lazyboyd6dbb262017-03-30 00:57:30539// Tests that unreadable files and deleted files correctly go through
540// ContentVerifyJob.
Clark DuVallc7e3b4692019-06-13 22:07:11541TEST_F(ExtensionProtocolsTest, VerificationSeenForFileAccessErrors) {
lazyboyd6dbb262017-03-30 00:57:30542 SetProtocolHandler(false);
543
Istiaque Ahmed72816eaa2018-01-30 22:37:06544 // Unzip extension containing verification hashes to a temporary directory.
lazyboyd6dbb262017-03-30 00:57:30545 base::ScopedTempDir temp_dir;
546 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Istiaque Ahmed72816eaa2018-01-30 22:37:06547 base::FilePath unzipped_path = temp_dir.GetPath();
548 scoped_refptr<Extension> extension =
549 content_verifier_test_utils::UnzipToDirAndLoadExtension(
550 GetContentVerifierTestPath().AppendASCII("source.zip"),
551 unzipped_path);
lazyboyd6dbb262017-03-30 00:57:30552 ASSERT_TRUE(extension.get());
Istiaque Ahmed72816eaa2018-01-30 22:37:06553 ExtensionId extension_id = extension->id();
lazyboyd6dbb262017-03-30 00:57:30554
Istiaque Ahmed72816eaa2018-01-30 22:37:06555 const std::string kJs("1024.js");
556 base::FilePath kRelativePath(FILE_PATH_LITERAL("1024.js"));
lazyboyd6dbb262017-03-30 00:57:30557
Istiaque Ahmed72816eaa2018-01-30 22:37:06558 // Valid and readable 1024.js.
559 {
Istiaque Ahmed584fe142018-03-13 09:19:04560 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
lazyboyd6dbb262017-03-30 00:57:30561
Chris Mumford8f812662018-02-22 00:27:57562 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
Istiaque Ahmed72816eaa2018-01-30 22:37:06563 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
564 content::RunAllPendingInMessageLoop();
565
Chris Mumford8f812662018-02-22 00:27:57566 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36567 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06568 }
569
570 // chmod -r 1024.js.
571 {
Istiaque Ahmed584fe142018-03-13 09:19:04572 TestContentVerifySingleJobObserver observer(extension->id(), kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06573 base::FilePath file_path = unzipped_path.AppendASCII(kJs);
574 ASSERT_TRUE(base::MakeFileUnreadable(file_path));
Chris Mumford8f812662018-02-22 00:27:57575 EXPECT_EQ(net::ERR_ACCESS_DENIED, DoRequestOrLoad(extension, kJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36576 EXPECT_EQ(ContentVerifyJob::HASH_MISMATCH, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06577 // NOTE: In production, hash mismatch would have disabled |extension|, but
578 // since UnzipToDirAndLoadExtension() doesn't add the extension to
579 // ExtensionRegistry, ChromeContentVerifierDelegate won't disable it.
580 // TODO(lazyboy): We may want to update this to more closely reflect the
581 // real flow.
582 }
583
584 // Delete 1024.js.
585 {
Istiaque Ahmed584fe142018-03-13 09:19:04586 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06587 base::FilePath file_path = unzipped_path.AppendASCII(kJs);
588 ASSERT_TRUE(base::DieFileDie(file_path, false));
Chris Mumford8f812662018-02-22 00:27:57589 EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
590 DoRequestOrLoad(extension, kJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36591 EXPECT_EQ(ContentVerifyJob::HASH_MISMATCH, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06592 }
lazyboyd6dbb262017-03-30 00:57:30593}
594
lazyboye83ab9c62017-03-30 03:18:26595// Tests that zero byte files correctly go through ContentVerifyJob.
Clark DuVallc7e3b4692019-06-13 22:07:11596TEST_F(ExtensionProtocolsTest, VerificationSeenForZeroByteFile) {
lazyboye83ab9c62017-03-30 03:18:26597 SetProtocolHandler(false);
598
Istiaque Ahmed72816eaa2018-01-30 22:37:06599 const std::string kEmptyJs("empty.js");
lazyboye83ab9c62017-03-30 03:18:26600 base::ScopedTempDir temp_dir;
601 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Istiaque Ahmed72816eaa2018-01-30 22:37:06602 base::FilePath unzipped_path = temp_dir.GetPath();
lazyboye83ab9c62017-03-30 03:18:26603
Istiaque Ahmed72816eaa2018-01-30 22:37:06604 scoped_refptr<Extension> extension =
605 content_verifier_test_utils::UnzipToDirAndLoadExtension(
606 GetContentVerifierTestPath().AppendASCII("source.zip"),
607 unzipped_path);
608 ASSERT_TRUE(extension.get());
609
610 base::FilePath kRelativePath(FILE_PATH_LITERAL("empty.js"));
611 ExtensionId extension_id = extension->id();
612
613 // Sanity check empty.js.
614 base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
lazyboye83ab9c62017-03-30 03:18:26615 int64_t foo_file_size = -1;
Istiaque Ahmed72816eaa2018-01-30 22:37:06616 ASSERT_TRUE(base::GetFileSize(file_path, &foo_file_size));
lazyboye83ab9c62017-03-30 03:18:26617 ASSERT_EQ(0, foo_file_size);
618
Istiaque Ahmed72816eaa2018-01-30 22:37:06619 // Request empty.js.
620 {
Istiaque Ahmed584fe142018-03-13 09:19:04621 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
lazyboye83ab9c62017-03-30 03:18:26622
Chris Mumford8f812662018-02-22 00:27:57623 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
Istiaque Ahmed72816eaa2018-01-30 22:37:06624 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
625 content::RunAllPendingInMessageLoop();
lazyboye83ab9c62017-03-30 03:18:26626
Chris Mumford8f812662018-02-22 00:27:57627 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kEmptyJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36628 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06629 }
630
631 // chmod -r empty.js.
632 // Unreadable empty file doesn't generate hash mismatch. Note that this is the
633 // current behavior of ContentVerifyJob.
634 // TODO(lazyboy): The behavior is probably incorrect.
635 {
Istiaque Ahmed584fe142018-03-13 09:19:04636 TestContentVerifySingleJobObserver observer(extension->id(), kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06637 base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
638 ASSERT_TRUE(base::MakeFileUnreadable(file_path));
Chris Mumford8f812662018-02-22 00:27:57639 EXPECT_EQ(net::ERR_ACCESS_DENIED,
640 DoRequestOrLoad(extension, kEmptyJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36641 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06642 }
643
644 // rm empty.js.
645 // Deleted empty file doesn't generate hash mismatch. Note that this is the
646 // current behavior of ContentVerifyJob.
647 // TODO(lazyboy): The behavior is probably incorrect.
648 {
Istiaque Ahmed584fe142018-03-13 09:19:04649 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
Istiaque Ahmed72816eaa2018-01-30 22:37:06650 base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
651 ASSERT_TRUE(base::DieFileDie(file_path, false));
Chris Mumford8f812662018-02-22 00:27:57652 EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
653 DoRequestOrLoad(extension, kEmptyJs).result());
Istiaque Ahmed1dec1d42018-02-02 00:01:36654 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
Istiaque Ahmed72816eaa2018-01-30 22:37:06655 }
lazyboye83ab9c62017-03-30 03:18:26656}
657
Clark DuVallc7e3b4692019-06-13 22:07:11658TEST_F(ExtensionProtocolsTest, VerifyScriptListedAsIcon) {
proberge4f9644c2018-03-27 23:01:54659 SetProtocolHandler(false);
660
661 const std::string kBackgroundJs("background.js");
662 base::ScopedTempDir temp_dir;
663 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
664 base::FilePath unzipped_path = temp_dir.GetPath();
665
666 base::FilePath path;
Avi Drissman9098f9002018-05-04 00:11:52667 EXPECT_TRUE(base::PathService::Get(extensions::DIR_TEST_DATA, &path));
proberge4f9644c2018-03-27 23:01:54668
669 scoped_refptr<Extension> extension =
670 content_verifier_test_utils::UnzipToDirAndLoadExtension(
671 path.AppendASCII("content_hash_fetcher")
672 .AppendASCII("manifest_mislabeled_script")
673 .AppendASCII("source.zip"),
674 unzipped_path);
675 ASSERT_TRUE(extension.get());
676
677 base::FilePath kRelativePath(FILE_PATH_LITERAL("background.js"));
678 ExtensionId extension_id = extension->id();
679
680 // Request background.js.
681 {
682 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
683
684 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
685 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
686 base::RunLoop().RunUntilIdle();
687
688 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kBackgroundJs).result());
689 EXPECT_EQ(ContentVerifyJob::NONE, observer.WaitForJobFinished());
690 }
691
692 // Modify background.js and request it.
693 {
694 base::FilePath file_path = unzipped_path.AppendASCII("background.js");
695 const std::string content = "new content";
696 EXPECT_NE(base::WriteFile(file_path, content.c_str(), content.size()), -1);
697 TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
698
699 content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
700 // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
701 base::RunLoop().RunUntilIdle();
702
703 EXPECT_EQ(net::OK, DoRequestOrLoad(extension, kBackgroundJs).result());
704 EXPECT_EQ(ContentVerifyJob::HASH_MISMATCH, observer.WaitForJobFinished());
705 }
706}
707
Devlin Croninc3f88072018-01-30 02:10:11708// Tests that mime types are properly set for returned extension resources.
Clark DuVallc7e3b4692019-06-13 22:07:11709TEST_F(ExtensionProtocolsTest, MimeTypesForKnownFiles) {
Devlin Croninc3f88072018-01-30 02:10:11710 // Register a non-incognito extension protocol handler.
711 SetProtocolHandler(false);
712
713 TestExtensionDir test_dir;
714 constexpr char kManifest[] = R"(
715 {
716 "name": "Test Ext",
717 "description": "A test extension",
718 "manifest_version": 2,
719 "version": "0.1",
720 "web_accessible_resources": ["*"]
721 })";
722 test_dir.WriteManifest(kManifest);
723 std::unique_ptr<base::DictionaryValue> manifest =
Lei Zhang9b9d5792019-02-20 07:24:42724 base::DictionaryValue::From(base::test::ParseJsonDeprecated(kManifest));
Devlin Croninc3f88072018-01-30 02:10:11725 ASSERT_TRUE(manifest);
726
727 test_dir.WriteFile(FILE_PATH_LITERAL("json_file.json"), "{}");
728 test_dir.WriteFile(FILE_PATH_LITERAL("js_file.js"), "function() {}");
729
730 base::FilePath unpacked_path = test_dir.UnpackedPath();
731 ASSERT_TRUE(base::PathExists(unpacked_path.AppendASCII("json_file.json")));
732 std::string error;
733 scoped_refptr<const Extension> extension =
734 ExtensionBuilder()
735 .SetManifest(std::move(manifest))
736 .SetPath(unpacked_path)
737 .SetLocation(Manifest::INTERNAL)
738 .Build();
739 ASSERT_TRUE(extension);
740
Chris Mumford8f812662018-02-22 00:27:57741 AddExtension(extension.get(), false, false);
Devlin Croninc3f88072018-01-30 02:10:11742
743 struct {
744 const char* file_name;
745 const char* expected_mime_type;
746 } test_cases[] = {
dstockwell00677932019-04-09 02:12:08747 {"json_file.json", "application/json"},
748 {"js_file.js", "text/javascript"},
749 {"mem_file.mem", ""},
Devlin Croninc3f88072018-01-30 02:10:11750 };
751
752 for (const auto& test_case : test_cases) {
753 SCOPED_TRACE(test_case.file_name);
Chris Mumford8f812662018-02-22 00:27:57754 auto result = RequestOrLoad(extension->GetResourceURL(test_case.file_name),
Daniel Chengaee5c0312019-04-18 23:49:05755 content::ResourceType::kSubResource);
Chris Mumford8f812662018-02-22 00:27:57756 EXPECT_EQ(
757 test_case.expected_mime_type,
758 result.GetResponseHeaderByName(net::HttpRequestHeaders::kContentType));
Devlin Croninc3f88072018-01-30 02:10:11759 }
760}
761
Kevin Marshall4cab5af2019-01-14 20:27:14762#if defined(OS_WIN)
763#define MAYBE_ExtensionRequestsNotAborted DISABLED_ExtensionRequestsNotAborted
764#else
765#define MAYBE_ExtensionRequestsNotAborted ExtensionRequestsNotAborted
766#endif
Karandeep Bhatiaab489a4d2018-11-28 21:56:06767// Tests that requests for extension resources (including the generated
768// background page) are not aborted on system suspend.
Kevin Marshall4cab5af2019-01-14 20:27:14769//
770// Flaky on Windows.
771// TODO(https://crbug.com/921687): Investigate and fix.
Clark DuVallc7e3b4692019-06-13 22:07:11772TEST_F(ExtensionProtocolsTest, MAYBE_ExtensionRequestsNotAborted) {
Karandeep Bhatiaab489a4d2018-11-28 21:56:06773 // Register a non-incognito extension protocol handler.
774 SetProtocolHandler(false);
775
776 base::FilePath extension_dir =
777 GetTestPath("common").AppendASCII("background_script");
778 std::string error;
779 scoped_refptr<Extension> extension = file_util::LoadExtension(
780 extension_dir, Manifest::INTERNAL, Extension::NO_FLAGS, &error);
781 ASSERT_TRUE(extension.get()) << error;
782
783 SimulateSystemSuspendForRequests();
784
785 // Request the generated background page. Ensure the request completes
786 // successfully.
787 EXPECT_EQ(net::OK,
788 DoRequestOrLoad(extension.get(), kGeneratedBackgroundPageFilename)
789 .result());
790
791 // Request the background.js file. Ensure the request completes successfully.
792 EXPECT_EQ(net::OK, DoRequestOrLoad(extension.get(), "background.js").result());
793}
794
[email protected]702d8b42013-02-27 20:55:50795} // namespace extensions