summaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-10-31 11:16:26 +0000
committerTorne (Richard Coles) <torne@google.com>2013-10-31 11:16:26 +0000
commit1e9bf3e0803691d0a228da41fc608347b6db4340 (patch)
treeab2e5565f71b4219b3da406e19f16fe306704ef5 /extensions
parentf10b58d5bc6ae3e74076fc4ccca14cbc57ef805c (diff)
downloadchromium_org-1e9bf3e0803691d0a228da41fc608347b6db4340.tar.gz
Merge from Chromium at DEPS revision 232015
This commit was generated by merge_to_master.py. Change-Id: If86767ad396b9e2e1a4c1e9df1427daea29703ef
Diffstat (limited to 'extensions')
-rw-r--r--extensions/browser/DEPS27
-rw-r--r--extensions/browser/OWNERS7
-rw-r--r--extensions/browser/extensions_browser_client.cc28
-rw-r--r--extensions/browser/extensions_browser_client.h51
-rw-r--r--extensions/browser/lazy_background_task_queue.cc191
-rw-r--r--extensions/browser/lazy_background_task_queue.h89
-rw-r--r--extensions/browser/lazy_background_task_queue_unittest.cc195
-rw-r--r--extensions/common/extensions_client.h18
-rw-r--r--extensions/common/manifest_constants.cc9
-rw-r--r--extensions/common/manifest_constants.h7
-rw-r--r--extensions/common/permissions/api_permission.h2
-rw-r--r--extensions/common/permissions/permission_message.h1
-rw-r--r--extensions/common/permissions/permission_set.cc251
-rw-r--r--extensions/common/permissions/permission_set.h143
-rw-r--r--extensions/extensions.gyp9
15 files changed, 1024 insertions, 4 deletions
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index 1c35d9ca69..3c1ac11cc4 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -1,3 +1,30 @@
include_rules = [
"+content/public/browser",
+
+ # Temporarily allowed includes as part of the app shell/extensions refactor.
+ #
+ # NOTE: Please do not add includes without talking to the app shell team;
+ # see OWNERS for this directory.
+ #
+ # TODO(jamescook): Remove these. http://crbug.com/162530
+ "+chrome/browser/chrome_notification_types.h",
+ "+chrome/browser/extensions/extension_host.h",
+ "+chrome/browser/extensions/extension_process_manager.h",
+ "+chrome/browser/extensions/extension_service.h",
+ "+chrome/browser/extensions/extension_system.h",
+ "+chrome/browser/extensions/process_map.h",
+ "+chrome/common/extensions/background_info.h",
+ "+chrome/common/extensions/extension.h",
+ "+chrome/common/extensions/extension_messages.h",
]
+
+specific_include_rules = {
+ ".*test\.cc": [
+ # Temporarily allowed testing includes. See above.
+ # TODO(jamescook): Remove these. http://crbug.com/159366
+ "+chrome/browser/extensions/extension_service_unittest.h",
+ "+chrome/browser/extensions/test_extension_system.h",
+ "+chrome/common/extensions/extension_builder.h",
+ "+chrome/test/base/testing_profile.h",
+ ]
+}
diff --git a/extensions/browser/OWNERS b/extensions/browser/OWNERS
new file mode 100644
index 0000000000..b06f377b52
--- /dev/null
+++ b/extensions/browser/OWNERS
@@ -0,0 +1,7 @@
+# Please talk to the apps shell team before adding DEPS.
+per-file DEPS=set noparent
+per-file DEPS=benwells@chromium.org
+per-file DEPS=derat@chromium.org
+per-file DEPS=jamescook@chromium.org
+per-file DEPS=miket@chromium.org
+per-file DEPS=yoz@chromium.org
diff --git a/extensions/browser/extensions_browser_client.cc b/extensions/browser/extensions_browser_client.cc
new file mode 100644
index 0000000000..2724d47623
--- /dev/null
+++ b/extensions/browser/extensions_browser_client.cc
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/extensions_browser_client.h"
+
+#include "base/basictypes.h"
+
+namespace extensions {
+
+namespace {
+
+ExtensionsBrowserClient* g_client = NULL;
+
+} // namespace
+
+ExtensionsBrowserClient* ExtensionsBrowserClient::Get() {
+ return g_client;
+}
+
+void ExtensionsBrowserClient::Set(ExtensionsBrowserClient* client) {
+ // This can happen in tests.
+ if (g_client)
+ return;
+ g_client = client;
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extensions_browser_client.h b/extensions/browser/extensions_browser_client.h
new file mode 100644
index 0000000000..4810836781
--- /dev/null
+++ b/extensions/browser/extensions_browser_client.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_CLIENT_H_
+#define EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_CLIENT_H_
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+// Interface to allow the extensions module to make browser-process-specific
+// queries of the embedder. Should be Set() once in the browser process.
+//
+// NOTE: Methods that do not require knowledge of browser concepts should be
+// added in ExtensionsClient (extensions/common/extensions_client.h) even if
+// they are only used in the browser process.
+class ExtensionsBrowserClient {
+ public:
+ virtual ~ExtensionsBrowserClient() {}
+
+ // Returns true if the embedder has started shutting down.
+ virtual bool IsShuttingDown() = 0;
+
+ // Returns true if the BrowserContexts could be considered equivalent, for
+ // example, if one is an off-the-record context owned by the other.
+ virtual bool IsSameContext(content::BrowserContext* first,
+ content::BrowserContext* second) = 0;
+
+ // Returns true if |context| has an off-the-record content associated with it.
+ virtual bool HasOffTheRecordContext(content::BrowserContext* context) = 0;
+
+ // Returns the off-the-record context associated with |context|. If |context|
+ // is already off-the-record, returns |context|.
+ // WARNING: This may create a new off-the-record context. To avoid creating
+ // another context, check HasOffTheRecordContext() first.
+ virtual content::BrowserContext* GetOffTheRecordContext(
+ content::BrowserContext* context) = 0;
+
+ // Returns the single instance of |this|.
+ static ExtensionsBrowserClient* Get();
+
+ // Initialize the single instance.
+ static void Set(ExtensionsBrowserClient* client);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_CLIENT_H_
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc
new file mode 100644
index 0000000000..584d897e2e
--- /dev/null
+++ b/extensions/browser/lazy_background_task_queue.cc
@@ -0,0 +1,191 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/lazy_background_task_queue.h"
+
+#include "base/callback.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/process_map.h"
+#include "chrome/common/extensions/background_info.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/common/view_type.h"
+
+namespace extensions {
+
+LazyBackgroundTaskQueue::LazyBackgroundTaskQueue(
+ content::BrowserContext* browser_context)
+ : browser_context_(browser_context) {
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
+ content::Source<content::BrowserContext>(browser_context));
+}
+
+LazyBackgroundTaskQueue::~LazyBackgroundTaskQueue() {
+}
+
+bool LazyBackgroundTaskQueue::ShouldEnqueueTask(
+ content::BrowserContext* browser_context,
+ const Extension* extension) {
+ DCHECK(extension);
+ if (BackgroundInfo::HasBackgroundPage(extension)) {
+ ExtensionProcessManager* pm = ExtensionSystem::GetForBrowserContext(
+ browser_context)->process_manager();
+ DCHECK(pm);
+ ExtensionHost* background_host =
+ pm->GetBackgroundHostForExtension(extension->id());
+ if (!background_host || !background_host->did_stop_loading())
+ return true;
+ if (pm->IsBackgroundHostClosing(extension->id()))
+ pm->CancelSuspend(extension);
+ }
+
+ return false;
+}
+
+void LazyBackgroundTaskQueue::AddPendingTask(
+ content::BrowserContext* browser_context,
+ const std::string& extension_id,
+ const PendingTask& task) {
+ if (ExtensionsBrowserClient::Get()->IsShuttingDown()) {
+ task.Run(NULL);
+ return;
+ }
+ PendingTasksList* tasks_list = NULL;
+ PendingTasksKey key(browser_context, extension_id);
+ PendingTasksMap::iterator it = pending_tasks_.find(key);
+ if (it == pending_tasks_.end()) {
+ tasks_list = new PendingTasksList();
+ pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list);
+
+ ExtensionService* extension_service = ExtensionSystem::GetForBrowserContext(
+ browser_context)->extension_service();
+ DCHECK(extension_service);
+ const Extension* extension =
+ extension_service->extensions()->GetByID(extension_id);
+ if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) {
+ // If this is the first enqueued task, and we're not waiting for the
+ // background page to unload, ensure the background page is loaded.
+ ExtensionProcessManager* pm = ExtensionSystem::GetForBrowserContext(
+ browser_context)->process_manager();
+ pm->IncrementLazyKeepaliveCount(extension);
+ // Creating the background host may fail, e.g. if |profile| is incognito
+ // but the extension isn't enabled in incognito mode.
+ if (!pm->CreateBackgroundHost(
+ extension, BackgroundInfo::GetBackgroundURL(extension))) {
+ task.Run(NULL);
+ return;
+ }
+ }
+ } else {
+ tasks_list = it->second.get();
+ }
+
+ tasks_list->push_back(task);
+}
+
+void LazyBackgroundTaskQueue::ProcessPendingTasks(
+ ExtensionHost* host,
+ content::BrowserContext* browser_context,
+ const Extension* extension) {
+ if (!ExtensionsBrowserClient::Get()->IsSameContext(browser_context,
+ browser_context_))
+ return;
+
+ PendingTasksKey key(browser_context, extension->id());
+ PendingTasksMap::iterator map_it = pending_tasks_.find(key);
+ if (map_it == pending_tasks_.end()) {
+ if (BackgroundInfo::HasLazyBackgroundPage(extension))
+ CHECK(!host); // lazy page should not load without any pending tasks
+ return;
+ }
+
+ // Swap the pending tasks to a temporary, to avoid problems if the task
+ // list is modified during processing.
+ PendingTasksList tasks;
+ tasks.swap(*map_it->second);
+ for (PendingTasksList::const_iterator it = tasks.begin();
+ it != tasks.end(); ++it) {
+ it->Run(host);
+ }
+
+ pending_tasks_.erase(key);
+
+ // Balance the keepalive in AddPendingTask. Note we don't do this on a
+ // failure to load, because the keepalive count is reset in that case.
+ if (host && BackgroundInfo::HasLazyBackgroundPage(extension)) {
+ ExtensionSystem::GetForBrowserContext(browser_context)->process_manager()->
+ DecrementLazyKeepaliveCount(extension);
+ }
+}
+
+void LazyBackgroundTaskQueue::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
+ // If an on-demand background page finished loading, dispatch queued up
+ // events for it.
+ ExtensionHost* host =
+ content::Details<ExtensionHost>(details).ptr();
+ if (host->extension_host_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
+ CHECK(host->did_stop_loading());
+ ProcessPendingTasks(host, host->browser_context(), host->extension());
+ }
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
+ // Notify consumers about the load failure when the background host dies.
+ // This can happen if the extension crashes. This is not strictly
+ // necessary, since we also unload the extension in that case (which
+ // dispatches the tasks below), but is a good extra precaution.
+ content::BrowserContext* browser_context =
+ content::Source<content::BrowserContext>(source).ptr();
+ ExtensionHost* host =
+ content::Details<ExtensionHost>(details).ptr();
+ if (host->extension_host_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
+ ProcessPendingTasks(NULL, browser_context, host->extension());
+ }
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
+ // Notify consumers that the page failed to load.
+ content::BrowserContext* browser_context =
+ content::Source<content::BrowserContext>(source).ptr();
+ UnloadedExtensionInfo* unloaded =
+ content::Details<UnloadedExtensionInfo>(details).ptr();
+ ProcessPendingTasks(NULL, browser_context, unloaded->extension);
+ // If this extension is also running in an off-the-record context,
+ // notify that task queue as well.
+ ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
+ if (browser_client->HasOffTheRecordContext(browser_context)) {
+ ProcessPendingTasks(
+ NULL,
+ browser_client->GetOffTheRecordContext(browser_context),
+ unloaded->extension);
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+} // namespace extensions
diff --git a/extensions/browser/lazy_background_task_queue.h b/extensions/browser/lazy_background_task_queue.h
new file mode 100644
index 0000000000..a92ec7c383
--- /dev/null
+++ b/extensions/browser/lazy_background_task_queue.h
@@ -0,0 +1,89 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_LAZY_BACKGROUND_TASK_QUEUE_H_
+#define EXTENSIONS_BROWSER_LAZY_BACKGROUND_TASK_QUEUE_H_
+
+#include <map>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/linked_ptr.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class Extension;
+class ExtensionHost;
+
+// This class maintains a queue of tasks that should execute when an
+// extension's lazy background page is loaded. It is also in charge of loading
+// the page when the first task is queued.
+//
+// It is the consumer's responsibility to use this class when appropriate, i.e.
+// only with extensions that have not-yet-loaded lazy background pages.
+class LazyBackgroundTaskQueue : public content::NotificationObserver {
+ public:
+ typedef base::Callback<void(ExtensionHost*)> PendingTask;
+
+ explicit LazyBackgroundTaskQueue(content::BrowserContext* browser_context);
+ virtual ~LazyBackgroundTaskQueue();
+
+ // Returns the number of extensions having pending tasks.
+ size_t extensions_with_pending_tasks() { return pending_tasks_.size(); }
+
+ // Returns true if the task should be added to the queue (that is, if the
+ // extension has a lazy background page that isn't ready yet). If the
+ // extension has a lazy background page that is being suspended this method
+ // cancels that suspension.
+ bool ShouldEnqueueTask(content::BrowserContext* context,
+ const Extension* extension);
+
+ // Adds a task to the queue for a given extension. If this is the first
+ // task added for the extension, its lazy background page will be loaded.
+ // The task will be called either when the page is loaded, or when the
+ // page fails to load for some reason (e.g. a crash or browser
+ // shutdown). In the latter case, the ExtensionHost parameter is NULL.
+ void AddPendingTask(
+ content::BrowserContext* context,
+ const std::string& extension_id,
+ const PendingTask& task);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(LazyBackgroundTaskQueueTest, ProcessPendingTasks);
+
+ // A map between a BrowserContext/extension_id pair and the queue of tasks
+ // pending the load of its background page.
+ typedef std::string ExtensionID;
+ typedef std::pair<content::BrowserContext*, ExtensionID> PendingTasksKey;
+ typedef std::vector<PendingTask> PendingTasksList;
+ typedef std::map<PendingTasksKey,
+ linked_ptr<PendingTasksList> > PendingTasksMap;
+
+ // content::NotificationObserver interface.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // Called when a lazy background page has finished loading, or has failed to
+ // load (host is NULL in that case). All enqueued tasks are run in order.
+ void ProcessPendingTasks(
+ ExtensionHost* host,
+ content::BrowserContext* context,
+ const Extension* extension);
+
+ content::BrowserContext* browser_context_;
+ content::NotificationRegistrar registrar_;
+ PendingTasksMap pending_tasks_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_LAZY_BACKGROUND_TASK_QUEUE_H_
diff --git a/extensions/browser/lazy_background_task_queue_unittest.cc b/extensions/browser/lazy_background_task_queue_unittest.cc
new file mode 100644
index 0000000000..27d847152f
--- /dev/null
+++ b/extensions/browser/lazy_background_task_queue_unittest.cc
@@ -0,0 +1,195 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/lazy_background_task_queue.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/extensions/extension_service_unittest.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_builder.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+// An ExtensionProcessManager that doesn't create background host pages.
+class TestExtensionProcessManager : public ExtensionProcessManager {
+ public:
+ explicit TestExtensionProcessManager(Profile* profile)
+ : ExtensionProcessManager(profile),
+ create_count_(0) {}
+ virtual ~TestExtensionProcessManager() {}
+
+ int create_count() { return create_count_; }
+
+ // ExtensionProcessManager overrides:
+ virtual extensions::ExtensionHost* CreateBackgroundHost(
+ const extensions::Extension* extension,
+ const GURL& url) OVERRIDE {
+ // Don't actually try to create a web contents.
+ create_count_++;
+ return NULL;
+ }
+
+ private:
+ int create_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestExtensionProcessManager);
+};
+
+// Derives from ExtensionServiceTestBase because ExtensionService is difficult
+// to initialize alone.
+class LazyBackgroundTaskQueueTest : public ExtensionServiceTestBase {
+ public:
+ LazyBackgroundTaskQueueTest() : task_run_count_(0) {}
+ virtual ~LazyBackgroundTaskQueueTest() {}
+
+ int task_run_count() { return task_run_count_; }
+
+ // A simple callback for AddPendingTask.
+ void RunPendingTask(ExtensionHost* host) {
+ task_run_count_++;
+ }
+
+ // Creates and registers an extension without a background page.
+ scoped_refptr<Extension> CreateSimpleExtension() {
+ scoped_refptr<Extension> extension = ExtensionBuilder()
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "No background")
+ .Set("version", "1")
+ .Set("manifest_version", 2))
+ .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ .Build();
+ service_->AddExtension(extension);
+ return extension;
+ }
+
+ // Creates and registers an extension with a lazy background page.
+ scoped_refptr<Extension> CreateLazyBackgroundExtension() {
+ scoped_refptr<Extension> extension = ExtensionBuilder()
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "Lazy background")
+ .Set("version", "1")
+ .Set("manifest_version", 2)
+ .Set("background",
+ DictionaryBuilder()
+ .Set("page", "background.html")
+ .SetBoolean("persistent", false)))
+ .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
+ .Build();
+ service_->AddExtension(extension);
+ return extension;
+ }
+
+ private:
+ // The total number of pending tasks that have been executed.
+ int task_run_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest);
+};
+
+// Tests that only extensions with background pages should have tasks queued.
+TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) {
+ InitializeEmptyExtensionService();
+ InitializeExtensionProcessManager();
+
+ LazyBackgroundTaskQueue queue(profile_.get());
+
+ // Build a simple extension with no background page.
+ scoped_refptr<Extension> no_background = CreateSimpleExtension();
+ EXPECT_FALSE(queue.ShouldEnqueueTask(profile_.get(), no_background.get()));
+
+ // Build another extension with a background page.
+ scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension();
+ EXPECT_TRUE(queue.ShouldEnqueueTask(profile_.get(), with_background.get()));
+}
+
+// Tests that adding tasks actually increases the pending task count, and that
+// multiple extensions can have pending tasks.
+TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) {
+ InitializeEmptyExtensionService();
+
+ // Swap in our stub TestExtensionProcessManager.
+ TestExtensionSystem* extension_system =
+ static_cast<extensions::TestExtensionSystem*>(
+ ExtensionSystem::Get(profile_.get()));
+ // Owned by |extension_system|.
+ TestExtensionProcessManager* process_manager =
+ new TestExtensionProcessManager(profile_.get());
+ extension_system->SetExtensionProcessManager(process_manager);
+
+ LazyBackgroundTaskQueue queue(profile_.get());
+
+ // Build a simple extension with no background page.
+ scoped_refptr<Extension> no_background = CreateSimpleExtension();
+
+ // Adding a pending task increases the number of extensions with tasks, but
+ // doesn't run the task.
+ queue.AddPendingTask(profile_.get(),
+ no_background->id(),
+ base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
+ base::Unretained(this)));
+ EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
+ EXPECT_EQ(0, task_run_count());
+
+ // Another task on the same extension doesn't increase the number of
+ // extensions that have tasks and doesn't run any tasks.
+ queue.AddPendingTask(profile_.get(),
+ no_background->id(),
+ base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
+ base::Unretained(this)));
+ EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
+ EXPECT_EQ(0, task_run_count());
+
+ // Adding a task on an extension with a lazy background page tries to create
+ // a background host, and if that fails, runs the task immediately.
+ scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension();
+ queue.AddPendingTask(profile_.get(),
+ lazy_background->id(),
+ base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
+ base::Unretained(this)));
+ EXPECT_EQ(2u, queue.extensions_with_pending_tasks());
+ // The process manager tried to create a background host.
+ EXPECT_EQ(1, process_manager->create_count());
+ // The task ran immediately because the creation failed.
+ EXPECT_EQ(1, task_run_count());
+}
+
+// Tests that pending tasks are actually run.
+TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) {
+ InitializeEmptyExtensionService();
+
+ LazyBackgroundTaskQueue queue(profile_.get());
+
+ // ProcessPendingTasks is a no-op if there are no tasks.
+ scoped_refptr<Extension> extension = CreateSimpleExtension();
+ queue.ProcessPendingTasks(NULL, profile_.get(), extension);
+ EXPECT_EQ(0, task_run_count());
+
+ // Schedule a task to run.
+ queue.AddPendingTask(profile_.get(),
+ extension->id(),
+ base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
+ base::Unretained(this)));
+ EXPECT_EQ(0, task_run_count());
+ EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
+
+ // Trying to run tasks for an unrelated profile should do nothing.
+ TestingProfile profile2;
+ queue.ProcessPendingTasks(NULL, &profile2, extension);
+ EXPECT_EQ(0, task_run_count());
+ EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
+
+ // Processing tasks when there is one pending runs the task and removes the
+ // extension from the list of extensions with pending tasks.
+ queue.ProcessPendingTasks(NULL, profile_.get(), extension);
+ EXPECT_EQ(1, task_run_count());
+ EXPECT_EQ(0u, queue.extensions_with_pending_tasks());
+}
+
+} // namespace extensions
diff --git a/extensions/common/extensions_client.h b/extensions/common/extensions_client.h
index ed06d32287..71a4dfded1 100644
--- a/extensions/common/extensions_client.h
+++ b/extensions/common/extensions_client.h
@@ -7,9 +7,12 @@
#include <set>
#include <string>
+#include <vector>
namespace extensions {
+class APIPermissionSet;
+class Extension;
class FeatureProvider;
class PermissionMessage;
class PermissionMessageProvider;
@@ -20,6 +23,8 @@ class URLPatternSet;
// process. This should be implemented by the client of the extensions system.
class ExtensionsClient {
public:
+ typedef std::vector<std::string> ScriptingWhitelist;
+
// Initializes global state. Not done in the constructor because unit tests
// can create additional ExtensionsClients because the utility thread runs
// in-process.
@@ -45,6 +50,19 @@ class ExtensionsClient {
URLPatternSet* new_hosts,
std::set<PermissionMessage>* messages) const = 0;
+ // Replaces the scripting whitelist with |whitelist|. Used in the renderer;
+ // only used for testing in the browser process.
+ virtual void SetScriptingWhitelist(const ScriptingWhitelist& whitelist) = 0;
+
+ // Return the whitelist of extensions that can run content scripts on
+ // any origin.
+ virtual const ScriptingWhitelist& GetScriptingWhitelist() const = 0;
+
+ // Get the set of chrome:// hosts that |extension| can run content scripts on.
+ virtual URLPatternSet GetPermittedChromeSchemeHosts(
+ const Extension* extension,
+ const APIPermissionSet& api_permissions) const = 0;
+
// Return the extensions client.
static ExtensionsClient* Get();
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc
index c03e3f4553..26df7ceaba 100644
--- a/extensions/common/manifest_constants.cc
+++ b/extensions/common/manifest_constants.cc
@@ -111,6 +111,8 @@ const char kRunAt[] = "run_at";
const char kSandboxedPages[] = "sandbox.pages";
const char kSandboxedPagesCSP[] = "sandbox.content_security_policy";
const char kScriptBadge[] = "script_badge";
+const char kSearchProvider[] = "chrome_settings_overrides.search_provider";
+const char kSettingsOverride[] = "chrome_settings_overrides";
const char kShiftKey[] = "shiftKey";
const char kShortcutKey[] = "shortcutKey";
const char kShortName[] = "short_name";
@@ -149,7 +151,6 @@ const char kUrlHandlers[] = "url_handlers";
const char kUrlHandlerTitle[] = "title";
const char kVersion[] = "version";
const char kWebAccessibleResources[] = "web_accessible_resources";
-const char kWebRtc[] = "webrtc";
const char kWebURLs[] = "app.urls";
const char kWebview[] = "webview";
const char kWebviewAccessibleResources[] = "accessible_resources";
@@ -337,6 +338,8 @@ const char kInvalidGlob[] =
"Invalid value for 'content_scripts[*].*[*]'.";
const char kInvalidGlobList[] =
"Invalid value for 'content_scripts[*].*'.";
+const char kInvalidHomepageOverrideURL[] =
+ "Invalid value for overriding homepage url: '[*]'.";
const char kInvalidHomepageURL[] =
"Invalid value for homepage url: '[*]'.";
const char kInvalidIconPath[] =
@@ -528,6 +531,8 @@ const char kInvalidSandboxedPagesCSP[] =
"Invalid value for 'sandbox.content_security_policy'.";
const char kInvalidScriptBadge[] =
"Invalid value for 'script_badge'.";
+const char kInvalidEmptySettingsOverrides[] =
+ "Empty dictionary for 'chrome_settings_overrides'.";
const char kInvalidShortName[] =
"Invalid value for 'short_name'.";
const char kInvalidSignature[] =
@@ -542,6 +547,8 @@ const char kInvalidSpellcheckDictionaryLocale[] =
"Invalid value for spellcheck dictionary locale.";
const char kInvalidSpellcheckDictionaryPath[] =
"Invalid value for spellcheck dictionary path.";
+const char kInvalidStartupOverrideURL[] =
+ "Invalid value for overriding startup URL: '[*]'.";
const char kInvalidSystemIndicator[] =
"Invalid value for 'system_indicator'.";
const char kInvalidTheme[] =
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h
index bf78fa5978..846845e200 100644
--- a/extensions/common/manifest_constants.h
+++ b/extensions/common/manifest_constants.h
@@ -48,7 +48,6 @@ extern const char kFileHandlerTypes[];
extern const char kFileFilters[];
extern const char kFileBrowserHandlers[];
extern const char kGlobal[];
-extern const char kMediaGalleriesHandlers[];
extern const char kHomepageURL[];
extern const char kIcons[];
extern const char kId[];
@@ -79,6 +78,7 @@ extern const char kLaunchWidth[];
extern const char kLayouts[];
extern const char kManifestVersion[];
extern const char kMatches[];
+extern const char kMediaGalleriesHandlers[];
extern const char kMIMETypes[];
extern const char kMimeTypesHandler[];
extern const char kMinimumChromeVersion[];
@@ -120,6 +120,8 @@ extern const char kRunAt[];
extern const char kSandboxedPages[];
extern const char kSandboxedPagesCSP[];
extern const char kScriptBadge[];
+extern const char kSearchProvider[];
+extern const char kSettingsOverride[];
extern const char kShiftKey[];
extern const char kShortcutKey[];
extern const char kShortName[];
@@ -283,6 +285,7 @@ extern const char kInvalidFileHandlerType[];
extern const char kInvalidFileHandlerTypeElement[];
extern const char kInvalidGlob[];
extern const char kInvalidGlobList[];
+extern const char kInvalidHomepageOverrideURL[];
extern const char kInvalidHomepageURL[];
extern const char kInvalidIconPath[];
extern const char kInvalidIcons[];
@@ -374,6 +377,7 @@ extern const char kInvalidSandboxedPagesList[];
extern const char kInvalidSandboxedPage[];
extern const char kInvalidSandboxedPagesCSP[];
extern const char kInvalidScriptBadge[];
+extern const char kInvalidEmptySettingsOverrides[];
extern const char kInvalidShortName[];
extern const char kInvalidSignature[];
extern const char kInvalidSpellcheck[];
@@ -381,6 +385,7 @@ extern const char kInvalidSpellcheckDictionaryFormat[];
extern const char kInvalidSpellcheckDictionaryLanguage[];
extern const char kInvalidSpellcheckDictionaryLocale[];
extern const char kInvalidSpellcheckDictionaryPath[];
+extern const char kInvalidStartupOverrideURL[];
extern const char kInvalidSystemIndicator[];
extern const char kInvalidTheme[];
extern const char kInvalidThemeColors[];
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index 7dd42c0046..2ff17eaef4 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -91,7 +91,6 @@ class APIPermission {
kGeolocation,
kHistory,
kIdentity,
- kIdentityEmail,
kIdentityPrivate,
kIdltest,
kIdle,
@@ -154,6 +153,7 @@ class APIPermission {
kWebRequestBlocking,
kWebRequestInternal,
kWebRtc,
+ kWebrtcAudioPrivate,
kWebrtcLoggingPrivate,
kWebstorePrivate,
kWebView,
diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h
index 3b745b2fa9..19c5799e71 100644
--- a/extensions/common/permissions/permission_message.h
+++ b/extensions/common/permissions/permission_message.h
@@ -74,7 +74,6 @@ class PermissionMessage {
kSignedInDevices,
kWallpaper,
kNetworkState,
- kIdentityEmail,
kEnumBoundary,
};
COMPILE_ASSERT(PermissionMessage::kNone > PermissionMessage::kUnknown,
diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc
new file mode 100644
index 0000000000..d3f46fc194
--- /dev/null
+++ b/extensions/common/permissions/permission_set.cc
@@ -0,0 +1,251 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/permission_set.h"
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+#include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/url_pattern.h"
+#include "extensions/common/url_pattern_set.h"
+#include "url/gurl.h"
+
+using extensions::URLPatternSet;
+
+namespace {
+
+void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) {
+ DCHECK(out);
+ for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) {
+ URLPattern p = *i;
+ p.SetPath("/*");
+ out->AddPattern(p);
+ }
+}
+
+} // namespace
+
+namespace extensions {
+
+//
+// PermissionSet
+//
+
+PermissionSet::PermissionSet() {}
+
+PermissionSet::PermissionSet(
+ const APIPermissionSet& apis,
+ const URLPatternSet& explicit_hosts,
+ const URLPatternSet& scriptable_hosts)
+ : apis_(apis),
+ scriptable_hosts_(scriptable_hosts) {
+ AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
+ InitImplicitPermissions();
+ InitEffectiveHosts();
+}
+
+// static
+PermissionSet* PermissionSet::CreateDifference(
+ const PermissionSet* set1,
+ const PermissionSet* set2) {
+ scoped_refptr<PermissionSet> empty = new PermissionSet();
+ const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
+ const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
+
+ APIPermissionSet apis;
+ APIPermissionSet::Difference(set1_safe->apis(), set2_safe->apis(), &apis);
+
+ URLPatternSet explicit_hosts;
+ URLPatternSet::CreateDifference(set1_safe->explicit_hosts(),
+ set2_safe->explicit_hosts(),
+ &explicit_hosts);
+
+ URLPatternSet scriptable_hosts;
+ URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(),
+ set2_safe->scriptable_hosts(),
+ &scriptable_hosts);
+
+ return new PermissionSet(apis, explicit_hosts, scriptable_hosts);
+}
+
+// static
+PermissionSet* PermissionSet::CreateIntersection(
+ const PermissionSet* set1,
+ const PermissionSet* set2) {
+ scoped_refptr<PermissionSet> empty = new PermissionSet();
+ const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
+ const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
+
+ APIPermissionSet apis;
+ APIPermissionSet::Intersection(set1_safe->apis(), set2_safe->apis(), &apis);
+
+ URLPatternSet explicit_hosts;
+ URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(),
+ set2_safe->explicit_hosts(),
+ &explicit_hosts);
+
+ URLPatternSet scriptable_hosts;
+ URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(),
+ set2_safe->scriptable_hosts(),
+ &scriptable_hosts);
+
+ return new PermissionSet(apis, explicit_hosts, scriptable_hosts);
+}
+
+// static
+PermissionSet* PermissionSet::CreateUnion(
+ const PermissionSet* set1,
+ const PermissionSet* set2) {
+ scoped_refptr<PermissionSet> empty = new PermissionSet();
+ const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
+ const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
+
+ APIPermissionSet apis;
+ APIPermissionSet::Union(set1_safe->apis(), set2_safe->apis(), &apis);
+
+ URLPatternSet explicit_hosts;
+ URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
+ set2_safe->explicit_hosts(),
+ &explicit_hosts);
+
+ URLPatternSet scriptable_hosts;
+ URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
+ set2_safe->scriptable_hosts(),
+ &scriptable_hosts);
+
+ return new PermissionSet(apis, explicit_hosts, scriptable_hosts);
+}
+
+bool PermissionSet::operator==(
+ const PermissionSet& rhs) const {
+ return apis_ == rhs.apis_ &&
+ scriptable_hosts_ == rhs.scriptable_hosts_ &&
+ explicit_hosts_ == rhs.explicit_hosts_;
+}
+
+bool PermissionSet::Contains(const PermissionSet& set) const {
+ return apis_.Contains(set.apis()) &&
+ explicit_hosts().Contains(set.explicit_hosts()) &&
+ scriptable_hosts().Contains(set.scriptable_hosts());
+}
+
+std::set<std::string> PermissionSet::GetAPIsAsStrings() const {
+ std::set<std::string> apis_str;
+ for (APIPermissionSet::const_iterator i = apis_.begin();
+ i != apis_.end(); ++i) {
+ apis_str.insert(i->name());
+ }
+ return apis_str;
+}
+
+bool PermissionSet::IsEmpty() const {
+ // Not default if any host permissions are present.
+ if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
+ return false;
+
+ // Or if it has no api permissions.
+ return apis().empty();
+}
+
+bool PermissionSet::HasAPIPermission(
+ APIPermission::ID id) const {
+ return apis().find(id) != apis().end();
+}
+
+bool PermissionSet::HasAPIPermission(const std::string& permission_name) const {
+ const APIPermissionInfo* permission =
+ PermissionsInfo::GetInstance()->GetByName(permission_name);
+ CHECK(permission) << permission_name;
+ return (permission && apis_.count(permission->id()));
+}
+
+bool PermissionSet::CheckAPIPermission(APIPermission::ID permission) const {
+ return CheckAPIPermissionWithParam(permission, NULL);
+}
+
+bool PermissionSet::CheckAPIPermissionWithParam(
+ APIPermission::ID permission,
+ const APIPermission::CheckParam* param) const {
+ APIPermissionSet::const_iterator iter = apis().find(permission);
+ if (iter == apis().end())
+ return false;
+ return iter->Check(param);
+}
+
+bool PermissionSet::HasExplicitAccessToOrigin(
+ const GURL& origin) const {
+ return explicit_hosts().MatchesURL(origin);
+}
+
+bool PermissionSet::HasScriptableAccessToURL(
+ const GURL& origin) const {
+ // We only need to check our host list to verify access. The host list should
+ // already reflect any special rules (such as chrome://favicon, all hosts
+ // access, etc.).
+ return scriptable_hosts().MatchesURL(origin);
+}
+
+bool PermissionSet::HasEffectiveAccessToAllHosts() const {
+ // There are two ways this set can have effective access to all hosts:
+ // 1) it has an <all_urls> URL pattern.
+ // 2) it has a named permission with implied full URL access.
+ for (URLPatternSet::const_iterator host = effective_hosts().begin();
+ host != effective_hosts().end(); ++host) {
+ if (host->match_all_urls() ||
+ (host->match_subdomains() && host->host().empty()))
+ return true;
+ }
+
+ for (APIPermissionSet::const_iterator i = apis().begin();
+ i != apis().end(); ++i) {
+ if (i->info()->implies_full_url_access())
+ return true;
+ }
+ return false;
+}
+
+bool PermissionSet::HasEffectiveAccessToURL(const GURL& url) const {
+ return effective_hosts().MatchesURL(url);
+}
+
+bool PermissionSet::HasEffectiveFullAccess() const {
+ for (APIPermissionSet::const_iterator i = apis().begin();
+ i != apis().end(); ++i) {
+ if (i->info()->implies_full_access())
+ return true;
+ }
+ return false;
+}
+
+PermissionSet::~PermissionSet() {}
+
+void PermissionSet::InitImplicitPermissions() {
+ // The downloads permission implies the internal version as well.
+ if (apis_.find(APIPermission::kDownloads) != apis_.end())
+ apis_.insert(APIPermission::kDownloadsInternal);
+
+ // TODO(fsamuel): Is there a better way to request access to the WebRequest
+ // API without exposing it to the Chrome App?
+ if (apis_.find(APIPermission::kWebView) != apis_.end())
+ apis_.insert(APIPermission::kWebRequestInternal);
+
+ // The webRequest permission implies the internal version as well.
+ if (apis_.find(APIPermission::kWebRequest) != apis_.end())
+ apis_.insert(APIPermission::kWebRequestInternal);
+
+ // The fileBrowserHandler permission implies the internal version as well.
+ if (apis_.find(APIPermission::kFileBrowserHandler) != apis_.end())
+ apis_.insert(APIPermission::kFileBrowserHandlerInternal);
+}
+
+void PermissionSet::InitEffectiveHosts() {
+ effective_hosts_.ClearPatterns();
+
+ URLPatternSet::CreateUnion(
+ explicit_hosts(), scriptable_hosts(), &effective_hosts_);
+}
+
+} // namespace extensions
diff --git a/extensions/common/permissions/permission_set.h b/extensions/common/permissions/permission_set.h
new file mode 100644
index 0000000000..14ffe12cda
--- /dev/null
+++ b/extensions/common/permissions/permission_set.h
@@ -0,0 +1,143 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_SET_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_SET_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/strings/string16.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/api_permission_set.h"
+#include "extensions/common/url_pattern_set.h"
+
+namespace extensions {
+class Extension;
+
+// The PermissionSet is an immutable class that encapsulates an
+// extension's permissions. The class exposes set operations for combining and
+// manipulating the permissions.
+class PermissionSet
+ : public base::RefCountedThreadSafe<PermissionSet> {
+ public:
+ // Creates an empty permission set (e.g. default permissions).
+ PermissionSet();
+
+ // Creates a new permission set based on the specified data: the API
+ // permissions, host permissions, and scriptable hosts. The effective hosts
+ // of the newly created permission set will be inferred from the given
+ // host permissions.
+ PermissionSet(const APIPermissionSet& apis,
+ const URLPatternSet& explicit_hosts,
+ const URLPatternSet& scriptable_hosts);
+
+ // Creates a new permission set equal to |set1| - |set2|, passing ownership of
+ // the new set to the caller.
+ static PermissionSet* CreateDifference(
+ const PermissionSet* set1, const PermissionSet* set2);
+
+ // Creates a new permission set equal to the intersection of |set1| and
+ // |set2|, passing ownership of the new set to the caller.
+ static PermissionSet* CreateIntersection(
+ const PermissionSet* set1, const PermissionSet* set2);
+
+ // Creates a new permission set equal to the union of |set1| and |set2|.
+ // Passes ownership of the new set to the caller.
+ static PermissionSet* CreateUnion(
+ const PermissionSet* set1, const PermissionSet* set2);
+
+ bool operator==(const PermissionSet& rhs) const;
+
+ // Returns true if every API or host permission available to |set| is also
+ // available to this. In other words, if the API permissions of |set| are a
+ // subset of this, and the host permissions in this encompass those in |set|.
+ bool Contains(const PermissionSet& set) const;
+
+ // Gets the API permissions in this set as a set of strings.
+ std::set<std::string> GetAPIsAsStrings() const;
+
+ // Returns true if this is an empty set (e.g., the default permission set).
+ bool IsEmpty() const;
+
+ // Returns true if the set has the specified API permission.
+ bool HasAPIPermission(APIPermission::ID permission) const;
+
+ // Returns true if the |extension| explicitly requests access to the given
+ // |permission_name|. Note this does not include APIs without no corresponding
+ // permission, like "runtime" or "browserAction".
+ bool HasAPIPermission(const std::string& permission_name) const;
+
+ // Returns true if the set allows the given permission with the default
+ // permission detal.
+ bool CheckAPIPermission(APIPermission::ID permission) const;
+
+ // Returns true if the set allows the given permission and permission param.
+ bool CheckAPIPermissionWithParam(APIPermission::ID permission,
+ const APIPermission::CheckParam* param) const;
+
+ // Returns true if this includes permission to access |origin|.
+ bool HasExplicitAccessToOrigin(const GURL& origin) const;
+
+ // Returns true if this permission set includes access to script |url|.
+ bool HasScriptableAccessToURL(const GURL& url) const;
+
+ // Returns true if this permission set includes effective access to all
+ // origins.
+ bool HasEffectiveAccessToAllHosts() const;
+
+ // Returns true if this permission set includes effective access to |url|.
+ bool HasEffectiveAccessToURL(const GURL& url) const;
+
+ // Returns ture if this permission set effectively represents full access
+ // (e.g. native code).
+ bool HasEffectiveFullAccess() const;
+
+ const APIPermissionSet& apis() const { return apis_; }
+
+ const URLPatternSet& effective_hosts() const { return effective_hosts_; }
+
+ const URLPatternSet& explicit_hosts() const { return explicit_hosts_; }
+
+ const URLPatternSet& scriptable_hosts() const { return scriptable_hosts_; }
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(PermissionsTest, GetWarningMessages_AudioVideo);
+ friend class base::RefCountedThreadSafe<PermissionSet>;
+
+ ~PermissionSet();
+
+ void AddAPIPermission(APIPermission::ID id);
+
+ // Adds permissions implied independently of other context.
+ void InitImplicitPermissions();
+
+ // Initializes the effective host permission based on the data in this set.
+ void InitEffectiveHosts();
+
+ // The api list is used when deciding if an extension can access certain
+ // extension APIs and features.
+ APIPermissionSet apis_;
+
+ // The list of hosts that can be accessed directly from the extension.
+ // TODO(jstritar): Rename to "hosts_"?
+ URLPatternSet explicit_hosts_;
+
+ // The list of hosts that can be scripted by content scripts.
+ // TODO(jstritar): Rename to "user_script_hosts_"?
+ URLPatternSet scriptable_hosts_;
+
+ // The list of hosts this effectively grants access to.
+ URLPatternSet effective_hosts_;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_SET_H_
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 0db3b4f454..e54d9651ae 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -3,6 +3,9 @@
# found in the LICENSE file.
{
+ 'variables': {
+ 'chromium_code': 1,
+ },
'targets': [
{
'target_name': 'extensions_common',
@@ -72,6 +75,8 @@
'common/permissions/permission_message.h',
'common/permissions/permission_message_provider.cc',
'common/permissions/permission_message_provider.h',
+ 'common/permissions/permission_set.cc',
+ 'common/permissions/permission_set.h',
'common/permissions/permissions_info.cc',
'common/permissions/permissions_info.h',
'common/permissions/permissions_provider.h',
@@ -107,10 +112,14 @@
'browser/extension_prefs_scope.h',
'browser/extension_error.cc',
'browser/extension_error.h',
+ 'browser/extensions_browser_client.cc',
+ 'browser/extensions_browser_client.h',
'browser/file_highlighter.cc',
'browser/file_highlighter.h',
'browser/file_reader.cc',
'browser/file_reader.h',
+ 'browser/lazy_background_task_queue.cc',
+ 'browser/lazy_background_task_queue.h',
'browser/pref_names.cc',
'browser/pref_names.h',
'browser/view_type_utils.cc',