blob: 9580bff1ea099d56c5518932abda2019ad899e07 [file] [log] [blame]
[email protected]ffbec692012-02-26 20:26:421// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]4361c7c2010-09-30 21:57:532// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]ffbec692012-02-26 20:26:425#include "base/json/json_file_value_serializer.h"
[email protected]4361c7c2010-09-30 21:57:536#include "base/message_loop.h"
7#include "base/path_service.h"
[email protected]4361c7c2010-09-30 21:57:538#include "chrome/browser/extensions/extension_info_map.h"
9#include "chrome/common/chrome_paths.h"
[email protected]6f229e82010-11-02 17:47:2610#include "chrome/common/extensions/extension.h"
[email protected]a52c0e92012-03-23 06:02:2411#include "chrome/common/extensions/extension_manifest_constants.h"
[email protected]e676f8f2013-04-04 09:04:3712#include "chrome/common/extensions/extension_unittest.h"
[email protected]e97882f2012-06-04 02:23:1713#include "content/public/test/test_browser_thread.h"
[email protected]4361c7c2010-09-30 21:57:5314#include "testing/gtest/include/gtest/gtest.h"
[email protected]12d5c8d2013-01-15 07:28:0115#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
16#include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
[email protected]4361c7c2010-09-30 21:57:5317
[email protected]631bb742011-11-02 11:29:3918using content::BrowserThread;
[email protected]c2e66e12012-06-27 06:27:0619using extensions::APIPermission;
[email protected]1c321ee2012-05-21 03:02:3420using extensions::Extension;
[email protected]1d5e58b2013-01-31 08:41:4021using extensions::Manifest;
[email protected]69729ca2011-12-02 08:01:2522using WebKit::WebSecurityOrigin;
23using WebKit::WebString;
[email protected]631bb742011-11-02 11:29:3924
[email protected]4361c7c2010-09-30 21:57:5325namespace keys = extension_manifest_keys;
26
27namespace {
28
[email protected]e676f8f2013-04-04 09:04:3729class ExtensionInfoMapTest : public extensions::ExtensionTest {
[email protected]4361c7c2010-09-30 21:57:5330 public:
31 ExtensionInfoMapTest()
[email protected]ca4b5fa32010-10-09 12:42:1832 : ui_thread_(BrowserThread::UI, &message_loop_),
33 io_thread_(BrowserThread::IO, &message_loop_) {
[email protected]4361c7c2010-09-30 21:57:5334 }
35
36 private:
37 MessageLoop message_loop_;
[email protected]c38831a12011-10-28 12:44:4938 content::TestBrowserThread ui_thread_;
39 content::TestBrowserThread io_thread_;
[email protected]4361c7c2010-09-30 21:57:5340};
41
42// Returns a barebones test Extension object with the given name.
[email protected]66e4eb32010-10-27 20:37:4143static scoped_refptr<Extension> CreateExtension(const std::string& name) {
[email protected]4361c7c2010-09-30 21:57:5344#if defined(OS_WIN)
[email protected]650b2d52013-02-10 03:41:4545 base::FilePath path(FILE_PATH_LITERAL("c:\\foo"));
[email protected]4361c7c2010-09-30 21:57:5346#elif defined(OS_POSIX)
[email protected]650b2d52013-02-10 03:41:4547 base::FilePath path(FILE_PATH_LITERAL("/foo"));
[email protected]4361c7c2010-09-30 21:57:5348#endif
49
[email protected]4361c7c2010-09-30 21:57:5350 DictionaryValue manifest;
51 manifest.SetString(keys::kVersion, "1.0.0.0");
52 manifest.SetString(keys::kName, name);
53
54 std::string error;
[email protected]66e4eb32010-10-27 20:37:4155 scoped_refptr<Extension> extension = Extension::Create(
[email protected]1d5e58b2013-01-31 08:41:4056 path.AppendASCII(name), Manifest::INVALID_LOCATION, manifest,
[email protected]ed3b9b12012-05-31 18:37:5157 Extension::NO_FLAGS, &error);
[email protected]66e4eb32010-10-27 20:37:4158 EXPECT_TRUE(extension) << error;
[email protected]4361c7c2010-09-30 21:57:5359
[email protected]66e4eb32010-10-27 20:37:4160 return extension;
[email protected]4361c7c2010-09-30 21:57:5361}
62
[email protected]66e4eb32010-10-27 20:37:4163static scoped_refptr<Extension> LoadManifest(const std::string& dir,
64 const std::string& test_file) {
[email protected]650b2d52013-02-10 03:41:4565 base::FilePath path;
[email protected]4361c7c2010-09-30 21:57:5366 PathService::Get(chrome::DIR_TEST_DATA, &path);
67 path = path.AppendASCII("extensions")
68 .AppendASCII(dir)
69 .AppendASCII(test_file);
70
71 JSONFileValueSerializer serializer(path);
72 scoped_ptr<Value> result(serializer.Deserialize(NULL, NULL));
[email protected]3eeddd892013-04-17 17:00:1173 if (!result)
[email protected]4361c7c2010-09-30 21:57:5374 return NULL;
75
76 std::string error;
[email protected]66e4eb32010-10-27 20:37:4177 scoped_refptr<Extension> extension = Extension::Create(
[email protected]1d5e58b2013-01-31 08:41:4078 path, Manifest::INVALID_LOCATION,
79 *static_cast<DictionaryValue*>(result.get()),
[email protected]ed3b9b12012-05-31 18:37:5180 Extension::NO_FLAGS, &error);
[email protected]66e4eb32010-10-27 20:37:4181 EXPECT_TRUE(extension) << error;
[email protected]4361c7c2010-09-30 21:57:5382
[email protected]66e4eb32010-10-27 20:37:4183 return extension;
[email protected]4361c7c2010-09-30 21:57:5384}
85
[email protected]4361c7c2010-09-30 21:57:5386// Test that the ExtensionInfoMap handles refcounting properly.
87TEST_F(ExtensionInfoMapTest, RefCounting) {
88 scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap());
89
[email protected]6f229e82010-11-02 17:47:2690 // New extensions should have a single reference holding onto them.
[email protected]66e4eb32010-10-27 20:37:4191 scoped_refptr<Extension> extension1(CreateExtension("extension1"));
92 scoped_refptr<Extension> extension2(CreateExtension("extension2"));
93 scoped_refptr<Extension> extension3(CreateExtension("extension3"));
[email protected]6f229e82010-11-02 17:47:2694 EXPECT_TRUE(extension1->HasOneRef());
95 EXPECT_TRUE(extension2->HasOneRef());
96 EXPECT_TRUE(extension3->HasOneRef());
[email protected]4361c7c2010-09-30 21:57:5397
[email protected]05cc4e72011-03-08 21:29:4898 // Add a ref to each extension and give it to the info map.
[email protected]c357acb42011-06-09 20:52:4299 info_map->AddExtension(extension1, base::Time(), false);
100 info_map->AddExtension(extension2, base::Time(), false);
101 info_map->AddExtension(extension3, base::Time(), false);
[email protected]4361c7c2010-09-30 21:57:53102
[email protected]6f229e82010-11-02 17:47:26103 // Release extension1, and the info map should have the only ref.
104 const Extension* weak_extension1 = extension1;
[email protected]66e4eb32010-10-27 20:37:41105 extension1 = NULL;
[email protected]6f229e82010-11-02 17:47:26106 EXPECT_TRUE(weak_extension1->HasOneRef());
[email protected]4361c7c2010-09-30 21:57:53107
108 // Remove extension2, and the extension2 object should have the only ref.
[email protected]814a7bf0f2011-08-13 05:30:59109 info_map->RemoveExtension(
110 extension2->id(), extension_misc::UNLOAD_REASON_UNINSTALL);
[email protected]6f229e82010-11-02 17:47:26111 EXPECT_TRUE(extension2->HasOneRef());
[email protected]4361c7c2010-09-30 21:57:53112
113 // Delete the info map, and the extension3 object should have the only ref.
114 info_map = NULL;
[email protected]6f229e82010-11-02 17:47:26115 EXPECT_TRUE(extension3->HasOneRef());
[email protected]4361c7c2010-09-30 21:57:53116}
117
118// Tests that we can query a few extension properties from the ExtensionInfoMap.
119TEST_F(ExtensionInfoMapTest, Properties) {
120 scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap());
121
[email protected]66e4eb32010-10-27 20:37:41122 scoped_refptr<Extension> extension1(CreateExtension("extension1"));
123 scoped_refptr<Extension> extension2(CreateExtension("extension2"));
[email protected]4361c7c2010-09-30 21:57:53124
[email protected]c357acb42011-06-09 20:52:42125 info_map->AddExtension(extension1, base::Time(), false);
126 info_map->AddExtension(extension2, base::Time(), false);
[email protected]4361c7c2010-09-30 21:57:53127
[email protected]be0a2cfd2011-06-02 21:36:42128 EXPECT_EQ(2u, info_map->extensions().size());
129 EXPECT_EQ(extension1.get(), info_map->extensions().GetByID(extension1->id()));
130 EXPECT_EQ(extension2.get(), info_map->extensions().GetByID(extension2->id()));
[email protected]4361c7c2010-09-30 21:57:53131}
132
133// Tests CheckURLAccessToExtensionPermission given both extension and app URLs.
134TEST_F(ExtensionInfoMapTest, CheckPermissions) {
135 scoped_refptr<ExtensionInfoMap> info_map(new ExtensionInfoMap());
136
[email protected]66e4eb32010-10-27 20:37:41137 scoped_refptr<Extension> app(LoadManifest("manifest_tests",
[email protected]be0a2cfd2011-06-02 21:36:42138 "valid_app.json"));
[email protected]66e4eb32010-10-27 20:37:41139 scoped_refptr<Extension> extension(LoadManifest("manifest_tests",
[email protected]be0a2cfd2011-06-02 21:36:42140 "tabs_extension.json"));
[email protected]4361c7c2010-09-30 21:57:53141
142 GURL app_url("http://www.google.com/mail/foo.html");
[email protected]69729ca2011-12-02 08:01:25143 WebSecurityOrigin app_origin = WebSecurityOrigin::create(
144 GURL("http://www.google.com/mail/foo.html"));
[email protected]4361c7c2010-09-30 21:57:53145 ASSERT_TRUE(app->is_app());
[email protected]cced75a2011-05-20 08:31:12146 ASSERT_TRUE(app->web_extent().MatchesURL(app_url));
[email protected]4361c7c2010-09-30 21:57:53147
[email protected]c357acb42011-06-09 20:52:42148 info_map->AddExtension(app, base::Time(), false);
149 info_map->AddExtension(extension, base::Time(), false);
[email protected]4361c7c2010-09-30 21:57:53150
151 // The app should have the notifications permission, either from a
152 // chrome-extension URL or from its web extent.
[email protected]615d88f2011-12-13 01:47:44153 const Extension* match = info_map->extensions().GetExtensionOrAppByURL(
[email protected]69729ca2011-12-02 08:01:25154 ExtensionURLInfo(app_origin, app->GetResourceURL("a.html")));
[email protected]be0a2cfd2011-06-02 21:36:42155 EXPECT_TRUE(match &&
[email protected]c2e66e12012-06-27 06:27:06156 match->HasAPIPermission(APIPermission::kNotification));
[email protected]615d88f2011-12-13 01:47:44157 match = info_map->extensions().GetExtensionOrAppByURL(
[email protected]69729ca2011-12-02 08:01:25158 ExtensionURLInfo(app_origin, app_url));
[email protected]be0a2cfd2011-06-02 21:36:42159 EXPECT_TRUE(match &&
[email protected]c2e66e12012-06-27 06:27:06160 match->HasAPIPermission(APIPermission::kNotification));
[email protected]be0a2cfd2011-06-02 21:36:42161 EXPECT_FALSE(match &&
[email protected]c2e66e12012-06-27 06:27:06162 match->HasAPIPermission(APIPermission::kTab));
[email protected]4361c7c2010-09-30 21:57:53163
164 // The extension should have the tabs permission.
[email protected]615d88f2011-12-13 01:47:44165 match = info_map->extensions().GetExtensionOrAppByURL(
[email protected]69729ca2011-12-02 08:01:25166 ExtensionURLInfo(app_origin, extension->GetResourceURL("a.html")));
[email protected]be0a2cfd2011-06-02 21:36:42167 EXPECT_TRUE(match &&
[email protected]c2e66e12012-06-27 06:27:06168 match->HasAPIPermission(APIPermission::kTab));
[email protected]be0a2cfd2011-06-02 21:36:42169 EXPECT_FALSE(match &&
[email protected]c2e66e12012-06-27 06:27:06170 match->HasAPIPermission(APIPermission::kNotification));
[email protected]4361c7c2010-09-30 21:57:53171
172 // Random URL should not have any permissions.
[email protected]69729ca2011-12-02 08:01:25173 GURL evil_url("http://evil.com/a.html");
[email protected]615d88f2011-12-13 01:47:44174 match = info_map->extensions().GetExtensionOrAppByURL(
[email protected]69729ca2011-12-02 08:01:25175 ExtensionURLInfo(WebSecurityOrigin::create(evil_url), evil_url));
176 EXPECT_FALSE(match);
177
178 // Sandboxed origins should not have any permissions.
[email protected]615d88f2011-12-13 01:47:44179 match = info_map->extensions().GetExtensionOrAppByURL(ExtensionURLInfo(
[email protected]69729ca2011-12-02 08:01:25180 WebSecurityOrigin::createFromString(WebString::fromUTF8("null")),
181 app_url));
[email protected]be0a2cfd2011-06-02 21:36:42182 EXPECT_FALSE(match);
[email protected]4361c7c2010-09-30 21:57:53183}
[email protected]5eaba82a2010-10-01 20:55:53184
185} // namespace