1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <vector>
6
7#include "base/command_line.h"
8#include "base/memory/ref_counted.h"
9#include "base/strings/string16.h"
10#include "base/strings/utf_string_conversions.h"
11#include "chrome/common/extensions/extension_test_util.h"
12#include "components/crx_file/id_util.h"
13#include "content/public/common/socket_permission_request.h"
14#include "extensions/common/error_utils.h"
15#include "extensions/common/extension.h"
16#include "extensions/common/extension_builder.h"
17#include "extensions/common/manifest.h"
18#include "extensions/common/manifest_constants.h"
19#include "extensions/common/permissions/api_permission.h"
20#include "extensions/common/permissions/permission_set.h"
21#include "extensions/common/permissions/permissions_data.h"
22#include "extensions/common/permissions/socket_permission.h"
23#include "extensions/common/switches.h"
24#include "extensions/common/url_pattern_set.h"
25#include "extensions/common/value_builder.h"
26#include "testing/gtest/include/gtest/gtest.h"
27#include "url/gurl.h"
28
29using base::UTF16ToUTF8;
30using content::SocketPermissionRequest;
31using extension_test_util::LoadManifest;
32using extension_test_util::LoadManifestUnchecked;
33using extension_test_util::LoadManifestStrict;
34
35namespace extensions {
36
37namespace {
38
39const char kAllHostsPermission[] = "*://*/*";
40
41bool CheckSocketPermission(
42    scoped_refptr<Extension> extension,
43    SocketPermissionRequest::OperationType type,
44    const char* host,
45    int port) {
46  SocketPermission::CheckParam param(type, host, port);
47  return extension->permissions_data()->CheckAPIPermissionWithParam(
48      APIPermission::kSocket, &param);
49}
50
51// Creates and returns an extension with the given |id|, |host_permissions|, and
52// manifest |location|.
53scoped_refptr<const Extension> GetExtensionWithHostPermission(
54    const std::string& id,
55    const std::string& host_permissions,
56    Manifest::Location location) {
57  ListBuilder permissions;
58  if (!host_permissions.empty())
59    permissions.Append(host_permissions);
60
61  return ExtensionBuilder()
62      .SetManifest(
63          DictionaryBuilder()
64              .Set("name", id)
65              .Set("description", "an extension")
66              .Set("manifest_version", 2)
67              .Set("version", "1.0.0")
68              .Set("permissions", permissions.Pass())
69              .Build())
70      .SetLocation(location)
71      .SetID(id)
72      .Build();
73}
74
75// Checks that urls are properly restricted for the given extension.
76void CheckRestrictedUrls(const Extension* extension,
77                         bool block_chrome_urls) {
78  // We log the name so we know _which_ extension failed here.
79  const std::string& name = extension->name();
80  const GURL chrome_settings_url("chrome://settings/");
81  const GURL chrome_extension_url("chrome-extension://foo/bar.html");
82  const GURL google_url("https://www.google.com/");
83  const GURL self_url("chrome-extension://" + extension->id() + "/foo.html");
84  const GURL invalid_url("chrome-debugger://foo/bar.html");
85
86  std::string error;
87  EXPECT_EQ(block_chrome_urls,
88            PermissionsData::IsRestrictedUrl(
89                chrome_settings_url,
90                chrome_settings_url,
91                extension,
92                &error)) << name;
93  if (block_chrome_urls)
94    EXPECT_EQ(manifest_errors::kCannotAccessChromeUrl, error) << name;
95  else
96    EXPECT_TRUE(error.empty()) << name;
97
98  error.clear();
99  EXPECT_EQ(block_chrome_urls,
100            PermissionsData::IsRestrictedUrl(
101                chrome_extension_url,
102                chrome_extension_url,
103                extension,
104                &error)) << name;
105  if (block_chrome_urls)
106    EXPECT_EQ(manifest_errors::kCannotAccessExtensionUrl, error) << name;
107  else
108    EXPECT_TRUE(error.empty()) << name;
109
110  // Google should never be a restricted url.
111  error.clear();
112  EXPECT_FALSE(PermissionsData::IsRestrictedUrl(
113      google_url, google_url, extension, &error)) << name;
114  EXPECT_TRUE(error.empty()) << name;
115
116  // We should always be able to access our own extension pages.
117  error.clear();
118  EXPECT_FALSE(PermissionsData::IsRestrictedUrl(
119      self_url, self_url, extension, &error)) << name;
120  EXPECT_TRUE(error.empty()) << name;
121
122  // We should only allow other schemes for extensions when it's a whitelisted
123  // extension.
124  error.clear();
125  bool allow_on_other_schemes =
126      PermissionsData::CanExecuteScriptEverywhere(extension);
127  EXPECT_EQ(!allow_on_other_schemes,
128            PermissionsData::IsRestrictedUrl(
129                invalid_url, invalid_url, extension, &error)) << name;
130  if (!allow_on_other_schemes) {
131    EXPECT_EQ(ErrorUtils::FormatErrorMessage(
132                  manifest_errors::kCannotAccessPage,
133                  invalid_url.spec()),
134              error) << name;
135  } else {
136    EXPECT_TRUE(error.empty());
137  }
138}
139
140}  // namespace
141
142// NOTE: These tests run in Chrome's unit_tests suite because they depend on
143// extension manifest keys (like "content_scripts") that do not exist yet in the
144// src/extensions module.
145TEST(PermissionsDataTest, EffectiveHostPermissions) {
146  scoped_refptr<Extension> extension;
147  URLPatternSet hosts;
148
149  extension = LoadManifest("effective_host_permissions", "empty.json");
150  EXPECT_EQ(0u,
151            extension->permissions_data()
152                ->GetEffectiveHostPermissions()
153                .patterns()
154                .size());
155  EXPECT_FALSE(hosts.MatchesURL(GURL("http://www.google.com")));
156  EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
157
158  extension = LoadManifest("effective_host_permissions", "one_host.json");
159  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
160  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
161  EXPECT_FALSE(hosts.MatchesURL(GURL("https://www.google.com")));
162  EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
163
164  extension = LoadManifest("effective_host_permissions",
165                           "one_host_wildcard.json");
166  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
167  EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
168  EXPECT_TRUE(hosts.MatchesURL(GURL("http://foo.google.com")));
169  EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
170
171  extension = LoadManifest("effective_host_permissions", "two_hosts.json");
172  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
173  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
174  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com")));
175  EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
176
177  extension = LoadManifest("effective_host_permissions",
178                           "https_not_considered.json");
179  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
180  EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
181  EXPECT_TRUE(hosts.MatchesURL(GURL("https://google.com")));
182  EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
183
184  extension = LoadManifest("effective_host_permissions",
185                           "two_content_scripts.json");
186  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
187  EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
188  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com")));
189  EXPECT_TRUE(extension->permissions_data()
190                  ->active_permissions()
191                  ->HasEffectiveAccessToURL(GURL("http://www.reddit.com")));
192  EXPECT_TRUE(hosts.MatchesURL(GURL("http://news.ycombinator.com")));
193  EXPECT_TRUE(
194      extension->permissions_data()
195          ->active_permissions()
196          ->HasEffectiveAccessToURL(GURL("http://news.ycombinator.com")));
197  EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
198
199  extension = LoadManifest("effective_host_permissions", "all_hosts.json");
200  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
201  EXPECT_TRUE(hosts.MatchesURL(GURL("http://test/")));
202  EXPECT_FALSE(hosts.MatchesURL(GURL("https://test/")));
203  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
204  EXPECT_TRUE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
205
206  extension = LoadManifest("effective_host_permissions", "all_hosts2.json");
207  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
208  EXPECT_TRUE(hosts.MatchesURL(GURL("http://test/")));
209  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
210  EXPECT_TRUE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
211
212  extension = LoadManifest("effective_host_permissions", "all_hosts3.json");
213  hosts = extension->permissions_data()->GetEffectiveHostPermissions();
214  EXPECT_FALSE(hosts.MatchesURL(GURL("http://test/")));
215  EXPECT_TRUE(hosts.MatchesURL(GURL("https://test/")));
216  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
217  EXPECT_TRUE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
218}
219
220TEST(PermissionsDataTest, SocketPermissions) {
221  scoped_refptr<Extension> extension;
222  std::string error;
223
224  extension = LoadManifest("socket_permissions", "empty.json");
225  EXPECT_FALSE(CheckSocketPermission(extension,
226      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
227
228  extension = LoadManifestUnchecked("socket_permissions",
229                                    "socket1.json",
230                                    Manifest::INTERNAL, Extension::NO_FLAGS,
231                                    &error);
232  EXPECT_TRUE(extension.get() == NULL);
233  std::string expected_error_msg_header = ErrorUtils::FormatErrorMessage(
234      manifest_errors::kInvalidPermissionWithDetail,
235      "socket",
236      "NULL or empty permission list");
237  EXPECT_EQ(expected_error_msg_header, error);
238
239  extension = LoadManifest("socket_permissions", "socket2.json");
240  EXPECT_TRUE(CheckSocketPermission(extension,
241      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
242  EXPECT_FALSE(CheckSocketPermission(
243        extension, SocketPermissionRequest::UDP_BIND, "", 80));
244  EXPECT_TRUE(CheckSocketPermission(
245        extension, SocketPermissionRequest::UDP_BIND, "", 8888));
246
247  EXPECT_FALSE(CheckSocketPermission(
248        extension, SocketPermissionRequest::UDP_SEND_TO, "example.com", 1900));
249  EXPECT_TRUE(CheckSocketPermission(
250        extension,
251        SocketPermissionRequest::UDP_SEND_TO,
252        "239.255.255.250", 1900));
253}
254
255TEST(PermissionsDataTest, IsRestrictedUrl) {
256  scoped_refptr<const Extension> extension =
257      GetExtensionWithHostPermission("normal_extension",
258                                     kAllHostsPermission,
259                                     Manifest::INTERNAL);
260  // Chrome urls should be blocked for normal extensions.
261  CheckRestrictedUrls(extension.get(), true);
262
263  scoped_refptr<const Extension> component =
264      GetExtensionWithHostPermission("component",
265                                     kAllHostsPermission,
266                                     Manifest::COMPONENT);
267  // Chrome urls should be accessible by component extensions.
268  CheckRestrictedUrls(component.get(), false);
269
270  base::CommandLine::ForCurrentProcess()->AppendSwitch(
271      switches::kExtensionsOnChromeURLs);
272  // Enabling the switch should allow all extensions to access chrome urls.
273  CheckRestrictedUrls(extension.get(), false);
274}
275
276TEST(PermissionsDataTest, GetPermissionMessages_ManyAPIPermissions) {
277  scoped_refptr<Extension> extension;
278  extension = LoadManifest("permissions", "many-apis.json");
279  std::vector<base::string16> warnings =
280      extension->permissions_data()->GetPermissionMessageStrings();
281  // Warning for "tabs" is suppressed by "history" permission.
282  ASSERT_EQ(5u, warnings.size());
283  EXPECT_EQ("Read and change your data on api.flickr.com",
284            UTF16ToUTF8(warnings[0]));
285  EXPECT_EQ("Read and change your bookmarks", UTF16ToUTF8(warnings[1]));
286  EXPECT_EQ("Detect your physical location", UTF16ToUTF8(warnings[2]));
287  EXPECT_EQ("Read and change your browsing history", UTF16ToUTF8(warnings[3]));
288  EXPECT_EQ("Manage your apps, extensions, and themes",
289            UTF16ToUTF8(warnings[4]));
290}
291
292TEST(PermissionsDataTest, GetPermissionMessages_ManyHostsPermissions) {
293  scoped_refptr<Extension> extension;
294  extension = LoadManifest("permissions", "more-than-3-hosts.json");
295  std::vector<base::string16> warnings =
296      extension->permissions_data()->GetPermissionMessageStrings();
297  std::vector<base::string16> warnings_details =
298      extension->permissions_data()->GetPermissionMessageDetailsStrings();
299  ASSERT_EQ(1u, warnings.size());
300  ASSERT_EQ(1u, warnings_details.size());
301  EXPECT_EQ("Read and change your data on a number of websites",
302            UTF16ToUTF8(warnings[0]));
303  EXPECT_EQ("- www.a.com\n- www.b.com\n- www.c.com\n- www.d.com\n- www.e.com",
304            UTF16ToUTF8(warnings_details[0]));
305}
306
307TEST(PermissionsDataTest, GetPermissionMessages_LocationApiPermission) {
308  scoped_refptr<Extension> extension;
309  extension = LoadManifest("permissions",
310                           "location-api.json",
311                           Manifest::COMPONENT,
312                           Extension::NO_FLAGS);
313  std::vector<base::string16> warnings =
314      extension->permissions_data()->GetPermissionMessageStrings();
315  ASSERT_EQ(1u, warnings.size());
316  EXPECT_EQ("Detect your physical location", UTF16ToUTF8(warnings[0]));
317}
318
319TEST(PermissionsDataTest, GetPermissionMessages_ManyHosts) {
320  scoped_refptr<Extension> extension;
321  extension = LoadManifest("permissions", "many-hosts.json");
322  std::vector<base::string16> warnings =
323      extension->permissions_data()->GetPermissionMessageStrings();
324  ASSERT_EQ(1u, warnings.size());
325  EXPECT_EQ(
326      "Read and change your data on encrypted.google.com and www.google.com",
327      UTF16ToUTF8(warnings[0]));
328}
329
330TEST(PermissionsDataTest, GetPermissionMessages_Plugins) {
331  scoped_refptr<Extension> extension;
332  extension = LoadManifest("permissions", "plugins.json");
333  std::vector<base::string16> warnings =
334      extension->permissions_data()->GetPermissionMessageStrings();
335// We don't parse the plugins key on Chrome OS, so it should not ask for any
336// permissions.
337#if defined(OS_CHROMEOS)
338  ASSERT_EQ(0u, warnings.size());
339#else
340  ASSERT_EQ(1u, warnings.size());
341  EXPECT_EQ(
342      "Read and change all your data on your computer and the websites you "
343      "visit",
344      UTF16ToUTF8(warnings[0]));
345#endif
346}
347
348// Base class for testing the CanAccessPage and CanCaptureVisiblePage
349// methods of Extension for extensions with various permissions.
350class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
351 protected:
352  ExtensionScriptAndCaptureVisibleTest()
353      : http_url("http://www.google.com"),
354        http_url_with_path("http://www.google.com/index.html"),
355        https_url("https://www.google.com"),
356        file_url("file:///foo/bar"),
357        favicon_url("chrome://favicon/http://www.google.com"),
358        extension_url("chrome-extension://" +
359                      crx_file::id_util::GenerateIdForPath(
360                          base::FilePath(FILE_PATH_LITERAL("foo")))),
361        settings_url("chrome://settings"),
362        about_url("about:flags") {
363    urls_.insert(http_url);
364    urls_.insert(http_url_with_path);
365    urls_.insert(https_url);
366    urls_.insert(file_url);
367    urls_.insert(favicon_url);
368    urls_.insert(extension_url);
369    urls_.insert(settings_url);
370    urls_.insert(about_url);
371    // Ignore the policy delegate for this test.
372    PermissionsData::SetPolicyDelegate(NULL);
373  }
374
375  bool AllowedScript(const Extension* extension, const GURL& url,
376                     const GURL& top_url) {
377    return AllowedScript(extension, url, top_url, -1);
378  }
379
380  bool AllowedScript(const Extension* extension, const GURL& url,
381                     const GURL& top_url, int tab_id) {
382    return extension->permissions_data()->CanAccessPage(
383        extension, url, top_url, tab_id, -1, NULL);
384  }
385
386  bool BlockedScript(const Extension* extension, const GURL& url,
387                     const GURL& top_url) {
388    return !extension->permissions_data()->CanAccessPage(
389        extension, url, top_url, -1, -1, NULL);
390  }
391
392  bool Allowed(const Extension* extension, const GURL& url) {
393    return Allowed(extension, url, -1);
394  }
395
396  bool Allowed(const Extension* extension, const GURL& url, int tab_id) {
397    return (extension->permissions_data()->CanAccessPage(
398                extension, url, url, tab_id, -1, NULL) &&
399            extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL));
400  }
401
402  bool CaptureOnly(const Extension* extension, const GURL& url) {
403    return CaptureOnly(extension, url, -1);
404  }
405
406  bool CaptureOnly(const Extension* extension, const GURL& url, int tab_id) {
407    return !extension->permissions_data()->CanAccessPage(
408               extension, url, url, tab_id, -1, NULL) &&
409           extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL);
410  }
411
412  bool ScriptOnly(const Extension* extension, const GURL& url,
413                  const GURL& top_url) {
414    return ScriptOnly(extension, url, top_url, -1);
415  }
416
417  bool ScriptOnly(const Extension* extension, const GURL& url,
418                  const GURL& top_url, int tab_id) {
419    return AllowedScript(extension, url, top_url, tab_id) &&
420           !extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL);
421  }
422
423  bool Blocked(const Extension* extension, const GURL& url) {
424    return Blocked(extension, url, -1);
425  }
426
427  bool Blocked(const Extension* extension, const GURL& url, int tab_id) {
428    return !(extension->permissions_data()->CanAccessPage(
429                 extension, url, url, tab_id, -1, NULL) ||
430             extension->permissions_data()->CanCaptureVisiblePage(tab_id,
431                                                                  NULL));
432  }
433
434  bool ScriptAllowedExclusivelyOnTab(
435      const Extension* extension,
436      const std::set<GURL>& allowed_urls,
437      int tab_id) {
438    bool result = true;
439    for (std::set<GURL>::iterator it = urls_.begin(); it != urls_.end(); ++it) {
440      const GURL& url = *it;
441      if (allowed_urls.count(url))
442        result &= AllowedScript(extension, url, url, tab_id);
443      else
444        result &= Blocked(extension, url, tab_id);
445    }
446    return result;
447  }
448
449  // URLs that are "safe" to provide scripting and capture visible tab access
450  // to if the permissions allow it.
451  const GURL http_url;
452  const GURL http_url_with_path;
453  const GURL https_url;
454  const GURL file_url;
455
456  // We should allow host permission but not scripting permission for favicon
457  // urls.
458  const GURL favicon_url;
459
460  // URLs that regular extensions should never get access to.
461  const GURL extension_url;
462  const GURL settings_url;
463  const GURL about_url;
464
465 private:
466  // The set of all URLs above.
467  std::set<GURL> urls_;
468};
469
470TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
471  // Test <all_urls> for regular extensions.
472  scoped_refptr<Extension> extension = LoadManifestStrict("script_and_capture",
473      "extension_regular_all.json");
474
475  EXPECT_TRUE(Allowed(extension.get(), http_url));
476  EXPECT_TRUE(Allowed(extension.get(), https_url));
477  EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
478  EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
479  EXPECT_TRUE(CaptureOnly(extension.get(), favicon_url));
480  EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
481  EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
482
483  // Test access to iframed content.
484  GURL within_extension_url = extension->GetResourceURL("page.html");
485  EXPECT_TRUE(AllowedScript(extension.get(), http_url, http_url_with_path));
486  EXPECT_TRUE(AllowedScript(extension.get(), https_url, http_url_with_path));
487  EXPECT_TRUE(AllowedScript(extension.get(), http_url, within_extension_url));
488  EXPECT_TRUE(AllowedScript(extension.get(), https_url, within_extension_url));
489  EXPECT_TRUE(BlockedScript(extension.get(), http_url, extension_url));
490  EXPECT_TRUE(BlockedScript(extension.get(), https_url, extension_url));
491
492  EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
493  EXPECT_FALSE(extension->permissions_data()->HasHostPermission(about_url));
494  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
495
496  // Test * for scheme, which implies just the http/https schemes.
497  extension = LoadManifestStrict("script_and_capture",
498      "extension_wildcard.json");
499  EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
500  EXPECT_TRUE(ScriptOnly(extension.get(), https_url, https_url));
501  EXPECT_TRUE(Blocked(extension.get(), settings_url));
502  EXPECT_TRUE(Blocked(extension.get(), about_url));
503  EXPECT_TRUE(Blocked(extension.get(), file_url));
504  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
505  extension =
506      LoadManifest("script_and_capture", "extension_wildcard_settings.json");
507  EXPECT_TRUE(Blocked(extension.get(), settings_url));
508
509  // Having chrome://*/ should not work for regular extensions. Note that
510  // for favicon access, we require the explicit pattern chrome://favicon/*.
511  std::string error;
512  extension = LoadManifestUnchecked("script_and_capture",
513                                    "extension_wildcard_chrome.json",
514                                    Manifest::INTERNAL, Extension::NO_FLAGS,
515                                    &error);
516  std::vector<InstallWarning> warnings = extension->install_warnings();
517  EXPECT_FALSE(warnings.empty());
518  EXPECT_EQ(ErrorUtils::FormatErrorMessage(
519                manifest_errors::kInvalidPermissionScheme,
520                "chrome://*/"),
521            warnings[0].message);
522  EXPECT_TRUE(Blocked(extension.get(), settings_url));
523  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
524  EXPECT_TRUE(Blocked(extension.get(), about_url));
525
526  // Having chrome://favicon/* should not give you chrome://*
527  extension = LoadManifestStrict("script_and_capture",
528      "extension_chrome_favicon_wildcard.json");
529  EXPECT_TRUE(Blocked(extension.get(), settings_url));
530  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
531  EXPECT_TRUE(Blocked(extension.get(), about_url));
532  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
533
534  // Having http://favicon should not give you chrome://favicon
535  extension = LoadManifestStrict("script_and_capture",
536      "extension_http_favicon.json");
537  EXPECT_TRUE(Blocked(extension.get(), settings_url));
538  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
539
540  // Component extensions with <all_urls> should get everything.
541  extension = LoadManifest("script_and_capture", "extension_component_all.json",
542      Manifest::COMPONENT, Extension::NO_FLAGS);
543  EXPECT_TRUE(Allowed(extension.get(), http_url));
544  EXPECT_TRUE(Allowed(extension.get(), https_url));
545  EXPECT_TRUE(Allowed(extension.get(), settings_url));
546  EXPECT_TRUE(Allowed(extension.get(), about_url));
547  EXPECT_TRUE(Allowed(extension.get(), favicon_url));
548  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
549
550  // Component extensions should only get access to what they ask for.
551  extension = LoadManifest("script_and_capture",
552      "extension_component_google.json", Manifest::COMPONENT,
553      Extension::NO_FLAGS);
554  EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
555  EXPECT_TRUE(Blocked(extension.get(), https_url));
556  EXPECT_TRUE(Blocked(extension.get(), file_url));
557  EXPECT_TRUE(Blocked(extension.get(), settings_url));
558  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
559  EXPECT_TRUE(Blocked(extension.get(), about_url));
560  EXPECT_TRUE(Blocked(extension.get(), extension_url));
561  EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
562}
563
564TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
565  CommandLine::ForCurrentProcess()->AppendSwitch(
566      switches::kExtensionsOnChromeURLs);
567
568  scoped_refptr<Extension> extension;
569
570  // Test <all_urls> for regular extensions.
571  extension = LoadManifestStrict("script_and_capture",
572      "extension_regular_all.json");
573  EXPECT_TRUE(Allowed(extension.get(), http_url));
574  EXPECT_TRUE(Allowed(extension.get(), https_url));
575  EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
576  EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
577  EXPECT_TRUE(Allowed(extension.get(), favicon_url));  // chrome:// requested
578  EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
579  EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
580
581  // Test access to iframed content.
582  GURL within_extension_url = extension->GetResourceURL("page.html");
583  EXPECT_TRUE(AllowedScript(extension.get(), http_url, http_url_with_path));
584  EXPECT_TRUE(AllowedScript(extension.get(), https_url, http_url_with_path));
585  EXPECT_TRUE(AllowedScript(extension.get(), http_url, within_extension_url));
586  EXPECT_TRUE(AllowedScript(extension.get(), https_url, within_extension_url));
587  EXPECT_TRUE(AllowedScript(extension.get(), http_url, extension_url));
588  EXPECT_TRUE(AllowedScript(extension.get(), https_url, extension_url));
589
590  const PermissionsData* permissions_data = extension->permissions_data();
591  EXPECT_FALSE(permissions_data->HasHostPermission(settings_url));
592  EXPECT_FALSE(permissions_data->HasHostPermission(about_url));
593  EXPECT_TRUE(permissions_data->HasHostPermission(favicon_url));
594
595  // Test * for scheme, which implies just the http/https schemes.
596  extension = LoadManifestStrict("script_and_capture",
597      "extension_wildcard.json");
598  EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
599  EXPECT_TRUE(ScriptOnly(extension.get(), https_url, https_url));
600  EXPECT_TRUE(Blocked(extension.get(), settings_url));
601  EXPECT_TRUE(Blocked(extension.get(), about_url));
602  EXPECT_TRUE(Blocked(extension.get(), file_url));
603  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
604  extension =
605      LoadManifest("script_and_capture", "extension_wildcard_settings.json");
606  EXPECT_TRUE(Blocked(extension.get(), settings_url));
607
608  // Having chrome://*/ should work for regular extensions with the flag
609  // enabled.
610  std::string error;
611  extension = LoadManifestUnchecked("script_and_capture",
612                                    "extension_wildcard_chrome.json",
613                                    Manifest::INTERNAL, Extension::NO_FLAGS,
614                                    &error);
615  EXPECT_FALSE(extension.get() == NULL);
616  EXPECT_TRUE(Blocked(extension.get(), http_url));
617  EXPECT_TRUE(Blocked(extension.get(), https_url));
618  EXPECT_TRUE(ScriptOnly(extension.get(), settings_url, settings_url));
619  EXPECT_TRUE(Blocked(extension.get(), about_url));
620  EXPECT_TRUE(Blocked(extension.get(), file_url));
621  EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url, favicon_url));
622
623  // Having chrome://favicon/* should not give you chrome://*
624  extension = LoadManifestStrict("script_and_capture",
625      "extension_chrome_favicon_wildcard.json");
626  EXPECT_TRUE(Blocked(extension.get(), settings_url));
627  EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url, favicon_url));
628  EXPECT_TRUE(Blocked(extension.get(), about_url));
629  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
630
631  // Having http://favicon should not give you chrome://favicon
632  extension = LoadManifestStrict("script_and_capture",
633      "extension_http_favicon.json");
634  EXPECT_TRUE(Blocked(extension.get(), settings_url));
635  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
636
637  // Component extensions with <all_urls> should get everything.
638  extension = LoadManifest("script_and_capture", "extension_component_all.json",
639      Manifest::COMPONENT, Extension::NO_FLAGS);
640  EXPECT_TRUE(Allowed(extension.get(), http_url));
641  EXPECT_TRUE(Allowed(extension.get(), https_url));
642  EXPECT_TRUE(Allowed(extension.get(), settings_url));
643  EXPECT_TRUE(Allowed(extension.get(), about_url));
644  EXPECT_TRUE(Allowed(extension.get(), favicon_url));
645  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
646
647  // Component extensions should only get access to what they ask for.
648  extension = LoadManifest("script_and_capture",
649      "extension_component_google.json", Manifest::COMPONENT,
650      Extension::NO_FLAGS);
651  EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
652  EXPECT_TRUE(Blocked(extension.get(), https_url));
653  EXPECT_TRUE(Blocked(extension.get(), file_url));
654  EXPECT_TRUE(Blocked(extension.get(), settings_url));
655  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
656  EXPECT_TRUE(Blocked(extension.get(), about_url));
657  EXPECT_TRUE(Blocked(extension.get(), extension_url));
658  EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
659}
660
661TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) {
662  scoped_refptr<Extension> extension =
663      LoadManifestStrict("script_and_capture", "tab_specific.json");
664
665  const PermissionsData* permissions_data = extension->permissions_data();
666  EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(0).get());
667  EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(1).get());
668  EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(2).get());
669
670  std::set<GURL> no_urls;
671
672  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
673  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
674  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
675
676  URLPatternSet allowed_hosts;
677  allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL,
678                                      http_url.spec()));
679  std::set<GURL> allowed_urls;
680  allowed_urls.insert(http_url);
681  // http_url_with_path() will also be allowed, because Extension should be
682  // considering the security origin of the URL not the URL itself, and
683  // http_url is in allowed_hosts.
684  allowed_urls.insert(http_url_with_path);
685
686  {
687    scoped_refptr<PermissionSet> permissions(
688        new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
689                          allowed_hosts, URLPatternSet()));
690    permissions_data->UpdateTabSpecificPermissions(0, permissions);
691    EXPECT_EQ(permissions->explicit_hosts(),
692              permissions_data->GetTabSpecificPermissionsForTesting(0)
693                  ->explicit_hosts());
694  }
695
696  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), allowed_urls, 0));
697  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
698  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
699
700  permissions_data->ClearTabSpecificPermissions(0);
701  EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(0).get());
702
703  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
704  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
705  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
706
707  std::set<GURL> more_allowed_urls = allowed_urls;
708  more_allowed_urls.insert(https_url);
709  URLPatternSet more_allowed_hosts = allowed_hosts;
710  more_allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL,
711                                           https_url.spec()));
712
713  {
714    scoped_refptr<PermissionSet> permissions(
715        new PermissionSet(APIPermissionSet(),  ManifestPermissionSet(),
716                          allowed_hosts, URLPatternSet()));
717    permissions_data->UpdateTabSpecificPermissions(0, permissions);
718    EXPECT_EQ(permissions->explicit_hosts(),
719              permissions_data->GetTabSpecificPermissionsForTesting(0)
720                  ->explicit_hosts());
721
722    permissions = new PermissionSet(APIPermissionSet(),
723                                    ManifestPermissionSet(),
724                                    more_allowed_hosts,
725                                    URLPatternSet());
726    permissions_data->UpdateTabSpecificPermissions(1, permissions);
727    EXPECT_EQ(permissions->explicit_hosts(),
728              permissions_data->GetTabSpecificPermissionsForTesting(1)
729                  ->explicit_hosts());
730  }
731
732  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), allowed_urls, 0));
733  EXPECT_TRUE(
734      ScriptAllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1));
735  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
736
737  permissions_data->ClearTabSpecificPermissions(0);
738  EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(0).get());
739
740  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
741  EXPECT_TRUE(
742      ScriptAllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1));
743  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
744
745  permissions_data->ClearTabSpecificPermissions(1);
746  EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(1).get());
747
748  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
749  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
750  EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
751}
752
753}  // namespace extensions
754