1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/files/file_path.h"
6 #include "base/strings/stringprintf.h"
7 #include "chrome/browser/extensions/extension_apitest.h"
8 #include "chrome/browser/extensions/test_extension_dir.h"
9 #include "chrome/browser/ui/tabs/tab_strip_model.h"
10 #include "chrome/test/base/ui_test_utils.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/test/browser_test_utils.h"
13 #include "extensions/common/extension.h"
14 #include "net/dns/mock_host_resolver.h"
15 #include "net/test/embedded_test_server/embedded_test_server.h"
17 namespace extensions
{
21 // JavaScript snippet which performs a fetch given a URL expression to be
22 // substituted as %s, then sends back the fetched content using the
23 // domAutomationController.
24 const char* kFetchScript
=
25 "fetch(%s).then(function(result) {\n"
26 " return result.text();\n"
27 "}).then(function(text) {\n"
28 " window.domAutomationController.send(text);\n"
29 "}).catch(function(err) {\n"
30 " window.domAutomationController.send(String(err));\n"
33 class ExtensionFetchTest
: public ExtensionApiTest
{
35 // Writes an empty background page and a text file called "text" with content
36 // "text content", then loads and returns the extension. |dir| must already
38 const Extension
* WriteFilesAndLoadTestExtension(TestExtensionDir
* dir
) {
39 dir
->WriteFile(FILE_PATH_LITERAL("text"), "text content");
40 dir
->WriteFile(FILE_PATH_LITERAL("bg.js"), "");
41 return LoadExtension(dir
->unpacked_path());
44 // Returns |kFetchScript| with |url_expression| substituted as its test URL.
45 std::string
GetFetchScript(const std::string
& url_expression
) {
46 return base::StringPrintf(kFetchScript
, url_expression
.c_str());
49 // Returns |url| as a string surrounded by single quotes, for passing to
50 // JavaScript as a string literal.
51 std::string
GetQuotedURL(const GURL
& url
) {
52 return base::StringPrintf("'%s'", url
.spec().c_str());
55 // Like GetQuotedURL(), but fetching the URL from the test server's |host|
57 std::string
GetQuotedTestServerURL(const std::string
& host
,
58 const std::string
& path
) {
59 return GetQuotedURL(embedded_test_server()->GetURL(host
, path
));
62 // Opens a tab, puts it in the foreground, navigates it to |url| then returns
64 content::WebContents
* CreateAndNavigateTab(const GURL
& url
) {
65 chrome::NavigateParams
params(browser(), url
, ui::PAGE_TRANSITION_LINK
);
66 params
.disposition
= NEW_FOREGROUND_TAB
;
67 ui_test_utils::NavigateToURL(¶ms
);
68 return browser()->tab_strip_model()->GetActiveWebContents();
72 void SetUpOnMainThread() override
{
73 ExtensionApiTest::SetUpOnMainThread();
74 host_resolver()->AddRule("*", "127.0.0.1");
75 ASSERT_TRUE(StartEmbeddedTestServer());
79 IN_PROC_BROWSER_TEST_F(ExtensionFetchTest
, ExtensionCanFetchExtensionResource
) {
81 dir
.WriteManifestWithSingleQuotes(
83 "'background': {'scripts': ['bg.js']},"
84 "'manifest_version': 2,"
85 "'name': 'ExtensionCanFetchExtensionResource',"
88 const Extension
* extension
= WriteFilesAndLoadTestExtension(&dir
);
89 ASSERT_TRUE(extension
);
93 ExecuteScriptInBackgroundPage(
94 extension
->id(), GetFetchScript("chrome.runtime.getURL('text')")));
97 IN_PROC_BROWSER_TEST_F(ExtensionFetchTest
,
98 ExtensionCanFetchHostedResourceWithHostPermissions
) {
100 dir
.WriteManifestWithSingleQuotes(
102 "'background': {'scripts': ['bg.js']},"
103 "'manifest_version': 2,"
104 "'name': 'ExtensionCanFetchHostedResourceWithHostPermissions',"
105 "'permissions': ['http://example.com/*'],"
108 const Extension
* extension
= WriteFilesAndLoadTestExtension(&dir
);
109 ASSERT_TRUE(extension
);
111 EXPECT_EQ("Hello!", ExecuteScriptInBackgroundPage(
113 GetFetchScript(GetQuotedTestServerURL(
114 "example.com", "/extensions/test_file.txt"))));
117 IN_PROC_BROWSER_TEST_F(
119 ExtensionCannotFetchHostedResourceWithoutHostPermissions
) {
120 TestExtensionDir dir
;
121 dir
.WriteManifestWithSingleQuotes(
123 "'background': {'scripts': ['bg.js']},"
124 "'manifest_version': 2,"
125 "'name': 'ExtensionCannotFetchHostedResourceWithoutHostPermissions',"
128 const Extension
* extension
= WriteFilesAndLoadTestExtension(&dir
);
129 ASSERT_TRUE(extension
);
131 // TODO(kalman): Another test would be to configure the test server to work
132 // with CORS, and test that the fetch succeeds.
134 "TypeError: Failed to fetch",
135 ExecuteScriptInBackgroundPage(
136 extension
->id(), GetFetchScript(GetQuotedTestServerURL(
137 "example.com", "/extensions/test_file.txt"))));
140 IN_PROC_BROWSER_TEST_F(ExtensionFetchTest
,
141 HostCanFetchWebAccessibleExtensionResource
) {
142 TestExtensionDir dir
;
143 dir
.WriteManifestWithSingleQuotes(
145 "'background': {'scripts': ['bg.js']},"
146 "'manifest_version': 2,"
147 "'name': 'HostCanFetchWebAccessibleExtensionResource',"
149 "'web_accessible_resources': ['text']"
151 const Extension
* extension
= WriteFilesAndLoadTestExtension(&dir
);
152 ASSERT_TRUE(extension
);
154 content::WebContents
* empty_tab
= CreateAndNavigateTab(
155 embedded_test_server()->GetURL("example.com", "/empty.html"));
157 // TODO(kalman): Test this from a content script too.
158 std::string fetch_result
;
159 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
161 GetFetchScript(GetQuotedURL(extension
->GetResourceURL("text"))),
163 EXPECT_EQ("text content", fetch_result
);
166 IN_PROC_BROWSER_TEST_F(ExtensionFetchTest
,
167 HostCannotFetchNonWebAccessibleExtensionResource
) {
168 TestExtensionDir dir
;
169 dir
.WriteManifestWithSingleQuotes(
171 "'background': {'scripts': ['bg.js']},"
172 "'manifest_version': 2,"
173 "'name': 'HostCannotFetchNonWebAccessibleExtensionResource',"
176 const Extension
* extension
= WriteFilesAndLoadTestExtension(&dir
);
177 ASSERT_TRUE(extension
);
179 content::WebContents
* empty_tab
= CreateAndNavigateTab(
180 embedded_test_server()->GetURL("example.com", "/empty.html"));
182 // TODO(kalman): Test this from a content script too.
183 std::string fetch_result
;
184 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
186 GetFetchScript(GetQuotedURL(extension
->GetResourceURL("text"))),
188 EXPECT_EQ("TypeError: Failed to fetch", fetch_result
);
193 } // namespace extensions