extension_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 "chrome/common/extensions/extension.h"
6
7#include "base/command_line.h"
8#include "base/file_util.h"
9#include "base/files/file_path.h"
10#include "base/format_macros.h"
11#include "base/json/json_file_value_serializer.h"
12#include "base/path_service.h"
13#include "base/stringprintf.h"
14#include "base/strings/string_number_conversions.h"
15#include "base/utf_string_conversions.h"
16#include "chrome/common/chrome_paths.h"
17#include "chrome/common/chrome_switches.h"
18#include "chrome/common/extensions/api/commands/commands_handler.h"
19#include "chrome/common/extensions/api/plugins/plugins_handler.h"
20#include "chrome/common/extensions/background_info.h"
21#include "chrome/common/extensions/command.h"
22#include "chrome/common/extensions/extension_file_util.h"
23#include "chrome/common/extensions/extension_manifest_constants.h"
24#include "chrome/common/extensions/features/feature.h"
25#include "chrome/common/extensions/incognito_handler.h"
26#include "chrome/common/extensions/manifest.h"
27#include "chrome/common/extensions/manifest_handler.h"
28#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
29#include "chrome/common/extensions/permissions/api_permission.h"
30#include "chrome/common/extensions/permissions/permission_set.h"
31#include "chrome/common/extensions/permissions/socket_permission.h"
32#include "chrome/common/extensions/permissions/usb_device_permission.h"
33#include "chrome/common/url_constants.h"
34#include "extensions/common/error_utils.h"
35#include "extensions/common/extension_resource.h"
36#include "extensions/common/id_util.h"
37#include "googleurl/src/gurl.h"
38#include "net/base/mime_sniffer.h"
39#include "net/dns/mock_host_resolver.h"
40#include "skia/ext/image_operations.h"
41#include "testing/gtest/include/gtest/gtest.h"
42#include "third_party/skia/include/core/SkBitmap.h"
43#include "ui/gfx/codec/png_codec.h"
44
45using content::SocketPermissionRequest;
46
47namespace keys = extension_manifest_keys;
48namespace values = extension_manifest_values;
49namespace errors = extension_manifest_errors;
50
51namespace extensions {
52namespace {
53
54scoped_refptr<Extension> LoadManifestUnchecked(
55    const std::string& dir,
56    const std::string& test_file,
57    Manifest::Location location,
58    int extra_flags,
59    std::string* error) {
60  base::FilePath path;
61  PathService::Get(chrome::DIR_TEST_DATA, &path);
62  path = path.AppendASCII("extensions")
63             .AppendASCII(dir)
64             .AppendASCII(test_file);
65
66  JSONFileValueSerializer serializer(path);
67  scoped_ptr<Value> result(serializer.Deserialize(NULL, error));
68  if (!result.get())
69    return NULL;
70
71  scoped_refptr<Extension> extension = Extension::Create(
72      path.DirName(), location, *static_cast<DictionaryValue*>(result.get()),
73      extra_flags, error);
74  return extension;
75}
76
77static scoped_refptr<Extension> LoadManifest(const std::string& dir,
78                                             const std::string& test_file,
79                                             Manifest::Location location,
80                                             int extra_flags) {
81  std::string error;
82  scoped_refptr<Extension> extension = LoadManifestUnchecked(dir, test_file,
83    location, extra_flags, &error);
84
85  EXPECT_TRUE(extension) << test_file << ":" << error;
86  return extension;
87}
88
89static scoped_refptr<Extension> LoadManifest(const std::string& dir,
90                                             const std::string& test_file,
91                                             int extra_flags) {
92  return LoadManifest(dir, test_file, Manifest::INVALID_LOCATION, extra_flags);
93}
94
95static scoped_refptr<Extension> LoadManifest(const std::string& dir,
96                                             const std::string& test_file) {
97  return LoadManifest(dir, test_file, Extension::NO_FLAGS);
98}
99
100static scoped_refptr<Extension> LoadManifestStrict(
101    const std::string& dir,
102    const std::string& test_file) {
103  return LoadManifest(dir, test_file, Extension::NO_FLAGS);
104}
105
106}  // namespace
107
108class ExtensionTest : public testing::Test {
109 protected:
110  virtual void SetUp() OVERRIDE {
111    testing::Test::SetUp();
112    (new BackgroundManifestHandler)->Register();
113    (new CommandsHandler)->Register();
114    (new ContentScriptsHandler)->Register();
115    (new PluginsHandler)->Register();
116    (new IncognitoHandler)->Register();
117  }
118
119  virtual void TearDown() OVERRIDE {
120    ManifestHandler::ClearRegistryForTesting();
121  }
122};
123
124// We persist location values in the preferences, so this is a sanity test that
125// someone doesn't accidentally change them.
126TEST_F(ExtensionTest, LocationValuesTest) {
127  ASSERT_EQ(0, Manifest::INVALID_LOCATION);
128  ASSERT_EQ(1, Manifest::INTERNAL);
129  ASSERT_EQ(2, Manifest::EXTERNAL_PREF);
130  ASSERT_EQ(3, Manifest::EXTERNAL_REGISTRY);
131  ASSERT_EQ(4, Manifest::UNPACKED);
132  ASSERT_EQ(5, Manifest::COMPONENT);
133  ASSERT_EQ(6, Manifest::EXTERNAL_PREF_DOWNLOAD);
134  ASSERT_EQ(7, Manifest::EXTERNAL_POLICY_DOWNLOAD);
135  ASSERT_EQ(8, Manifest::COMMAND_LINE);
136}
137
138TEST_F(ExtensionTest, LocationPriorityTest) {
139  for (int i = 0; i < Manifest::NUM_LOCATIONS; i++) {
140    Manifest::Location loc = static_cast<Manifest::Location>(i);
141
142    // INVALID is not a valid location.
143    if (loc == Manifest::INVALID_LOCATION)
144      continue;
145
146    // Comparing a location that has no rank will hit a CHECK. Do a
147    // compare with every valid location, to be sure each one is covered.
148
149    // Check that no install source can override a componenet extension.
150    ASSERT_EQ(Manifest::COMPONENT,
151              Manifest::GetHigherPriorityLocation(Manifest::COMPONENT, loc));
152    ASSERT_EQ(Manifest::COMPONENT,
153              Manifest::GetHigherPriorityLocation(loc, Manifest::COMPONENT));
154
155    // Check that any source can override a user install. This might change
156    // in the future, in which case this test should be updated.
157    ASSERT_EQ(loc,
158              Manifest::GetHigherPriorityLocation(Manifest::INTERNAL, loc));
159    ASSERT_EQ(loc,
160              Manifest::GetHigherPriorityLocation(loc, Manifest::INTERNAL));
161  }
162
163  // Check a few interesting cases that we know can happen:
164  ASSERT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD,
165            Manifest::GetHigherPriorityLocation(
166                Manifest::EXTERNAL_POLICY_DOWNLOAD,
167                Manifest::EXTERNAL_PREF));
168
169  ASSERT_EQ(Manifest::EXTERNAL_PREF,
170            Manifest::GetHigherPriorityLocation(
171                Manifest::INTERNAL,
172                Manifest::EXTERNAL_PREF));
173}
174
175TEST_F(ExtensionTest, GetResourceURLAndPath) {
176  scoped_refptr<Extension> extension = LoadManifestStrict("empty_manifest",
177      "empty.json");
178  EXPECT_TRUE(extension.get());
179
180  EXPECT_EQ(extension->url().spec() + "bar/baz.js",
181            Extension::GetResourceURL(extension->url(), "bar/baz.js").spec());
182  EXPECT_EQ(extension->url().spec() + "baz.js",
183            Extension::GetResourceURL(extension->url(),
184                                      "bar/../baz.js").spec());
185  EXPECT_EQ(extension->url().spec() + "baz.js",
186            Extension::GetResourceURL(extension->url(), "../baz.js").spec());
187
188  // Test that absolute-looking paths ("/"-prefixed) are pasted correctly.
189  EXPECT_EQ(extension->url().spec() + "test.html",
190            extension->GetResourceURL("/test.html").spec());
191}
192
193TEST_F(ExtensionTest, GetAbsolutePathNoError) {
194  scoped_refptr<Extension> extension = LoadManifestStrict("absolute_path",
195      "absolute.json");
196  EXPECT_TRUE(extension.get());
197  std::string err;
198  std::vector<InstallWarning> warnings;
199  EXPECT_TRUE(extension_file_util::ValidateExtension(extension.get(),
200                                                     &err, &warnings));
201  EXPECT_EQ(0U, warnings.size());
202
203  EXPECT_EQ(extension->path().AppendASCII("test.html").value(),
204            extension->GetResource("test.html").GetFilePath().value());
205  EXPECT_EQ(extension->path().AppendASCII("test.js").value(),
206            extension->GetResource("test.js").GetFilePath().value());
207}
208
209
210TEST_F(ExtensionTest, IdIsValid) {
211  EXPECT_TRUE(Extension::IdIsValid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
212  EXPECT_TRUE(Extension::IdIsValid("pppppppppppppppppppppppppppppppp"));
213  EXPECT_TRUE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnop"));
214  EXPECT_TRUE(Extension::IdIsValid("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"));
215  EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmno"));
216  EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnopa"));
217  EXPECT_FALSE(Extension::IdIsValid("0123456789abcdef0123456789abcdef"));
218  EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnoq"));
219  EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmno0"));
220}
221
222
223// This test ensures that the mimetype sniffing code stays in sync with the
224// actual crx files that we test other parts of the system with.
225TEST_F(ExtensionTest, MimeTypeSniffing) {
226  base::FilePath path;
227  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
228  path = path.AppendASCII("extensions").AppendASCII("good.crx");
229
230  std::string data;
231  ASSERT_TRUE(file_util::ReadFileToString(path, &data));
232
233  std::string result;
234  EXPECT_TRUE(net::SniffMimeType(data.c_str(), data.size(),
235              GURL("http://www.example.com/foo.crx"), "", &result));
236  EXPECT_EQ(std::string(Extension::kMimeType), result);
237
238  data.clear();
239  result.clear();
240  path = path.DirName().AppendASCII("bad_magic.crx");
241  ASSERT_TRUE(file_util::ReadFileToString(path, &data));
242  EXPECT_TRUE(net::SniffMimeType(data.c_str(), data.size(),
243              GURL("http://www.example.com/foo.crx"), "", &result));
244  EXPECT_EQ("application/octet-stream", result);
245}
246
247TEST_F(ExtensionTest, EffectiveHostPermissions) {
248  scoped_refptr<Extension> extension;
249  URLPatternSet hosts;
250
251  extension = LoadManifest("effective_host_permissions", "empty.json");
252  EXPECT_EQ(0u, extension->GetEffectiveHostPermissions().patterns().size());
253  EXPECT_FALSE(hosts.MatchesURL(GURL("http://www.google.com")));
254  EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
255
256  extension = LoadManifest("effective_host_permissions", "one_host.json");
257  hosts = extension->GetEffectiveHostPermissions();
258  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
259  EXPECT_FALSE(hosts.MatchesURL(GURL("https://www.google.com")));
260  EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
261
262  extension = LoadManifest("effective_host_permissions",
263                           "one_host_wildcard.json");
264  hosts = extension->GetEffectiveHostPermissions();
265  EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
266  EXPECT_TRUE(hosts.MatchesURL(GURL("http://foo.google.com")));
267  EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
268
269  extension = LoadManifest("effective_host_permissions", "two_hosts.json");
270  hosts = extension->GetEffectiveHostPermissions();
271  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
272  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com")));
273  EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
274
275  extension = LoadManifest("effective_host_permissions",
276                           "https_not_considered.json");
277  hosts = extension->GetEffectiveHostPermissions();
278  EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
279  EXPECT_TRUE(hosts.MatchesURL(GURL("https://google.com")));
280  EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
281
282  extension = LoadManifest("effective_host_permissions",
283                           "two_content_scripts.json");
284  hosts = extension->GetEffectiveHostPermissions();
285  EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com")));
286  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com")));
287  EXPECT_TRUE(extension->GetActivePermissions()->HasEffectiveAccessToURL(
288      GURL("http://www.reddit.com")));
289  EXPECT_TRUE(hosts.MatchesURL(GURL("http://news.ycombinator.com")));
290  EXPECT_TRUE(extension->GetActivePermissions()->HasEffectiveAccessToURL(
291      GURL("http://news.ycombinator.com")));
292  EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
293
294  extension = LoadManifest("effective_host_permissions", "all_hosts.json");
295  hosts = extension->GetEffectiveHostPermissions();
296  EXPECT_TRUE(hosts.MatchesURL(GURL("http://test/")));
297  EXPECT_FALSE(hosts.MatchesURL(GURL("https://test/")));
298  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
299  EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts());
300
301  extension = LoadManifest("effective_host_permissions", "all_hosts2.json");
302  hosts = extension->GetEffectiveHostPermissions();
303  EXPECT_TRUE(hosts.MatchesURL(GURL("http://test/")));
304  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
305  EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts());
306
307  extension = LoadManifest("effective_host_permissions", "all_hosts3.json");
308  hosts = extension->GetEffectiveHostPermissions();
309  EXPECT_FALSE(hosts.MatchesURL(GURL("http://test/")));
310  EXPECT_TRUE(hosts.MatchesURL(GURL("https://test/")));
311  EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com")));
312  EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts());
313}
314
315static bool CheckSocketPermission(scoped_refptr<Extension> extension,
316    SocketPermissionRequest::OperationType type,
317    const char* host,
318    int port) {
319  SocketPermission::CheckParam param(type, host, port);
320  return extension->CheckAPIPermissionWithParam(
321      APIPermission::kSocket, &param);
322}
323
324TEST_F(ExtensionTest, SocketPermissions) {
325  // Set feature current channel to appropriate value.
326  Feature::ScopedCurrentChannel scoped_channel(
327      chrome::VersionInfo::CHANNEL_DEV);
328  scoped_refptr<Extension> extension;
329  std::string error;
330
331  extension = LoadManifest("socket_permissions", "empty.json");
332  EXPECT_FALSE(CheckSocketPermission(extension,
333      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
334
335  extension = LoadManifestUnchecked("socket_permissions",
336                                    "socket1.json",
337                                    Manifest::INTERNAL, Extension::NO_FLAGS,
338                                    &error);
339  EXPECT_TRUE(extension == NULL);
340  ASSERT_EQ(ErrorUtils::FormatErrorMessage(
341        errors::kInvalidPermission, "socket"), error);
342
343  extension = LoadManifest("socket_permissions", "socket2.json");
344  EXPECT_TRUE(CheckSocketPermission(extension,
345      SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80));
346  EXPECT_FALSE(CheckSocketPermission(
347        extension, SocketPermissionRequest::UDP_BIND, "", 80));
348  EXPECT_TRUE(CheckSocketPermission(
349        extension, SocketPermissionRequest::UDP_BIND, "", 8888));
350
351  EXPECT_FALSE(CheckSocketPermission(
352        extension, SocketPermissionRequest::UDP_SEND_TO, "example.com", 1900));
353  EXPECT_TRUE(CheckSocketPermission(
354        extension,
355        SocketPermissionRequest::UDP_SEND_TO,
356        "239.255.255.250", 1900));
357}
358
359// This tests the API permissions with an empty manifest (one that just
360// specifies a name and a version and nothing else).
361TEST_F(ExtensionTest, ApiPermissions) {
362  const struct {
363    const char* permission_name;
364    bool expect_success;
365  } kTests[] = {
366    // Negative test.
367    { "non_existing_permission", false },
368    // Test default module/package permission.
369    { "browserAction",  true },
370    { "devtools",       true },
371    { "extension",      true },
372    { "i18n",           true },
373    { "pageAction",     true },
374    { "pageActions",    true },
375    { "test",           true },
376    // Some negative tests.
377    { "bookmarks",      false },
378    { "cookies",        false },
379    { "history",        false },
380    // Make sure we find the module name after stripping '.' and '/'.
381    { "browserAction/abcd/onClick",  true },
382    { "browserAction.abcd.onClick",  true },
383    // Test Tabs functions.
384    { "tabs.create",      true},
385    { "tabs.duplicate",   true},
386    { "tabs.onRemoved",   true},
387    { "tabs.remove",      true},
388    { "tabs.update",      true},
389    { "tabs.getSelected", true},
390    { "tabs.onUpdated",   true },
391    // Test getPermissionWarnings functions. Only one requires permissions.
392    { "management.getPermissionWarningsById", false },
393    { "management.getPermissionWarningsByManifest", true },
394  };
395
396  scoped_refptr<Extension> extension;
397  extension = LoadManifest("empty_manifest", "empty.json");
398
399  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
400    EXPECT_EQ(kTests[i].expect_success,
401              extension->HasAPIPermission(kTests[i].permission_name))
402                  << "Permission being tested: " << kTests[i].permission_name;
403  }
404}
405
406TEST_F(ExtensionTest, GetPermissionMessages_ManyApiPermissions) {
407  scoped_refptr<Extension> extension;
408  extension = LoadManifest("permissions", "many-apis.json");
409  std::vector<string16> warnings = extension->GetPermissionMessageStrings();
410  ASSERT_EQ(6u, warnings.size());
411  EXPECT_EQ("Access your data on api.flickr.com",
412            UTF16ToUTF8(warnings[0]));
413  EXPECT_EQ("Read and modify your bookmarks", UTF16ToUTF8(warnings[1]));
414  EXPECT_EQ("Detect your physical location", UTF16ToUTF8(warnings[2]));
415  EXPECT_EQ("Read and modify your browsing history", UTF16ToUTF8(warnings[3]));
416  EXPECT_EQ("Access your tabs and browsing activity", UTF16ToUTF8(warnings[4]));
417  EXPECT_EQ("Manage your apps, extensions, and themes",
418            UTF16ToUTF8(warnings[5]));
419}
420
421TEST_F(ExtensionTest, GetPermissionMessages_ManyHosts) {
422  scoped_refptr<Extension> extension;
423  extension = LoadManifest("permissions", "many-hosts.json");
424  std::vector<string16> warnings = extension->GetPermissionMessageStrings();
425  ASSERT_EQ(1u, warnings.size());
426  EXPECT_EQ("Access your data on encrypted.google.com and www.google.com",
427            UTF16ToUTF8(warnings[0]));
428}
429
430TEST_F(ExtensionTest, GetPermissionMessages_Plugins) {
431  scoped_refptr<Extension> extension;
432  extension = LoadManifest("permissions", "plugins.json");
433  std::vector<string16> warnings = extension->GetPermissionMessageStrings();
434  // We don't parse the plugins key on Chrome OS, so it should not ask for any
435  // permissions.
436#if defined(OS_CHROMEOS)
437  ASSERT_EQ(0u, warnings.size());
438#else
439  ASSERT_EQ(1u, warnings.size());
440  EXPECT_EQ("Access all data on your computer and the websites you visit",
441            UTF16ToUTF8(warnings[0]));
442#endif
443}
444
445TEST_F(ExtensionTest, WantsFileAccess) {
446  scoped_refptr<Extension> extension;
447  GURL file_url("file:///etc/passwd");
448
449  // <all_urls> permission
450  extension = LoadManifest("permissions", "permissions_all_urls.json");
451  EXPECT_TRUE(extension->wants_file_access());
452  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
453      file_url, file_url, -1, NULL, NULL));
454  extension = LoadManifest(
455      "permissions", "permissions_all_urls.json", Extension::ALLOW_FILE_ACCESS);
456  EXPECT_TRUE(extension->wants_file_access());
457  EXPECT_TRUE(extension->CanExecuteScriptOnPage(
458      file_url, file_url, -1, NULL, NULL));
459
460  // file:///* permission
461  extension = LoadManifest("permissions", "permissions_file_scheme.json");
462  EXPECT_TRUE(extension->wants_file_access());
463  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
464      file_url, file_url, -1, NULL, NULL));
465  extension = LoadManifest("permissions", "permissions_file_scheme.json",
466      Extension::ALLOW_FILE_ACCESS);
467  EXPECT_TRUE(extension->wants_file_access());
468  EXPECT_TRUE(extension->CanExecuteScriptOnPage(
469      file_url, file_url, -1, NULL, NULL));
470
471  // http://* permission
472  extension = LoadManifest("permissions", "permissions_http_scheme.json");
473  EXPECT_FALSE(extension->wants_file_access());
474  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
475      file_url, file_url, -1, NULL, NULL));
476  extension = LoadManifest("permissions", "permissions_http_scheme.json",
477      Extension::ALLOW_FILE_ACCESS);
478  EXPECT_FALSE(extension->wants_file_access());
479  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
480      file_url, file_url, -1, NULL, NULL));
481
482  // <all_urls> content script match
483  extension = LoadManifest("permissions", "content_script_all_urls.json");
484  EXPECT_TRUE(extension->wants_file_access());
485  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
486      file_url,
487      file_url,
488      -1,
489      &ContentScriptsInfo::GetContentScripts(extension)[0],
490      NULL));
491  extension = LoadManifest("permissions", "content_script_all_urls.json",
492      Extension::ALLOW_FILE_ACCESS);
493  EXPECT_TRUE(extension->wants_file_access());
494  EXPECT_TRUE(extension->CanExecuteScriptOnPage(
495      file_url,
496      file_url,
497      -1,
498      &ContentScriptsInfo::GetContentScripts(extension)[0],
499      NULL));
500
501  // file:///* content script match
502  extension = LoadManifest("permissions", "content_script_file_scheme.json");
503  EXPECT_TRUE(extension->wants_file_access());
504  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
505      file_url,
506      file_url,
507      -1,
508      &ContentScriptsInfo::GetContentScripts(extension)[0],
509      NULL));
510  extension = LoadManifest("permissions", "content_script_file_scheme.json",
511      Extension::ALLOW_FILE_ACCESS);
512  EXPECT_TRUE(extension->wants_file_access());
513  EXPECT_TRUE(extension->CanExecuteScriptOnPage(
514      file_url,
515      file_url,
516      -1,
517      &ContentScriptsInfo::GetContentScripts(extension)[0],
518      NULL));
519
520  // http://* content script match
521  extension = LoadManifest("permissions", "content_script_http_scheme.json");
522  EXPECT_FALSE(extension->wants_file_access());
523  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
524      file_url,
525      file_url,
526      -1,
527      &ContentScriptsInfo::GetContentScripts(extension)[0],
528      NULL));
529  extension = LoadManifest("permissions", "content_script_http_scheme.json",
530      Extension::ALLOW_FILE_ACCESS);
531  EXPECT_FALSE(extension->wants_file_access());
532  EXPECT_FALSE(extension->CanExecuteScriptOnPage(
533      file_url,
534      file_url,
535      -1,
536      &ContentScriptsInfo::GetContentScripts(extension)[0],
537      NULL));
538}
539
540TEST_F(ExtensionTest, ExtraFlags) {
541  scoped_refptr<Extension> extension;
542  extension = LoadManifest("app", "manifest.json", Extension::FROM_WEBSTORE);
543  EXPECT_TRUE(extension->from_webstore());
544
545  extension = LoadManifest("app", "manifest.json", Extension::FROM_BOOKMARK);
546  EXPECT_TRUE(extension->from_bookmark());
547
548  extension = LoadManifest("app", "manifest.json", Extension::NO_FLAGS);
549  EXPECT_FALSE(extension->from_bookmark());
550  EXPECT_FALSE(extension->from_webstore());
551}
552
553TEST_F(ExtensionTest, BrowserActionSynthesizesCommand) {
554  scoped_refptr<Extension> extension;
555
556  extension = LoadManifest("api_test/browser_action/synthesized",
557                           "manifest.json");
558  // An extension with a browser action but no extension command specified
559  // should get a command assigned to it.
560  const extensions::Command* command =
561      CommandsInfo::GetBrowserActionCommand(extension);
562  ASSERT_TRUE(command != NULL);
563  ASSERT_EQ(ui::VKEY_UNKNOWN, command->accelerator().key_code());
564}
565
566// Base class for testing the CanExecuteScriptOnPage and CanCaptureVisiblePage
567// methods of Extension for extensions with various permissions.
568class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
569 protected:
570  ExtensionScriptAndCaptureVisibleTest()
571      : http_url("http://www.google.com"),
572        http_url_with_path("http://www.google.com/index.html"),
573        https_url("https://www.google.com"),
574        file_url("file:///foo/bar"),
575        favicon_url("chrome://favicon/http://www.google.com"),
576        extension_url("chrome-extension://" +
577            id_util::GenerateIdForPath(
578                base::FilePath(FILE_PATH_LITERAL("foo")))),
579        settings_url("chrome://settings"),
580        about_url("about:flags") {
581    urls_.insert(http_url);
582    urls_.insert(http_url_with_path);
583    urls_.insert(https_url);
584    urls_.insert(file_url);
585    urls_.insert(favicon_url);
586    urls_.insert(extension_url);
587    urls_.insert(settings_url);
588    urls_.insert(about_url);
589  }
590
591  bool AllowedScript(const Extension* extension, const GURL& url,
592                     const GURL& top_url) {
593    return extension->CanExecuteScriptOnPage(url, top_url, -1, NULL, NULL);
594  }
595
596  bool BlockedScript(const Extension* extension, const GURL& url,
597                     const GURL& top_url) {
598    return !extension->CanExecuteScriptOnPage(url, top_url, -1, NULL, NULL);
599  }
600
601  bool Allowed(const Extension* extension, const GURL& url) {
602    return Allowed(extension, url, -1);
603  }
604
605  bool Allowed(const Extension* extension, const GURL& url, int tab_id) {
606    return (extension->CanExecuteScriptOnPage(url, url, tab_id, NULL, NULL) &&
607            extension->CanCaptureVisiblePage(url, tab_id, NULL));
608  }
609
610  bool CaptureOnly(const Extension* extension, const GURL& url) {
611    return CaptureOnly(extension, url, -1);
612  }
613
614  bool CaptureOnly(const Extension* extension, const GURL& url, int tab_id) {
615    return !extension->CanExecuteScriptOnPage(url, url, tab_id, NULL, NULL) &&
616            extension->CanCaptureVisiblePage(url, tab_id, NULL);
617  }
618
619  bool Blocked(const Extension* extension, const GURL& url) {
620    return Blocked(extension, url, -1);
621  }
622
623  bool Blocked(const Extension* extension, const GURL& url, int tab_id) {
624    return !(extension->CanExecuteScriptOnPage(url, url, tab_id, NULL, NULL) ||
625             extension->CanCaptureVisiblePage(url, tab_id, NULL));
626  }
627
628  bool AllowedExclusivelyOnTab(
629      const Extension* extension,
630      const std::set<GURL>& allowed_urls,
631      int tab_id) {
632    bool result = true;
633    for (std::set<GURL>::iterator it = urls_.begin(); it != urls_.end(); ++it) {
634      const GURL& url = *it;
635      if (allowed_urls.count(url))
636        result &= Allowed(extension, url, tab_id);
637      else
638        result &= Blocked(extension, url, tab_id);
639    }
640    return result;
641  }
642
643  // URLs that are "safe" to provide scripting and capture visible tab access
644  // to if the permissions allow it.
645  const GURL http_url;
646  const GURL http_url_with_path;
647  const GURL https_url;
648  const GURL file_url;
649
650  // We should allow host permission but not scripting permission for favicon
651  // urls.
652  const GURL favicon_url;
653
654  // URLs that regular extensions should never get access to.
655  const GURL extension_url;
656  const GURL settings_url;
657  const GURL about_url;
658
659 private:
660  // The set of all URLs above.
661  std::set<GURL> urls_;
662};
663
664TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
665  // Test <all_urls> for regular extensions.
666  scoped_refptr<Extension> extension = LoadManifestStrict("script_and_capture",
667      "extension_regular_all.json");
668
669  EXPECT_TRUE(Allowed(extension, http_url));
670  EXPECT_TRUE(Allowed(extension, https_url));
671  EXPECT_TRUE(Blocked(extension, file_url));
672  EXPECT_TRUE(Blocked(extension, settings_url));
673  EXPECT_TRUE(CaptureOnly(extension, favicon_url));
674  EXPECT_TRUE(Blocked(extension, about_url));
675  EXPECT_TRUE(Blocked(extension, extension_url));
676
677  // Test access to iframed content.
678  GURL within_extension_url = extension->GetResourceURL("page.html");
679  EXPECT_TRUE(AllowedScript(extension, http_url, http_url_with_path));
680  EXPECT_TRUE(AllowedScript(extension, https_url, http_url_with_path));
681  EXPECT_TRUE(AllowedScript(extension, http_url, within_extension_url));
682  EXPECT_TRUE(AllowedScript(extension, https_url, within_extension_url));
683  EXPECT_TRUE(BlockedScript(extension, http_url, extension_url));
684  EXPECT_TRUE(BlockedScript(extension, https_url, extension_url));
685
686  EXPECT_FALSE(extension->HasHostPermission(settings_url));
687  EXPECT_FALSE(extension->HasHostPermission(about_url));
688  EXPECT_TRUE(extension->HasHostPermission(favicon_url));
689
690  // Test * for scheme, which implies just the http/https schemes.
691  extension = LoadManifestStrict("script_and_capture",
692      "extension_wildcard.json");
693  EXPECT_TRUE(Allowed(extension, http_url));
694  EXPECT_TRUE(Allowed(extension, https_url));
695  EXPECT_TRUE(Blocked(extension, settings_url));
696  EXPECT_TRUE(Blocked(extension, about_url));
697  EXPECT_TRUE(Blocked(extension, file_url));
698  EXPECT_TRUE(Blocked(extension, favicon_url));
699  extension = LoadManifest("script_and_capture",
700      "extension_wildcard_settings.json");
701  EXPECT_TRUE(Blocked(extension, settings_url));
702
703  // Having chrome://*/ should not work for regular extensions. Note that
704  // for favicon access, we require the explicit pattern chrome://favicon/*.
705  std::string error;
706  extension = LoadManifestUnchecked("script_and_capture",
707                                    "extension_wildcard_chrome.json",
708                                    Manifest::INTERNAL, Extension::NO_FLAGS,
709                                    &error);
710  EXPECT_TRUE(extension == NULL);
711  EXPECT_EQ(ErrorUtils::FormatErrorMessage(
712      errors::kInvalidPermissionScheme, "chrome://*/"), error);
713
714  // Having chrome://favicon/* should not give you chrome://*
715  extension = LoadManifestStrict("script_and_capture",
716      "extension_chrome_favicon_wildcard.json");
717  EXPECT_TRUE(Blocked(extension, settings_url));
718  EXPECT_TRUE(CaptureOnly(extension, favicon_url));
719  EXPECT_TRUE(Blocked(extension, about_url));
720  EXPECT_TRUE(extension->HasHostPermission(favicon_url));
721
722  // Having http://favicon should not give you chrome://favicon
723  extension = LoadManifestStrict("script_and_capture",
724      "extension_http_favicon.json");
725  EXPECT_TRUE(Blocked(extension, settings_url));
726  EXPECT_TRUE(Blocked(extension, favicon_url));
727
728  // Component extensions with <all_urls> should get everything.
729  extension = LoadManifest("script_and_capture", "extension_component_all.json",
730      Manifest::COMPONENT, Extension::NO_FLAGS);
731  EXPECT_TRUE(Allowed(extension, http_url));
732  EXPECT_TRUE(Allowed(extension, https_url));
733  EXPECT_TRUE(Allowed(extension, settings_url));
734  EXPECT_TRUE(Allowed(extension, about_url));
735  EXPECT_TRUE(Allowed(extension, favicon_url));
736  EXPECT_TRUE(extension->HasHostPermission(favicon_url));
737
738  // Component extensions should only get access to what they ask for.
739  extension = LoadManifest("script_and_capture",
740      "extension_component_google.json", Manifest::COMPONENT,
741      Extension::NO_FLAGS);
742  EXPECT_TRUE(Allowed(extension, http_url));
743  EXPECT_TRUE(Blocked(extension, https_url));
744  EXPECT_TRUE(Blocked(extension, file_url));
745  EXPECT_TRUE(Blocked(extension, settings_url));
746  EXPECT_TRUE(Blocked(extension, favicon_url));
747  EXPECT_TRUE(Blocked(extension, about_url));
748  EXPECT_TRUE(Blocked(extension, extension_url));
749  EXPECT_FALSE(extension->HasHostPermission(settings_url));
750}
751
752
753TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
754  CommandLine::ForCurrentProcess()->AppendSwitch(
755      switches::kExtensionsOnChromeURLs);
756
757  scoped_refptr<Extension> extension;
758
759  // Test <all_urls> for regular extensions.
760  extension = LoadManifestStrict("script_and_capture",
761      "extension_regular_all.json");
762  EXPECT_TRUE(Allowed(extension, http_url));
763  EXPECT_TRUE(Allowed(extension, https_url));
764  EXPECT_TRUE(Blocked(extension, file_url));
765  EXPECT_TRUE(Blocked(extension, settings_url));
766  EXPECT_TRUE(Allowed(extension, favicon_url));  // chrome:// requested
767  EXPECT_TRUE(Blocked(extension, about_url));
768  EXPECT_TRUE(Blocked(extension, extension_url));
769
770  // Test access to iframed content.
771  GURL within_extension_url = extension->GetResourceURL("page.html");
772  EXPECT_TRUE(AllowedScript(extension, http_url, http_url_with_path));
773  EXPECT_TRUE(AllowedScript(extension, https_url, http_url_with_path));
774  EXPECT_TRUE(AllowedScript(extension, http_url, within_extension_url));
775  EXPECT_TRUE(AllowedScript(extension, https_url, within_extension_url));
776  EXPECT_TRUE(BlockedScript(extension, http_url, extension_url));
777  EXPECT_TRUE(BlockedScript(extension, https_url, extension_url));
778
779  EXPECT_FALSE(extension->HasHostPermission(settings_url));
780  EXPECT_FALSE(extension->HasHostPermission(about_url));
781  EXPECT_TRUE(extension->HasHostPermission(favicon_url));
782
783  // Test * for scheme, which implies just the http/https schemes.
784  extension = LoadManifestStrict("script_and_capture",
785      "extension_wildcard.json");
786  EXPECT_TRUE(Allowed(extension, http_url));
787  EXPECT_TRUE(Allowed(extension, https_url));
788  EXPECT_TRUE(Blocked(extension, settings_url));
789  EXPECT_TRUE(Blocked(extension, about_url));
790  EXPECT_TRUE(Blocked(extension, file_url));
791  EXPECT_TRUE(Blocked(extension, favicon_url));
792  extension = LoadManifest("script_and_capture",
793      "extension_wildcard_settings.json");
794  EXPECT_TRUE(Blocked(extension, settings_url));
795
796  // Having chrome://*/ should work for regular extensions with the flag
797  // enabled.
798  std::string error;
799  extension = LoadManifestUnchecked("script_and_capture",
800                                    "extension_wildcard_chrome.json",
801                                    Manifest::INTERNAL, Extension::NO_FLAGS,
802                                    &error);
803  EXPECT_FALSE(extension == NULL);
804  EXPECT_TRUE(Blocked(extension, http_url));
805  EXPECT_TRUE(Blocked(extension, https_url));
806  EXPECT_TRUE(Allowed(extension, settings_url));
807  EXPECT_TRUE(Blocked(extension, about_url));
808  EXPECT_TRUE(Blocked(extension, file_url));
809  EXPECT_TRUE(Allowed(extension, favicon_url));  // chrome:// requested
810
811  // Having chrome://favicon/* should not give you chrome://*
812  extension = LoadManifestStrict("script_and_capture",
813      "extension_chrome_favicon_wildcard.json");
814  EXPECT_TRUE(Blocked(extension, settings_url));
815  EXPECT_TRUE(Allowed(extension, favicon_url));  // chrome:// requested
816  EXPECT_TRUE(Blocked(extension, about_url));
817  EXPECT_TRUE(extension->HasHostPermission(favicon_url));
818
819  // Having http://favicon should not give you chrome://favicon
820  extension = LoadManifestStrict("script_and_capture",
821      "extension_http_favicon.json");
822  EXPECT_TRUE(Blocked(extension, settings_url));
823  EXPECT_TRUE(Blocked(extension, favicon_url));
824
825  // Component extensions with <all_urls> should get everything.
826  extension = LoadManifest("script_and_capture", "extension_component_all.json",
827      Manifest::COMPONENT, Extension::NO_FLAGS);
828  EXPECT_TRUE(Allowed(extension, http_url));
829  EXPECT_TRUE(Allowed(extension, https_url));
830  EXPECT_TRUE(Allowed(extension, settings_url));
831  EXPECT_TRUE(Allowed(extension, about_url));
832  EXPECT_TRUE(Allowed(extension, favicon_url));
833  EXPECT_TRUE(extension->HasHostPermission(favicon_url));
834
835  // Component extensions should only get access to what they ask for.
836  extension = LoadManifest("script_and_capture",
837      "extension_component_google.json", Manifest::COMPONENT,
838      Extension::NO_FLAGS);
839  EXPECT_TRUE(Allowed(extension, http_url));
840  EXPECT_TRUE(Blocked(extension, https_url));
841  EXPECT_TRUE(Blocked(extension, file_url));
842  EXPECT_TRUE(Blocked(extension, settings_url));
843  EXPECT_TRUE(Blocked(extension, favicon_url));
844  EXPECT_TRUE(Blocked(extension, about_url));
845  EXPECT_TRUE(Blocked(extension, extension_url));
846  EXPECT_FALSE(extension->HasHostPermission(settings_url));
847}
848
849TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) {
850  scoped_refptr<Extension> extension =
851      LoadManifestStrict("script_and_capture", "tab_specific.json");
852
853  EXPECT_FALSE(extension->GetTabSpecificPermissions(0).get());
854  EXPECT_FALSE(extension->GetTabSpecificPermissions(1).get());
855  EXPECT_FALSE(extension->GetTabSpecificPermissions(2).get());
856
857  std::set<GURL> no_urls;
858
859  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 0));
860  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 1));
861  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 2));
862
863  URLPatternSet allowed_hosts;
864  allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL,
865                                      http_url.spec()));
866  std::set<GURL> allowed_urls;
867  allowed_urls.insert(http_url);
868  // http_url_with_path() will also be allowed, because Extension should be
869  // considering the security origin of the URL not the URL itself, and
870  // http_url is in allowed_hosts.
871  allowed_urls.insert(http_url_with_path);
872
873  {
874    scoped_refptr<PermissionSet> permissions(
875        new PermissionSet(APIPermissionSet(), allowed_hosts, URLPatternSet()));
876    extension->UpdateTabSpecificPermissions(0, permissions);
877    EXPECT_EQ(permissions->explicit_hosts(),
878              extension->GetTabSpecificPermissions(0)->explicit_hosts());
879  }
880
881  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, allowed_urls, 0));
882  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 1));
883  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 2));
884
885  extension->ClearTabSpecificPermissions(0);
886  EXPECT_FALSE(extension->GetTabSpecificPermissions(0).get());
887
888  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 0));
889  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 1));
890  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 2));
891
892  std::set<GURL> more_allowed_urls = allowed_urls;
893  more_allowed_urls.insert(https_url);
894  URLPatternSet more_allowed_hosts = allowed_hosts;
895  more_allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL,
896                                           https_url.spec()));
897
898  {
899    scoped_refptr<PermissionSet> permissions(
900        new PermissionSet(APIPermissionSet(), allowed_hosts, URLPatternSet()));
901    extension->UpdateTabSpecificPermissions(0, permissions);
902    EXPECT_EQ(permissions->explicit_hosts(),
903              extension->GetTabSpecificPermissions(0)->explicit_hosts());
904
905    permissions = new PermissionSet(APIPermissionSet(),
906                                    more_allowed_hosts,
907                                    URLPatternSet());
908    extension->UpdateTabSpecificPermissions(1, permissions);
909    EXPECT_EQ(permissions->explicit_hosts(),
910              extension->GetTabSpecificPermissions(1)->explicit_hosts());
911  }
912
913  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, allowed_urls, 0));
914  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, more_allowed_urls, 1));
915  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 2));
916
917  extension->ClearTabSpecificPermissions(0);
918  EXPECT_FALSE(extension->GetTabSpecificPermissions(0).get());
919
920  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 0));
921  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, more_allowed_urls, 1));
922  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 2));
923
924  extension->ClearTabSpecificPermissions(1);
925  EXPECT_FALSE(extension->GetTabSpecificPermissions(1).get());
926
927  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 0));
928  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 1));
929  EXPECT_TRUE(AllowedExclusivelyOnTab(extension, no_urls, 2));
930}
931
932namespace {
933enum SyncTestExtensionType {
934  EXTENSION,
935  APP,
936  USER_SCRIPT,
937  THEME
938};
939
940static scoped_refptr<Extension> MakeSyncTestExtension(
941    SyncTestExtensionType type,
942    const GURL& update_url,
943    const GURL& launch_url,
944    Manifest::Location location,
945    int num_plugins,
946    const base::FilePath& extension_path,
947    int creation_flags) {
948  DictionaryValue source;
949  source.SetString(extension_manifest_keys::kName,
950                   "PossiblySyncableExtension");
951  source.SetString(extension_manifest_keys::kVersion, "0.0.0.0");
952  if (type == APP)
953    source.SetString(extension_manifest_keys::kApp, "true");
954  if (type == THEME)
955    source.Set(extension_manifest_keys::kTheme, new DictionaryValue());
956  if (!update_url.is_empty()) {
957    source.SetString(extension_manifest_keys::kUpdateURL,
958                     update_url.spec());
959  }
960  if (!launch_url.is_empty()) {
961    source.SetString(extension_manifest_keys::kLaunchWebURL,
962                     launch_url.spec());
963  }
964  if (type != THEME) {
965    source.SetBoolean(extension_manifest_keys::kConvertedFromUserScript,
966                      type == USER_SCRIPT);
967    ListValue* plugins = new ListValue();
968    for (int i = 0; i < num_plugins; ++i) {
969      DictionaryValue* plugin = new DictionaryValue();
970      plugin->SetString(extension_manifest_keys::kPluginsPath, "");
971      plugins->Set(i, plugin);
972    }
973    source.Set(extension_manifest_keys::kPlugins, plugins);
974  }
975
976  std::string error;
977  scoped_refptr<Extension> extension = Extension::Create(
978      extension_path, location, source, creation_flags, &error);
979  EXPECT_TRUE(extension);
980  EXPECT_EQ("", error);
981  return extension;
982}
983
984static const char kValidUpdateUrl1[] =
985    "http://clients2.google.com/service/update2/crx";
986static const char kValidUpdateUrl2[] =
987    "https://clients2.google.com/service/update2/crx";
988}
989
990TEST_F(ExtensionTest, GetSyncTypeNormalExtensionNoUpdateUrl) {
991  scoped_refptr<Extension> extension(
992      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
993                            Manifest::INTERNAL, 0, base::FilePath(),
994                            Extension::NO_FLAGS));
995  EXPECT_NE(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
996}
997
998// http://crbug.com/172712
999TEST_F(ExtensionTest, DISABLED_GetSyncTypeUserScriptValidUpdateUrl) {
1000  scoped_refptr<Extension> extension(
1001      MakeSyncTestExtension(USER_SCRIPT, GURL(kValidUpdateUrl1), GURL(),
1002                            Manifest::INTERNAL, 0, base::FilePath(),
1003                            Extension::NO_FLAGS));
1004  EXPECT_NE(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1005}
1006
1007TEST_F(ExtensionTest, GetSyncTypeUserScriptNoUpdateUrl) {
1008  scoped_refptr<Extension> extension(
1009      MakeSyncTestExtension(USER_SCRIPT, GURL(), GURL(),
1010                            Manifest::INTERNAL, 0, base::FilePath(),
1011                            Extension::NO_FLAGS));
1012  EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1013}
1014
1015TEST_F(ExtensionTest, GetSyncTypeThemeNoUpdateUrl) {
1016  scoped_refptr<Extension> extension(
1017      MakeSyncTestExtension(THEME, GURL(), GURL(),
1018                            Manifest::INTERNAL, 0, base::FilePath(),
1019                            Extension::NO_FLAGS));
1020  EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1021}
1022
1023TEST_F(ExtensionTest, GetSyncTypeExtensionWithLaunchUrl) {
1024  scoped_refptr<Extension> extension(
1025      MakeSyncTestExtension(EXTENSION, GURL(), GURL("http://www.google.com"),
1026                            Manifest::INTERNAL, 0, base::FilePath(),
1027                            Extension::NO_FLAGS));
1028  EXPECT_NE(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1029}
1030
1031TEST_F(ExtensionTest, GetSyncTypeExtensionExternal) {
1032  scoped_refptr<Extension> extension(
1033      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1034                            Manifest::EXTERNAL_PREF, 0, base::FilePath(),
1035                            Extension::NO_FLAGS));
1036
1037  EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1038}
1039
1040TEST_F(ExtensionTest, GetSyncTypeUserScriptThirdPartyUpdateUrl) {
1041  scoped_refptr<Extension> extension(
1042      MakeSyncTestExtension(
1043          USER_SCRIPT, GURL("http://third-party.update_url.com"), GURL(),
1044          Manifest::INTERNAL, 0, base::FilePath(), Extension::NO_FLAGS));
1045  EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1046}
1047
1048TEST_F(ExtensionTest, OnlyDisplayAppsInLauncher) {
1049  scoped_refptr<Extension> extension(
1050      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1051                            Manifest::INTERNAL, 0, base::FilePath(),
1052                            Extension::NO_FLAGS));
1053
1054  EXPECT_FALSE(extension->ShouldDisplayInAppLauncher());
1055  EXPECT_FALSE(extension->ShouldDisplayInNewTabPage());
1056
1057  scoped_refptr<Extension> app(
1058      MakeSyncTestExtension(APP, GURL(), GURL("http://www.google.com"),
1059                            Manifest::INTERNAL, 0, base::FilePath(),
1060                            Extension::NO_FLAGS));
1061  EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
1062  EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
1063}
1064
1065TEST_F(ExtensionTest, DisplayInXManifestProperties) {
1066  DictionaryValue manifest;
1067  manifest.SetString(keys::kName, "TestComponentApp");
1068  manifest.SetString(keys::kVersion, "0.0.0.0");
1069  manifest.SetString(keys::kApp, "true");
1070  manifest.SetString(keys::kPlatformAppBackgroundPage, "");
1071
1072  std::string error;
1073  scoped_refptr<Extension> app;
1074
1075  // Default to true.
1076  app = Extension::Create(
1077      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
1078  EXPECT_EQ(error, std::string());
1079  EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
1080  EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
1081
1082  // Value display_in_NTP defaults to display_in_launcher.
1083  manifest.SetBoolean(keys::kDisplayInLauncher, false);
1084  app = Extension::Create(
1085      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
1086  EXPECT_EQ(error, std::string());
1087  EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
1088  EXPECT_FALSE(app->ShouldDisplayInNewTabPage());
1089
1090  // Value display_in_NTP = true overriding display_in_launcher = false.
1091  manifest.SetBoolean(keys::kDisplayInNewTabPage, true);
1092  app = Extension::Create(
1093      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
1094  EXPECT_EQ(error, std::string());
1095  EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
1096  EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
1097
1098  // Value display_in_NTP = false only, overrides default = true.
1099  manifest.Remove(keys::kDisplayInLauncher, NULL);
1100  manifest.SetBoolean(keys::kDisplayInNewTabPage, false);
1101  app = Extension::Create(
1102      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
1103  EXPECT_EQ(error, std::string());
1104  EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
1105  EXPECT_FALSE(app->ShouldDisplayInNewTabPage());
1106
1107  // Error checking.
1108  manifest.SetString(keys::kDisplayInNewTabPage, "invalid");
1109  app = Extension::Create(
1110      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
1111  EXPECT_EQ(error, std::string(errors::kInvalidDisplayInNewTabPage));
1112}
1113
1114TEST_F(ExtensionTest, OnlySyncInternal) {
1115  scoped_refptr<Extension> extension_internal(
1116      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1117                            Manifest::INTERNAL, 0, base::FilePath(),
1118                            Extension::NO_FLAGS));
1119  EXPECT_TRUE(extension_internal->IsSyncable());
1120
1121  scoped_refptr<Extension> extension_noninternal(
1122      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1123                            Manifest::COMPONENT, 0, base::FilePath(),
1124                            Extension::NO_FLAGS));
1125  EXPECT_FALSE(extension_noninternal->IsSyncable());
1126}
1127
1128TEST_F(ExtensionTest, DontSyncDefault) {
1129  scoped_refptr<Extension> extension_default(
1130      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1131                            Manifest::INTERNAL, 0, base::FilePath(),
1132                            Extension::WAS_INSTALLED_BY_DEFAULT));
1133  EXPECT_FALSE(extension_default->IsSyncable());
1134}
1135
1136TEST_F(ExtensionTest, OptionalOnlyPermission) {
1137  // Set feature current channel to dev because the only permission that must
1138  // be optional (usbDevices) is only available on dev channel.
1139  Feature::ScopedCurrentChannel scoped_channel(
1140      chrome::VersionInfo::CHANNEL_DEV);
1141
1142  scoped_refptr<Extension> extension;
1143  std::string error;
1144  extension = LoadManifestUnchecked("optional_only_permission",
1145                                    "manifest1.json",
1146                                    Manifest::INTERNAL, Extension::NO_FLAGS,
1147                                    &error);
1148  EXPECT_TRUE(extension == NULL);
1149  ASSERT_EQ(ErrorUtils::FormatErrorMessage(
1150        errors::kPermissionMustBeOptional, "usbDevices"), error);
1151
1152  error.clear();
1153  extension = LoadManifestUnchecked("optional_only_permission",
1154                                    "manifest2.json",
1155                                    Manifest::INTERNAL, Extension::NO_FLAGS,
1156                                    &error);
1157  EXPECT_TRUE(extension != NULL);
1158  EXPECT_TRUE(error.empty());
1159}
1160
1161// These last 2 tests don't make sense on Chrome OS, where extension plugins
1162// are not allowed.
1163#if !defined(OS_CHROMEOS)
1164TEST_F(ExtensionTest, GetSyncTypeExtensionWithPlugin) {
1165  scoped_refptr<Extension> extension(
1166      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1167                            Manifest::INTERNAL, 1, base::FilePath(),
1168                            Extension::NO_FLAGS));
1169  if (extension)
1170    EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1171}
1172
1173TEST_F(ExtensionTest, GetSyncTypeExtensionWithTwoPlugins) {
1174  scoped_refptr<Extension> extension(
1175      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
1176                            Manifest::INTERNAL, 2, base::FilePath(),
1177                            Extension::NO_FLAGS));
1178  if (extension)
1179    EXPECT_EQ(extension->GetSyncType(), Extension::SYNC_TYPE_NONE);
1180}
1181#endif // !defined(OS_CHROMEOS)
1182
1183}  // namespace extensions
1184