summaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-02-21 12:16:55 +0000
committerTorne (Richard Coles) <torne@google.com>2014-02-21 12:16:55 +0000
commit5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7 (patch)
tree5d4ae202b870bd86673f596f0d424bc4b3e55ebe /extensions
parente862bac9c33104a29d98631d62668ae7b6676510 (diff)
downloadchromium_org-5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7.tar.gz
Merge from Chromium at DEPS revision 251904
This commit was generated by merge_to_master.py. Change-Id: I1f9543259d7d2a57d81aa41a1b84f85837439d21
Diffstat (limited to 'extensions')
-rw-r--r--extensions/DEPS1
-rw-r--r--extensions/OWNERS1
-rw-r--r--extensions/browser/DEPS9
-rw-r--r--extensions/browser/admin_policy.cc19
-rw-r--r--extensions/browser/admin_policy.h6
-rw-r--r--extensions/browser/admin_policy_unittest.cc12
-rw-r--r--extensions/browser/api_activity_monitor.h39
-rw-r--r--extensions/browser/app_sorting.h3
-rw-r--r--extensions/browser/blacklist_state.h24
-rw-r--r--extensions/browser/error_map.cc138
-rw-r--r--extensions/browser/error_map.h84
-rw-r--r--extensions/browser/error_map_unittest.cc147
-rw-r--r--extensions/browser/event_router.cc151
-rw-r--r--extensions/browser/event_router.h36
-rw-r--r--extensions/browser/event_router_unittest.cc8
-rw-r--r--extensions/browser/extension_error.cc15
-rw-r--r--extensions/browser/extension_error_test_util.cc64
-rw-r--r--extensions/browser/extension_error_test_util.h35
-rw-r--r--extensions/browser/extension_function.cc63
-rw-r--r--extensions/browser/extension_function.h25
-rw-r--r--extensions/browser/extension_message_filter.cc175
-rw-r--r--extensions/browser/extension_message_filter.h77
-rw-r--r--extensions/browser/extension_pref_store.cc43
-rw-r--r--extensions/browser/extension_pref_store.h38
-rw-r--r--extensions/browser/extension_pref_value_map.cc376
-rw-r--r--extensions/browser/extension_pref_value_map.h198
-rw-r--r--extensions/browser/extension_pref_value_map_factory.cc35
-rw-r--r--extensions/browser/extension_pref_value_map_factory.h31
-rw-r--r--extensions/browser/extension_pref_value_map_unittest.cc400
-rw-r--r--extensions/browser/extension_prefs.cc1911
-rw-r--r--extensions/browser/extension_prefs.h652
-rw-r--r--extensions/browser/extension_prefs_factory.cc61
-rw-r--r--extensions/browser/extension_prefs_factory.h39
-rw-r--r--extensions/browser/extension_registry.cc114
-rw-r--r--extensions/browser/extension_registry.h137
-rw-r--r--extensions/browser/extension_registry_factory.cc47
-rw-r--r--extensions/browser/extension_registry_factory.h42
-rw-r--r--extensions/browser/extension_registry_observer.h25
-rw-r--r--extensions/browser/extension_registry_unittest.cc169
-rw-r--r--extensions/browser/extension_scoped_prefs.h56
-rw-r--r--extensions/browser/extension_system.cc26
-rw-r--r--extensions/browser/extension_system.h131
-rw-r--r--extensions/browser/extension_system_provider.cc18
-rw-r--r--extensions/browser/extension_system_provider.h35
-rw-r--r--extensions/browser/extensions_browser_client.h49
-rw-r--r--extensions/browser/info_map.cc19
-rw-r--r--extensions/browser/info_map.h24
-rw-r--r--extensions/browser/info_map_unittest.cc6
-rw-r--r--extensions/browser/lazy_background_task_queue.cc16
-rw-r--r--extensions/browser/management_policy.cc19
-rw-r--r--extensions/browser/management_policy.h21
-rw-r--r--extensions/browser/management_policy_unittest.cc24
-rw-r--r--extensions/browser/pending_extension_manager.cc10
-rw-r--r--extensions/browser/pref_names.cc23
-rw-r--r--extensions/browser/pref_names.h97
-rw-r--r--extensions/browser/process_manager.cc134
-rw-r--r--extensions/browser/process_manager.h22
-rw-r--r--extensions/browser/process_map.cc9
-rw-r--r--extensions/browser/process_map.h15
-rw-r--r--extensions/browser/process_map_factory.cc46
-rw-r--r--extensions/browser/process_map_factory.h42
-rw-r--r--extensions/browser/quota_service.h7
-rw-r--r--extensions/browser/renderer_startup_helper.cc127
-rw-r--r--extensions/browser/renderer_startup_helper.h74
-rw-r--r--extensions/browser/runtime_data.cc76
-rw-r--r--extensions/browser/runtime_data.h84
-rw-r--r--extensions/browser/runtime_data_unittest.cc108
-rw-r--r--extensions/browser/test_management_policy.cc13
-rw-r--r--extensions/browser/test_management_policy.h11
-rw-r--r--extensions/common/common_manifest_handlers.cc34
-rw-r--r--extensions/common/common_manifest_handlers.h17
-rw-r--r--extensions/common/constants.cc1
-rw-r--r--extensions/common/constants.h3
-rw-r--r--extensions/common/error_utils.cc35
-rw-r--r--extensions/common/error_utils.h18
-rw-r--r--extensions/common/event_filter.cc6
-rw-r--r--extensions/common/event_filter.h28
-rw-r--r--extensions/common/event_filter_unittest.cc4
-rw-r--r--extensions/common/event_filtering_info.cc2
-rw-r--r--extensions/common/extension.cc75
-rw-r--r--extensions/common/extension.h35
-rw-r--r--extensions/common/extension_api.cc37
-rw-r--r--extensions/common/extension_api.h19
-rw-r--r--extensions/common/extension_api_stub.cc10
-rw-r--r--extensions/common/extension_set.cc150
-rw-r--r--extensions/common/extension_set.h148
-rw-r--r--extensions/common/extension_set_unittest.cc142
-rw-r--r--extensions/common/extensions_client.cc2
-rw-r--r--extensions/common/extensions_client.h2
-rw-r--r--extensions/common/feature_switch.cc28
-rw-r--r--extensions/common/feature_switch.h4
-rw-r--r--extensions/common/features/feature.h7
-rw-r--r--extensions/common/features/feature_provider.h11
-rw-r--r--extensions/common/manifest.cc2
-rw-r--r--extensions/common/manifest.h11
-rw-r--r--extensions/common/manifest_constants.cc29
-rw-r--r--extensions/common/manifest_constants.h20
-rw-r--r--extensions/common/manifest_handler.cc5
-rw-r--r--extensions/common/manifest_handler.h10
-rw-r--r--extensions/common/manifest_handler_unittest.cc8
-rw-r--r--extensions/common/manifest_handlers/background_info.cc18
-rw-r--r--extensions/common/manifest_handlers/background_info.h15
-rw-r--r--extensions/common/manifest_handlers/csp_info.cc8
-rw-r--r--extensions/common/manifest_handlers/csp_info.h2
-rw-r--r--extensions/common/manifest_handlers/incognito_info.cc6
-rw-r--r--extensions/common/manifest_handlers/incognito_info.h2
-rw-r--r--extensions/common/manifest_handlers/kiosk_mode_info.cc9
-rw-r--r--extensions/common/manifest_handlers/kiosk_mode_info.h2
-rw-r--r--extensions/common/manifest_handlers/offline_enabled_info.cc4
-rw-r--r--extensions/common/manifest_handlers/offline_enabled_info.h2
-rw-r--r--extensions/common/manifest_handlers/requirements_info.cc6
-rw-r--r--extensions/common/manifest_handlers/requirements_info.h2
-rw-r--r--extensions/common/manifest_handlers/sandboxed_page_info.cc8
-rw-r--r--extensions/common/manifest_handlers/sandboxed_page_info.h2
-rw-r--r--extensions/common/manifest_handlers/shared_module_info.cc15
-rw-r--r--extensions/common/manifest_handlers/shared_module_info.h4
-rw-r--r--extensions/common/manifest_handlers/web_accessible_resources_info.cc99
-rw-r--r--extensions/common/manifest_handlers/web_accessible_resources_info.h50
-rw-r--r--extensions/common/manifest_handlers/webview_info.cc182
-rw-r--r--extensions/common/manifest_handlers/webview_info.h54
-rw-r--r--extensions/common/matcher/OWNERS1
-rw-r--r--extensions/common/matcher/regex_set_matcher.cc113
-rw-r--r--extensions/common/matcher/regex_set_matcher.h82
-rw-r--r--extensions/common/matcher/regex_set_matcher_unittest.cc61
-rw-r--r--extensions/common/matcher/string_pattern.cc20
-rw-r--r--extensions/common/matcher/string_pattern.h42
-rw-r--r--extensions/common/matcher/string_pattern_unittest.cc23
-rw-r--r--extensions/common/matcher/substring_set_matcher.cc272
-rw-r--r--extensions/common/matcher/substring_set_matcher.h140
-rw-r--r--extensions/common/matcher/substring_set_matcher_unittest.cc167
-rw-r--r--extensions/common/matcher/url_matcher.cc881
-rw-r--r--extensions/common/matcher/url_matcher.h355
-rw-r--r--extensions/common/matcher/url_matcher_constants.cc34
-rw-r--r--extensions/common/matcher/url_matcher_constants.h39
-rw-r--r--extensions/common/matcher/url_matcher_factory.cc277
-rw-r--r--extensions/common/matcher/url_matcher_factory.h62
-rw-r--r--extensions/common/matcher/url_matcher_factory_unittest.cc339
-rw-r--r--extensions/common/matcher/url_matcher_helpers.cc31
-rw-r--r--extensions/common/matcher/url_matcher_helpers.h27
-rw-r--r--extensions/common/matcher/url_matcher_unittest.cc682
-rw-r--r--extensions/common/one_shot_event.cc3
-rw-r--r--extensions/common/one_shot_event.h5
-rw-r--r--extensions/common/permissions/api_permission.cc20
-rw-r--r--extensions/common/permissions/api_permission.h16
-rw-r--r--extensions/common/permissions/api_permission_set.cc22
-rw-r--r--extensions/common/permissions/api_permission_set.h2
-rw-r--r--extensions/common/permissions/api_permission_set_unittest.cc40
-rw-r--r--extensions/common/permissions/manifest_permission_set.cc4
-rw-r--r--extensions/common/permissions/manifest_permission_set.h2
-rw-r--r--extensions/common/permissions/permission_message.cc6
-rw-r--r--extensions/common/permissions/permission_message.h16
-rw-r--r--extensions/common/permissions/permission_message_provider.h4
-rw-r--r--extensions/common/permissions/permission_set.cc1
-rw-r--r--extensions/common/permissions/permissions_data.cc61
-rw-r--r--extensions/common/permissions/permissions_data.h7
-rw-r--r--extensions/common/permissions/permissions_data_unittest.cc123
-rw-r--r--extensions/common/permissions/permissions_info.cc1
-rw-r--r--extensions/common/stack_frame_unittest.cc8
-rw-r--r--extensions/common/switches.cc22
-rw-r--r--extensions/common/switches.h5
-rw-r--r--extensions/common/test_util.cc31
-rw-r--r--extensions/common/test_util.h27
-rw-r--r--extensions/common/url_pattern.cc17
-rw-r--r--extensions/common/url_pattern_set.cc6
-rw-r--r--extensions/common/value_builder.cc4
-rw-r--r--extensions/common/value_builder.h5
-rw-r--r--extensions/common/view_type.h3
-rw-r--r--extensions/extensions.gyp85
168 files changed, 7999 insertions, 4380 deletions
diff --git a/extensions/DEPS b/extensions/DEPS
index f286a2e609..898a76b883 100644
--- a/extensions/DEPS
+++ b/extensions/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/url_matcher",
"+content/public/common",
"+crypto",
"+testing",
diff --git a/extensions/OWNERS b/extensions/OWNERS
index 3393de66e4..3dced1e92b 100644
--- a/extensions/OWNERS
+++ b/extensions/OWNERS
@@ -4,7 +4,6 @@ koz@chromium.org
yoz@chromium.org
asargent@chromium.org
scheib@chromium.org
-mpcomplete@chromium.org
jyasskin@chromium.org
kalman@chromium.org
mek@chromium.org
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index 35e31587e4..f1751ccf32 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -1,4 +1,6 @@
include_rules = [
+ "+components/browser_context_keyed_service",
+ "+components/user_prefs",
"+content/public/browser",
"+sync",
@@ -9,17 +11,16 @@ include_rules = [
#
# TODO(jamescook): Remove these. http://crbug.com/162530
"+chrome/browser/chrome_notification_types.h",
+ "+chrome/browser/extensions/api/content_settings/content_settings_store.h",
+ "+chrome/browser/extensions/api/preference/preference_api.h",
"+chrome/browser/extensions/api/runtime/runtime_api.h",
"+chrome/browser/extensions/extension_function_dispatcher.h",
"+chrome/browser/extensions/extension_function_histogram_value.h",
"+chrome/browser/extensions/extension_host.h",
- "+chrome/browser/extensions/extension_prefs.h",
"+chrome/browser/extensions/extension_service.h",
- "+chrome/browser/extensions/extension_system.h",
- "+chrome/browser/extensions/extension_util.h",
"+chrome/browser/renderer_host/chrome_render_message_filter.h",
"+chrome/common/extensions/extension_messages.h",
- "+chrome/common/extensions/extension_set.h",
+ "+chrome/common/extensions/features/feature_channel.h",
"+grit/generated_resources.h",
]
diff --git a/extensions/browser/admin_policy.cc b/extensions/browser/admin_policy.cc
index 903c4e0956..cb948879aa 100644
--- a/extensions/browser/admin_policy.cc
+++ b/extensions/browser/admin_policy.cc
@@ -13,10 +13,10 @@
namespace {
bool ManagementPolicyImpl(const extensions::Extension* extension,
- string16* error,
+ base::string16* error,
bool modifiable_value) {
bool modifiable =
- extension->location() != extensions::Manifest::COMPONENT &&
+ !extensions::Manifest::IsComponentLocation(extension->location()) &&
!extensions::Manifest::IsPolicyLocation(extension->location());
// Some callers equate "no restriction" to true, others to false.
if (modifiable)
@@ -25,17 +25,18 @@ bool ManagementPolicyImpl(const extensions::Extension* extension,
if (error) {
*error = l10n_util::GetStringFUTF16(
IDS_EXTENSION_CANT_MODIFY_POLICY_REQUIRED,
- UTF8ToUTF16(extension->name()));
+ base::UTF8ToUTF16(extension->name()));
}
return !modifiable_value;
}
-bool ReturnLoadError(const extensions::Extension* extension, string16* error) {
+bool ReturnLoadError(const extensions::Extension* extension,
+ base::string16* error) {
if (error) {
*error = l10n_util::GetStringFUTF16(
IDS_EXTENSION_CANT_INSTALL_POLICY_BLOCKED,
- UTF8ToUTF16(extension->name()),
- UTF8ToUTF16(extension->id()));
+ base::UTF8ToUTF16(extension->name()),
+ base::UTF8ToUTF16(extension->id()));
}
return false;
}
@@ -55,7 +56,7 @@ bool UserMayLoad(const base::ListValue* blacklist,
const base::DictionaryValue* forcelist,
const base::ListValue* allowed_types,
const Extension* extension,
- string16* error) {
+ base::string16* error) {
// Component extensions are always allowed.
if (extension->location() == Manifest::COMPONENT)
return true;
@@ -109,11 +110,11 @@ bool UserMayLoad(const base::ListValue* blacklist,
return true;
}
-bool UserMayModifySettings(const Extension* extension, string16* error) {
+bool UserMayModifySettings(const Extension* extension, base::string16* error) {
return ManagementPolicyImpl(extension, error, true);
}
-bool MustRemainEnabled(const Extension* extension, string16* error) {
+bool MustRemainEnabled(const Extension* extension, base::string16* error) {
return ManagementPolicyImpl(extension, error, false);
}
diff --git a/extensions/browser/admin_policy.h b/extensions/browser/admin_policy.h
index ea32ee78d5..6091bf8e78 100644
--- a/extensions/browser/admin_policy.h
+++ b/extensions/browser/admin_policy.h
@@ -26,15 +26,15 @@ bool UserMayLoad(const base::ListValue* blacklist,
const base::DictionaryValue* forcelist,
const base::ListValue* allowed_types,
const Extension* extension,
- string16* error);
+ base::string16* error);
// Returns false if the extension is required to remain running. In practice
// this enforces the admin policy forcelist.
-bool UserMayModifySettings(const Extension* extension, string16* error);
+bool UserMayModifySettings(const Extension* extension, base::string16* error);
// Returns false if the extension is required to remain running. In practice
// this enforces the admin policy forcelist.
-bool MustRemainEnabled(const Extension* extension, string16* error);
+bool MustRemainEnabled(const Extension* extension, base::string16* error);
} // namespace
} // namespace
diff --git a/extensions/browser/admin_policy_unittest.cc b/extensions/browser/admin_policy_unittest.cc
index f85e3ef5a6..13b3f03de7 100644
--- a/extensions/browser/admin_policy_unittest.cc
+++ b/extensions/browser/admin_policy_unittest.cc
@@ -64,7 +64,7 @@ TEST_F(ExtensionAdminPolicyTest, BlacklistedByDefault) {
TEST_F(ExtensionAdminPolicyTest, UserMayLoadRequired) {
CreateExtension(Manifest::COMPONENT);
EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, NULL, extension_.get(), NULL));
- string16 error;
+ base::string16 error;
EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, NULL, extension_.get(),
&error));
EXPECT_TRUE(error.empty());
@@ -87,7 +87,7 @@ TEST_F(ExtensionAdminPolicyTest, UserMayLoadNoBlacklist) {
base::ListValue blacklist;
EXPECT_TRUE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(),
NULL));
- string16 error;
+ base::string16 error;
EXPECT_TRUE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(),
&error));
EXPECT_TRUE(error.empty());
@@ -106,7 +106,7 @@ TEST_F(ExtensionAdminPolicyTest, UserMayLoadWhitelisted) {
blacklist.Append(new base::StringValue(extension_->id()));
EXPECT_TRUE(ap::UserMayLoad(NULL, &whitelist, NULL, NULL, extension_.get(),
NULL));
- string16 error;
+ base::string16 error;
EXPECT_TRUE(ap::UserMayLoad(NULL, &whitelist, NULL, NULL, extension_.get(),
&error));
EXPECT_TRUE(error.empty());
@@ -121,7 +121,7 @@ TEST_F(ExtensionAdminPolicyTest, UserMayLoadBlacklisted) {
blacklist.Append(new base::StringValue("*"));
EXPECT_FALSE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(),
NULL));
- string16 error;
+ base::string16 error;
EXPECT_FALSE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(),
&error));
EXPECT_FALSE(error.empty());
@@ -170,7 +170,7 @@ TEST_F(ExtensionAdminPolicyTest, UserMayLoadAllowedTypes) {
TEST_F(ExtensionAdminPolicyTest, UserMayModifySettings) {
CreateExtension(Manifest::INTERNAL);
EXPECT_TRUE(ap::UserMayModifySettings(extension_.get(), NULL));
- string16 error;
+ base::string16 error;
EXPECT_TRUE(ap::UserMayModifySettings(extension_.get(), &error));
EXPECT_TRUE(error.empty());
@@ -184,7 +184,7 @@ TEST_F(ExtensionAdminPolicyTest, UserMayModifySettings) {
TEST_F(ExtensionAdminPolicyTest, MustRemainEnabled) {
CreateExtension(Manifest::EXTERNAL_POLICY_DOWNLOAD);
EXPECT_TRUE(ap::MustRemainEnabled(extension_.get(), NULL));
- string16 error;
+ base::string16 error;
EXPECT_TRUE(ap::MustRemainEnabled(extension_.get(), &error));
EXPECT_FALSE(error.empty());
diff --git a/extensions/browser/api_activity_monitor.h b/extensions/browser/api_activity_monitor.h
new file mode 100644
index 0000000000..b8f0cc32c4
--- /dev/null
+++ b/extensions/browser/api_activity_monitor.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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_API_ACTIVITY_MONITOR_H_
+#define EXTENSIONS_BROWSER_API_ACTIVITY_MONITOR_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace extensions {
+
+// ApiActivityMonitor is used to monitor extension API event dispatch and API
+// function calls. An embedder can use this interface to log low-level extension
+// activity.
+class ApiActivityMonitor {
+ public:
+ // Called when an API event is dispatched to an extension.
+ virtual void OnApiEventDispatched(const std::string& extension_id,
+ const std::string& event_name,
+ scoped_ptr<base::ListValue> event_args) = 0;
+
+ // Called when an extension calls an API function.
+ virtual void OnApiFunctionCalled(const std::string& extension_id,
+ const std::string& api_name,
+ scoped_ptr<base::ListValue> args) = 0;
+
+ protected:
+ virtual ~ApiActivityMonitor() {}
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_ACTIVITY_MONITOR_H_
diff --git a/extensions/browser/app_sorting.h b/extensions/browser/app_sorting.h
index 967fb46eea..ede93f134d 100644
--- a/extensions/browser/app_sorting.h
+++ b/extensions/browser/app_sorting.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 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.
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "sync/api/string_ordinal.h"
diff --git a/extensions/browser/blacklist_state.h b/extensions/browser/blacklist_state.h
new file mode 100644
index 0000000000..d7f16e2315
--- /dev/null
+++ b/extensions/browser/blacklist_state.h
@@ -0,0 +1,24 @@
+// Copyright 2014 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_BLACKLIST_STATE_H_
+#define EXTENSIONS_BROWSER_BLACKLIST_STATE_H_
+
+namespace extensions {
+
+// The numeric values here match the values of the respective enum in
+// ClientCRXListInfoResponse proto.
+enum BlacklistState {
+ NOT_BLACKLISTED = 0,
+ BLACKLISTED_MALWARE = 1,
+ BLACKLISTED_SECURITY_VULNERABILITY = 2,
+ BLACKLISTED_CWS_POLICY_VIOLATION = 3,
+ BLACKLISTED_POTENTIALLY_UNWANTED = 4,
+ BLACKLISTED_UNKNOWN // Used when we couldn't connect to server,
+ // e.g. when offline.
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_BLACKLIST_STATE_H_
diff --git a/extensions/browser/error_map.cc b/extensions/browser/error_map.cc
new file mode 100644
index 0000000000..dfcef9fd05
--- /dev/null
+++ b/extensions/browser/error_map.cc
@@ -0,0 +1,138 @@
+// Copyright 2014 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/error_map.h"
+
+#include "base/lazy_instance.h"
+#include "base/stl_util.h"
+#include "extensions/common/extension.h"
+
+namespace extensions {
+namespace {
+
+// The maximum number of errors to be stored per extension.
+const size_t kMaxErrorsPerExtension = 100;
+
+base::LazyInstance<ErrorList> g_empty_error_list = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// ErrorMap::ExtensionEntry
+ErrorMap::ExtensionEntry::ExtensionEntry() {
+}
+
+ErrorMap::ExtensionEntry::~ExtensionEntry() {
+ DeleteAllErrors();
+}
+
+void ErrorMap::ExtensionEntry::DeleteAllErrors() {
+ STLDeleteContainerPointers(list_.begin(), list_.end());
+ list_.clear();
+}
+
+void ErrorMap::ExtensionEntry::DeleteIncognitoErrors() {
+ ErrorList::iterator iter = list_.begin();
+ while (iter != list_.end()) {
+ if ((*iter)->from_incognito()) {
+ delete *iter;
+ iter = list_.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+void ErrorMap::ExtensionEntry::DeleteErrorsOfType(ExtensionError::Type type) {
+ ErrorList::iterator iter = list_.begin();
+ while (iter != list_.end()) {
+ if ((*iter)->type() == type) {
+ delete *iter;
+ iter = list_.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+const ExtensionError* ErrorMap::ExtensionEntry::AddError(
+ scoped_ptr<ExtensionError> error) {
+ for (ErrorList::iterator iter = list_.begin(); iter != list_.end(); ++iter) {
+ // If we find a duplicate error, remove the old error and add the new one,
+ // incrementing the occurrence count of the error. We use the new error
+ // for runtime errors, so we can link to the latest context, inspectable
+ // view, etc.
+ if (error->IsEqual(*iter)) {
+ error->set_occurrences((*iter)->occurrences() + 1);
+ delete *iter;
+ list_.erase(iter);
+ break;
+ }
+ }
+
+ // If there are too many errors for an extension already, limit ourselves to
+ // the most recent ones.
+ if (list_.size() >= kMaxErrorsPerExtension) {
+ delete list_.front();
+ list_.pop_front();
+ }
+
+ list_.push_back(error.release());
+ return list_.back();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ErrorMap
+ErrorMap::ErrorMap() {
+}
+
+ErrorMap::~ErrorMap() {
+ RemoveAllErrors();
+}
+
+const ErrorList& ErrorMap::GetErrorsForExtension(
+ const std::string& extension_id) const {
+ EntryMap::const_iterator iter = map_.find(extension_id);
+ return iter != map_.end() ? *iter->second->list() : g_empty_error_list.Get();
+}
+
+const ExtensionError* ErrorMap::AddError(scoped_ptr<ExtensionError> error) {
+ EntryMap::iterator iter = map_.find(error->extension_id());
+ if (iter == map_.end()) {
+ iter = map_.insert(std::pair<std::string, ExtensionEntry*>(
+ error->extension_id(), new ExtensionEntry)).first;
+ }
+ return iter->second->AddError(error.Pass());
+}
+
+void ErrorMap::Remove(const std::string& extension_id) {
+ EntryMap::iterator iter = map_.find(extension_id);
+ if (iter == map_.end())
+ return;
+
+ delete iter->second;
+ map_.erase(iter);
+}
+
+void ErrorMap::RemoveErrorsForExtensionOfType(const std::string& extension_id,
+ ExtensionError::Type type) {
+ EntryMap::iterator iter = map_.find(extension_id);
+ if (iter != map_.end())
+ iter->second->DeleteErrorsOfType(type);
+}
+
+void ErrorMap::RemoveIncognitoErrors() {
+ for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter)
+ iter->second->DeleteIncognitoErrors();
+}
+
+void ErrorMap::RemoveAllErrors() {
+ for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) {
+ iter->second->DeleteAllErrors();
+ delete iter->second;
+ }
+ map_.clear();
+}
+
+} // namespace extensions
diff --git a/extensions/browser/error_map.h b/extensions/browser/error_map.h
new file mode 100644
index 0000000000..2dcff220cb
--- /dev/null
+++ b/extensions/browser/error_map.h
@@ -0,0 +1,84 @@
+// Copyright 2014 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_ERROR_MAP_H_
+#define EXTENSIONS_BROWSER_ERROR_MAP_H_
+
+#include <deque>
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "extensions/browser/extension_error.h"
+
+namespace extensions {
+
+typedef std::deque<const ExtensionError*> ErrorList;
+
+// An ErrorMap is responsible for storing Extension-related errors, keyed by
+// Extension ID. The errors are owned by the ErrorMap, and are deleted upon
+// destruction.
+class ErrorMap {
+ public:
+ explicit ErrorMap();
+ ~ErrorMap();
+
+ // Return the list of all errors associated with the given extension.
+ const ErrorList& GetErrorsForExtension(const std::string& extension_id) const;
+
+ // Add the |error| to the ErrorMap.
+ const ExtensionError* AddError(scoped_ptr<ExtensionError> error);
+
+ // Remove an extension from the ErrorMap, deleting all associated errors.
+ void Remove(const std::string& extension_id);
+ // Remove all errors of a given type for an extension.
+ void RemoveErrorsForExtensionOfType(const std::string& extension_id,
+ ExtensionError::Type type);
+ // Remove all incognito errors for all extensions.
+ void RemoveIncognitoErrors();
+ // Remove all errors for all extensions, and clear the map.
+ void RemoveAllErrors();
+
+ size_t size() const { return map_.size(); }
+
+ private:
+ // An Entry is created for each Extension ID, and stores the errors related to
+ // that Extension.
+ class ExtensionEntry {
+ public:
+ explicit ExtensionEntry();
+ ~ExtensionEntry();
+
+ // Delete all errors associated with this extension.
+ void DeleteAllErrors();
+ // Delete all incognito errors associated with this extension.
+ void DeleteIncognitoErrors();
+ // Delete all errors of the given |type| associated with this extension.
+ void DeleteErrorsOfType(ExtensionError::Type type);
+
+ // Add the error to the list, and return a weak reference.
+ const ExtensionError* AddError(scoped_ptr<ExtensionError> error);
+
+ const ErrorList* list() const { return &list_; }
+
+ private:
+ // The list of all errors associated with the extension. The errors are
+ // owned by the Entry (in turn owned by the ErrorMap) and are deleted upon
+ // destruction.
+ ErrorList list_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionEntry);
+ };
+ typedef std::map<std::string, ExtensionEntry*> EntryMap;
+
+ // The mapping between Extension IDs and their corresponding Entries.
+ EntryMap map_;
+
+ DISALLOW_COPY_AND_ASSIGN(ErrorMap);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_ERROR_MAP_H_
diff --git a/extensions/browser/error_map_unittest.cc b/extensions/browser/error_map_unittest.cc
new file mode 100644
index 0000000000..8330c6afe7
--- /dev/null
+++ b/extensions/browser/error_map_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2014 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/error_map.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "extensions/browser/extension_error.h"
+#include "extensions/browser/extension_error_test_util.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/id_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+using error_test_util::CreateNewRuntimeError;
+
+class ErrorMapUnitTest : public testing::Test {
+ public:
+ ErrorMapUnitTest() { }
+ virtual ~ErrorMapUnitTest() { }
+
+ virtual void SetUp() OVERRIDE {
+ testing::Test::SetUp();
+ }
+
+ protected:
+ ErrorMap errors_;
+};
+
+// Test adding errors, and removing them by reference, by incognito status,
+// and in bulk.
+TEST_F(ErrorMapUnitTest, AddAndRemoveErrors) {
+ ASSERT_EQ(0u, errors_.size());
+
+ const size_t kNumTotalErrors = 6;
+ const size_t kNumNonIncognitoErrors = 3;
+ const std::string kId = id_util::GenerateId("id");
+ // Populate with both incognito and non-incognito errors (evenly distributed).
+ for (size_t i = 0; i < kNumTotalErrors; ++i) {
+ ASSERT_TRUE(errors_.AddError(
+ CreateNewRuntimeError(kId, base::UintToString(i), i % 2 == 0)));
+ }
+
+ // There should only be one entry in the map, since errors are stored in lists
+ // keyed by extension id.
+ ASSERT_EQ(1u, errors_.size());
+
+ ASSERT_EQ(kNumTotalErrors, errors_.GetErrorsForExtension(kId).size());
+
+ // Remove the incognito errors; three errors should remain, and all should
+ // be from non-incognito contexts.
+ errors_.RemoveIncognitoErrors();
+ const ErrorList& list = errors_.GetErrorsForExtension(kId);
+ ASSERT_EQ(kNumNonIncognitoErrors, list.size());
+ for (size_t i = 0; i < list.size(); ++i)
+ ASSERT_FALSE(list[i]->from_incognito());
+
+ // Add another error for a different extension id.
+ const std::string kSecondId = id_util::GenerateId("id2");
+ ASSERT_TRUE(errors_.AddError(CreateNewRuntimeError(kSecondId, "foo")));
+
+ // There should be two entries now, one for each id, and there should be one
+ // error for the second extension.
+ ASSERT_EQ(2u, errors_.size());
+ ASSERT_EQ(1u, errors_.GetErrorsForExtension(kSecondId).size());
+
+ // Remove all errors for the second id.
+ errors_.Remove(kSecondId);
+ ASSERT_EQ(1u, errors_.size());
+ ASSERT_EQ(0u, errors_.GetErrorsForExtension(kSecondId).size());
+ // First extension should be unaffected.
+ ASSERT_EQ(kNumNonIncognitoErrors,
+ errors_.GetErrorsForExtension(kId).size());
+
+ // Remove remaining errors.
+ errors_.RemoveAllErrors();
+ ASSERT_EQ(0u, errors_.size());
+ ASSERT_EQ(0u, errors_.GetErrorsForExtension(kId).size());
+}
+
+// Test that if we add enough errors, only the most recent
+// kMaxErrorsPerExtension are kept.
+TEST_F(ErrorMapUnitTest, ExcessiveErrorsGetCropped) {
+ ASSERT_EQ(0u, errors_.size());
+
+ // This constant matches one of the same name in error_console.cc.
+ const size_t kMaxErrorsPerExtension = 100;
+ const size_t kNumExtraErrors = 5;
+ const std::string kId = id_util::GenerateId("id");
+
+ // Add new errors, with each error's message set to its number.
+ for (size_t i = 0; i < kMaxErrorsPerExtension + kNumExtraErrors; ++i) {
+ ASSERT_TRUE(errors_.AddError(
+ CreateNewRuntimeError(kId, base::UintToString(i))));
+ }
+
+ ASSERT_EQ(1u, errors_.size());
+
+ const ErrorList& list = errors_.GetErrorsForExtension(kId);
+ ASSERT_EQ(kMaxErrorsPerExtension, list.size());
+
+ // We should have popped off errors in the order they arrived, so the
+ // first stored error should be the 6th reported (zero-based)...
+ ASSERT_EQ(base::UintToString16(kNumExtraErrors),
+ list.front()->message());
+ // ..and the last stored should be the 105th reported.
+ ASSERT_EQ(base::UintToString16(kMaxErrorsPerExtension + kNumExtraErrors - 1),
+ list.back()->message());
+}
+
+// Test to ensure that the error console will not add duplicate errors, but will
+// keep the latest version of an error.
+TEST_F(ErrorMapUnitTest, DuplicateErrorsAreReplaced) {
+ ASSERT_EQ(0u, errors_.size());
+
+ const std::string kId = id_util::GenerateId("id");
+ const size_t kNumErrors = 3u;
+
+ // Report three errors.
+ for (size_t i = 0; i < kNumErrors; ++i) {
+ ASSERT_TRUE(errors_.AddError(
+ CreateNewRuntimeError(kId, base::UintToString(i))));
+ }
+
+ // Create an error identical to the second error reported, save its
+ // location, and add it to the error map.
+ scoped_ptr<ExtensionError> runtime_error2 =
+ CreateNewRuntimeError(kId, base::UintToString(1u));
+ const ExtensionError* weak_error = runtime_error2.get();
+ ASSERT_TRUE(errors_.AddError(runtime_error2.Pass()));
+
+ // We should only have three errors stored, since two of the four reported
+ // were identical, and the older should have been replaced.
+ ASSERT_EQ(1u, errors_.size());
+ const ErrorList& list = errors_.GetErrorsForExtension(kId);
+ ASSERT_EQ(kNumErrors, list.size());
+
+ // The duplicate error should be the last reported (pointer comparison)...
+ ASSERT_EQ(weak_error, list.back());
+ // ... and should have two reported occurrences.
+ ASSERT_EQ(2u, list.back()->occurrences());
+}
+
+} // namespace extensions
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index 6105572a22..58cbf24607 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -13,13 +13,13 @@
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_prefs.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/extension_util.h"
#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
+#include "extensions/browser/api_activity_monitor.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/lazy_background_task_queue.h"
#include "extensions/browser/process_manager.h"
@@ -45,6 +45,35 @@ void DoNothing(ExtensionHost* host) {}
// registered from its lazy background page.
const char kFilteredEvents[] = "filtered_events";
+// Sends a notification about an event to the API activity monitor on the
+// UI thread. Can be called from any thread.
+void NotifyApiEventDispatched(void* browser_context_id,
+ const std::string& extension_id,
+ const std::string& event_name,
+ scoped_ptr<ListValue> args) {
+ // The ApiActivityMonitor can only be accessed from the UI thread.
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&NotifyApiEventDispatched,
+ browser_context_id,
+ extension_id,
+ event_name,
+ base::Passed(&args)));
+ return;
+ }
+
+ // Notify the ApiActivityMonitor about the event dispatch.
+ BrowserContext* context = static_cast<BrowserContext*>(browser_context_id);
+ if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
+ return;
+ ApiActivityMonitor* monitor =
+ ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context);
+ if (monitor)
+ monitor->OnApiEventDispatched(extension_id, event_name, args.Pass());
+}
+
} // namespace
const char EventRouter::kRegisteredEvents[] = "events";
@@ -67,33 +96,6 @@ struct EventRouter::ListenerProcess {
};
// static
-void EventRouter::NotifyExtensionDispatchObserverOnUIThread(
- void* browser_context_id,
- scoped_ptr<EventDispatchInfo> details) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&NotifyExtensionDispatchObserverOnUIThread,
- browser_context_id, base::Passed(&details)));
- } else {
- BrowserContext* context =
- reinterpret_cast<BrowserContext*>(browser_context_id);
- if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
- return;
- ExtensionSystem* extension_system =
- ExtensionSystem::GetForBrowserContext(context);
- EventRouter* event_router = extension_system->event_router();
- if (!event_router)
- return;
- if (event_router->event_dispatch_observer_) {
- event_router->event_dispatch_observer_->OnWillDispatchEvent(
- details.Pass());
- }
- }
-}
-
-// static
void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
void* browser_context_id,
const std::string& extension_id,
@@ -101,12 +103,10 @@ void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
ListValue* event_args,
UserGestureState user_gesture,
const EventFilteringInfo& info) {
- NotifyExtensionDispatchObserverOnUIThread(
- browser_context_id,
- make_scoped_ptr(new EventDispatchInfo(
- extension_id,
- event_name,
- make_scoped_ptr(event_args->DeepCopy()))));
+ NotifyApiEventDispatched(browser_context_id,
+ extension_id,
+ event_name,
+ make_scoped_ptr(event_args->DeepCopy()));
ListValue args;
args.Set(0, new base::StringValue(event_name));
@@ -122,7 +122,7 @@ void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
// DispatchExtensionMessage does _not_ take ownership of event_args, so we
// must ensure that the destruction of args does not attempt to free it.
- scoped_ptr<Value> removed_event_args;
+ scoped_ptr<base::Value> removed_event_args;
args.Remove(1, &removed_event_args);
ignore_result(removed_event_args.release());
}
@@ -161,8 +161,7 @@ EventRouter::EventRouter(BrowserContext* browser_context,
ExtensionPrefs* extension_prefs)
: browser_context_(browser_context),
extension_prefs_(extension_prefs),
- listeners_(this),
- event_dispatch_observer_(NULL) {
+ listeners_(this) {
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
@@ -210,11 +209,6 @@ void EventRouter::UnregisterObserver(Observer* observer) {
observers_.erase(iters_to_remove[i]);
}
-void EventRouter::SetEventDispatchObserver(EventDispatchObserver* observer) {
- CHECK(!event_dispatch_observer_);
- event_dispatch_observer_ = observer;
-}
-
void EventRouter::OnListenerAdded(const EventListener* listener) {
const EventListenerInfo details(
listener->event_name,
@@ -356,7 +350,7 @@ void EventRouter::SetRegisteredEvents(const std::string& extension_id,
ListValue* events_value = new ListValue;
for (std::set<std::string>::const_iterator iter = events.begin();
iter != events.end(); ++iter) {
- events_value->Append(new StringValue(*iter));
+ events_value->Append(new base::StringValue(*iter));
}
extension_prefs_->UpdateExtensionPref(
extension_id, kRegisteredEvents, events_value);
@@ -482,12 +476,12 @@ void EventRouter::DispatchLazyEvent(
const std::string& extension_id,
const linked_ptr<Event>& event,
std::set<EventDispatchIdentifier>* already_dispatched) {
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
- browser_context_)->extension_service();
// Check both the original and the incognito browser context to see if we
// should load a lazy bg page to handle the event. The latter case
// occurs in the case of split-mode extensions.
- const Extension* extension = service->extensions()->GetByID(extension_id);
+ const Extension* extension =
+ ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
+ extension_id);
if (!extension)
return;
@@ -512,9 +506,9 @@ void EventRouter::DispatchLazyEvent(
void EventRouter::DispatchEventToProcess(const std::string& extension_id,
content::RenderProcessHost* process,
const linked_ptr<Event>& event) {
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
- browser_context_)->extension_service();
- const Extension* extension = service->extensions()->GetByID(extension_id);
+ const Extension* extension =
+ ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
+ extension_id);
// The extension could have been removed, but we do not unregister it until
// the extension process is unloaded.
@@ -522,10 +516,7 @@ void EventRouter::DispatchEventToProcess(const std::string& extension_id,
return;
BrowserContext* listener_context = process->GetBrowserContext();
- ProcessMap* process_map =
- ExtensionSystem::GetForBrowserContext(listener_context)
- ->extension_service()
- ->process_map();
+ ProcessMap* process_map = ProcessMap::Get(listener_context);
// If the event is privileged, only send to extension processes. Otherwise,
// it's OK to send to normal renderers (e.g., for content scripts).
if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
@@ -566,19 +557,26 @@ bool EventRouter::CanDispatchEventToBrowserContext(
context != event->restrict_to_browser_context;
if (!cross_incognito)
return true;
- ExtensionService* service =
- ExtensionSystem::GetForBrowserContext(context)->extension_service();
- return extension_util::CanCrossIncognito(extension, service);
+ return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
+ extension, context);
}
bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
BrowserContext* context,
const Extension* extension,
const linked_ptr<Event>& event) {
+ if (extension->is_ephemeral() && !event->can_load_ephemeral_apps) {
+ // Most events can only be dispatched to ephemeral apps that are already
+ // running.
+ ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
+ if (!pm->GetBackgroundHostForExtension(extension->id()))
+ return false;
+ }
+
if (!CanDispatchEventToBrowserContext(context, extension, event))
return false;
- LazyBackgroundTaskQueue* queue = ExtensionSystem::GetForBrowserContext(
+ LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
context)->lazy_background_task_queue();
if (queue->ShouldEnqueueTask(context, extension)) {
linked_ptr<Event> dispatched_event(event);
@@ -612,14 +610,13 @@ void EventRouter::IncrementInFlightEventsOnUI(
reinterpret_cast<BrowserContext*>(browser_context_id);
if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
return;
- ExtensionSystem* extension_system =
- ExtensionSystem::GetForBrowserContext(browser_context);
+ ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context);
EventRouter* event_router = extension_system->event_router();
if (!event_router)
return;
- ExtensionService* extension_service = extension_system->extension_service();
const Extension* extension =
- extension_service->extensions()->GetByID(extension_id);
+ ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
+ extension_id);
if (!extension)
return;
event_router->IncrementInFlightEvents(browser_context, extension);
@@ -630,8 +627,7 @@ void EventRouter::IncrementInFlightEvents(BrowserContext* context,
// Only increment in-flight events if the lazy background page is active,
// because that's the only time we'll get an ACK.
if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
- ProcessManager* pm =
- ExtensionSystem::GetForBrowserContext(context)->process_manager();
+ ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
if (host)
pm->IncrementLazyKeepaliveCount(extension);
@@ -640,8 +636,7 @@ void EventRouter::IncrementInFlightEvents(BrowserContext* context,
void EventRouter::OnEventAck(BrowserContext* context,
const std::string& extension_id) {
- ProcessManager* pm =
- ExtensionSystem::GetForBrowserContext(context)->process_manager();
+ ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
// The event ACK is routed to the background host, so this should never be
// NULL.
@@ -683,7 +678,7 @@ void EventRouter::Observe(int type,
const Extension* extension =
content::Details<const Extension>(details).ptr();
if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
- LazyBackgroundTaskQueue* queue = ExtensionSystem::GetForBrowserContext(
+ LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
browser_context_)->lazy_background_task_queue();
queue->AddPendingTask(browser_context_, extension->id(),
base::Bind(&DoNothing));
@@ -722,7 +717,8 @@ Event::Event(const std::string& event_name,
: event_name(event_name),
event_args(event_args.Pass()),
restrict_to_browser_context(NULL),
- user_gesture(EventRouter::USER_GESTURE_UNKNOWN) {
+ user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
+ can_load_ephemeral_apps(false) {
DCHECK(this->event_args.get());
}
@@ -732,7 +728,8 @@ Event::Event(const std::string& event_name,
: event_name(event_name),
event_args(event_args.Pass()),
restrict_to_browser_context(restrict_to_browser_context),
- user_gesture(EventRouter::USER_GESTURE_UNKNOWN) {
+ user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
+ can_load_ephemeral_apps(false) {
DCHECK(this->event_args.get());
}
@@ -747,7 +744,8 @@ Event::Event(const std::string& event_name,
restrict_to_browser_context(restrict_to_browser_context),
event_url(event_url),
user_gesture(user_gesture),
- filter_info(filter_info) {
+ filter_info(filter_info),
+ can_load_ephemeral_apps(false) {
DCHECK(this->event_args.get());
}
@@ -771,13 +769,4 @@ EventListenerInfo::EventListenerInfo(const std::string& event_name,
extension_id(extension_id),
browser_context(browser_context) {}
-EventDispatchInfo::EventDispatchInfo(const std::string& extension_id,
- const std::string& event_name,
- scoped_ptr<ListValue> event_args)
- : extension_id(extension_id),
- event_name(event_name),
- event_args(event_args.Pass()) {}
-
-EventDispatchInfo::~EventDispatchInfo() {}
-
} // namespace extensions
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index d65adb097d..467e7f396a 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -68,13 +68,6 @@ class EventRouter : public content::NotificationObserver,
virtual void OnListenerRemoved(const EventListenerInfo& details) {}
};
- // The EventDispatchObserver is notified on the UI thread whenever
- // an event is dispatched. There can be only one EventDispatchObserver.
- class EventDispatchObserver {
- public:
- virtual void OnWillDispatchEvent(scoped_ptr<EventDispatchInfo> details) = 0;
- };
-
// Converts event names like "foo.onBar/123" into "foo.onBar". Event names
// without a "/" are returned unchanged.
static std::string GetBaseEventName(const std::string& full_event_name);
@@ -117,10 +110,6 @@ class EventRouter : public content::NotificationObserver,
// Unregisters an observer from all events.
void UnregisterObserver(Observer* observer);
- // Sets the observer to be notified whenever an event is dispatched to an
- // extension.
- void SetEventDispatchObserver(EventDispatchObserver* observer);
-
// Add or remove the extension as having a lazy background page that listens
// to the event. The difference from the above methods is that these will be
// remembered even after the process goes away. We use this list to decide
@@ -192,12 +181,6 @@ class EventRouter : public content::NotificationObserver,
typedef std::pair<const content::BrowserContext*, std::string>
EventDispatchIdentifier;
- // Sends a notification about an event to the event dispatch observer on the
- // UI thread. Can be called from any thread.
- static void NotifyExtensionDispatchObserverOnUIThread(
- void* browser_context_id,
- scoped_ptr<EventDispatchInfo> details);
-
// TODO(gdk): Document this.
static void DispatchExtensionMessage(
IPC::Sender* ipc_sender,
@@ -300,8 +283,6 @@ class EventRouter : public content::NotificationObserver,
typedef base::hash_map<std::string, Observer*> ObserverMap;
ObserverMap observers_;
- EventDispatchObserver* event_dispatch_observer_;
-
DISALLOW_COPY_AND_ASSIGN(EventRouter);
};
@@ -338,6 +319,12 @@ struct Event {
// DispatchEvent, so callers don't need to worry about lifetime.
WillDispatchCallback will_dispatch_callback;
+ // If true, this event will always be dispatched to ephemeral apps, regardless
+ // of whether they are running or inactive. Defaults to false.
+ // Most events can only be dispatched to ephemeral apps that are already
+ // running. Cached ephemeral apps are inactive until launched by the user.
+ bool can_load_ephemeral_apps;
+
Event(const std::string& event_name,
scoped_ptr<base::ListValue> event_args);
@@ -371,17 +358,6 @@ struct EventListenerInfo {
content::BrowserContext* browser_context;
};
-struct EventDispatchInfo {
- EventDispatchInfo(const std::string& extension_id,
- const std::string& event_name,
- scoped_ptr<ListValue> event_args);
- ~EventDispatchInfo();
-
- const std::string extension_id;
- const std::string event_name;
- scoped_ptr<ListValue> event_args;
-};
-
} // namespace extensions
#endif // EXTENSIONS_BROWSER_EVENT_ROUTER_H_
diff --git a/extensions/browser/event_router_unittest.cc b/extensions/browser/event_router_unittest.cc
index ba5fed300d..c47b7f20ed 100644
--- a/extensions/browser/event_router_unittest.cc
+++ b/extensions/browser/event_router_unittest.cc
@@ -69,7 +69,7 @@ TEST_F(EventRouterTest, GetBaseEventName) {
TEST_F(EventRouterTest, EventRouterObserver) {
EventRouter router(NULL, NULL);
EventListener listener(
- "event_name", "extension_id", NULL, scoped_ptr<DictionaryValue>());
+ "event_name", "extension_id", NULL, scoped_ptr<base::DictionaryValue>());
// Add/remove works without any observers.
router.OnListenerAdded(&listener);
@@ -104,8 +104,10 @@ TEST_F(EventRouterTest, EventRouterObserver) {
// Adding a listener with a sub-event notifies the main observer with
// proper details.
matching_observer.Reset();
- EventListener sub_event_listener(
- "event_name/1", "extension_id", NULL, scoped_ptr<DictionaryValue>());
+ EventListener sub_event_listener("event_name/1",
+ "extension_id",
+ NULL,
+ scoped_ptr<base::DictionaryValue>());
router.OnListenerAdded(&sub_event_listener);
EXPECT_EQ(1, matching_observer.listener_added_count());
EXPECT_EQ(0, matching_observer.listener_removed_count());
diff --git a/extensions/browser/extension_error.cc b/extensions/browser/extension_error.cc
index ee6b47e58a..d8733fe51d 100644
--- a/extensions/browser/extension_error.cc
+++ b/extensions/browser/extension_error.cc
@@ -10,7 +10,6 @@
#include "extensions/common/constants.h"
#include "url/gurl.h"
-using base::string16;
using base::DictionaryValue;
namespace extensions {
@@ -30,8 +29,8 @@ ExtensionError::ExtensionError(Type type,
const std::string& extension_id,
bool from_incognito,
logging::LogSeverity level,
- const string16& source,
- const string16& message)
+ const base::string16& source,
+ const base::string16& message)
: type_(type),
extension_id_(extension_id),
from_incognito_(from_incognito),
@@ -84,9 +83,9 @@ const char ManifestError::kManifestKeyKey[] = "manifestKey";
const char ManifestError::kManifestSpecificKey[] = "manifestSpecific";
ManifestError::ManifestError(const std::string& extension_id,
- const string16& message,
- const string16& manifest_key,
- const string16& manifest_specific)
+ const base::string16& message,
+ const base::string16& manifest_key,
+ const base::string16& manifest_specific)
: ExtensionError(ExtensionError::MANIFEST_ERROR,
extension_id,
false, // extensions can't be installed while incognito.
@@ -135,8 +134,8 @@ const char RuntimeError::kRenderViewIdKey[] = "renderViewId";
RuntimeError::RuntimeError(const std::string& extension_id,
bool from_incognito,
- const string16& source,
- const string16& message,
+ const base::string16& source,
+ const base::string16& message,
const StackTrace& stack_trace,
const GURL& context_url,
logging::LogSeverity level,
diff --git a/extensions/browser/extension_error_test_util.cc b/extensions/browser/extension_error_test_util.cc
new file mode 100644
index 0000000000..cdf4917dd0
--- /dev/null
+++ b/extensions/browser/extension_error_test_util.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 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/extension_error_test_util.h"
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/browser/extension_error.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/stack_frame.h"
+#include "url/gurl.h"
+
+namespace extensions {
+namespace error_test_util {
+
+namespace {
+const char kDefaultStackTrace[] = "function_name (https://url.com:1:1)";
+}
+
+scoped_ptr<ExtensionError> CreateNewRuntimeError(
+ const std::string& extension_id,
+ const std::string& message,
+ bool from_incognito) {
+ StackTrace stack_trace;
+ scoped_ptr<StackFrame> frame =
+ StackFrame::CreateFromText(base::UTF8ToUTF16(kDefaultStackTrace));
+ CHECK(frame.get());
+ stack_trace.push_back(*frame);
+
+ base::string16 source =
+ base::UTF8ToUTF16(std::string(kExtensionScheme) +
+ content::kStandardSchemeSeparator +
+ extension_id);
+
+ return scoped_ptr<ExtensionError>(new RuntimeError(
+ extension_id,
+ from_incognito,
+ source,
+ base::UTF8ToUTF16(message),
+ stack_trace,
+ GURL::EmptyGURL(), // no context url
+ logging::LOG_INFO,
+ 0, 0 /* Render [View|Process] ID */ ));
+}
+
+scoped_ptr<ExtensionError> CreateNewRuntimeError(
+ const std::string& extension_id, const std::string& message) {
+ return CreateNewRuntimeError(extension_id, message, false);
+}
+
+scoped_ptr<ExtensionError> CreateNewManifestError(
+ const std::string& extension_id, const std::string& message) {
+ return scoped_ptr<ExtensionError>(
+ new ManifestError(extension_id,
+ base::UTF8ToUTF16(message),
+ base::EmptyString16(),
+ base::EmptyString16()));
+}
+
+} // namespace error_test_util
+} // namespace extensions
diff --git a/extensions/browser/extension_error_test_util.h b/extensions/browser/extension_error_test_util.h
new file mode 100644
index 0000000000..4866cefe25
--- /dev/null
+++ b/extensions/browser/extension_error_test_util.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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_EXTENSION_ERROR_TEST_UTIL_H_
+#define EXTENSIONS_BROWSER_EXTENSION_ERROR_TEST_UTIL_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace extensions {
+
+class ExtensionError;
+
+namespace error_test_util {
+
+// Create a new RuntimeError.
+scoped_ptr<ExtensionError> CreateNewRuntimeError(
+ const std::string& extension_id,
+ const std::string& message,
+ bool from_incognito);
+
+// Create a new RuntimeError; incognito defaults to "false".
+scoped_ptr<ExtensionError> CreateNewRuntimeError(
+ const std::string& extension_id, const std::string& message);
+
+// Create a new ManifestError.
+scoped_ptr<ExtensionError> CreateNewManifestError(
+ const std::string& extension_id, const std::string& mnessage);
+
+} // namespace error_test_util
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_ERROR_TEST_UTIL_H_
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index a06d2c496d..8c7c7527d6 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -12,6 +12,7 @@
#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
@@ -28,15 +29,18 @@ void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
x->Destruct();
}
-// Helper class to track the lifetime of ExtensionFunction's RenderViewHost
-// pointer and NULL it out when it dies. It also allows us to filter IPC
-// messages coming from the RenderViewHost.
-class UIThreadExtensionFunction::RenderViewHostTracker
+// Helper class to track the lifetime of ExtensionFunction's RenderViewHost or
+// RenderFrameHost pointer and NULL it out when it dies. It also allows us to
+// filter IPC messages coming from the RenderViewHost/RenderFrameHost.
+class UIThreadExtensionFunction::RenderHostTracker
: public content::WebContentsObserver {
public:
- explicit RenderViewHostTracker(UIThreadExtensionFunction* function)
+ explicit RenderHostTracker(UIThreadExtensionFunction* function)
: content::WebContentsObserver(
- WebContents::FromRenderViewHost(function->render_view_host())),
+ function->render_view_host() ?
+ WebContents::FromRenderViewHost(function->render_view_host()) :
+ WebContents::FromRenderFrameHost(
+ function->render_frame_host())),
function_(function) {
}
@@ -49,14 +53,21 @@ class UIThreadExtensionFunction::RenderViewHostTracker
function_->SetRenderViewHost(NULL);
}
+ virtual void RenderFrameDeleted(
+ content::RenderFrameHost* render_frame_host) OVERRIDE {
+ if (render_frame_host != function_->render_frame_host())
+ return;
+
+ function_->SetRenderFrameHost(NULL);
+ }
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
- return function_->OnMessageReceivedFromRenderView(message);
+ return function_->OnMessageReceived(message);
}
UIThreadExtensionFunction* function_;
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostTracker);
+ DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
};
ExtensionFunction::ExtensionFunction()
@@ -66,7 +77,9 @@ ExtensionFunction::ExtensionFunction()
include_incognito_(false),
user_gesture_(false),
bad_message_(false),
- histogram_value_(extensions::functions::UNKNOWN) {}
+ histogram_value_(extensions::functions::UNKNOWN),
+ source_tab_id_(-1) {
+}
ExtensionFunction::~ExtensionFunction() {
}
@@ -125,8 +138,8 @@ bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
}
bool ExtensionFunction::HasOptionalArgument(size_t index) {
- Value* value;
- return args_->Get(index, &value) && !value->IsType(Value::TYPE_NULL);
+ base::Value* value;
+ return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
}
void ExtensionFunction::SendResponseImpl(bool success) {
@@ -146,7 +159,11 @@ void ExtensionFunction::SendResponseImpl(bool success) {
}
UIThreadExtensionFunction::UIThreadExtensionFunction()
- : render_view_host_(NULL), context_(NULL), delegate_(NULL) {}
+ : render_view_host_(NULL),
+ render_frame_host_(NULL),
+ context_(NULL),
+ delegate_(NULL) {
+}
UIThreadExtensionFunction::~UIThreadExtensionFunction() {
if (dispatcher() && render_view_host())
@@ -158,8 +175,7 @@ UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
return this;
}
-bool UIThreadExtensionFunction::OnMessageReceivedFromRenderView(
- const IPC::Message& message) {
+bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
return false;
}
@@ -169,8 +185,16 @@ void UIThreadExtensionFunction::Destruct() const {
void UIThreadExtensionFunction::SetRenderViewHost(
RenderViewHost* render_view_host) {
+ DCHECK(!render_frame_host_);
render_view_host_ = render_view_host;
- tracker_.reset(render_view_host ? new RenderViewHostTracker(this) : NULL);
+ tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
+}
+
+void UIThreadExtensionFunction::SetRenderFrameHost(
+ content::RenderFrameHost* render_frame_host) {
+ DCHECK(!render_view_host_);
+ render_frame_host_ = render_frame_host;
+ tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
}
content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
@@ -191,8 +215,13 @@ void UIThreadExtensionFunction::SendResponse(bool success) {
void UIThreadExtensionFunction::WriteToConsole(
content::ConsoleMessageLevel level,
const std::string& message) {
- render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
- render_view_host_->GetRoutingID(), level, message));
+ if (render_view_host_) {
+ render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
+ render_view_host_->GetRoutingID(), level, message));
+ } else {
+ render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
+ render_frame_host_->GetRoutingID(), level, message));
+ }
}
IOThreadExtensionFunction::IOThreadExtensionFunction()
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h
index aa0ed038b0..099dff1661 100644
--- a/extensions/browser/extension_function.h
+++ b/extensions/browser/extension_function.h
@@ -35,6 +35,7 @@ class Value;
namespace content {
class BrowserContext;
+class RenderFrameHost;
class RenderViewHost;
class WebContents;
}
@@ -191,6 +192,9 @@ class ExtensionFunction
response_callback_ = callback;
}
+ void set_source_tab_id(int source_tab_id) { source_tab_id_ = source_tab_id; }
+ int source_tab_id() const { return source_tab_id_; }
+
protected:
friend struct ExtensionFunctionDeleteTraits;
@@ -263,6 +267,10 @@ class ExtensionFunction
// The callback to run once the function has done execution.
ResponseCallback response_callback_;
+ // The ID of the tab triggered this function call, or -1 if there is no tab.
+ int source_tab_id_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
};
@@ -290,7 +298,7 @@ class UIThreadExtensionFunction : public ExtensionFunction {
// Called when a message was received.
// Should return true if it processed the message.
- virtual bool OnMessageReceivedFromRenderView(const IPC::Message& message);
+ virtual bool OnMessageReceived(const IPC::Message& message);
// Set the browser context which contains the extension that has originated
// this function call.
@@ -301,6 +309,10 @@ class UIThreadExtensionFunction : public ExtensionFunction {
content::RenderViewHost* render_view_host() const {
return render_view_host_;
}
+ void SetRenderFrameHost(content::RenderFrameHost* render_frame_host);
+ content::RenderFrameHost* render_frame_host() const {
+ return render_frame_host_;
+ }
void set_dispatcher(
const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher) {
@@ -330,18 +342,23 @@ class UIThreadExtensionFunction : public ExtensionFunction {
// The dispatcher that will service this extension function call.
base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_;
- // The RenderViewHost we will send responses too.
+ // The RenderViewHost we will send responses to.
content::RenderViewHost* render_view_host_;
+ // The RenderFrameHost we will send responses to.
+ // NOTE: either render_view_host_ or render_frame_host_ will be set, as we
+ // port code to use RenderFrames for OOPIF. See http://crbug.com/304341.
+ content::RenderFrameHost* render_frame_host_;
+
// The content::BrowserContext of this function's extension.
content::BrowserContext* context_;
private:
- class RenderViewHostTracker;
+ class RenderHostTracker;
virtual void Destruct() const OVERRIDE;
- scoped_ptr<RenderViewHostTracker> tracker_;
+ scoped_ptr<RenderHostTracker> tracker_;
DelegateForTests* delegate_;
};
diff --git a/extensions/browser/extension_message_filter.cc b/extensions/browser/extension_message_filter.cc
new file mode 100644
index 0000000000..ea5bfa7f80
--- /dev/null
+++ b/extensions/browser/extension_message_filter.cc
@@ -0,0 +1,175 @@
+// Copyright 2014 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/extension_message_filter.h"
+
+#include "chrome/common/extensions/extension_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_dispatcher_host.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/process_manager.h"
+#include "ipc/ipc_message_macros.h"
+
+using content::BrowserThread;
+using content::RenderProcessHost;
+
+namespace extensions {
+
+ExtensionMessageFilter::ExtensionMessageFilter(int render_process_id,
+ content::BrowserContext* context)
+ : BrowserMessageFilter(ExtensionMsgStart),
+ render_process_id_(render_process_id),
+ browser_context_(context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+ExtensionMessageFilter::~ExtensionMessageFilter() {}
+
+void ExtensionMessageFilter::OverrideThreadForMessage(
+ const IPC::Message& message,
+ BrowserThread::ID* thread) {
+ switch (message.type()) {
+ case ExtensionHostMsg_AddListener::ID:
+ case ExtensionHostMsg_RemoveListener::ID:
+ case ExtensionHostMsg_AddLazyListener::ID:
+ case ExtensionHostMsg_RemoveLazyListener::ID:
+ case ExtensionHostMsg_AddFilteredListener::ID:
+ case ExtensionHostMsg_RemoveFilteredListener::ID:
+ case ExtensionHostMsg_ShouldSuspendAck::ID:
+ case ExtensionHostMsg_SuspendAck::ID:
+ *thread = BrowserThread::UI;
+ break;
+ default:
+ break;
+ }
+}
+
+bool ExtensionMessageFilter::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(ExtensionMessageFilter, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener,
+ OnExtensionAddListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener,
+ OnExtensionRemoveListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddLazyListener,
+ OnExtensionAddLazyListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener,
+ OnExtensionRemoveLazyListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddFilteredListener,
+ OnExtensionAddFilteredListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveFilteredListener,
+ OnExtensionRemoveFilteredListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_ShouldSuspendAck,
+ OnExtensionShouldSuspendAck)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_SuspendAck,
+ OnExtensionSuspendAck)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_GenerateUniqueID,
+ OnExtensionGenerateUniqueID)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_ResumeRequests,
+ OnExtensionResumeRequests);
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ExtensionMessageFilter::OnExtensionAddListener(
+ const std::string& extension_id,
+ const std::string& event_name) {
+ RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
+ if (!process)
+ return;
+ EventRouter* router = ExtensionSystem::Get(browser_context_)->event_router();
+ if (!router)
+ return;
+ router->AddEventListener(event_name, process, extension_id);
+}
+
+void ExtensionMessageFilter::OnExtensionRemoveListener(
+ const std::string& extension_id,
+ const std::string& event_name) {
+ RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
+ if (!process)
+ return;
+ EventRouter* router = ExtensionSystem::Get(browser_context_)->event_router();
+ if (!router)
+ return;
+ router->RemoveEventListener(event_name, process, extension_id);
+}
+
+void ExtensionMessageFilter::OnExtensionAddLazyListener(
+ const std::string& extension_id, const std::string& event_name) {
+ EventRouter* router = ExtensionSystem::Get(browser_context_)->event_router();
+ if (!router)
+ return;
+ router->AddLazyEventListener(event_name, extension_id);
+}
+
+void ExtensionMessageFilter::OnExtensionRemoveLazyListener(
+ const std::string& extension_id, const std::string& event_name) {
+ EventRouter* router = ExtensionSystem::Get(browser_context_)->event_router();
+ if (!router)
+ return;
+ router->RemoveLazyEventListener(event_name, extension_id);
+}
+
+void ExtensionMessageFilter::OnExtensionAddFilteredListener(
+ const std::string& extension_id,
+ const std::string& event_name,
+ const base::DictionaryValue& filter,
+ bool lazy) {
+ RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
+ if (!process)
+ return;
+ EventRouter* router = ExtensionSystem::Get(browser_context_)->event_router();
+ if (!router)
+ return;
+ router->AddFilteredEventListener(
+ event_name, process, extension_id, filter, lazy);
+}
+
+void ExtensionMessageFilter::OnExtensionRemoveFilteredListener(
+ const std::string& extension_id,
+ const std::string& event_name,
+ const base::DictionaryValue& filter,
+ bool lazy) {
+ RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
+ if (!process)
+ return;
+ EventRouter* router = ExtensionSystem::Get(browser_context_)->event_router();
+ if (!router)
+ return;
+ router->RemoveFilteredEventListener(
+ event_name, process, extension_id, filter, lazy);
+}
+
+void ExtensionMessageFilter::OnExtensionShouldSuspendAck(
+ const std::string& extension_id, int sequence_id) {
+ ProcessManager* process_manager =
+ ExtensionSystem::Get(browser_context_)->process_manager();
+ if (process_manager)
+ process_manager->OnShouldSuspendAck(extension_id, sequence_id);
+}
+
+void ExtensionMessageFilter::OnExtensionSuspendAck(
+ const std::string& extension_id) {
+ ProcessManager* process_manager =
+ ExtensionSystem::Get(browser_context_)->process_manager();
+ if (process_manager)
+ process_manager->OnSuspendAck(extension_id);
+}
+
+void ExtensionMessageFilter::OnExtensionGenerateUniqueID(int* unique_id) {
+ static int next_unique_id = 0;
+ *unique_id = ++next_unique_id;
+}
+
+void ExtensionMessageFilter::OnExtensionResumeRequests(int route_id) {
+ content::ResourceDispatcherHost::Get()->ResumeBlockedRequestsForRoute(
+ render_process_id_, route_id);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_message_filter.h b/extensions/browser/extension_message_filter.h
new file mode 100644
index 0000000000..8518bf9e81
--- /dev/null
+++ b/extensions/browser/extension_message_filter.h
@@ -0,0 +1,77 @@
+// Copyright 2014 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_EXTENSION_RENDER_MESSAGE_FILTER_H_
+#define EXTENSIONS_BROWSER_EXTENSION_RENDER_MESSAGE_FILTER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+// This class filters out incoming extension-specific IPC messages from the
+// renderer process. It is created on the UI thread. Messages may be handled on
+// the IO thread or the UI thread.
+class ExtensionMessageFilter : public content::BrowserMessageFilter {
+ public:
+ ExtensionMessageFilter(int render_process_id,
+ content::BrowserContext* context);
+
+ private:
+ virtual ~ExtensionMessageFilter();
+
+ // content::BrowserMessageFilter implementation.
+ virtual void OverrideThreadForMessage(
+ const IPC::Message& message,
+ content::BrowserThread::ID* thread) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ // Message handlers on the UI thread.
+ void OnExtensionAddListener(const std::string& extension_id,
+ const std::string& event_name);
+ void OnExtensionRemoveListener(const std::string& extension_id,
+ const std::string& event_name);
+ void OnExtensionAddLazyListener(const std::string& extension_id,
+ const std::string& event_name);
+ void OnExtensionRemoveLazyListener(const std::string& extension_id,
+ const std::string& event_name);
+ void OnExtensionAddFilteredListener(const std::string& extension_id,
+ const std::string& event_name,
+ const base::DictionaryValue& filter,
+ bool lazy);
+ void OnExtensionRemoveFilteredListener(const std::string& extension_id,
+ const std::string& event_name,
+ const base::DictionaryValue& filter,
+ bool lazy);
+ void OnExtensionShouldSuspendAck(const std::string& extension_id,
+ int sequence_id);
+ void OnExtensionSuspendAck(const std::string& extension_id);
+
+ // Message handlers on the IO thread.
+ void OnExtensionGenerateUniqueID(int* unique_id);
+ void OnExtensionResumeRequests(int route_id);
+
+ const int render_process_id_;
+
+ // Should only be accessed on the UI thread.
+ content::BrowserContext* browser_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionMessageFilter);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_RENDER_MESSAGE_FILTER_H_
diff --git a/extensions/browser/extension_pref_store.cc b/extensions/browser/extension_pref_store.cc
new file mode 100644
index 0000000000..3f26cbb3e3
--- /dev/null
+++ b/extensions/browser/extension_pref_store.cc
@@ -0,0 +1,43 @@
+// Copyright 2014 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/extension_pref_store.h"
+
+#include "base/values.h"
+#include "extensions/browser/extension_pref_value_map.h"
+
+ExtensionPrefStore::ExtensionPrefStore(
+ ExtensionPrefValueMap* extension_pref_value_map,
+ bool incognito_pref_store)
+ : extension_pref_value_map_(extension_pref_value_map),
+ incognito_pref_store_(incognito_pref_store) {
+ extension_pref_value_map_->AddObserver(this);
+}
+
+void ExtensionPrefStore::OnInitializationCompleted() {
+ NotifyInitializationCompleted();
+}
+
+void ExtensionPrefStore::OnPrefValueChanged(const std::string& key) {
+ CHECK(extension_pref_value_map_);
+ const base::Value *winner =
+ extension_pref_value_map_->GetEffectivePrefValue(key,
+ incognito_pref_store_,
+ NULL);
+ if (winner)
+ SetValue(key, winner->DeepCopy());
+ else
+ RemoveValue(key);
+}
+
+void ExtensionPrefStore::OnExtensionPrefValueMapDestruction() {
+ CHECK(extension_pref_value_map_);
+ extension_pref_value_map_->RemoveObserver(this);
+ extension_pref_value_map_ = NULL;
+}
+
+ExtensionPrefStore::~ExtensionPrefStore() {
+ if (extension_pref_value_map_)
+ extension_pref_value_map_->RemoveObserver(this);
+}
diff --git a/extensions/browser/extension_pref_store.h b/extensions/browser/extension_pref_store.h
new file mode 100644
index 0000000000..d93018c90d
--- /dev/null
+++ b/extensions/browser/extension_pref_store.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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_EXTENSION_PREF_STORE_H_
+#define EXTENSIONS_BROWSER_EXTENSION_PREF_STORE_H_
+
+#include <string>
+
+#include "base/prefs/value_map_pref_store.h"
+#include "extensions/browser/extension_pref_value_map.h"
+
+// A (non-persistent) PrefStore implementation that holds effective preferences
+// set by extensions. These preferences are managed by and fetched from an
+// ExtensionPrefValueMap.
+class ExtensionPrefStore : public ValueMapPrefStore,
+ public ExtensionPrefValueMap::Observer {
+ public:
+ // Constructs an ExtensionPrefStore for a regular or an incognito profile.
+ ExtensionPrefStore(ExtensionPrefValueMap* extension_pref_value_map,
+ bool incognito_pref_store);
+
+ // Overrides for ExtensionPrefValueMap::Observer:
+ virtual void OnInitializationCompleted() OVERRIDE;
+ virtual void OnPrefValueChanged(const std::string& key) OVERRIDE;
+ virtual void OnExtensionPrefValueMapDestruction() OVERRIDE;
+
+ protected:
+ virtual ~ExtensionPrefStore();
+
+ private:
+ ExtensionPrefValueMap* extension_pref_value_map_; // Weak pointer.
+ bool incognito_pref_store_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPrefStore);
+};
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_PREF_STORE_H_
diff --git a/extensions/browser/extension_pref_value_map.cc b/extensions/browser/extension_pref_value_map.cc
new file mode 100644
index 0000000000..5cba7e510a
--- /dev/null
+++ b/extensions/browser/extension_pref_value_map.cc
@@ -0,0 +1,376 @@
+// Copyright 2014 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/extension_pref_value_map.h"
+
+#include "base/prefs/pref_value_map.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+
+using extensions::ExtensionPrefsScope;
+
+struct ExtensionPrefValueMap::ExtensionEntry {
+ // Installation time of the extension.
+ base::Time install_time;
+ // Whether extension is enabled in the profile.
+ bool enabled;
+ // Extension controlled preferences for the regular profile.
+ PrefValueMap regular_profile_preferences;
+ // Extension controlled preferences that should *only* apply to the regular
+ // profile.
+ PrefValueMap regular_only_profile_preferences;
+ // Persistent extension controlled preferences for the incognito profile,
+ // empty for regular profile ExtensionPrefStore.
+ PrefValueMap incognito_profile_preferences_persistent;
+ // Session only extension controlled preferences for the incognito profile.
+ // These preferences are deleted when the incognito profile is destroyed.
+ PrefValueMap incognito_profile_preferences_session_only;
+};
+
+ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
+}
+
+ExtensionPrefValueMap::~ExtensionPrefValueMap() {
+ if (!destroyed_) {
+ NotifyOfDestruction();
+ destroyed_ = true;
+ }
+ STLDeleteValues(&entries_);
+ entries_.clear();
+}
+
+void ExtensionPrefValueMap::Shutdown() {
+ NotifyOfDestruction();
+ destroyed_ = true;
+}
+
+void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ ExtensionPrefsScope scope,
+ base::Value* value) {
+ PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
+
+ if (prefs->SetValue(key, value))
+ NotifyPrefValueChanged(key);
+}
+
+void ExtensionPrefValueMap::RemoveExtensionPref(
+ const std::string& ext_id,
+ const std::string& key,
+ ExtensionPrefsScope scope) {
+ PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
+ if (prefs->RemoveValue(key))
+ NotifyPrefValueChanged(key);
+}
+
+bool ExtensionPrefValueMap::CanExtensionControlPref(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ bool incognito) const {
+ ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
+ if (ext == entries_.end()) {
+ NOTREACHED();
+ return false;
+ }
+
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(pref_key, incognito, NULL);
+ if (winner == entries_.end())
+ return true;
+
+ return winner->second->install_time <= ext->second->install_time;
+}
+
+void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
+ typedef std::set<std::string> KeySet;
+ KeySet deleted_keys;
+
+ ExtensionEntryMap::iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i) {
+ PrefValueMap& inc_prefs =
+ i->second->incognito_profile_preferences_session_only;
+ PrefValueMap::iterator j;
+ for (j = inc_prefs.begin(); j != inc_prefs.end(); ++j)
+ deleted_keys.insert(j->first);
+ inc_prefs.Clear();
+ }
+
+ KeySet::iterator k;
+ for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
+ NotifyPrefValueChanged(*k);
+}
+
+bool ExtensionPrefValueMap::DoesExtensionControlPref(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ bool* from_incognito) const {
+ bool incognito = (from_incognito != NULL);
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(pref_key, incognito, from_incognito);
+ if (winner == entries_.end())
+ return false;
+ return winner->first == extension_id;
+}
+
+void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
+ const base::Time& install_time,
+ bool is_enabled) {
+ if (entries_.find(ext_id) == entries_.end()) {
+ entries_[ext_id] = new ExtensionEntry;
+
+ // Only update the install time if the extension is newly installed.
+ entries_[ext_id]->install_time = install_time;
+ }
+
+ entries_[ext_id]->enabled = is_enabled;
+}
+
+void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
+ ExtensionEntryMap::iterator i = entries_.find(ext_id);
+ if (i == entries_.end())
+ return;
+ std::set<std::string> keys; // keys set by this extension
+ GetExtensionControlledKeys(*(i->second), &keys);
+
+ delete i->second;
+ entries_.erase(i);
+
+ NotifyPrefValueChanged(keys);
+}
+
+void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
+ bool is_enabled) {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ // This may happen when sync sets the extension state for an
+ // extension that is not installed.
+ if (i == entries_.end())
+ return;
+ if (i->second->enabled == is_enabled)
+ return;
+ std::set<std::string> keys; // keys set by this extension
+ GetExtensionControlledKeys(*(i->second), &keys);
+ i->second->enabled = is_enabled;
+ NotifyPrefValueChanged(keys);
+}
+
+PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ ExtensionPrefsScope scope) {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ switch (scope) {
+ case extensions::kExtensionPrefsScopeRegular:
+ return &(i->second->regular_profile_preferences);
+ case extensions::kExtensionPrefsScopeRegularOnly:
+ return &(i->second->regular_only_profile_preferences);
+ case extensions::kExtensionPrefsScopeIncognitoPersistent:
+ return &(i->second->incognito_profile_preferences_persistent);
+ case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
+ return &(i->second->incognito_profile_preferences_session_only);
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ ExtensionPrefsScope scope) const {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ switch (scope) {
+ case extensions::kExtensionPrefsScopeRegular:
+ return &(i->second->regular_profile_preferences);
+ case extensions::kExtensionPrefsScopeRegularOnly:
+ return &(i->second->regular_only_profile_preferences);
+ case extensions::kExtensionPrefsScopeIncognitoPersistent:
+ return &(i->second->incognito_profile_preferences_persistent);
+ case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
+ return &(i->second->incognito_profile_preferences_session_only);
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+void ExtensionPrefValueMap::GetExtensionControlledKeys(
+ const ExtensionEntry& entry,
+ std::set<std::string>* out) const {
+ PrefValueMap::const_iterator i;
+
+ const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
+ for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& regular_only_prefs =
+ entry.regular_only_profile_preferences;
+ for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& inc_prefs_pers =
+ entry.incognito_profile_preferences_persistent;
+ for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& inc_prefs_session =
+ entry.incognito_profile_preferences_session_only;
+ for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
+ out->insert(i->first);
+}
+
+const base::Value* ExtensionPrefValueMap::GetEffectivePrefValue(
+ const std::string& key,
+ bool incognito,
+ bool* from_incognito) const {
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(key, incognito, from_incognito);
+ if (winner == entries_.end())
+ return NULL;
+
+ const base::Value* value = NULL;
+ const std::string& ext_id = winner->first;
+
+ // First search for incognito session only preferences.
+ if (incognito) {
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
+ prefs->GetValue(key, &value);
+ if (value)
+ return value;
+
+ // If no incognito session only preference exists, fall back to persistent
+ // incognito preference.
+ prefs = GetExtensionPrefValueMap(
+ ext_id,
+ extensions::kExtensionPrefsScopeIncognitoPersistent);
+ prefs->GetValue(key, &value);
+ if (value)
+ return value;
+ } else {
+ // Regular-only preference.
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegularOnly);
+ prefs->GetValue(key, &value);
+ if (value)
+ return value;
+ }
+
+ // Regular preference.
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegular);
+ prefs->GetValue(key, &value);
+ return value;
+}
+
+ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
+ExtensionPrefValueMap::GetEffectivePrefValueController(
+ const std::string& key,
+ bool incognito,
+ bool* from_incognito) const {
+ ExtensionEntryMap::const_iterator winner = entries_.end();
+ base::Time winners_install_time;
+
+ ExtensionEntryMap::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i) {
+ const std::string& ext_id = i->first;
+ const base::Time& install_time = i->second->install_time;
+ const bool enabled = i->second->enabled;
+
+ if (!enabled)
+ continue;
+ if (install_time < winners_install_time)
+ continue;
+
+ const base::Value* value = NULL;
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegular);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = false;
+ }
+
+ if (!incognito) {
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeRegularOnly);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = false;
+ }
+ // Ignore the following prefs, because they're incognito-only.
+ continue;
+ }
+
+ prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = true;
+ }
+
+ prefs = GetExtensionPrefValueMap(
+ ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
+ if (prefs->GetValue(key, &value)) {
+ winner = i;
+ winners_install_time = install_time;
+ if (from_incognito)
+ *from_incognito = true;
+ }
+ }
+ return winner;
+}
+
+void ExtensionPrefValueMap::AddObserver(
+ ExtensionPrefValueMap::Observer* observer) {
+ observers_.AddObserver(observer);
+
+ // Collect all currently used keys and notify the new observer.
+ std::set<std::string> keys;
+ ExtensionEntryMap::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i)
+ GetExtensionControlledKeys(*(i->second), &keys);
+
+ std::set<std::string>::const_iterator j;
+ for (j = keys.begin(); j != keys.end(); ++j)
+ observer->OnPrefValueChanged(*j);
+}
+
+void ExtensionPrefValueMap::RemoveObserver(
+ ExtensionPrefValueMap::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+std::string ExtensionPrefValueMap::GetExtensionControllingPref(
+ const std::string& pref_key) const {
+ ExtensionEntryMap::const_iterator winner =
+ GetEffectivePrefValueController(pref_key, false, NULL);
+ if (winner == entries_.end())
+ return std::string();
+ return winner->first;
+}
+
+void ExtensionPrefValueMap::NotifyInitializationCompleted() {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnInitializationCompleted());
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(
+ const std::set<std::string>& keys) {
+ std::set<std::string>::const_iterator i;
+ for (i = keys.begin(); i != keys.end(); ++i)
+ NotifyPrefValueChanged(*i);
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnPrefValueChanged(key));
+}
+
+void ExtensionPrefValueMap::NotifyOfDestruction() {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnExtensionPrefValueMapDestruction());
+}
diff --git a/extensions/browser/extension_pref_value_map.h b/extensions/browser/extension_pref_value_map.h
new file mode 100644
index 0000000000..48f30d9918
--- /dev/null
+++ b/extensions/browser/extension_pref_value_map.h
@@ -0,0 +1,198 @@
+// Copyright 2014 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_EXTENSION_PREF_VALUE_MAP_H_
+#define EXTENSIONS_BROWSER_EXTENSION_PREF_VALUE_MAP_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/observer_list.h"
+#include "base/prefs/pref_value_map.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "extensions/browser/extension_prefs_scope.h"
+
+// Non-persistent data container that is shared by ExtensionPrefStores. All
+// extension pref values (incognito and regular) are stored herein and
+// provided to ExtensionPrefStores.
+//
+// The semantics of the ExtensionPrefValueMap are:
+// - A regular setting applies to regular browsing sessions as well as incognito
+// browsing sessions.
+// - An incognito setting applies only to incognito browsing sessions, not to
+// regular ones. It takes precedence over a regular setting set by the same
+// extension.
+// - A regular-only setting applies only to regular browsing sessions, not to
+// incognito ones. It takes precedence over a regular setting set by the same
+// extension.
+// - If two different extensions set a value for the same preference (and both
+// values apply to the regular/incognito browsing session), the extension that
+// was installed later takes precedence, regardless of whether the settings
+// are regular, incognito or regular-only.
+//
+// The following table illustrates the behavior:
+// A.reg | A.reg_only | A.inc | B.reg | B.reg_only | B.inc | E.reg | E.inc
+// 1 | - | - | - | - | - | 1 | 1
+// 1 | 2 | - | - | - | - | 2 | 1
+// 1 | - | 3 | - | - | - | 1 | 3
+// 1 | 2 | 3 | - | - | - | 2 | 3
+// 1 | - | - | 4 | - | - | 4 | 4
+// 1 | 2 | 3 | 4 | - | - | 4 | 4
+// 1 | - | - | - | 5 | - | 5 | 1
+// 1 | - | 3 | 4 | 5 | - | 5 | 4
+// 1 | - | - | - | - | 6 | 1 | 6
+// 1 | 2 | - | 4 | - | 6 | 4 | 6
+// 1 | 2 | 3 | - | 5 | 6 | 5 | 6
+//
+// A = extension A, B = extension B, E = effective value
+// .reg = regular value
+// .reg_only = regular-only value
+// .inc = incognito value
+// Extension B has higher precedence than A.
+class ExtensionPrefValueMap : public BrowserContextKeyedService {
+ public:
+ // Observer interface for monitoring ExtensionPrefValueMap.
+ class Observer {
+ public:
+ // Called when the value for the given |key| set by one of the extensions
+ // changes. This does not necessarily mean that the effective value has
+ // changed.
+ virtual void OnPrefValueChanged(const std::string& key) = 0;
+ // Notification about the ExtensionPrefValueMap being fully initialized.
+ virtual void OnInitializationCompleted() = 0;
+ // Called when the ExtensionPrefValueMap is being destroyed. When called,
+ // observers must unsubscribe.
+ virtual void OnExtensionPrefValueMapDestruction() = 0;
+
+ protected:
+ virtual ~Observer() {}
+ };
+
+ ExtensionPrefValueMap();
+ virtual ~ExtensionPrefValueMap();
+
+ // BrowserContextKeyedService implementation.
+ virtual void Shutdown() OVERRIDE;
+
+ // Set an extension preference |value| for |key| of extension |ext_id|.
+ // Takes ownership of |value|.
+ // Note that regular extension pref values need to be reported to
+ // incognito and to regular ExtensionPrefStores.
+ // Precondition: the extension must be registered.
+ void SetExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ extensions::ExtensionPrefsScope scope,
+ base::Value* value);
+
+ // Remove the extension preference value for |key| of extension |ext_id|.
+ // Precondition: the extension must be registered.
+ void RemoveExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ extensions::ExtensionPrefsScope scope);
+
+ // Returns true if currently no extension with higher precedence controls the
+ // preference.
+ // Note that the this function does does not consider the existence of
+ // policies. An extension is only really able to control a preference if
+ // PrefService::Preference::IsExtensionModifiable() returns true as well.
+ bool CanExtensionControlPref(const std::string& extension_id,
+ const std::string& pref_key,
+ bool incognito) const;
+
+ // Removes all "incognito session only" preference values.
+ void ClearAllIncognitoSessionOnlyPreferences();
+
+ // Returns true if an extension identified by |extension_id| controls the
+ // preference. This means this extension has set a preference value and no
+ // other extension with higher precedence overrides it. If |from_incognito|
+ // is not NULL, looks at incognito preferences first, and |from_incognito| is
+ // set to true if the effective pref value is coming from the incognito
+ // preferences, false if it is coming from the normal ones.
+ // Note that the this function does does not consider the existence of
+ // policies. An extension is only really able to control a preference if
+ // PrefService::Preference::IsExtensionModifiable() returns true as well.
+ bool DoesExtensionControlPref(const std::string& extension_id,
+ const std::string& pref_key,
+ bool* from_incognito) const;
+
+ // Returns the ID of the extension that currently controls this preference.
+ // Returns an empty string if this preference is not controlled by an
+ // extension.
+ std::string GetExtensionControllingPref(const std::string& pref_key) const;
+
+ // Tell the store it's now fully initialized.
+ void NotifyInitializationCompleted();
+
+ // Registers the time when an extension |ext_id| is installed.
+ void RegisterExtension(const std::string& ext_id,
+ const base::Time& install_time,
+ bool is_enabled);
+
+ // Deletes all entries related to extension |ext_id|.
+ void UnregisterExtension(const std::string& ext_id);
+
+ // Hides or makes the extension preference values of the specified extension
+ // visible.
+ void SetExtensionState(const std::string& ext_id, bool is_enabled);
+
+ // Adds an observer and notifies it about the currently stored keys.
+ void AddObserver(Observer* observer);
+
+ void RemoveObserver(Observer* observer);
+
+ const base::Value* GetEffectivePrefValue(const std::string& key,
+ bool incognito,
+ bool* from_incognito) const;
+
+ private:
+ struct ExtensionEntry;
+
+ typedef std::map<std::string, ExtensionEntry*> ExtensionEntryMap;
+
+ const PrefValueMap* GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ extensions::ExtensionPrefsScope scope) const;
+
+ PrefValueMap* GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ extensions::ExtensionPrefsScope scope);
+
+ // Returns all keys of pref values that are set by the extension of |entry|,
+ // regardless whether they are set for incognito or regular pref values.
+ void GetExtensionControlledKeys(const ExtensionEntry& entry,
+ std::set<std::string>* out) const;
+
+ // Returns an iterator to the extension which controls the preference |key|.
+ // If |incognito| is true, looks at incognito preferences first. In that case,
+ // if |from_incognito| is not NULL, it is set to true if the effective pref
+ // value is coming from the incognito preferences, false if it is coming from
+ // the normal ones.
+ ExtensionEntryMap::const_iterator GetEffectivePrefValueController(
+ const std::string& key,
+ bool incognito,
+ bool* from_incognito) const;
+
+ void NotifyOfDestruction();
+ void NotifyPrefValueChanged(const std::string& key);
+ void NotifyPrefValueChanged(const std::set<std::string>& keys);
+
+ // Mapping of which extension set which preference value. The effective
+ // preferences values (i.e. the ones with the highest precedence)
+ // are stored in ExtensionPrefStores.
+ ExtensionEntryMap entries_;
+
+ // In normal Profile shutdown, Shutdown() notifies observers that we are
+ // being destroyed. In tests, it isn't called, so the notification must
+ // be done in the destructor. This bit tracks whether it has been done yet.
+ bool destroyed_;
+
+ ObserverList<Observer, true> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMap);
+};
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_PREF_VALUE_MAP_H_
diff --git a/extensions/browser/extension_pref_value_map_factory.cc b/extensions/browser/extension_pref_value_map_factory.cc
new file mode 100644
index 0000000000..c8d3bfbac5
--- /dev/null
+++ b/extensions/browser/extension_pref_value_map_factory.cc
@@ -0,0 +1,35 @@
+// Copyright 2014 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/extension_pref_value_map_factory.h"
+
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "extensions/browser/extension_pref_value_map.h"
+
+ExtensionPrefValueMapFactory::ExtensionPrefValueMapFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ExtensionPrefValueMap",
+ BrowserContextDependencyManager::GetInstance()) {
+}
+
+ExtensionPrefValueMapFactory::~ExtensionPrefValueMapFactory() {
+}
+
+// static
+ExtensionPrefValueMap* ExtensionPrefValueMapFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<ExtensionPrefValueMap*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+ExtensionPrefValueMapFactory* ExtensionPrefValueMapFactory::GetInstance() {
+ return Singleton<ExtensionPrefValueMapFactory>::get();
+}
+
+BrowserContextKeyedService*
+ExtensionPrefValueMapFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new ExtensionPrefValueMap();
+}
diff --git a/extensions/browser/extension_pref_value_map_factory.h b/extensions/browser/extension_pref_value_map_factory.h
new file mode 100644
index 0000000000..84537d3038
--- /dev/null
+++ b/extensions/browser/extension_pref_value_map_factory.h
@@ -0,0 +1,31 @@
+// Copyright 2014 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_EXTENSION_PREF_VALUE_MAP_FACTORY_H_
+#define EXTENSIONS_BROWSER_EXTENSION_PREF_VALUE_MAP_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+class ExtensionPrefValueMap;
+
+// The usual factory boilerplate for ExtensionPrefValueMap.
+class ExtensionPrefValueMapFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static ExtensionPrefValueMap* GetForBrowserContext(
+ content::BrowserContext* context);
+
+ static ExtensionPrefValueMapFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<ExtensionPrefValueMapFactory>;
+
+ ExtensionPrefValueMapFactory();
+ virtual ~ExtensionPrefValueMapFactory();
+
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+};
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_PREF_VALUE_MAP_FACTORY_H_
diff --git a/extensions/browser/extension_pref_value_map_unittest.cc b/extensions/browser/extension_pref_value_map_unittest.cc
new file mode 100644
index 0000000000..35fa3c6b4b
--- /dev/null
+++ b/extensions/browser/extension_pref_value_map_unittest.cc
@@ -0,0 +1,400 @@
+// Copyright 2014 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 "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_store_observer_mock.h"
+#include "base/values.h"
+#include "extensions/browser/extension_pref_value_map.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kExt1[] = "ext1";
+const char kExt2[] = "ext2";
+const char kExt3[] = "ext3";
+
+const char kPref1[] = "path1.subpath";
+const char kPref2[] = "path2";
+const char kPref3[] = "path3";
+const char kPref4[] = "path4";
+} // namespace
+
+static base::Value* CreateVal(const char* str) {
+ return new base::StringValue(str);
+}
+
+static base::Time CreateTime(int64 t) {
+ return base::Time::FromInternalValue(t);
+}
+
+template <typename BASECLASS>
+class ExtensionPrefValueMapTestBase : public BASECLASS {
+ public:
+ static const extensions::ExtensionPrefsScope kRegular =
+ extensions::kExtensionPrefsScopeRegular;
+ static const extensions::ExtensionPrefsScope kRegularOnly =
+ extensions::kExtensionPrefsScopeRegularOnly;
+ static const extensions::ExtensionPrefsScope kIncognitoPersistent =
+ extensions::kExtensionPrefsScopeIncognitoPersistent;
+ static const extensions::ExtensionPrefsScope kIncognitoSessionOnly =
+ extensions::kExtensionPrefsScopeIncognitoSessionOnly;
+
+ // Returns an empty string if the key is not set.
+ std::string GetValue(const char * key, bool incognito) const {
+ const base::Value *value =
+ epvm_.GetEffectivePrefValue(key, incognito, NULL);
+ std::string string_value;
+ if (value)
+ value->GetAsString(&string_value);
+ return string_value;
+ }
+
+ protected:
+ ExtensionPrefValueMap epvm_;
+};
+
+class ExtensionPrefValueMapTest
+ : public ExtensionPrefValueMapTestBase<testing::Test> {
+};
+
+// A gmock-ified implementation of PrefStore::Observer.
+class ExtensionPrefValueMapObserverMock
+ : public ExtensionPrefValueMap::Observer {
+ public:
+ ExtensionPrefValueMapObserverMock() {}
+ virtual ~ExtensionPrefValueMapObserverMock() {}
+
+ MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
+ MOCK_METHOD0(OnInitializationCompleted, void());
+ MOCK_METHOD0(OnExtensionPrefValueMapDestruction, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMapObserverMock);
+};
+
+TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValue) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ EXPECT_EQ("val1", GetValue(kPref1, false));
+};
+
+TEST_F(ExtensionPrefValueMapTest, GetNotSetPrefValue) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ EXPECT_EQ("", GetValue(kPref1, false));
+};
+
+// Make sure the last-installed extension wins for each preference.
+TEST_F(ExtensionPrefValueMapTest, Override) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
+ epvm_.SetExtensionPref(kExt3, kPref1, kRegular, CreateVal("val3"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val4"));
+ epvm_.SetExtensionPref(kExt2, kPref2, kRegular, CreateVal("val5"));
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val6"));
+ epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val7"));
+ epvm_.SetExtensionPref(kExt1, kPref3, kRegular, CreateVal("val8"));
+
+ EXPECT_EQ("val3", GetValue(kPref1, false));
+ EXPECT_EQ("val5", GetValue(kPref2, false));
+ EXPECT_EQ("val8", GetValue(kPref3, false));
+}
+
+TEST_F(ExtensionPrefValueMapTest, OverrideChecks) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, NULL));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt2, kPref1, NULL));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, NULL));
+ EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
+ EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
+ EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
+
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val1"));
+
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, NULL));
+ EXPECT_TRUE(epvm_.DoesExtensionControlPref(kExt2, kPref1, NULL));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, NULL));
+ EXPECT_FALSE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
+ EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
+ EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
+}
+
+TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValueIncognito) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ EXPECT_EQ("val1", GetValue(kPref1, true));
+}
+
+TEST_F(ExtensionPrefValueMapTest, UninstallOnlyExtension) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.UnregisterExtension(kExt1);
+
+ EXPECT_EQ("", GetValue(kPref1, false));
+}
+
+// Tests uninstalling an extension that wasn't winning for any preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallIrrelevantExtension) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(10), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val3"));
+ epvm_.SetExtensionPref(kExt2, kPref2, kRegular, CreateVal("val4"));
+
+ epvm_.UnregisterExtension(kExt1);
+
+ EXPECT_EQ("val2", GetValue(kPref1, false));
+ EXPECT_EQ("val4", GetValue(kPref2, false));
+}
+
+// Tests uninstalling an extension that was winning for all preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromTop) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
+ epvm_.SetExtensionPref(kExt3, kPref1, kRegular, CreateVal("val3"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val4"));
+ epvm_.SetExtensionPref(kExt3, kPref2, kRegular, CreateVal("val5"));
+
+ epvm_.UnregisterExtension(kExt3);
+
+ EXPECT_EQ("val2", GetValue(kPref1, false));
+ EXPECT_EQ("val4", GetValue(kPref2, false));
+}
+
+// Tests uninstalling an extension that was winning for only some preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromMiddle) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
+ epvm_.SetExtensionPref(kExt3, kPref1, kRegular, CreateVal("val3"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val4"));
+ epvm_.SetExtensionPref(kExt2, kPref2, kRegular, CreateVal("val5"));
+
+ epvm_.SetExtensionPref(kExt1, kPref3, kRegular, CreateVal("val6"));
+
+ epvm_.SetExtensionPref(kExt2, kPref4, kRegular, CreateVal("val7"));
+
+ epvm_.UnregisterExtension(kExt2);
+
+ EXPECT_EQ("val3", GetValue(kPref1, false));
+ EXPECT_EQ("val4", GetValue(kPref2, false));
+ EXPECT_EQ("val6", GetValue(kPref3, false));
+ EXPECT_EQ("", GetValue(kPref4, false));
+}
+
+// Tests triggering of notifications to registered observers.
+TEST_F(ExtensionPrefValueMapTest, NotifyWhenNeeded) {
+ using testing::Mock;
+ using testing::StrEq;
+
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+ ExtensionPrefValueMapObserverMock observer;
+ epvm_.AddObserver(&observer);
+
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Write the same value again.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Override incognito value.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val2"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Override non-incognito value.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val3"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Disable.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionState(kExt1, false);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Enable.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionState(kExt1, true);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Uninstall
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.UnregisterExtension(kExt1);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ epvm_.RemoveObserver(&observer);
+
+ // Write new value --> no notification after removing observer.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val4"));
+ Mock::VerifyAndClearExpectations(&observer);
+}
+
+// Tests disabling an extension.
+TEST_F(ExtensionPrefValueMapTest, DisableExt) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.SetExtensionState(kExt1, false);
+ EXPECT_EQ("", GetValue(kPref1, false));
+}
+
+// Tests disabling and reenabling an extension.
+TEST_F(ExtensionPrefValueMapTest, ReenableExt) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
+ epvm_.SetExtensionState(kExt1, false);
+ epvm_.SetExtensionState(kExt1, true);
+ EXPECT_EQ("val1", GetValue(kPref1, false));
+}
+
+struct OverrideIncognitoTestCase {
+ OverrideIncognitoTestCase(int val_ext1_regular,
+ int val_ext1_regular_only,
+ int val_ext1_incognito_pers,
+ int val_ext1_incognito_sess,
+ int val_ext2_regular,
+ int val_ext2_regular_only,
+ int val_ext2_incognito_pers,
+ int val_ext2_incognito_sess,
+ int effective_value_regular,
+ int effective_value_incognito)
+ : val_ext1_regular_(val_ext1_regular),
+ val_ext1_regular_only_(val_ext1_regular_only),
+ val_ext1_incognito_pers_(val_ext1_incognito_pers),
+ val_ext1_incognito_sess_(val_ext1_incognito_sess),
+ val_ext2_regular_(val_ext2_regular),
+ val_ext2_regular_only_(val_ext2_regular_only),
+ val_ext2_incognito_pers_(val_ext2_incognito_pers),
+ val_ext2_incognito_sess_(val_ext2_incognito_sess),
+ effective_value_regular_(effective_value_regular),
+ effective_value_incognito_(effective_value_incognito) {}
+
+ // pers. = persistent
+ // sess. = session only
+ int val_ext1_regular_; // pref value of extension 1
+ int val_ext1_regular_only_; // pref value of extension 1 regular-only.
+ int val_ext1_incognito_pers_; // pref value of extension 1 incognito pers.
+ int val_ext1_incognito_sess_; // pref value of extension 1 incognito sess.
+ int val_ext2_regular_; // pref value of extension 2
+ int val_ext2_regular_only_; // pref value of extension 2 regular-only.
+ int val_ext2_incognito_pers_; // pref value of extension 2 incognito pers.
+ int val_ext2_incognito_sess_; // pref value of extension 2 incognito sess.
+ int effective_value_regular_; // desired winner regular
+ int effective_value_incognito_; // desired winner incognito
+};
+
+class ExtensionPrefValueMapTestIncognitoTests
+ : public ExtensionPrefValueMapTestBase<
+ testing::TestWithParam<OverrideIncognitoTestCase> > {
+};
+
+TEST_P(ExtensionPrefValueMapTestIncognitoTests, OverrideIncognito) {
+ OverrideIncognitoTestCase test = GetParam();
+ const char* strings[] = {
+ "undefined",
+ "val1",
+ "val2",
+ "val3",
+ "val4",
+ "val5",
+ "val6",
+ "val7",
+ "val8",
+ };
+
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ if (test.val_ext1_regular_) {
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegular,
+ CreateVal(strings[test.val_ext1_regular_]));
+ }
+ if (test.val_ext1_regular_only_) {
+ epvm_.SetExtensionPref(kExt1, kPref1, kRegularOnly,
+ CreateVal(strings[test.val_ext1_regular_only_]));
+ }
+ if (test.val_ext1_incognito_pers_) {
+ epvm_.SetExtensionPref(kExt1, kPref1, kIncognitoPersistent,
+ CreateVal(strings[test.val_ext1_incognito_pers_]));
+ }
+ if (test.val_ext1_incognito_sess_) {
+ epvm_.SetExtensionPref(kExt1, kPref1, kIncognitoSessionOnly,
+ CreateVal(strings[test.val_ext1_incognito_sess_]));
+ }
+ if (test.val_ext2_regular_) {
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegular,
+ CreateVal(strings[test.val_ext2_regular_]));
+ }
+ if (test.val_ext2_regular_only_) {
+ epvm_.SetExtensionPref(kExt2, kPref1, kRegularOnly,
+ CreateVal(strings[test.val_ext2_regular_only_]));
+ }
+ if (test.val_ext2_incognito_pers_) {
+ epvm_.SetExtensionPref(kExt2, kPref1, kIncognitoPersistent,
+ CreateVal(strings[test.val_ext2_incognito_pers_]));
+ }
+ if (test.val_ext2_incognito_sess_) {
+ epvm_.SetExtensionPref(kExt2, kPref1, kIncognitoSessionOnly,
+ CreateVal(strings[test.val_ext2_incognito_sess_]));
+ }
+ std::string actual;
+ EXPECT_EQ(strings[test.effective_value_regular_], GetValue(kPref1, false));
+ EXPECT_EQ(strings[test.effective_value_incognito_], GetValue(kPref1, true));
+ epvm_.UnregisterExtension(kExt1);
+ epvm_.UnregisterExtension(kExt2);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ ExtensionPrefValueMapTestIncognitoTestsInstance,
+ ExtensionPrefValueMapTestIncognitoTests,
+ testing::Values(
+ // e.g. (1, 0, 0, 0, 0, 0, 7, 0, 1, 7), means:
+ // ext1 regular is set to "val1", ext2 incognito persistent is set to
+ // "val7"
+ // --> the winning regular value is "val1", the winning incognito
+ // value is "val7".
+ OverrideIncognitoTestCase(1, 0, 0, 0, 0, 0, 0, 0, 1, 1),
+ OverrideIncognitoTestCase(1, 2, 0, 0, 0, 0, 0, 0, 2, 1),
+ OverrideIncognitoTestCase(1, 0, 3, 0, 0, 0, 0, 0, 1, 3),
+ OverrideIncognitoTestCase(1, 0, 0, 4, 0, 0, 0, 0, 1, 4),
+ OverrideIncognitoTestCase(1, 0, 3, 4, 0, 0, 0, 0, 1, 4),
+ OverrideIncognitoTestCase(1, 2, 3, 0, 0, 0, 0, 0, 2, 3),
+ OverrideIncognitoTestCase(1, 0, 0, 0, 5, 0, 0, 0, 5, 5),
+ OverrideIncognitoTestCase(1, 2, 3, 0, 5, 0, 0, 0, 5, 5),
+ OverrideIncognitoTestCase(1, 0, 0, 0, 0, 6, 0, 0, 6, 1),
+ OverrideIncognitoTestCase(1, 0, 3, 0, 5, 6, 0, 0, 6, 5),
+ OverrideIncognitoTestCase(1, 0, 0, 4, 5, 6, 0, 0, 6, 5),
+ OverrideIncognitoTestCase(1, 0, 0, 0, 0, 0, 7, 0, 1, 7),
+ OverrideIncognitoTestCase(1, 2, 0, 0, 5, 0, 7, 0, 5, 7),
+ OverrideIncognitoTestCase(1, 2, 0, 0, 5, 0, 0, 8, 5, 8),
+ OverrideIncognitoTestCase(1, 2, 0, 0, 5, 0, 7, 8, 5, 8),
+ OverrideIncognitoTestCase(1, 2, 3, 0, 0, 6, 7, 0, 6, 7)));
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
new file mode 100644
index 0000000000..8c26aa339d
--- /dev/null
+++ b/extensions/browser/extension_prefs.cc
@@ -0,0 +1,1911 @@
+// Copyright 2014 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/extension_prefs.h"
+
+#include <iterator>
+
+#include "base/command_line.h"
+#include "base/prefs/pref_notifier.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/value_conversions.h"
+#include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
+#include "chrome/browser/extensions/api/preference/preference_api.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "extensions/browser/admin_policy.h"
+#include "extensions/browser/app_sorting.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_pref_store.h"
+#include "extensions/browser/extension_prefs_factory.h"
+#include "extensions/browser/pref_names.h"
+#include "extensions/common/feature_switch.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/url_pattern.h"
+#include "extensions/common/user_script.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using base::Value;
+using base::DictionaryValue;
+using base::ListValue;
+
+namespace extensions {
+
+namespace {
+
+// Additional preferences keys, which are not needed by external clients.
+
+// True if this extension is running. Note this preference stops getting updated
+// during Chrome shutdown (and won't be updated on a browser crash) and so can
+// be used at startup to determine whether the extension was running when Chrome
+// was last terminated.
+const char kPrefRunning[] = "running";
+
+// Whether this extension had windows when it was last running.
+const char kIsActive[] = "is_active";
+
+// Where an extension was installed from. (see Manifest::Location)
+const char kPrefLocation[] = "location";
+
+// Enabled, disabled, killed, etc. (see Extension::State)
+const char kPrefState[] = "state";
+
+// The path to the current version's manifest file.
+const char kPrefPath[] = "path";
+
+// The dictionary containing the extension's manifest.
+const char kPrefManifest[] = "manifest";
+
+// The version number.
+const char kPrefVersion[] = "manifest.version";
+
+// Indicates whether an extension is blacklisted.
+const char kPrefBlacklist[] = "blacklist";
+
+// If extension is greylisted.
+const char kPrefBlacklistState[] = "blacklist_state";
+
+// The count of how many times we prompted the user to acknowledge an
+// extension.
+const char kPrefAcknowledgePromptCount[] = "ack_prompt_count";
+
+// Indicates whether the user has acknowledged various types of extensions.
+const char kPrefExternalAcknowledged[] = "ack_external";
+const char kPrefBlacklistAcknowledged[] = "ack_blacklist";
+const char kPrefWipeoutAcknowledged[] = "ack_wiped";
+
+// Indicates whether the external extension was installed during the first
+// run of this profile.
+const char kPrefExternalInstallFirstRun[] = "external_first_run";
+
+// Indicates whether to show an install warning when the user enables.
+const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable";
+
+// DO NOT USE, use kPrefDisableReasons instead.
+// Indicates whether the extension was updated while it was disabled.
+const char kDeprecatedPrefDisableReason[] = "disable_reason";
+
+// A bitmask of all the reasons an extension is disabled.
+const char kPrefDisableReasons[] = "disable_reasons";
+
+// The key for a serialized Time value indicating the start of the day (from the
+// server's perspective) an extension last included a "ping" parameter during
+// its update check.
+const char kLastPingDay[] = "lastpingday";
+
+// Similar to kLastPingDay, but for "active" instead of "rollcall" pings.
+const char kLastActivePingDay[] = "last_active_pingday";
+
+// A bit we use to keep track of whether we need to do an "active" ping.
+const char kActiveBit[] = "active_bit";
+
+// Path for settings specific to blacklist update.
+const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate";
+
+// Path for the delayed install info dictionary preference. The actual string
+// value is a legacy artifact for when delayed installs only pertained to
+// updates that were waiting for idle.
+const char kDelayedInstallInfo[] = "idle_install_info";
+
+// Reason why the extension's install was delayed.
+const char kDelayedInstallReason[] = "delay_install_reason";
+
+// Path for the suggested page ordinal of a delayed extension install.
+const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
+
+// A preference that, if true, will allow this extension to run in incognito
+// mode.
+const char kPrefIncognitoEnabled[] = "incognito";
+
+// A preference to control whether an extension is allowed to inject script in
+// pages with file URLs.
+const char kPrefAllowFileAccess[] = "newAllowFileAccess";
+// TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all
+// extension file access by renaming the pref. We should eventually clean up
+// the old flag and possibly go back to that name.
+// const char kPrefAllowFileAccessOld[] = "allowFileAccess";
+
+// A preference specifying if the user dragged the app on the NTP.
+const char kPrefUserDraggedApp[] = "user_dragged_app_ntp";
+
+// Preferences that hold which permissions the user has granted the extension.
+// We explicitly keep track of these so that extensions can contain unknown
+// permissions, for backwards compatibility reasons, and we can still prompt
+// the user to accept them once recognized. We store the active permission
+// permissions because they may differ from those defined in the manifest.
+const char kPrefActivePermissions[] = "active_permissions";
+const char kPrefGrantedPermissions[] = "granted_permissions";
+
+// The preference names for PermissionSet values.
+const char kPrefAPIs[] = "api";
+const char kPrefManifestPermissions[] = "manifest_permissions";
+const char kPrefExplicitHosts[] = "explicit_host";
+const char kPrefScriptableHosts[] = "scriptable_host";
+
+// The preference names for the old granted permissions scheme.
+const char kPrefOldGrantedFullAccess[] = "granted_permissions.full";
+const char kPrefOldGrantedHosts[] = "granted_permissions.host";
+const char kPrefOldGrantedAPIs[] = "granted_permissions.api";
+
+// A preference that indicates when an extension was installed.
+const char kPrefInstallTime[] = "install_time";
+
+// A preference which saves the creation flags for extensions.
+const char kPrefCreationFlags[] = "creation_flags";
+
+// A preference that indicates whether the extension was installed from the
+// Chrome Web Store.
+const char kPrefFromWebStore[] = "from_webstore";
+
+// A preference that indicates whether the extension was installed from a
+// mock App created from a bookmark.
+const char kPrefFromBookmark[] = "from_bookmark";
+
+// A preference that indicates whether the extension was installed as
+// default apps.
+const char kPrefWasInstalledByDefault[] = "was_installed_by_default";
+
+// Key for Geometry Cache preference.
+const char kPrefGeometryCache[] = "geometry_cache";
+
+// A preference that indicates when an extension is last launched.
+const char kPrefLastLaunchTime[] = "last_launch_time";
+
+// A list of installed ids and a signature.
+const char kInstallSignature[] = "extensions.install_signature";
+
+// Provider of write access to a dictionary storing extension prefs.
+class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate {
+ public:
+ ScopedExtensionPrefUpdate(PrefService* service,
+ const std::string& extension_id) :
+ DictionaryPrefUpdate(service, pref_names::kExtensions),
+ extension_id_(extension_id) {}
+
+ virtual ~ScopedExtensionPrefUpdate() {
+ }
+
+ // DictionaryPrefUpdate overrides:
+ virtual base::DictionaryValue* Get() OVERRIDE {
+ base::DictionaryValue* dict = DictionaryPrefUpdate::Get();
+ base::DictionaryValue* extension = NULL;
+ if (!dict->GetDictionary(extension_id_, &extension)) {
+ // Extension pref does not exist, create it.
+ extension = new base::DictionaryValue();
+ dict->SetWithoutPathExpansion(extension_id_, extension);
+ }
+ return extension;
+ }
+
+ private:
+ const std::string extension_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate);
+};
+
+std::string JoinPrefs(const std::string& parent, const char* child) {
+ return parent + "." + child;
+}
+
+// Checks if kPrefBlacklist is set to true in the base::DictionaryValue.
+// Return false if the value is false or kPrefBlacklist does not exist.
+// This is used to decide if an extension is blacklisted.
+bool IsBlacklistBitSet(const base::DictionaryValue* ext) {
+ bool bool_value;
+ return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value;
+}
+
+} // namespace
+
+//
+// TimeProvider
+//
+
+ExtensionPrefs::TimeProvider::TimeProvider() {
+}
+
+ExtensionPrefs::TimeProvider::~TimeProvider() {
+}
+
+base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const {
+ return base::Time::Now();
+}
+
+//
+// ScopedUpdate
+//
+template <typename T, base::Value::Type type_enum_value>
+ExtensionPrefs::ScopedUpdate<T, type_enum_value>::ScopedUpdate(
+ ExtensionPrefs* prefs,
+ const std::string& extension_id,
+ const std::string& key)
+ : update_(prefs->pref_service(), pref_names::kExtensions),
+ extension_id_(extension_id),
+ key_(key) {
+ DCHECK(Extension::IdIsValid(extension_id_));
+}
+
+template <typename T, base::Value::Type type_enum_value>
+ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() {
+}
+
+template <typename T, base::Value::Type type_enum_value>
+T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Get() {
+ base::DictionaryValue* dict = update_.Get();
+ base::DictionaryValue* extension = NULL;
+ base::Value* key_value = NULL;
+ if (!dict->GetDictionary(extension_id_, &extension) ||
+ !extension->Get(key_, &key_value)) {
+ return NULL;
+ }
+ return key_value->GetType() == type_enum_value ?
+ static_cast<T*>(key_value) :
+ NULL;
+}
+
+template <typename T, base::Value::Type type_enum_value>
+T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Create() {
+ base::DictionaryValue* dict = update_.Get();
+ base::DictionaryValue* extension = NULL;
+ base::Value* key_value = NULL;
+ T* value_as_t = NULL;
+ if (!dict->GetDictionary(extension_id_, &extension)) {
+ extension = new base::DictionaryValue;
+ dict->SetWithoutPathExpansion(extension_id_, extension);
+ }
+ if (!extension->Get(key_, &key_value)) {
+ value_as_t = new T;
+ extension->SetWithoutPathExpansion(key_, value_as_t);
+ } else {
+ CHECK(key_value->GetType() == type_enum_value);
+ value_as_t = static_cast<T*>(key_value);
+ }
+ return value_as_t;
+}
+
+// Explicit instantiations for Dictionary and List value types.
+template class ExtensionPrefs::ScopedUpdate<base::DictionaryValue,
+ base::Value::TYPE_DICTIONARY>;
+template class ExtensionPrefs::ScopedUpdate<base::ListValue,
+ base::Value::TYPE_LIST>;
+
+//
+// ExtensionPrefs
+//
+
+// static
+ExtensionPrefs* ExtensionPrefs::Create(
+ PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ bool extensions_disabled) {
+ return ExtensionPrefs::Create(prefs,
+ root_dir,
+ extension_pref_value_map,
+ app_sorting.Pass(),
+ extensions_disabled,
+ make_scoped_ptr(new TimeProvider()));
+}
+
+// static
+ExtensionPrefs* ExtensionPrefs::Create(
+ PrefService* pref_service,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ bool extensions_disabled,
+ scoped_ptr<TimeProvider> time_provider) {
+ return new ExtensionPrefs(pref_service,
+ root_dir,
+ extension_pref_value_map,
+ app_sorting.Pass(),
+ time_provider.Pass(),
+ extensions_disabled);
+}
+
+ExtensionPrefs::~ExtensionPrefs() {
+}
+
+// static
+ExtensionPrefs* ExtensionPrefs::Get(content::BrowserContext* context) {
+ return ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(context);
+}
+
+static base::FilePath::StringType MakePathRelative(const base::FilePath& parent,
+ const base::FilePath& child) {
+ if (!parent.IsParent(child))
+ return child.value();
+
+ base::FilePath::StringType retval = child.value().substr(
+ parent.value().length());
+ if (base::FilePath::IsSeparator(retval[0]))
+ return retval.substr(1);
+ else
+ return retval;
+}
+
+void ExtensionPrefs::MakePathsRelative() {
+ const base::DictionaryValue* dict =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ if (!dict || dict->empty())
+ return;
+
+ // Collect all extensions ids with absolute paths in |absolute_keys|.
+ std::set<std::string> absolute_keys;
+ for (base::DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
+ const base::DictionaryValue* extension_dict = NULL;
+ if (!i.value().GetAsDictionary(&extension_dict))
+ continue;
+ int location_value;
+ if (extension_dict->GetInteger(kPrefLocation, &location_value) &&
+ Manifest::IsUnpackedLocation(
+ static_cast<Manifest::Location>(location_value))) {
+ // Unpacked extensions can have absolute paths.
+ continue;
+ }
+ base::FilePath::StringType path_string;
+ if (!extension_dict->GetString(kPrefPath, &path_string))
+ continue;
+ base::FilePath path(path_string);
+ if (path.IsAbsolute())
+ absolute_keys.insert(i.key());
+ }
+ if (absolute_keys.empty())
+ return;
+
+ // Fix these paths.
+ DictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
+ base::DictionaryValue* update_dict = update.Get();
+ for (std::set<std::string>::iterator i = absolute_keys.begin();
+ i != absolute_keys.end(); ++i) {
+ base::DictionaryValue* extension_dict = NULL;
+ if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
+ NOTREACHED() << "Control should never reach here for extension " << *i;
+ continue;
+ }
+ base::FilePath::StringType path_string;
+ extension_dict->GetString(kPrefPath, &path_string);
+ base::FilePath path(path_string);
+ extension_dict->SetString(kPrefPath,
+ MakePathRelative(install_directory_, path));
+ }
+}
+
+const base::DictionaryValue* ExtensionPrefs::GetExtensionPref(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ const base::DictionaryValue* extension_dict = NULL;
+ if (!extensions ||
+ !extensions->GetDictionary(extension_id, &extension_dict)) {
+ return NULL;
+ }
+ return extension_dict;
+}
+
+void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id,
+ const std::string& key,
+ base::Value* data_value) {
+ if (!Extension::IdIsValid(extension_id)) {
+ NOTREACHED() << "Invalid extension_id " << extension_id;
+ return;
+ }
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ if (data_value)
+ update->Set(key, data_value);
+ else
+ update->Remove(key, NULL);
+}
+
+void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
+ extension_pref_value_map_->UnregisterExtension(extension_id);
+ content_settings_store_->UnregisterExtension(extension_id);
+ DictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
+ base::DictionaryValue* dict = update.Get();
+ dict->Remove(extension_id, NULL);
+}
+
+bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id,
+ const std::string& pref_key,
+ bool* out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ if (!ext || !ext->GetBoolean(pref_key, out_value))
+ return false;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id,
+ const std::string& pref_key,
+ int* out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ if (!ext || !ext->GetInteger(pref_key, out_value))
+ return false;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id,
+ const std::string& pref_key,
+ std::string* out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ if (!ext || !ext->GetString(pref_key, out_value))
+ return false;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id,
+ const std::string& pref_key,
+ const base::ListValue** out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ const base::ListValue* out = NULL;
+ if (!ext || !ext->GetList(pref_key, &out))
+ return false;
+ if (out_value)
+ *out_value = out;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsDictionary(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const base::DictionaryValue** out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ const base::DictionaryValue* out = NULL;
+ if (!ext || !ext->GetDictionary(pref_key, &out))
+ return false;
+ if (out_value)
+ *out_value = out;
+
+ return true;
+}
+
+bool ExtensionPrefs::HasPrefForExtension(
+ const std::string& extension_id) const {
+ return GetExtensionPref(extension_id) != NULL;
+}
+
+bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id,
+ const std::string& pref_key,
+ URLPatternSet* result,
+ int valid_schemes) {
+ const base::ListValue* value = NULL;
+ if (!ReadPrefAsList(extension_id, pref_key, &value))
+ return false;
+
+ bool allow_file_access = AllowFileAccess(extension_id);
+ return result->Populate(*value, valid_schemes, allow_file_access, NULL);
+}
+
+void ExtensionPrefs::SetExtensionPrefURLPatternSet(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const URLPatternSet& new_value) {
+ UpdateExtensionPref(extension_id, pref_key, new_value.ToValue().release());
+}
+
+bool ExtensionPrefs::ReadPrefAsBooleanAndReturn(
+ const std::string& extension_id,
+ const std::string& pref_key) const {
+ bool out_value = false;
+ return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value;
+}
+
+PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet(
+ const std::string& extension_id,
+ const std::string& pref_key) {
+ if (!GetExtensionPref(extension_id))
+ return NULL;
+
+ // Retrieve the API permissions. Please refer SetExtensionPrefPermissionSet()
+ // for api_values format.
+ APIPermissionSet apis;
+ const base::ListValue* api_values = NULL;
+ std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
+ if (ReadPrefAsList(extension_id, api_pref, &api_values)) {
+ APIPermissionSet::ParseFromJSON(api_values,
+ APIPermissionSet::kAllowInternalPermissions,
+ &apis, NULL, NULL);
+ }
+
+ // Retrieve the Manifest Keys permissions. Please refer to
+ // |SetExtensionPrefPermissionSet| for manifest_permissions_values format.
+ ManifestPermissionSet manifest_permissions;
+ const base::ListValue* manifest_permissions_values = NULL;
+ std::string manifest_permission_pref =
+ JoinPrefs(pref_key, kPrefManifestPermissions);
+ if (ReadPrefAsList(extension_id, manifest_permission_pref,
+ &manifest_permissions_values)) {
+ ManifestPermissionSet::ParseFromJSON(
+ manifest_permissions_values, &manifest_permissions, NULL, NULL);
+ }
+
+ // Retrieve the explicit host permissions.
+ URLPatternSet explicit_hosts;
+ ReadPrefAsURLPatternSet(
+ extension_id, JoinPrefs(pref_key, kPrefExplicitHosts),
+ &explicit_hosts, Extension::kValidHostPermissionSchemes);
+
+ // Retrieve the scriptable host permissions.
+ URLPatternSet scriptable_hosts;
+ ReadPrefAsURLPatternSet(
+ extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
+ &scriptable_hosts, UserScript::ValidUserScriptSchemes());
+
+ return new PermissionSet(
+ apis, manifest_permissions, explicit_hosts, scriptable_hosts);
+}
+
+// Set the API or Manifest permissions.
+// The format of api_values is:
+// [ "permission_name1", // permissions do not support detail.
+// "permission_name2",
+// {"permission_name3": value },
+// // permission supports detail, permission detail will be stored in value.
+// ...
+// ]
+template<typename T>
+static base::ListValue* CreatePermissionList(const T& permissions) {
+ base::ListValue* values = new base::ListValue();
+ for (typename T::const_iterator i = permissions.begin();
+ i != permissions.end(); ++i) {
+ scoped_ptr<base::Value> detail(i->ToValue());
+ if (detail) {
+ base::DictionaryValue* tmp = new base::DictionaryValue();
+ tmp->Set(i->name(), detail.release());
+ values->Append(tmp);
+ } else {
+ values->Append(new base::StringValue(i->name()));
+ }
+ }
+ return values;
+}
+
+void ExtensionPrefs::SetExtensionPrefPermissionSet(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const PermissionSet* new_value) {
+ std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
+ base::ListValue* api_values = CreatePermissionList(new_value->apis());
+ UpdateExtensionPref(extension_id, api_pref, api_values);
+
+ std::string manifest_permissions_pref =
+ JoinPrefs(pref_key, kPrefManifestPermissions);
+ base::ListValue* manifest_permissions_values = CreatePermissionList(
+ new_value->manifest_permissions());
+ UpdateExtensionPref(extension_id,
+ manifest_permissions_pref,
+ manifest_permissions_values);
+
+ // Set the explicit host permissions.
+ if (!new_value->explicit_hosts().is_empty()) {
+ SetExtensionPrefURLPatternSet(extension_id,
+ JoinPrefs(pref_key, kPrefExplicitHosts),
+ new_value->explicit_hosts());
+ }
+
+ // Set the scriptable host permissions.
+ if (!new_value->scriptable_hosts().is_empty()) {
+ SetExtensionPrefURLPatternSet(extension_id,
+ JoinPrefs(pref_key, kPrefScriptableHosts),
+ new_value->scriptable_hosts());
+ }
+}
+
+int ExtensionPrefs::IncrementAcknowledgePromptCount(
+ const std::string& extension_id) {
+ int count = 0;
+ ReadPrefAsInteger(extension_id, kPrefAcknowledgePromptCount, &count);
+ ++count;
+ UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount,
+ new base::FundamentalValue(count));
+ return count;
+}
+
+bool ExtensionPrefs::IsExternalExtensionAcknowledged(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
+}
+
+void ExtensionPrefs::AcknowledgeExternalExtension(
+ const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ UpdateExtensionPref(extension_id, kPrefExternalAcknowledged,
+ new base::FundamentalValue(true));
+ UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
+}
+
+bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
+}
+
+void ExtensionPrefs::AcknowledgeBlacklistedExtension(
+ const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged,
+ new base::FundamentalValue(true));
+ UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
+}
+
+bool ExtensionPrefs::IsExternalInstallFirstRun(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
+}
+
+void ExtensionPrefs::SetExternalInstallFirstRun(
+ const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ UpdateExtensionPref(extension_id, kPrefExternalInstallFirstRun,
+ new base::FundamentalValue(true));
+}
+
+bool ExtensionPrefs::HasWipeoutBeenAcknowledged(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefWipeoutAcknowledged);
+}
+
+void ExtensionPrefs::SetWipeoutAcknowledged(
+ const std::string& extension_id,
+ bool value) {
+ UpdateExtensionPref(extension_id, kPrefWipeoutAcknowledged,
+ value ? base::Value::CreateBooleanValue(value) : NULL);
+}
+
+bool ExtensionPrefs::SetAlertSystemFirstRun() {
+ if (prefs_->GetBoolean(pref_names::kAlertsInitialized)) {
+ return true;
+ }
+ prefs_->SetBoolean(pref_names::kAlertsInitialized, true);
+ return false;
+}
+
+bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const {
+ return admin_policy::BlacklistedByDefault(
+ prefs_->GetList(pref_names::kInstallDenyList));
+}
+
+bool ExtensionPrefs::DidExtensionEscalatePermissions(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id,
+ kExtensionDidEscalatePermissions);
+}
+
+void ExtensionPrefs::SetDidExtensionEscalatePermissions(
+ const Extension* extension, bool did_escalate) {
+ UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
+ new base::FundamentalValue(did_escalate));
+}
+
+int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) const {
+ int value = -1;
+ if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) &&
+ value >= 0) {
+ return value;
+ }
+ return Extension::DISABLE_NONE;
+}
+
+void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
+ Extension::DisableReason disable_reason) {
+ int new_value = GetDisableReasons(extension_id) |
+ static_cast<int>(disable_reason);
+ UpdateExtensionPref(extension_id, kPrefDisableReasons,
+ new base::FundamentalValue(new_value));
+}
+
+void ExtensionPrefs::RemoveDisableReason(
+ const std::string& extension_id,
+ Extension::DisableReason disable_reason) {
+ int new_value = GetDisableReasons(extension_id) &
+ ~static_cast<int>(disable_reason);
+ if (new_value == Extension::DISABLE_NONE) {
+ UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
+ } else {
+ UpdateExtensionPref(extension_id, kPrefDisableReasons,
+ new base::FundamentalValue(new_value));
+ }
+}
+
+void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
+ UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
+}
+
+std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
+ std::set<std::string> ids;
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ if (!extensions)
+ return ids;
+
+ for (base::DictionaryValue::Iterator it(*extensions);
+ !it.IsAtEnd(); it.Advance()) {
+ if (!it.value().IsType(base::Value::TYPE_DICTIONARY)) {
+ NOTREACHED() << "Invalid pref for extension " << it.key();
+ continue;
+ }
+ if (IsBlacklistBitSet(
+ static_cast<const base::DictionaryValue*>(&it.value()))) {
+ ids.insert(it.key());
+ }
+ }
+
+ return ids;
+}
+
+void ExtensionPrefs::SetExtensionBlacklisted(const std::string& extension_id,
+ bool is_blacklisted) {
+ bool currently_blacklisted = IsExtensionBlacklisted(extension_id);
+ if (is_blacklisted == currently_blacklisted)
+ return;
+
+ // Always make sure the "acknowledged" bit is cleared since the blacklist bit
+ // is changing.
+ UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, NULL);
+
+ if (is_blacklisted) {
+ UpdateExtensionPref(extension_id,
+ kPrefBlacklist,
+ new base::FundamentalValue(true));
+ } else {
+ UpdateExtensionPref(extension_id, kPrefBlacklist, NULL);
+ const base::DictionaryValue* dict = GetExtensionPref(extension_id);
+ if (dict && dict->empty())
+ DeleteExtensionPrefs(extension_id);
+ }
+}
+
+bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const {
+ const base::DictionaryValue* ext_prefs = GetExtensionPref(id);
+ return ext_prefs && IsBlacklistBitSet(ext_prefs);
+}
+
+namespace {
+
+// Serializes |time| as a string value mapped to |key| in |dictionary|.
+void SaveTime(base::DictionaryValue* dictionary,
+ const char* key,
+ const base::Time& time) {
+ if (!dictionary)
+ return;
+ std::string string_value = base::Int64ToString(time.ToInternalValue());
+ dictionary->SetString(key, string_value);
+}
+
+// The opposite of SaveTime. If |key| is not found, this returns an empty Time
+// (is_null() will return true).
+base::Time ReadTime(const base::DictionaryValue* dictionary, const char* key) {
+ if (!dictionary)
+ return base::Time();
+ std::string string_value;
+ int64 value;
+ if (dictionary->GetString(key, &string_value)) {
+ if (base::StringToInt64(string_value, &value)) {
+ return base::Time::FromInternalValue(value);
+ }
+ }
+ return base::Time();
+}
+
+} // namespace
+
+base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
+ DCHECK(Extension::IdIsValid(extension_id));
+ return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
+}
+
+void ExtensionPrefs::SetLastPingDay(const std::string& extension_id,
+ const base::Time& time) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ SaveTime(update.Get(), kLastPingDay, time);
+}
+
+base::Time ExtensionPrefs::BlacklistLastPingDay() const {
+ return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate),
+ kLastPingDay);
+}
+
+void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
+ DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate);
+ SaveTime(update.Get(), kLastPingDay, time);
+}
+
+base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
+}
+
+void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id,
+ const base::Time& time) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ SaveTime(update.Get(), kLastActivePingDay, time);
+}
+
+bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary && dictionary->GetBoolean(kActiveBit, &result))
+ return result;
+ return false;
+}
+
+void ExtensionPrefs::SetActiveBit(const std::string& extension_id,
+ bool active) {
+ UpdateExtensionPref(extension_id, kActiveBit,
+ new base::FundamentalValue(active));
+}
+
+void ExtensionPrefs::MigratePermissions(const ExtensionIdList& extension_ids) {
+ PermissionsInfo* info = PermissionsInfo::GetInstance();
+ for (ExtensionIdList::const_iterator ext_id =
+ extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
+ // An extension's granted permissions need to be migrated if the
+ // full_access bit is present. This bit was always present in the previous
+ // scheme and is never present now.
+ bool full_access;
+ const base::DictionaryValue* ext = GetExtensionPref(*ext_id);
+ if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access))
+ continue;
+
+ // Remove the full access bit (empty list will get trimmed).
+ UpdateExtensionPref(
+ *ext_id, kPrefOldGrantedFullAccess, new base::ListValue());
+
+ // Add the plugin permission if the full access bit was set.
+ if (full_access) {
+ const base::ListValue* apis = NULL;
+ base::ListValue* new_apis = NULL;
+
+ std::string granted_apis = JoinPrefs(kPrefGrantedPermissions, kPrefAPIs);
+ if (ext->GetList(kPrefOldGrantedAPIs, &apis))
+ new_apis = apis->DeepCopy();
+ else
+ new_apis = new base::ListValue();
+
+ std::string plugin_name = info->GetByID(APIPermission::kPlugin)->name();
+ new_apis->Append(new base::StringValue(plugin_name));
+ UpdateExtensionPref(*ext_id, granted_apis, new_apis);
+ }
+
+ // The granted permissions originally only held the effective hosts,
+ // which are a combination of host and user script host permissions.
+ // We now maintain these lists separately. For migration purposes, it
+ // does not matter how we treat the old effective hosts as long as the
+ // new effective hosts will be the same, so we move them to explicit
+ // host permissions.
+ const base::ListValue* hosts = NULL;
+ std::string explicit_hosts =
+ JoinPrefs(kPrefGrantedPermissions, kPrefExplicitHosts);
+ if (ext->GetList(kPrefOldGrantedHosts, &hosts)) {
+ UpdateExtensionPref(
+ *ext_id, explicit_hosts, hosts->DeepCopy());
+
+ // We can get rid of the old one by setting it to an empty list.
+ UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new base::ListValue());
+ }
+ }
+}
+
+void ExtensionPrefs::MigrateDisableReasons(
+ const ExtensionIdList& extension_ids) {
+ for (ExtensionIdList::const_iterator ext_id =
+ extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
+ int value = -1;
+ if (ReadPrefAsInteger(*ext_id, kDeprecatedPrefDisableReason, &value)) {
+ int new_value = Extension::DISABLE_NONE;
+ switch (value) {
+ case Extension::DEPRECATED_DISABLE_USER_ACTION:
+ new_value = Extension::DISABLE_USER_ACTION;
+ break;
+ case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE:
+ new_value = Extension::DISABLE_PERMISSIONS_INCREASE;
+ break;
+ case Extension::DEPRECATED_DISABLE_RELOAD:
+ new_value = Extension::DISABLE_RELOAD;
+ break;
+ }
+
+ UpdateExtensionPref(*ext_id, kPrefDisableReasons,
+ new base::FundamentalValue(new_value));
+ // Remove the old disable reason.
+ UpdateExtensionPref(*ext_id, kDeprecatedPrefDisableReason, NULL);
+ }
+ }
+}
+
+PermissionSet* ExtensionPrefs::GetGrantedPermissions(
+ const std::string& extension_id) {
+ CHECK(Extension::IdIsValid(extension_id));
+ return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
+}
+
+void ExtensionPrefs::AddGrantedPermissions(
+ const std::string& extension_id,
+ const PermissionSet* permissions) {
+ CHECK(Extension::IdIsValid(extension_id));
+
+ scoped_refptr<PermissionSet> granted_permissions(
+ GetGrantedPermissions(extension_id));
+
+ // The new granted permissions are the union of the already granted
+ // permissions and the newly granted permissions.
+ scoped_refptr<PermissionSet> new_perms(
+ PermissionSet::CreateUnion(
+ permissions, granted_permissions.get()));
+
+ SetExtensionPrefPermissionSet(
+ extension_id, kPrefGrantedPermissions, new_perms.get());
+}
+
+void ExtensionPrefs::RemoveGrantedPermissions(
+ const std::string& extension_id,
+ const PermissionSet* permissions) {
+ CHECK(Extension::IdIsValid(extension_id));
+
+ scoped_refptr<PermissionSet> granted_permissions(
+ GetGrantedPermissions(extension_id));
+
+ // The new granted permissions are the difference of the already granted
+ // permissions and the newly ungranted permissions.
+ scoped_refptr<PermissionSet> new_perms(
+ PermissionSet::CreateDifference(
+ granted_permissions.get(), permissions));
+
+ SetExtensionPrefPermissionSet(
+ extension_id, kPrefGrantedPermissions, new_perms.get());
+}
+
+PermissionSet* ExtensionPrefs::GetActivePermissions(
+ const std::string& extension_id) {
+ CHECK(Extension::IdIsValid(extension_id));
+ return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
+}
+
+void ExtensionPrefs::SetActivePermissions(
+ const std::string& extension_id,
+ const PermissionSet* permissions) {
+ SetExtensionPrefPermissionSet(
+ extension_id, kPrefActivePermissions, permissions);
+}
+
+void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id,
+ bool is_running) {
+ base::Value* value = new base::FundamentalValue(is_running);
+ UpdateExtensionPref(extension_id, kPrefRunning, value);
+}
+
+bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return false;
+ bool running = false;
+ extension->GetBoolean(kPrefRunning, &running);
+ return running;
+}
+
+void ExtensionPrefs::SetIsActive(const std::string& extension_id,
+ bool is_active) {
+ base::Value* value = new base::FundamentalValue(is_active);
+ UpdateExtensionPref(extension_id, kIsActive, value);
+}
+
+bool ExtensionPrefs::IsActive(const std::string& extension_id) {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return false;
+ bool is_active = false;
+ extension->GetBoolean(kIsActive, &is_active);
+ return is_active;
+}
+
+bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) const {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled);
+}
+
+void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id,
+ bool enabled) {
+ UpdateExtensionPref(extension_id, kPrefIncognitoEnabled,
+ new base::FundamentalValue(enabled));
+}
+
+bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) const {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess);
+}
+
+void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
+ bool allow) {
+ UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
+ new base::FundamentalValue(allow));
+}
+
+bool ExtensionPrefs::HasAllowFileAccessSetting(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ return ext && ext->HasKey(kPrefAllowFileAccess);
+}
+
+bool ExtensionPrefs::DoesExtensionHaveState(
+ const std::string& id, Extension::State check_state) const {
+ const base::DictionaryValue* extension = GetExtensionPref(id);
+ int state = -1;
+ if (!extension || !extension->GetInteger(kPrefState, &state))
+ return false;
+
+ if (state < 0 || state >= Extension::NUM_STATES) {
+ LOG(ERROR) << "Bad pref 'state' for extension '" << id << "'";
+ return false;
+ }
+
+ return state == check_state;
+}
+
+bool ExtensionPrefs::IsExternalExtensionUninstalled(
+ const std::string& id) const {
+ return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED);
+}
+
+bool ExtensionPrefs::IsExtensionDisabled(
+ const std::string& id) const {
+ return DoesExtensionHaveState(id, Extension::DISABLED);
+}
+
+ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
+ ExtensionIdList id_list_out;
+ GetUserExtensionPrefIntoContainer(pref_names::kToolbar, &id_list_out);
+ return id_list_out;
+}
+
+void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) {
+ SetExtensionPrefFromContainer(pref_names::kToolbar, extension_ids);
+}
+
+bool ExtensionPrefs::GetKnownDisabled(ExtensionIdSet* id_set_out) {
+ return GetUserExtensionPrefIntoContainer(pref_names::kKnownDisabled,
+ id_set_out);
+}
+
+void ExtensionPrefs::SetKnownDisabled(const ExtensionIdSet& extension_ids) {
+ SetExtensionPrefFromContainer(pref_names::kKnownDisabled, extension_ids);
+}
+
+void ExtensionPrefs::OnExtensionInstalled(
+ const Extension* extension,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ const syncer::StringOrdinal& page_ordinal) {
+ ScopedExtensionPrefUpdate update(prefs_, extension->id());
+ base::DictionaryValue* extension_dict = update.Get();
+ const base::Time install_time = time_provider_->GetCurrentTime();
+ PopulateExtensionInfoPrefs(extension, install_time, initial_state,
+ blacklisted_for_malware, extension_dict);
+ FinishExtensionInfoPrefs(extension->id(), install_time,
+ extension->RequiresSortOrdinal(),
+ page_ordinal, extension_dict);
+}
+
+void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
+ const Manifest::Location& location,
+ bool external_uninstall) {
+ app_sorting_->ClearOrdinals(extension_id);
+
+ // For external extensions, we save a preference reminding ourself not to try
+ // and install the extension anymore (except when |external_uninstall| is
+ // true, which signifies that the registry key was deleted or the pref file
+ // no longer lists the extension).
+ if (!external_uninstall && Manifest::IsExternalLocation(location)) {
+ UpdateExtensionPref(extension_id, kPrefState,
+ new base::FundamentalValue(
+ Extension::EXTERNAL_EXTENSION_UNINSTALLED));
+ extension_pref_value_map_->SetExtensionState(extension_id, false);
+ content_settings_store_->SetExtensionState(extension_id, false);
+ } else {
+ DeleteExtensionPrefs(extension_id);
+ }
+}
+
+void ExtensionPrefs::SetExtensionState(const std::string& extension_id,
+ Extension::State state) {
+ UpdateExtensionPref(extension_id, kPrefState,
+ new base::FundamentalValue(state));
+ bool enabled = (state == Extension::ENABLED);
+ extension_pref_value_map_->SetExtensionState(extension_id, enabled);
+ content_settings_store_->SetExtensionState(extension_id, enabled);
+}
+
+void ExtensionPrefs::SetExtensionBlacklistState(const std::string& extension_id,
+ BlacklistState state) {
+ SetExtensionBlacklisted(extension_id, state == BLACKLISTED_MALWARE);
+ UpdateExtensionPref(extension_id, kPrefBlacklistState,
+ new base::FundamentalValue(state));
+}
+
+BlacklistState ExtensionPrefs::GetExtensionBlacklistState(
+ const std::string& extension_id) {
+ if (IsExtensionBlacklisted(extension_id))
+ return BLACKLISTED_MALWARE;
+ const base::DictionaryValue* ext_prefs = GetExtensionPref(extension_id);
+ int int_value;
+ if (ext_prefs && ext_prefs->GetInteger(kPrefBlacklistState, &int_value))
+ return static_cast<BlacklistState>(int_value);
+
+ return NOT_BLACKLISTED;
+}
+
+std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return std::string();
+
+ std::string version;
+ extension->GetString(kPrefVersion, &version);
+
+ return version;
+}
+
+void ExtensionPrefs::UpdateManifest(const Extension* extension) {
+ if (!Manifest::IsUnpackedLocation(extension->location())) {
+ const base::DictionaryValue* extension_dict =
+ GetExtensionPref(extension->id());
+ if (!extension_dict)
+ return;
+ const base::DictionaryValue* old_manifest = NULL;
+ bool update_required =
+ !extension_dict->GetDictionary(kPrefManifest, &old_manifest) ||
+ !extension->manifest()->value()->Equals(old_manifest);
+ if (update_required) {
+ UpdateExtensionPref(extension->id(), kPrefManifest,
+ extension->manifest()->value()->DeepCopy());
+ }
+ }
+}
+
+base::FilePath ExtensionPrefs::GetExtensionPath(
+ const std::string& extension_id) {
+ const base::DictionaryValue* dict = GetExtensionPref(extension_id);
+ if (!dict)
+ return base::FilePath();
+
+ std::string path;
+ if (!dict->GetString(kPrefPath, &path))
+ return base::FilePath();
+
+ return install_directory_.Append(base::FilePath::FromUTF8Unsafe(path));
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledInfoHelper(
+ const std::string& extension_id,
+ const base::DictionaryValue* extension) const {
+ int location_value;
+ if (!extension->GetInteger(kPrefLocation, &location_value))
+ return scoped_ptr<ExtensionInfo>();
+
+ base::FilePath::StringType path;
+ if (!extension->GetString(kPrefPath, &path))
+ return scoped_ptr<ExtensionInfo>();
+
+ // Make path absolute. Unpacked extensions will already have absolute paths,
+ // otherwise make it so.
+ Manifest::Location location = static_cast<Manifest::Location>(location_value);
+ if (!Manifest::IsUnpackedLocation(location)) {
+ DCHECK(location == Manifest::COMPONENT ||
+ !base::FilePath(path).IsAbsolute());
+ path = install_directory_.Append(path).value();
+ }
+
+ // Only the following extension types have data saved in the preferences.
+ if (location != Manifest::INTERNAL &&
+ !Manifest::IsUnpackedLocation(location) &&
+ !Manifest::IsExternalLocation(location)) {
+ NOTREACHED();
+ return scoped_ptr<ExtensionInfo>();
+ }
+
+ const base::DictionaryValue* manifest = NULL;
+ if (!Manifest::IsUnpackedLocation(location) &&
+ !extension->GetDictionary(kPrefManifest, &manifest)) {
+ LOG(WARNING) << "Missing manifest for extension " << extension_id;
+ // Just a warning for now.
+ }
+
+ return scoped_ptr<ExtensionInfo>(new ExtensionInfo(
+ manifest, extension_id, base::FilePath(path), location));
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledExtensionInfo(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* ext = NULL;
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ if (!extensions ||
+ !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext))
+ return scoped_ptr<ExtensionInfo>();
+ int state_value;
+ if (!ext->GetInteger(kPrefState, &state_value) ||
+ state_value == Extension::ENABLED_COMPONENT) {
+ // Old preferences files may not have kPrefState for component extensions.
+ return scoped_ptr<ExtensionInfo>();
+ }
+
+ if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) {
+ LOG(WARNING) << "External extension with id " << extension_id
+ << " has been uninstalled by the user";
+ return scoped_ptr<ExtensionInfo>();
+ }
+
+ return GetInstalledInfoHelper(extension_id, ext);
+}
+
+scoped_ptr<ExtensionPrefs::ExtensionsInfo>
+ExtensionPrefs::GetInstalledExtensionsInfo() const {
+ scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ for (base::DictionaryValue::Iterator extension_id(*extensions);
+ !extension_id.IsAtEnd(); extension_id.Advance()) {
+ if (!Extension::IdIsValid(extension_id.key()))
+ continue;
+
+ scoped_ptr<ExtensionInfo> info =
+ GetInstalledExtensionInfo(extension_id.key());
+ if (info)
+ extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+ }
+
+ return extensions_info.Pass();
+}
+
+scoped_ptr<ExtensionPrefs::ExtensionsInfo>
+ExtensionPrefs::GetUninstalledExtensionsInfo() const {
+ scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ for (base::DictionaryValue::Iterator extension_id(*extensions);
+ !extension_id.IsAtEnd(); extension_id.Advance()) {
+ const base::DictionaryValue* ext = NULL;
+ if (!Extension::IdIsValid(extension_id.key()) ||
+ !IsExternalExtensionUninstalled(extension_id.key()) ||
+ !extension_id.value().GetAsDictionary(&ext))
+ continue;
+
+ scoped_ptr<ExtensionInfo> info =
+ GetInstalledInfoHelper(extension_id.key(), ext);
+ if (info)
+ extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+ }
+
+ return extensions_info.Pass();
+}
+
+void ExtensionPrefs::SetDelayedInstallInfo(
+ const Extension* extension,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ DelayReason delay_reason,
+ const syncer::StringOrdinal& page_ordinal) {
+ base::DictionaryValue* extension_dict = new base::DictionaryValue();
+ PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(),
+ initial_state, blacklisted_for_malware,
+ extension_dict);
+
+ // Add transient data that is needed by FinishDelayedInstallInfo(), but
+ // should not be in the final extension prefs. All entries here should have
+ // a corresponding Remove() call in FinishDelayedInstallInfo().
+ if (extension->RequiresSortOrdinal()) {
+ extension_dict->SetString(
+ kPrefSuggestedPageOrdinal,
+ page_ordinal.IsValid() ? page_ordinal.ToInternalValue()
+ : std::string());
+ }
+ extension_dict->SetInteger(kDelayedInstallReason,
+ static_cast<int>(delay_reason));
+
+ UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict);
+}
+
+bool ExtensionPrefs::RemoveDelayedInstallInfo(
+ const std::string& extension_id) {
+ if (!GetExtensionPref(extension_id))
+ return false;
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ bool result = update->Remove(kDelayedInstallInfo, NULL);
+ return result;
+}
+
+bool ExtensionPrefs::FinishDelayedInstallInfo(
+ const std::string& extension_id) {
+ CHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ base::DictionaryValue* extension_dict = update.Get();
+ base::DictionaryValue* pending_install_dict = NULL;
+ if (!extension_dict->GetDictionary(kDelayedInstallInfo,
+ &pending_install_dict)) {
+ return false;
+ }
+
+ // Retrieve and clear transient values populated by SetDelayedInstallInfo().
+ // Also do any other data cleanup that makes sense.
+ std::string serialized_ordinal;
+ syncer::StringOrdinal suggested_page_ordinal;
+ bool needs_sort_ordinal = false;
+ if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal,
+ &serialized_ordinal)) {
+ suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal);
+ needs_sort_ordinal = true;
+ pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL);
+ }
+ pending_install_dict->Remove(kDelayedInstallReason, NULL);
+
+ const base::Time install_time = time_provider_->GetCurrentTime();
+ pending_install_dict->Set(
+ kPrefInstallTime,
+ new base::StringValue(
+ base::Int64ToString(install_time.ToInternalValue())));
+
+ // Commit the delayed install data.
+ for (base::DictionaryValue::Iterator it(*pending_install_dict); !it.IsAtEnd();
+ it.Advance()) {
+ extension_dict->Set(it.key(), it.value().DeepCopy());
+ }
+ FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal,
+ suggested_page_ordinal, extension_dict);
+ return true;
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension_prefs =
+ GetExtensionPref(extension_id);
+ if (!extension_prefs)
+ return scoped_ptr<ExtensionInfo>();
+
+ const base::DictionaryValue* ext = NULL;
+ if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
+ return scoped_ptr<ExtensionInfo>();
+
+ return GetInstalledInfoHelper(extension_id, ext);
+}
+
+ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension_prefs =
+ GetExtensionPref(extension_id);
+ if (!extension_prefs)
+ return DELAY_REASON_NONE;
+
+ const base::DictionaryValue* ext = NULL;
+ if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
+ return DELAY_REASON_NONE;
+
+ int delay_reason;
+ if (!ext->GetInteger(kDelayedInstallReason, &delay_reason))
+ return DELAY_REASON_NONE;
+
+ return static_cast<DelayReason>(delay_reason);
+}
+
+scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs::
+ GetAllDelayedInstallInfo() const {
+ scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ for (base::DictionaryValue::Iterator extension_id(*extensions);
+ !extension_id.IsAtEnd(); extension_id.Advance()) {
+ if (!Extension::IdIsValid(extension_id.key()))
+ continue;
+
+ scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key());
+ if (info)
+ extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+ }
+
+ return extensions_info.Pass();
+}
+
+bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
+}
+
+void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) {
+ UpdateExtensionPref(extension_id, kPrefUserDraggedApp,
+ new base::FundamentalValue(true));
+}
+
+bool ExtensionPrefs::IsFromWebStore(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary && dictionary->GetBoolean(kPrefFromWebStore, &result))
+ return result;
+ return false;
+}
+
+bool ExtensionPrefs::IsFromBookmark(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary && dictionary->GetBoolean(kPrefFromBookmark, &result))
+ return result;
+ return false;
+}
+
+int ExtensionPrefs::GetCreationFlags(const std::string& extension_id) const {
+ int creation_flags = Extension::NO_FLAGS;
+ if (!ReadPrefAsInteger(extension_id, kPrefCreationFlags, &creation_flags)) {
+ // Since kPrefCreationFlags was added later, it will be missing for
+ // previously installed extensions.
+ if (IsFromBookmark(extension_id))
+ creation_flags |= Extension::FROM_BOOKMARK;
+ if (IsFromWebStore(extension_id))
+ creation_flags |= Extension::FROM_WEBSTORE;
+ if (WasInstalledByDefault(extension_id))
+ creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
+ }
+ return creation_flags;
+}
+
+int ExtensionPrefs::GetDelayedInstallCreationFlags(
+ const std::string& extension_id) const {
+ int creation_flags = Extension::NO_FLAGS;
+ const base::DictionaryValue* delayed_info = NULL;
+ if (ReadPrefAsDictionary(extension_id, kDelayedInstallInfo, &delayed_info)) {
+ delayed_info->GetInteger(kPrefCreationFlags, &creation_flags);
+ }
+ return creation_flags;
+}
+
+bool ExtensionPrefs::WasInstalledByDefault(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary &&
+ dictionary->GetBoolean(kPrefWasInstalledByDefault, &result))
+ return result;
+ return false;
+}
+
+base::Time ExtensionPrefs::GetInstallTime(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension) {
+ NOTREACHED();
+ return base::Time();
+ }
+ std::string install_time_str;
+ if (!extension->GetString(kPrefInstallTime, &install_time_str))
+ return base::Time();
+ int64 install_time_i64 = 0;
+ if (!base::StringToInt64(install_time_str, &install_time_i64))
+ return base::Time();
+ return base::Time::FromInternalValue(install_time_i64);
+}
+
+base::Time ExtensionPrefs::GetLastLaunchTime(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return base::Time();
+
+ std::string launch_time_str;
+ if (!extension->GetString(kPrefLastLaunchTime, &launch_time_str))
+ return base::Time();
+ int64 launch_time_i64 = 0;
+ if (!base::StringToInt64(launch_time_str, &launch_time_i64))
+ return base::Time();
+ return base::Time::FromInternalValue(launch_time_i64);
+}
+
+void ExtensionPrefs::SetLastLaunchTime(const std::string& extension_id,
+ const base::Time& time) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ SaveTime(update.Get(), kPrefLastLaunchTime, time);
+}
+
+void ExtensionPrefs::GetExtensions(ExtensionIdList* out) {
+ CHECK(out);
+
+ scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
+
+ for (size_t i = 0; i < extensions_info->size(); ++i) {
+ ExtensionInfo* info = extensions_info->at(i).get();
+ out->push_back(info->extension_id);
+ }
+}
+
+// static
+ExtensionIdList ExtensionPrefs::GetExtensionsFrom(
+ const PrefService* pref_service) {
+ ExtensionIdList result;
+
+ const base::DictionaryValue* extension_prefs = NULL;
+ const base::Value* extension_prefs_value =
+ pref_service->GetUserPrefValue(pref_names::kExtensions);
+ if (!extension_prefs_value ||
+ !extension_prefs_value->GetAsDictionary(&extension_prefs)) {
+ return result; // Empty set
+ }
+
+ for (base::DictionaryValue::Iterator it(*extension_prefs); !it.IsAtEnd();
+ it.Advance()) {
+ const base::DictionaryValue* ext = NULL;
+ if (!it.value().GetAsDictionary(&ext)) {
+ NOTREACHED() << "Invalid pref for extension " << it.key();
+ continue;
+ }
+ if (!IsBlacklistBitSet(ext))
+ result.push_back(it.key());
+ }
+ return result;
+}
+
+void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) {
+ // Fix old entries that did not get an installation time entry when they
+ // were installed or don't have a preferences field.
+ for (ExtensionIdList::const_iterator ext_id = extension_ids.begin();
+ ext_id != extension_ids.end(); ++ext_id) {
+ if (GetInstallTime(*ext_id) == base::Time()) {
+ VLOG(1) << "Could not parse installation time of extension "
+ << *ext_id << ". It was probably installed before setting "
+ << kPrefInstallTime << " was introduced. Updating "
+ << kPrefInstallTime << " to the current time.";
+ const base::Time install_time = time_provider_->GetCurrentTime();
+ UpdateExtensionPref(*ext_id,
+ kPrefInstallTime,
+ new base::StringValue(base::Int64ToString(
+ install_time.ToInternalValue())));
+ }
+ }
+}
+
+void ExtensionPrefs::InitPrefStore() {
+ if (extensions_disabled_) {
+ extension_pref_value_map_->NotifyInitializationCompleted();
+ return;
+ }
+
+ // When this is called, the PrefService is initialized and provides access
+ // to the user preferences stored in a JSON file.
+ ExtensionIdList extension_ids;
+ GetExtensions(&extension_ids);
+ // Create empty preferences dictionary for each extension (these dictionaries
+ // are pruned when persisting the preferences to disk).
+ for (ExtensionIdList::iterator ext_id = extension_ids.begin();
+ ext_id != extension_ids.end(); ++ext_id) {
+ ScopedExtensionPrefUpdate update(prefs_, *ext_id);
+ // This creates an empty dictionary if none is stored.
+ update.Get();
+ }
+
+ FixMissingPrefs(extension_ids);
+ MigratePermissions(extension_ids);
+ MigrateDisableReasons(extension_ids);
+ app_sorting_->Initialize(extension_ids);
+
+ PreferenceAPI::InitExtensionControlledPrefs(this, extension_pref_value_map_);
+
+ extension_pref_value_map_->NotifyInitializationCompleted();
+}
+
+bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
+ bool has_incognito_pref_value = false;
+ extension_pref_value_map_->GetEffectivePrefValue(pref_key,
+ true,
+ &has_incognito_pref_value);
+ return has_incognito_pref_value;
+}
+
+URLPatternSet ExtensionPrefs::GetAllowedInstallSites() {
+ URLPatternSet result;
+ const base::ListValue* list =
+ prefs_->GetList(pref_names::kAllowedInstallSites);
+ CHECK(list);
+
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ std::string entry_string;
+ URLPattern entry(URLPattern::SCHEME_ALL);
+ if (!list->GetString(i, &entry_string) ||
+ entry.Parse(entry_string) != URLPattern::PARSE_SUCCESS) {
+ LOG(ERROR) << "Invalid value for preference: "
+ << pref_names::kAllowedInstallSites << "." << i;
+ continue;
+ }
+ result.AddPattern(entry);
+ }
+
+ return result;
+}
+
+const base::DictionaryValue* ExtensionPrefs::GetGeometryCache(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
+ if (!extension_prefs)
+ return NULL;
+
+ const base::DictionaryValue* ext = NULL;
+ if (!extension_prefs->GetDictionary(kPrefGeometryCache, &ext))
+ return NULL;
+
+ return ext;
+}
+
+void ExtensionPrefs::SetGeometryCache(
+ const std::string& extension_id,
+ scoped_ptr<base::DictionaryValue> cache) {
+ UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
+}
+
+const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() {
+ return prefs_->GetDictionary(kInstallSignature);
+}
+
+void ExtensionPrefs::SetInstallSignature(
+ const base::DictionaryValue* signature) {
+ if (signature) {
+ prefs_->Set(kInstallSignature, *signature);
+ DVLOG(1) << "SetInstallSignature - saving";
+ } else {
+ DVLOG(1) << "SetInstallSignature - clearing";
+ prefs_->ClearPref(kInstallSignature);
+ }
+}
+
+
+ExtensionPrefs::ExtensionPrefs(
+ PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ scoped_ptr<TimeProvider> time_provider,
+ bool extensions_disabled)
+ : prefs_(prefs),
+ install_directory_(root_dir),
+ extension_pref_value_map_(extension_pref_value_map),
+ app_sorting_(app_sorting.Pass()),
+ content_settings_store_(new ContentSettingsStore()),
+ time_provider_(time_provider.Pass()),
+ extensions_disabled_(extensions_disabled) {
+ app_sorting_->SetExtensionScopedPrefs(this);
+ MakePathsRelative();
+ InitPrefStore();
+}
+
+void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
+ prefs_->SetBoolean(pref_names::kStorageGarbageCollect, value);
+}
+
+bool ExtensionPrefs::NeedsStorageGarbageCollection() {
+ return prefs_->GetBoolean(pref_names::kStorageGarbageCollect);
+}
+
+// static
+void ExtensionPrefs::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterDictionaryPref(
+ pref_names::kExtensions,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kToolbar,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterIntegerPref(
+ pref_names::kToolbarSize,
+ -1, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterDictionaryPref(
+ kExtensionsBlacklistUpdate,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kInstallAllowList,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kInstallDenyList,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterDictionaryPref(
+ pref_names::kInstallForceList,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kAllowedTypes,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterBooleanPref(
+ pref_names::kStorageGarbageCollect,
+ false, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterInt64Pref(
+ pref_names::kLastUpdateCheck,
+ 0, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterInt64Pref(
+ pref_names::kNextUpdateCheck,
+ 0, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kAllowedInstallSites,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterStringPref(
+ pref_names::kLastChromeVersion,
+ std::string(), // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kKnownDisabled,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+#if defined(TOOLKIT_VIEWS)
+ registry->RegisterIntegerPref(
+ pref_names::kBrowserActionContainerWidth,
+ 0,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+#endif
+ registry->RegisterDictionaryPref(
+ kInstallSignature,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+
+ registry->RegisterListPref(pref_names::kNativeMessagingBlacklist,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kNativeMessagingWhitelist,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterBooleanPref(
+ pref_names::kNativeMessagingUserLevelHosts,
+ true, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+template <class ExtensionIdContainer>
+bool ExtensionPrefs::GetUserExtensionPrefIntoContainer(
+ const char* pref,
+ ExtensionIdContainer* id_container_out) {
+ DCHECK(id_container_out->empty());
+
+ const base::Value* user_pref_value = prefs_->GetUserPrefValue(pref);
+ const base::ListValue* user_pref_as_list;
+ if (!user_pref_value || !user_pref_value->GetAsList(&user_pref_as_list))
+ return false;
+
+ std::insert_iterator<ExtensionIdContainer> insert_iterator(
+ *id_container_out, id_container_out->end());
+ std::string extension_id;
+ for (base::ListValue::const_iterator value_it = user_pref_as_list->begin();
+ value_it != user_pref_as_list->end(); ++value_it) {
+ if (!(*value_it)->GetAsString(&extension_id)) {
+ NOTREACHED();
+ continue;
+ }
+ insert_iterator = extension_id;
+ }
+ return true;
+}
+
+template <class ExtensionIdContainer>
+void ExtensionPrefs::SetExtensionPrefFromContainer(
+ const char* pref,
+ const ExtensionIdContainer& strings) {
+ ListPrefUpdate update(prefs_, pref);
+ base::ListValue* list_of_values = update.Get();
+ list_of_values->Clear();
+ for (typename ExtensionIdContainer::const_iterator iter = strings.begin();
+ iter != strings.end(); ++iter) {
+ list_of_values->Append(new base::StringValue(*iter));
+ }
+}
+
+void ExtensionPrefs::PopulateExtensionInfoPrefs(
+ const Extension* extension,
+ const base::Time install_time,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ base::DictionaryValue* extension_dict) {
+ // Leave the state blank for component extensions so that old chrome versions
+ // loading new profiles do not fail in GetInstalledExtensionInfo. Older
+ // Chrome versions would only check for an omitted state.
+ if (initial_state != Extension::ENABLED_COMPONENT)
+ extension_dict->Set(kPrefState, new base::FundamentalValue(initial_state));
+
+ extension_dict->Set(kPrefLocation,
+ new base::FundamentalValue(extension->location()));
+ extension_dict->Set(kPrefCreationFlags,
+ new base::FundamentalValue(extension->creation_flags()));
+ extension_dict->Set(kPrefFromWebStore,
+ new base::FundamentalValue(extension->from_webstore()));
+ extension_dict->Set(kPrefFromBookmark,
+ new base::FundamentalValue(extension->from_bookmark()));
+ extension_dict->Set(
+ kPrefWasInstalledByDefault,
+ new base::FundamentalValue(extension->was_installed_by_default()));
+ extension_dict->Set(kPrefInstallTime,
+ new base::StringValue(
+ base::Int64ToString(install_time.ToInternalValue())));
+ if (blacklisted_for_malware)
+ extension_dict->Set(kPrefBlacklist, new base::FundamentalValue(true));
+
+ base::FilePath::StringType path = MakePathRelative(install_directory_,
+ extension->path());
+ extension_dict->Set(kPrefPath, new base::StringValue(path));
+ // We store prefs about LOAD extensions, but don't cache their manifest
+ // since it may change on disk.
+ if (!Manifest::IsUnpackedLocation(extension->location())) {
+ extension_dict->Set(kPrefManifest,
+ extension->manifest()->value()->DeepCopy());
+ }
+}
+
+void ExtensionPrefs::FinishExtensionInfoPrefs(
+ const std::string& extension_id,
+ const base::Time install_time,
+ bool needs_sort_ordinal,
+ const syncer::StringOrdinal& suggested_page_ordinal,
+ base::DictionaryValue* extension_dict) {
+ // Reinitializes various preferences with empty dictionaries.
+ if (!extension_dict->HasKey(pref_names::kPrefPreferences)) {
+ extension_dict->Set(pref_names::kPrefPreferences,
+ new base::DictionaryValue);
+ }
+
+ if (!extension_dict->HasKey(pref_names::kPrefIncognitoPreferences)) {
+ extension_dict->Set(pref_names::kPrefIncognitoPreferences,
+ new base::DictionaryValue);
+ }
+
+ if (!extension_dict->HasKey(pref_names::kPrefRegularOnlyPreferences)) {
+ extension_dict->Set(pref_names::kPrefRegularOnlyPreferences,
+ new base::DictionaryValue);
+ }
+
+ if (!extension_dict->HasKey(pref_names::kPrefContentSettings))
+ extension_dict->Set(pref_names::kPrefContentSettings, new base::ListValue);
+
+ if (!extension_dict->HasKey(pref_names::kPrefIncognitoContentSettings)) {
+ extension_dict->Set(pref_names::kPrefIncognitoContentSettings,
+ new base::ListValue);
+ }
+
+ // If this point has been reached, any pending installs should be considered
+ // out of date.
+ extension_dict->Remove(kDelayedInstallInfo, NULL);
+
+ // Clear state that may be registered from a previous install.
+ extension_dict->Remove(EventRouter::kRegisteredEvents, NULL);
+
+ // FYI, all code below here races on sudden shutdown because |extension_dict|,
+ // |app_sorting_|, |extension_pref_value_map_|, and |content_settings_store_|
+ // are updated non-transactionally. This is probably not fixable without
+ // nested transactional updates to pref dictionaries.
+ if (needs_sort_ordinal)
+ app_sorting_->EnsureValidOrdinals(extension_id, suggested_page_ordinal);
+
+ bool is_enabled = false;
+ int initial_state;
+ if (extension_dict->GetInteger(kPrefState, &initial_state)) {
+ is_enabled = initial_state == Extension::ENABLED;
+ }
+
+ extension_pref_value_map_->RegisterExtension(extension_id, install_time,
+ is_enabled);
+ content_settings_store_->RegisterExtension(extension_id, install_time,
+ is_enabled);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h
new file mode 100644
index 0000000000..89258ae8d0
--- /dev/null
+++ b/extensions/browser/extension_prefs.h
@@ -0,0 +1,652 @@
+// Copyright 2014 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_EXTENSION_PREFS_H_
+#define EXTENSIONS_BROWSER_EXTENSION_PREFS_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/scoped_user_pref_update.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "extensions/browser/app_sorting.h"
+#include "extensions/browser/blacklist_state.h"
+#include "extensions/browser/extension_scoped_prefs.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/url_pattern_set.h"
+#include "sync/api/string_ordinal.h"
+
+class ExtensionPrefValueMap;
+class PrefService;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace extensions {
+
+class AppSorting;
+class ContentSettingsStore;
+class ExtensionPrefsUninstallExtension;
+class URLPatternSet;
+
+// Class for managing global and per-extension preferences.
+//
+// This class distinguishes the following kinds of preferences:
+// - global preferences:
+// internal state for the extension system in general, not associated
+// with an individual extension, such as lastUpdateTime.
+// - per-extension preferences:
+// meta-preferences describing properties of the extension like
+// installation time, whether the extension is enabled, etc.
+// - extension controlled preferences:
+// browser preferences that an extension controls. For example, an
+// extension could use the proxy API to specify the browser's proxy
+// preference. Extension-controlled preferences are stored in
+// PrefValueStore::extension_prefs(), which this class populates and
+// maintains as the underlying extensions change.
+class ExtensionPrefs : public ExtensionScopedPrefs,
+ public BrowserContextKeyedService {
+ public:
+ typedef std::vector<linked_ptr<ExtensionInfo> > ExtensionsInfo;
+
+ // Vector containing identifiers for preferences.
+ typedef std::set<std::string> PrefKeySet;
+
+ // This enum is used to store the reason an extension's install has been
+ // delayed. Do not remove items or re-order this enum as it is used in
+ // preferences.
+ enum DelayReason {
+ DELAY_REASON_NONE = 0,
+ DELAY_REASON_GC = 1,
+ DELAY_REASON_WAIT_FOR_IDLE = 2,
+ DELAY_REASON_WAIT_FOR_IMPORTS = 3,
+ };
+
+
+ // Creates base::Time classes. The default implementation is just to return
+ // the current time, but tests can inject alternative implementations.
+ class TimeProvider {
+ public:
+ TimeProvider();
+
+ virtual ~TimeProvider();
+
+ // By default, returns the current time (base::Time::Now()).
+ virtual base::Time GetCurrentTime() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TimeProvider);
+ };
+
+ // A wrapper around a ScopedUserPrefUpdate, which allows us to access the
+ // entry of a particular key for an extension. Use this if you need a mutable
+ // record of a dictionary or list in the current settings. Otherwise, prefer
+ // ReadPrefAsT() and UpdateExtensionPref() methods.
+ template <typename T, base::Value::Type type_enum_value>
+ class ScopedUpdate {
+ public:
+ ScopedUpdate(ExtensionPrefs* prefs,
+ const std::string& extension_id,
+ const std::string& key);
+ virtual ~ScopedUpdate();
+
+ // Returns a mutable value for the key (ownership remains with the prefs),
+ // if one exists. Otherwise, returns NULL.
+ virtual T* Get();
+
+ // Creates and returns a mutable value for the key (the prefs own the new
+ // value), if one does not already exist. Otherwise, returns the current
+ // value.
+ virtual T* Create();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedUpdate);
+
+ DictionaryPrefUpdate update_;
+ const std::string extension_id_;
+ const std::string key_;
+ };
+ typedef ScopedUpdate<base::DictionaryValue, base::Value::TYPE_DICTIONARY>
+ ScopedDictionaryUpdate;
+ typedef ScopedUpdate<base::ListValue, base::Value::TYPE_LIST>
+ ScopedListUpdate;
+
+ // Creates and initializes an ExtensionPrefs object.
+ // Does not take ownership of |prefs| and |extension_pref_value_map|.
+ // If |extensions_disabled| is true, extension controlled preferences and
+ // content settings do not become effective.
+ static ExtensionPrefs* Create(
+ PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ bool extensions_disabled);
+
+ // A version of Create which allows injection of a custom base::Time provider.
+ // Use this as needed for testing.
+ static ExtensionPrefs* Create(
+ PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ bool extensions_disabled,
+ scoped_ptr<TimeProvider> time_provider);
+
+ virtual ~ExtensionPrefs();
+
+ // Convenience function to get the ExtensionPrefs for a BrowserContext.
+ static ExtensionPrefs* Get(content::BrowserContext* context);
+
+ // Returns all installed extensions from extension preferences provided by
+ // |pref_service|. This is exposed for ProtectedPrefsWatcher because it needs
+ // access to the extension ID list before the ExtensionService is initialized.
+ static ExtensionIdList GetExtensionsFrom(const PrefService* pref_service);
+
+ // Returns true if the specified external extension was uninstalled by the
+ // user.
+ bool IsExternalExtensionUninstalled(const std::string& id) const;
+
+ // Checks whether |extension_id| is disabled. If there's no state pref for
+ // the extension, this will return false. Generally you should use
+ // ExtensionService::IsExtensionEnabled instead.
+ bool IsExtensionDisabled(const std::string& id) const;
+
+ // Get/Set the order that the browser actions appear in the toolbar.
+ ExtensionIdList GetToolbarOrder();
+ void SetToolbarOrder(const ExtensionIdList& extension_ids);
+
+ // Gets the set of known disabled extension IDs into |id_set_out|. Returns
+ // false iff the set of known disabled extension IDs hasn't been set yet.
+ bool GetKnownDisabled(ExtensionIdSet* id_set_out);
+
+ // Sets the set of known disabled extension IDs.
+ void SetKnownDisabled(const ExtensionIdSet& extension_ids);
+
+ // Called when an extension is installed, so that prefs get created.
+ // |blacklisted_for_malware| should be set if the extension was included in a
+ // blacklist due to being malware. If |page_ordinal| is an invalid ordinal,
+ // then a page will be found for the App.
+ void OnExtensionInstalled(const Extension* extension,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ const syncer::StringOrdinal& page_ordinal);
+
+ // Called when an extension is uninstalled, so that prefs get cleaned up.
+ void OnExtensionUninstalled(const std::string& extension_id,
+ const Manifest::Location& location,
+ bool external_uninstall);
+
+ // Called to change the extension's state when it is enabled/disabled.
+ void SetExtensionState(const std::string& extension_id, Extension::State);
+
+ // Called to change the extension's BlacklistState. Currently only used for
+ // non-malicious extensions.
+ // TODO(oleg): replace SetExtensionBlacklisted by this function.
+ void SetExtensionBlacklistState(const std::string& extension_id,
+ BlacklistState state);
+
+ // Checks whether |extension_id| is marked as greylisted.
+ // TODO(oleg): Replace IsExtensionBlacklisted by this method.
+ BlacklistState GetExtensionBlacklistState(const std::string& extension_id);
+
+ // Populates |out| with the ids of all installed extensions.
+ void GetExtensions(ExtensionIdList* out);
+
+ // ExtensionScopedPrefs methods:
+ virtual void UpdateExtensionPref(const std::string& id,
+ const std::string& key,
+ base::Value* value) OVERRIDE;
+
+ virtual void DeleteExtensionPrefs(const std::string& id) OVERRIDE;
+
+ virtual bool ReadPrefAsBoolean(const std::string& extension_id,
+ const std::string& pref_key,
+ bool* out_value) const OVERRIDE;
+
+ virtual bool ReadPrefAsInteger(const std::string& extension_id,
+ const std::string& pref_key,
+ int* out_value) const OVERRIDE;
+
+ virtual bool ReadPrefAsString(const std::string& extension_id,
+ const std::string& pref_key,
+ std::string* out_value) const OVERRIDE;
+
+ virtual bool ReadPrefAsList(const std::string& extension_id,
+ const std::string& pref_key,
+ const base::ListValue** out_value) const OVERRIDE;
+
+ virtual bool ReadPrefAsDictionary(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const base::DictionaryValue** out_value) const OVERRIDE;
+
+ virtual bool HasPrefForExtension(const std::string& extension_id) const
+ OVERRIDE;
+
+ // Did the extension ask to escalate its permission during an upgrade?
+ bool DidExtensionEscalatePermissions(const std::string& id);
+
+ // If |did_escalate| is true, the preferences for |extension| will be set to
+ // require the install warning when the user tries to enable.
+ void SetDidExtensionEscalatePermissions(
+ const Extension* extension,
+ bool did_escalate);
+
+ // Getter and setters for disabled reason.
+ int GetDisableReasons(const std::string& extension_id) const;
+ void AddDisableReason(const std::string& extension_id,
+ Extension::DisableReason disable_reason);
+ void RemoveDisableReason(const std::string& extension_id,
+ Extension::DisableReason disable_reason);
+ void ClearDisableReasons(const std::string& extension_id);
+
+ // Gets the set of extensions that have been blacklisted in prefs. This will
+ // return only the blocked extensions, not the "greylist" extensions.
+ // TODO(oleg): Make method names consistent here, in extension service and in
+ // blacklist.
+ std::set<std::string> GetBlacklistedExtensions();
+
+ // Sets whether the extension with |id| is blacklisted.
+ void SetExtensionBlacklisted(const std::string& extension_id,
+ bool is_blacklisted);
+
+ // Returns the version string for the currently installed extension, or
+ // the empty string if not found.
+ std::string GetVersionString(const std::string& extension_id);
+
+ // Re-writes the extension manifest into the prefs.
+ // Called to change the extension's manifest when it's re-localized.
+ void UpdateManifest(const Extension* extension);
+
+ // Returns extension path based on extension ID, or empty FilePath on error.
+ base::FilePath GetExtensionPath(const std::string& extension_id);
+
+ // Returns base extensions install directory.
+ const base::FilePath& install_directory() const { return install_directory_; }
+
+ // Returns whether the extension with |id| has its blacklist bit set.
+ //
+ // WARNING: this only checks the extension's entry in prefs, so by definition
+ // can only check extensions that prefs knows about. There may be other
+ // sources of blacklist information, such as safebrowsing. You probably want
+ // to use Blacklist::GetBlacklistedIDs rather than this method.
+ bool IsExtensionBlacklisted(const std::string& id) const;
+
+ // Increment the count of how many times we prompted the user to acknowledge
+ // the given extension, and return the new count.
+ int IncrementAcknowledgePromptCount(const std::string& extension_id);
+
+ // Whether the user has acknowledged an external extension.
+ bool IsExternalExtensionAcknowledged(const std::string& extension_id);
+ void AcknowledgeExternalExtension(const std::string& extension_id);
+
+ // Whether the user has acknowledged a blacklisted extension.
+ bool IsBlacklistedExtensionAcknowledged(const std::string& extension_id);
+ void AcknowledgeBlacklistedExtension(const std::string& extension_id);
+
+ // Whether the external extension was installed during the first run
+ // of this profile.
+ bool IsExternalInstallFirstRun(const std::string& extension_id);
+ void SetExternalInstallFirstRun(const std::string& extension_id);
+
+ // Whether the user has been notified about extension with |extension_id|
+ // being wiped out.
+ bool HasWipeoutBeenAcknowledged(const std::string& extension_id);
+ void SetWipeoutAcknowledged(const std::string& extension_id, bool value);
+
+ // Returns true if the extension notification code has already run for the
+ // first time for this profile. Currently we use this flag to mean that any
+ // extensions that would trigger notifications should get silently
+ // acknowledged. This is a fuse. Calling it the first time returns false.
+ // Subsequent calls return true. It's not possible through an API to ever
+ // reset it. Don't call it unless you mean it!
+ bool SetAlertSystemFirstRun();
+
+ // Checks if extensions are blacklisted by default, by policy.
+ // The ManagementPolicy::Provider methods also take this into account, and
+ // should be used instead when the extension ID is known.
+ bool ExtensionsBlacklistedByDefault() const;
+
+ // Returns the last value set via SetLastPingDay. If there isn't such a
+ // pref, the returned Time will return true for is_null().
+ base::Time LastPingDay(const std::string& extension_id) const;
+
+ // The time stored is based on the server's perspective of day start time, not
+ // the client's.
+ void SetLastPingDay(const std::string& extension_id, const base::Time& time);
+
+ // Similar to the 2 above, but for the extensions blacklist.
+ base::Time BlacklistLastPingDay() const;
+ void SetBlacklistLastPingDay(const base::Time& time);
+
+ // Similar to LastPingDay/SetLastPingDay, but for sending "days since active"
+ // ping.
+ base::Time LastActivePingDay(const std::string& extension_id);
+ void SetLastActivePingDay(const std::string& extension_id,
+ const base::Time& time);
+
+ // A bit we use for determining if we should send the "days since active"
+ // ping. A value of true means the item has been active (launched) since the
+ // last update check.
+ bool GetActiveBit(const std::string& extension_id);
+ void SetActiveBit(const std::string& extension_id, bool active);
+
+ // Returns the granted permission set for the extension with |extension_id|,
+ // and NULL if no preferences were found for |extension_id|.
+ // This passes ownership of the returned set to the caller.
+ PermissionSet* GetGrantedPermissions(const std::string& extension_id);
+
+ // Adds |permissions| to the granted permissions set for the extension with
+ // |extension_id|. The new granted permissions set will be the union of
+ // |permissions| and the already granted permissions.
+ void AddGrantedPermissions(const std::string& extension_id,
+ const PermissionSet* permissions);
+
+ // As above, but subtracts the given |permissions| from the granted set.
+ void RemoveGrantedPermissions(const std::string& extension_id,
+ const PermissionSet* permissions);
+
+ // Gets the active permission set for the specified extension. This may
+ // differ from the permissions in the manifest due to the optional
+ // permissions API. This passes ownership of the set to the caller.
+ PermissionSet* GetActivePermissions(const std::string& extension_id);
+
+ // Sets the active |permissions| for the extension with |extension_id|.
+ void SetActivePermissions(const std::string& extension_id,
+ const PermissionSet* permissions);
+
+ // Records whether or not this extension is currently running.
+ void SetExtensionRunning(const std::string& extension_id, bool is_running);
+
+ // Returns whether or not this extension is marked as running. This is used to
+ // restart apps across browser restarts.
+ bool IsExtensionRunning(const std::string& extension_id);
+
+ // Set/Get whether or not the app is active. Used to force a launch of apps
+ // that don't handle onRestarted() on a restart. We can only safely do that if
+ // the app was active when it was last running.
+ void SetIsActive(const std::string& extension_id, bool is_active);
+ bool IsActive(const std::string& extension_id);
+
+ // Returns true if the user enabled this extension to be loaded in incognito
+ // mode.
+ //
+ // IMPORTANT: you probably want to use extensions::util::IsIncognitoEnabled
+ // instead of this method.
+ bool IsIncognitoEnabled(const std::string& extension_id) const;
+ void SetIsIncognitoEnabled(const std::string& extension_id, bool enabled);
+
+ // Returns true if the user has chosen to allow this extension to inject
+ // scripts into pages with file URLs.
+ //
+ // IMPORTANT: you probably want to use extensions::util::AllowFileAccess
+ // instead of this method.
+ bool AllowFileAccess(const std::string& extension_id) const;
+ void SetAllowFileAccess(const std::string& extension_id, bool allow);
+ bool HasAllowFileAccessSetting(const std::string& extension_id) const;
+
+ // Saves ExtensionInfo for each installed extension with the path to the
+ // version directory and the location. Blacklisted extensions won't be saved
+ // and neither will external extensions the user has explicitly uninstalled.
+ // Caller takes ownership of returned structure.
+ scoped_ptr<ExtensionsInfo> GetInstalledExtensionsInfo() const;
+
+ // Same as above, but only includes external extensions the user has
+ // explicitly uninstalled.
+ scoped_ptr<ExtensionsInfo> GetUninstalledExtensionsInfo() const;
+
+ // Returns the ExtensionInfo from the prefs for the given extension. If the
+ // extension is not present, NULL is returned.
+ scoped_ptr<ExtensionInfo> GetInstalledExtensionInfo(
+ const std::string& extension_id) const;
+
+ // We've downloaded an updated .crx file for the extension, but are waiting
+ // to install it.
+ void SetDelayedInstallInfo(const Extension* extension,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ DelayReason delay_reason,
+ const syncer::StringOrdinal& page_ordinal);
+
+ // Removes any delayed install information we have for the given
+ // |extension_id|. Returns true if there was info to remove; false otherwise.
+ bool RemoveDelayedInstallInfo(const std::string& extension_id);
+
+ // Update the prefs to finish the update for an extension.
+ bool FinishDelayedInstallInfo(const std::string& extension_id);
+
+ // Returns the ExtensionInfo from the prefs for delayed install information
+ // for |extension_id|, if we have any. Otherwise returns NULL.
+ scoped_ptr<ExtensionInfo> GetDelayedInstallInfo(
+ const std::string& extension_id) const;
+
+ DelayReason GetDelayedInstallReason(const std::string& extension_id) const;
+
+ // Returns information about all the extensions that have delayed install
+ // information.
+ scoped_ptr<ExtensionsInfo> GetAllDelayedInstallInfo() const;
+
+ // Returns true if the user repositioned the app on the app launcher via drag
+ // and drop.
+ bool WasAppDraggedByUser(const std::string& extension_id);
+
+ // Sets a flag indicating that the user repositioned the app on the app
+ // launcher by drag and dropping it.
+ void SetAppDraggedByUser(const std::string& extension_id);
+
+ // Returns true if there is an extension which controls the preference value
+ // for |pref_key| *and* it is specific to incognito mode.
+ bool HasIncognitoPrefValue(const std::string& pref_key);
+
+ // Returns the creation flags mask for the extension.
+ int GetCreationFlags(const std::string& extension_id) const;
+
+ // Returns the creation flags mask for a delayed install extension.
+ int GetDelayedInstallCreationFlags(const std::string& extension_id) const;
+
+ // Returns true if the extension was installed from the Chrome Web Store.
+ bool IsFromWebStore(const std::string& extension_id) const;
+
+ // Returns true if the extension was installed from an App generated from a
+ // bookmark.
+ bool IsFromBookmark(const std::string& extension_id) const;
+
+ // Returns true if the extension was installed as a default app.
+ bool WasInstalledByDefault(const std::string& extension_id) const;
+
+ // Helper method to acquire the installation time of an extension.
+ // Returns base::Time() if the installation time could not be parsed or
+ // found.
+ base::Time GetInstallTime(const std::string& extension_id) const;
+
+ // Gets/sets the last launch time of an extension.
+ base::Time GetLastLaunchTime(const std::string& extension_id) const;
+ void SetLastLaunchTime(const std::string& extension_id,
+ const base::Time& time);
+
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ bool extensions_disabled() { return extensions_disabled_; }
+
+ ContentSettingsStore* content_settings_store() {
+ return content_settings_store_.get();
+ }
+
+ // The underlying PrefService.
+ PrefService* pref_service() const { return prefs_; }
+
+ // The underlying AppSorting.
+ AppSorting* app_sorting() const { return app_sorting_.get(); }
+
+ // Describes the URLs that are able to install extensions. See
+ // pref_names::kAllowedInstallSites for more information.
+ URLPatternSet GetAllowedInstallSites();
+
+ // Schedules garbage collection of an extension's on-disk data on the next
+ // start of this ExtensionService. Applies only to extensions with isolated
+ // storage.
+ void SetNeedsStorageGarbageCollection(bool value);
+ bool NeedsStorageGarbageCollection();
+
+ // Used by AppWindowGeometryCache to persist its cache. These methods
+ // should not be called directly.
+ const base::DictionaryValue* GetGeometryCache(
+ const std::string& extension_id) const;
+ void SetGeometryCache(const std::string& extension_id,
+ scoped_ptr<base::DictionaryValue> cache);
+
+ // Used for verification of installed extension ids. For the Set method, pass
+ // null to remove the preference.
+ const base::DictionaryValue* GetInstallSignature();
+ void SetInstallSignature(const base::DictionaryValue* signature);
+
+ private:
+ friend class ExtensionPrefsBlacklistedExtensions; // Unit test.
+ friend class ExtensionPrefsUninstallExtension; // Unit test.
+
+ // See the Create methods.
+ ExtensionPrefs(PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ scoped_ptr<TimeProvider> time_provider,
+ bool extensions_disabled);
+
+ // Converts absolute paths in the pref to paths relative to the
+ // install_directory_.
+ void MakePathsRelative();
+
+ // Converts internal relative paths to be absolute. Used for export to
+ // consumers who expect full paths.
+ void MakePathsAbsolute(base::DictionaryValue* dict);
+
+ // Helper function used by GetInstalledExtensionInfo() and
+ // GetDelayedInstallInfo() to construct an ExtensionInfo from the provided
+ // |extension| dictionary.
+ scoped_ptr<ExtensionInfo> GetInstalledInfoHelper(
+ const std::string& extension_id,
+ const base::DictionaryValue* extension) const;
+
+ // Interprets the list pref, |pref_key| in |extension_id|'s preferences, as a
+ // URLPatternSet. The |valid_schemes| specify how to parse the URLPatterns.
+ bool ReadPrefAsURLPatternSet(const std::string& extension_id,
+ const std::string& pref_key,
+ URLPatternSet* result,
+ int valid_schemes);
+
+ // Converts |new_value| to a list of strings and sets the |pref_key| pref
+ // belonging to |extension_id|.
+ void SetExtensionPrefURLPatternSet(const std::string& extension_id,
+ const std::string& pref_key,
+ const URLPatternSet& new_value);
+
+ // Read the boolean preference entry and return true if the preference exists
+ // and the preference's value is true; false otherwise.
+ bool ReadPrefAsBooleanAndReturn(const std::string& extension_id,
+ const std::string& key) const;
+
+ // Interprets |pref_key| in |extension_id|'s preferences as an
+ // PermissionSet, and passes ownership of the set to the caller.
+ PermissionSet* ReadPrefAsPermissionSet(const std::string& extension_id,
+ const std::string& pref_key);
+
+ // Converts the |new_value| to its value and sets the |pref_key| pref
+ // belonging to |extension_id|.
+ void SetExtensionPrefPermissionSet(const std::string& extension_id,
+ const std::string& pref_key,
+ const PermissionSet* new_value);
+
+ // Returns an immutable dictionary for extension |id|'s prefs, or NULL if it
+ // doesn't exist.
+ const base::DictionaryValue* GetExtensionPref(const std::string& id) const;
+
+ // Fix missing preference entries in the extensions that are were introduced
+ // in a later Chrome version.
+ void FixMissingPrefs(const ExtensionIdList& extension_ids);
+
+ // Installs the persistent extension preferences into |prefs_|'s extension
+ // pref store. Does nothing if extensions_disabled_ is true.
+ void InitPrefStore();
+
+ // Migrates the permissions data in the pref store.
+ void MigratePermissions(const ExtensionIdList& extension_ids);
+
+ // Migrates the disable reasons from a single enum to a bit mask.
+ void MigrateDisableReasons(const ExtensionIdList& extension_ids);
+
+ // Checks whether there is a state pref for the extension and if so, whether
+ // it matches |check_state|.
+ bool DoesExtensionHaveState(const std::string& id,
+ Extension::State check_state) const;
+
+ // Reads the list of strings for |pref| from user prefs into
+ // |id_container_out|. Returns false if the pref wasn't found in the user
+ // pref store.
+ template <class ExtensionIdContainer>
+ bool GetUserExtensionPrefIntoContainer(
+ const char* pref,
+ ExtensionIdContainer* id_container_out);
+
+ // Writes the list of strings contained in |strings| to |pref| in prefs.
+ template <class ExtensionIdContainer>
+ void SetExtensionPrefFromContainer(const char* pref,
+ const ExtensionIdContainer& strings);
+
+ // Helper function to populate |extension_dict| with the values needed
+ // by a newly installed extension. Work is broken up between this
+ // function and FinishExtensionInfoPrefs() to accomodate delayed
+ // installations.
+ void PopulateExtensionInfoPrefs(const Extension* extension,
+ const base::Time install_time,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ base::DictionaryValue* extension_dict);
+
+ // Helper function to complete initialization of the values in
+ // |extension_dict| for an extension install. Also see
+ // PopulateExtensionInfoPrefs().
+ void FinishExtensionInfoPrefs(
+ const std::string& extension_id,
+ const base::Time install_time,
+ bool needs_sort_ordinal,
+ const syncer::StringOrdinal& suggested_page_ordinal,
+ base::DictionaryValue* extension_dict);
+
+ // The pref service specific to this set of extension prefs. Owned by the
+ // BrowserContext.
+ PrefService* prefs_;
+
+ // Base extensions install directory.
+ base::FilePath install_directory_;
+
+ // Weak pointer, owned by BrowserContext.
+ ExtensionPrefValueMap* extension_pref_value_map_;
+
+ // Contains all the logic for handling the order for various extension
+ // properties.
+ scoped_ptr<AppSorting> app_sorting_;
+
+ scoped_refptr<ContentSettingsStore> content_settings_store_;
+
+ scoped_ptr<TimeProvider> time_provider_;
+
+ bool extensions_disabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPrefs);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_PREFS_H_
diff --git a/extensions/browser/extension_prefs_factory.cc b/extensions/browser/extension_prefs_factory.cc
new file mode 100644
index 0000000000..e83e33b27a
--- /dev/null
+++ b/extensions/browser/extension_prefs_factory.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 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 "base/command_line.h"
+#include "base/prefs/pref_service.h"
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "extensions/browser/extension_pref_value_map.h"
+#include "extensions/browser/extension_pref_value_map_factory.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_prefs_factory.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/common/constants.h"
+
+namespace extensions {
+
+// static
+ExtensionPrefs* ExtensionPrefsFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<ExtensionPrefs*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+ExtensionPrefsFactory* ExtensionPrefsFactory::GetInstance() {
+ return Singleton<ExtensionPrefsFactory>::get();
+}
+
+void ExtensionPrefsFactory::SetInstanceForTesting(
+ content::BrowserContext* context, ExtensionPrefs* prefs) {
+ Associate(context, prefs);
+}
+
+ExtensionPrefsFactory::ExtensionPrefsFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ExtensionPrefs",
+ BrowserContextDependencyManager::GetInstance()) {
+}
+
+ExtensionPrefsFactory::~ExtensionPrefsFactory() {
+}
+
+BrowserContextKeyedService* ExtensionPrefsFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
+ return ExtensionPrefs::Create(
+ client->GetPrefServiceForContext(context),
+ context->GetPath().AppendASCII(extensions::kInstallDirectoryName),
+ ExtensionPrefValueMapFactory::GetForBrowserContext(context),
+ client->CreateAppSorting().Pass(),
+ client->AreExtensionsDisabled(
+ *CommandLine::ForCurrentProcess(), context));
+}
+
+content::BrowserContext* ExtensionPrefsFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_prefs_factory.h b/extensions/browser/extension_prefs_factory.h
new file mode 100644
index 0000000000..3aee29ace1
--- /dev/null
+++ b/extensions/browser/extension_prefs_factory.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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_EXTENSION_PREFS_FACTORY_H_
+#define EXTENSIONS_BROWSER_EXTENSION_PREFS_FACTORY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+namespace extensions {
+
+class ExtensionPrefs;
+
+class ExtensionPrefsFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static ExtensionPrefs* GetForBrowserContext(content::BrowserContext* context);
+
+ static ExtensionPrefsFactory* GetInstance();
+
+ void SetInstanceForTesting(
+ content::BrowserContext* context, ExtensionPrefs* prefs);
+
+ private:
+ friend struct DefaultSingletonTraits<ExtensionPrefsFactory>;
+
+ ExtensionPrefsFactory();
+ virtual ~ExtensionPrefsFactory();
+
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const OVERRIDE;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_PREFS_FACTORY_H_
diff --git a/extensions/browser/extension_registry.cc b/extensions/browser/extension_registry.cc
new file mode 100644
index 0000000000..5c4cf5d4a9
--- /dev/null
+++ b/extensions/browser/extension_registry.cc
@@ -0,0 +1,114 @@
+// 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/extension_registry.h"
+
+#include "base/strings/string_util.h"
+#include "extensions/browser/extension_registry_factory.h"
+#include "extensions/browser/extension_registry_observer.h"
+
+namespace extensions {
+
+ExtensionRegistry::ExtensionRegistry() {}
+ExtensionRegistry::~ExtensionRegistry() {}
+
+// static
+ExtensionRegistry* ExtensionRegistry::Get(content::BrowserContext* context) {
+ return ExtensionRegistryFactory::GetForBrowserContext(context);
+}
+
+void ExtensionRegistry::AddObserver(ExtensionRegistryObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void ExtensionRegistry::RemoveObserver(ExtensionRegistryObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void ExtensionRegistry::TriggerOnUnloaded(const Extension* extension) {
+ DCHECK(!enabled_extensions_.Contains(extension->id()));
+ FOR_EACH_OBSERVER(
+ ExtensionRegistryObserver, observers_, OnExtensionUnloaded(extension));
+}
+
+const Extension* ExtensionRegistry::GetExtensionById(const std::string& id,
+ int include_mask) const {
+ std::string lowercase_id = StringToLowerASCII(id);
+ if (include_mask & ENABLED) {
+ const Extension* extension = enabled_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ if (include_mask & DISABLED) {
+ const Extension* extension = disabled_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ if (include_mask & TERMINATED) {
+ const Extension* extension = terminated_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ if (include_mask & BLACKLISTED) {
+ const Extension* extension = blacklisted_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ return NULL;
+}
+
+bool ExtensionRegistry::AddEnabled(
+ const scoped_refptr<const Extension>& extension) {
+ return enabled_extensions_.Insert(extension);
+}
+
+bool ExtensionRegistry::RemoveEnabled(const std::string& id) {
+ return enabled_extensions_.Remove(id);
+}
+
+bool ExtensionRegistry::AddDisabled(
+ const scoped_refptr<const Extension>& extension) {
+ return disabled_extensions_.Insert(extension);
+}
+
+bool ExtensionRegistry::RemoveDisabled(const std::string& id) {
+ return disabled_extensions_.Remove(id);
+}
+
+bool ExtensionRegistry::AddTerminated(
+ const scoped_refptr<const Extension>& extension) {
+ return terminated_extensions_.Insert(extension);
+}
+
+bool ExtensionRegistry::RemoveTerminated(const std::string& id) {
+ return terminated_extensions_.Remove(id);
+}
+
+bool ExtensionRegistry::AddBlacklisted(
+ const scoped_refptr<const Extension>& extension) {
+ return blacklisted_extensions_.Insert(extension);
+}
+
+bool ExtensionRegistry::RemoveBlacklisted(const std::string& id) {
+ return blacklisted_extensions_.Remove(id);
+}
+
+void ExtensionRegistry::ClearAll() {
+ enabled_extensions_.Clear();
+ disabled_extensions_.Clear();
+ terminated_extensions_.Clear();
+ blacklisted_extensions_.Clear();
+}
+
+void ExtensionRegistry::SetDisabledModificationCallback(
+ const ExtensionSet::ModificationCallback& callback) {
+ disabled_extensions_.set_modification_callback(callback);
+}
+
+void ExtensionRegistry::Shutdown() {
+ // Release references to all Extension objects in the sets.
+ ClearAll();
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_registry.h b/extensions/browser/extension_registry.h
new file mode 100644
index 0000000000..89256e1583
--- /dev/null
+++ b/extensions/browser/extension_registry.h
@@ -0,0 +1,137 @@
+// 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_EXTENSION_REGISTRY_H_
+#define EXTENSIONS_BROWSER_EXTENSION_REGISTRY_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "extensions/common/extension_set.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class Extension;
+class ExtensionRegistryObserver;
+
+// ExtensionRegistry holds sets of the installed extensions for a given
+// BrowserContext. An incognito browser context and its master browser context
+// share a single registry.
+class ExtensionRegistry : public BrowserContextKeyedService {
+ public:
+ // Flags to pass to GetExtensionById() to select which sets to look in.
+ enum IncludeFlag {
+ NONE = 0,
+ ENABLED = 1 << 0,
+ DISABLED = 1 << 1,
+ TERMINATED = 1 << 2,
+ BLACKLISTED = 1 << 3,
+ EVERYTHING = (1 << 4) - 1,
+ };
+
+ ExtensionRegistry();
+ virtual ~ExtensionRegistry();
+
+ // Returns the instance for the given |browser_context|.
+ static ExtensionRegistry* Get(content::BrowserContext* browser_context);
+
+ // NOTE: These sets are *eventually* mututally exclusive, but an extension can
+ // appear in two sets for short periods of time.
+ const ExtensionSet& enabled_extensions() const {
+ return enabled_extensions_;
+ }
+ const ExtensionSet& disabled_extensions() const {
+ return disabled_extensions_;
+ }
+ const ExtensionSet& terminated_extensions() const {
+ return terminated_extensions_;
+ }
+ const ExtensionSet& blacklisted_extensions() const {
+ return blacklisted_extensions_;
+ }
+
+ // The usual observer interface.
+ void AddObserver(ExtensionRegistryObserver* observer);
+ void RemoveObserver(ExtensionRegistryObserver* observer);
+
+ // Invokes the observer method OnExtensionUnloaded(). The extension must not
+ // be enabled at the time of the call.
+ void TriggerOnUnloaded(const Extension* extension);
+
+ // Find an extension by ID using |include_mask| to pick the sets to search:
+ // * enabled_extensions() --> ExtensionRegistry::ENABLED
+ // * disabled_extensions() --> ExtensionRegistry::DISABLED
+ // * terminated_extensions() --> ExtensionRegistry::TERMINATED
+ // * blacklisted_extensions() --> ExtensionRegistry::BLACKLISTED
+ // Returns NULL if the extension is not found in the selected sets.
+ const Extension* GetExtensionById(const std::string& id,
+ int include_mask) const;
+
+ // Adds the specified extension to the enabled set. The registry becomes an
+ // owner. Any previous extension with the same ID is removed.
+ // Returns true if there is no previous extension.
+ // NOTE: You probably want to use ExtensionService instead of calling this
+ // method directly.
+ bool AddEnabled(const scoped_refptr<const Extension>& extension);
+
+ // Removes the specified extension from the enabled set.
+ // Returns true if the set contained the specified extension.
+ // NOTE: You probably want to use ExtensionService instead of calling this
+ // method directly.
+ bool RemoveEnabled(const std::string& id);
+
+ // As above, but for the disabled set.
+ bool AddDisabled(const scoped_refptr<const Extension>& extension);
+ bool RemoveDisabled(const std::string& id);
+
+ // As above, but for the terminated set.
+ bool AddTerminated(const scoped_refptr<const Extension>& extension);
+ bool RemoveTerminated(const std::string& id);
+
+ // As above, but for the blacklisted set.
+ bool AddBlacklisted(const scoped_refptr<const Extension>& extension);
+ bool RemoveBlacklisted(const std::string& id);
+
+ // Removes all extensions from all sets.
+ void ClearAll();
+
+ // Sets a callback to run when the disabled extension set is modified.
+ // TODO(jamescook): This is too specific for a generic registry; find some
+ // other way to do this.
+ void SetDisabledModificationCallback(
+ const ExtensionSet::ModificationCallback& callback);
+
+ // BrowserContextKeyedService implementation:
+ virtual void Shutdown() OVERRIDE;
+
+ private:
+ // Extensions that are installed, enabled and not terminated.
+ ExtensionSet enabled_extensions_;
+
+ // Extensions that are installed and disabled.
+ ExtensionSet disabled_extensions_;
+
+ // Extensions that are installed and terminated.
+ ExtensionSet terminated_extensions_;
+
+ // Extensions that are installed and blacklisted. Generally these shouldn't be
+ // considered as installed by the extension platform: we only keep them around
+ // so that if extensions are blacklisted by mistake they can easily be
+ // un-blacklisted.
+ ExtensionSet blacklisted_extensions_;
+
+ ObserverList<ExtensionRegistryObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionRegistry);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_REGISTRY_H_
diff --git a/extensions/browser/extension_registry_factory.cc b/extensions/browser/extension_registry_factory.cc
new file mode 100644
index 0000000000..9f02012dd5
--- /dev/null
+++ b/extensions/browser/extension_registry_factory.cc
@@ -0,0 +1,47 @@
+// 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/extension_registry_factory.h"
+
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extensions_browser_client.h"
+
+using content::BrowserContext;
+
+namespace extensions {
+
+// static
+ExtensionRegistry* ExtensionRegistryFactory::GetForBrowserContext(
+ BrowserContext* context) {
+ return static_cast<ExtensionRegistry*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+ExtensionRegistryFactory* ExtensionRegistryFactory::GetInstance() {
+ return Singleton<ExtensionRegistryFactory>::get();
+}
+
+ExtensionRegistryFactory::ExtensionRegistryFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ExtensionRegistry",
+ BrowserContextDependencyManager::GetInstance()) {
+ // No dependencies on other services.
+}
+
+ExtensionRegistryFactory::~ExtensionRegistryFactory() {}
+
+BrowserContextKeyedService* ExtensionRegistryFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new ExtensionRegistry;
+}
+
+BrowserContext* ExtensionRegistryFactory::GetBrowserContextToUse(
+ BrowserContext* context) const {
+ // Redirected in incognito.
+ return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_registry_factory.h b/extensions/browser/extension_registry_factory.h
new file mode 100644
index 0000000000..5b06c4f986
--- /dev/null
+++ b/extensions/browser/extension_registry_factory.h
@@ -0,0 +1,42 @@
+// 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_EXTENSION_REGISTRY_FACTORY_H_
+#define EXTENSIONS_BROWSER_EXTENSION_REGISTRY_FACTORY_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+namespace extensions {
+
+class ExtensionRegistry;
+
+// Factory for ExtensionRegistry objects. ExtensionRegistry objects are shared
+// between an incognito browser context and its master browser context.
+class ExtensionRegistryFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static ExtensionRegistry* GetForBrowserContext(
+ content::BrowserContext* context);
+
+ static ExtensionRegistryFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<ExtensionRegistryFactory>;
+
+ ExtensionRegistryFactory();
+ virtual ~ExtensionRegistryFactory();
+
+ // BrowserContextKeyedServiceFactory implementation:
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionRegistryFactory);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_REGISTRY_FACTORY_H_
diff --git a/extensions/browser/extension_registry_observer.h b/extensions/browser/extension_registry_observer.h
new file mode 100644
index 0000000000..33828850e5
--- /dev/null
+++ b/extensions/browser/extension_registry_observer.h
@@ -0,0 +1,25 @@
+// Copyright 2014 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_EXTENSION_REGISTRY_OBSERVER_H_
+#define EXTENSIONS_BROWSER_EXTENSION_REGISTRY_OBSERVER_H_
+
+namespace extensions {
+
+class Extension;
+
+// Observer for ExtensionRegistry. Exists in a separate header file to reduce
+// the include file burden for typical clients of ExtensionRegistry.
+class ExtensionRegistryObserver {
+ public:
+ virtual ~ExtensionRegistryObserver() {}
+
+ // Called after an extension is unloaded. The extension no longer exists in
+ // any of the ExtensionRegistry sets (enabled, disabled, etc.).
+ virtual void OnExtensionUnloaded(const Extension* extension) {}
+};
+
+}
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_REGISTRY_OBSERVER_H_
diff --git a/extensions/browser/extension_registry_unittest.cc b/extensions/browser/extension_registry_unittest.cc
new file mode 100644
index 0000000000..075019b244
--- /dev/null
+++ b/extensions/browser/extension_registry_unittest.cc
@@ -0,0 +1,169 @@
+// 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/extension_registry.h"
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+namespace {
+
+typedef testing::Test ExtensionRegistryTest;
+
+TEST_F(ExtensionRegistryTest, FillAndClearRegistry) {
+ ExtensionRegistry registry;
+ scoped_refptr<Extension> extension1 = test_util::CreateExtensionWithID("id1");
+ scoped_refptr<Extension> extension2 = test_util::CreateExtensionWithID("id2");
+ scoped_refptr<Extension> extension3 = test_util::CreateExtensionWithID("id3");
+ scoped_refptr<Extension> extension4 = test_util::CreateExtensionWithID("id4");
+
+ // All the sets start empty.
+ EXPECT_EQ(0u, registry.enabled_extensions().size());
+ EXPECT_EQ(0u, registry.disabled_extensions().size());
+ EXPECT_EQ(0u, registry.terminated_extensions().size());
+ EXPECT_EQ(0u, registry.blacklisted_extensions().size());
+
+ // Extensions can be added to each set.
+ registry.AddEnabled(extension1);
+ registry.AddDisabled(extension2);
+ registry.AddTerminated(extension3);
+ registry.AddBlacklisted(extension4);
+
+ EXPECT_EQ(1u, registry.enabled_extensions().size());
+ EXPECT_EQ(1u, registry.disabled_extensions().size());
+ EXPECT_EQ(1u, registry.terminated_extensions().size());
+ EXPECT_EQ(1u, registry.blacklisted_extensions().size());
+
+ // Clearing the registry clears all sets.
+ registry.ClearAll();
+
+ EXPECT_EQ(0u, registry.enabled_extensions().size());
+ EXPECT_EQ(0u, registry.disabled_extensions().size());
+ EXPECT_EQ(0u, registry.terminated_extensions().size());
+ EXPECT_EQ(0u, registry.blacklisted_extensions().size());
+}
+
+// A simple test of adding and removing things from sets.
+TEST_F(ExtensionRegistryTest, AddAndRemoveExtensionFromRegistry) {
+ ExtensionRegistry registry;
+
+ // Adding an extension works.
+ scoped_refptr<Extension> extension = test_util::CreateExtensionWithID("id");
+ EXPECT_TRUE(registry.AddEnabled(extension));
+ EXPECT_EQ(1u, registry.enabled_extensions().size());
+
+ // The extension was only added to one set.
+ EXPECT_EQ(0u, registry.disabled_extensions().size());
+ EXPECT_EQ(0u, registry.terminated_extensions().size());
+ EXPECT_EQ(0u, registry.blacklisted_extensions().size());
+
+ // Removing an extension works.
+ EXPECT_TRUE(registry.RemoveEnabled(extension->id()));
+ EXPECT_EQ(0u, registry.enabled_extensions().size());
+
+ // Trying to remove an extension that isn't in the set fails cleanly.
+ EXPECT_FALSE(registry.RemoveEnabled(extension->id()));
+}
+
+TEST_F(ExtensionRegistryTest, AddExtensionToRegistryTwice) {
+ ExtensionRegistry registry;
+ scoped_refptr<Extension> extension = test_util::CreateExtensionWithID("id");
+
+ // An extension can exist in two sets at once. It would be nice to eliminate
+ // this functionality, but some users of ExtensionRegistry need it.
+ EXPECT_TRUE(registry.AddEnabled(extension));
+ EXPECT_TRUE(registry.AddDisabled(extension));
+
+ EXPECT_EQ(1u, registry.enabled_extensions().size());
+ EXPECT_EQ(1u, registry.disabled_extensions().size());
+ EXPECT_EQ(0u, registry.terminated_extensions().size());
+ EXPECT_EQ(0u, registry.blacklisted_extensions().size());
+}
+
+TEST_F(ExtensionRegistryTest, GetExtensionById) {
+ ExtensionRegistry registry;
+
+ // Trying to get an extension fails cleanly when the sets are empty.
+ EXPECT_FALSE(
+ registry.GetExtensionById("id", ExtensionRegistry::EVERYTHING));
+
+ scoped_refptr<Extension> enabled =
+ test_util::CreateExtensionWithID("enabled");
+ scoped_refptr<Extension> disabled =
+ test_util::CreateExtensionWithID("disabled");
+ scoped_refptr<Extension> terminated =
+ test_util::CreateExtensionWithID("terminated");
+ scoped_refptr<Extension> blacklisted =
+ test_util::CreateExtensionWithID("blacklisted");
+
+ // Add an extension to each set.
+ registry.AddEnabled(enabled);
+ registry.AddDisabled(disabled);
+ registry.AddTerminated(terminated);
+ registry.AddBlacklisted(blacklisted);
+
+ // Enabled is part of everything and the enabled list.
+ EXPECT_TRUE(
+ registry.GetExtensionById("enabled", ExtensionRegistry::EVERYTHING));
+ EXPECT_TRUE(
+ registry.GetExtensionById("enabled", ExtensionRegistry::ENABLED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("enabled", ExtensionRegistry::DISABLED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("enabled", ExtensionRegistry::TERMINATED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("enabled", ExtensionRegistry::BLACKLISTED));
+
+ // Disabled is part of everything and the disabled list.
+ EXPECT_TRUE(
+ registry.GetExtensionById("disabled", ExtensionRegistry::EVERYTHING));
+ EXPECT_FALSE(
+ registry.GetExtensionById("disabled", ExtensionRegistry::ENABLED));
+ EXPECT_TRUE(
+ registry.GetExtensionById("disabled", ExtensionRegistry::DISABLED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("disabled", ExtensionRegistry::TERMINATED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("disabled", ExtensionRegistry::BLACKLISTED));
+
+ // Terminated is part of everything and the terminated list.
+ EXPECT_TRUE(
+ registry.GetExtensionById("terminated", ExtensionRegistry::EVERYTHING));
+ EXPECT_FALSE(
+ registry.GetExtensionById("terminated", ExtensionRegistry::ENABLED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("terminated", ExtensionRegistry::DISABLED));
+ EXPECT_TRUE(
+ registry.GetExtensionById("terminated", ExtensionRegistry::TERMINATED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("terminated", ExtensionRegistry::BLACKLISTED));
+
+ // Blacklisted is part of everything and the blacklisted list.
+ EXPECT_TRUE(
+ registry.GetExtensionById("blacklisted", ExtensionRegistry::EVERYTHING));
+ EXPECT_FALSE(
+ registry.GetExtensionById("blacklisted", ExtensionRegistry::ENABLED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("blacklisted", ExtensionRegistry::DISABLED));
+ EXPECT_FALSE(
+ registry.GetExtensionById("blacklisted", ExtensionRegistry::TERMINATED));
+ EXPECT_TRUE(
+ registry.GetExtensionById("blacklisted", ExtensionRegistry::BLACKLISTED));
+
+ // Enabled can be found with multiple flags set.
+ EXPECT_TRUE(registry.GetExtensionById(
+ "enabled", ExtensionRegistry::ENABLED | ExtensionRegistry::TERMINATED));
+
+ // Enabled isn't found if the wrong flags are set.
+ EXPECT_FALSE(registry.GetExtensionById(
+ "enabled", ExtensionRegistry::DISABLED | ExtensionRegistry::BLACKLISTED));
+}
+
+} // namespace
+} // namespace extensions
diff --git a/extensions/browser/extension_scoped_prefs.h b/extensions/browser/extension_scoped_prefs.h
new file mode 100644
index 0000000000..15fc577f2d
--- /dev/null
+++ b/extensions/browser/extension_scoped_prefs.h
@@ -0,0 +1,56 @@
+// Copyright 2014 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_EXTENSION_SCOPED_PREFS_H_
+#define EXTENSIONS_BROWSER_EXTENSION_SCOPED_PREFS_H_
+
+namespace extensions {
+
+class ExtensionScopedPrefs {
+ public:
+ ExtensionScopedPrefs() {}
+ ~ExtensionScopedPrefs() {}
+
+ // Sets the pref |key| for extension |id| to |value|.
+ virtual void UpdateExtensionPref(const std::string& id,
+ const std::string& key,
+ base::Value* value) = 0;
+
+ // Deletes the pref dictionary for extension |id|.
+ virtual void DeleteExtensionPrefs(const std::string& id) = 0;
+
+ // Reads a boolean pref |pref_key| from extension with id |extension_id|.
+ virtual bool ReadPrefAsBoolean(const std::string& extension_id,
+ const std::string& pref_key,
+ bool* out_value) const = 0;
+
+ // Reads an integer pref |pref_key| from extension with id |extension_id|.
+ virtual bool ReadPrefAsInteger(const std::string& extension_id,
+ const std::string& pref_key,
+ int* out_value) const = 0;
+
+ // Reads a string pref |pref_key| from extension with id |extension_id|.
+ virtual bool ReadPrefAsString(const std::string& extension_id,
+ const std::string& pref_key,
+ std::string* out_value) const = 0;
+
+ // Reads a list pref |pref_key| from extension with id |extension_id|.
+ virtual bool ReadPrefAsList(const std::string& extension_id,
+ const std::string& pref_key,
+ const base::ListValue** out_value) const = 0;
+
+ // Reads a dictionary pref |pref_key| from extension with id |extension_id|.
+ virtual bool ReadPrefAsDictionary(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const base::DictionaryValue** out_value) const = 0;
+
+ // Returns true if the prefs contain an entry for an extension with id
+ // |extension_id|.
+ virtual bool HasPrefForExtension(const std::string& extension_id) const = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_SCOPED_PREFS_H_
diff --git a/extensions/browser/extension_system.cc b/extensions/browser/extension_system.cc
new file mode 100644
index 0000000000..910e7d9021
--- /dev/null
+++ b/extensions/browser/extension_system.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 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/extension_system.h"
+
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+#include "extensions/browser/extension_system_provider.h"
+#include "extensions/browser/extensions_browser_client.h"
+
+namespace extensions {
+
+ExtensionSystem::ExtensionSystem() {
+}
+
+ExtensionSystem::~ExtensionSystem() {
+}
+
+// static
+ExtensionSystem* ExtensionSystem::Get(content::BrowserContext* context) {
+ return ExtensionsBrowserClient::Get()
+ ->GetExtensionSystemFactory()
+ ->GetForBrowserContext(context);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_system.h b/extensions/browser/extension_system.h
new file mode 100644
index 0000000000..b1e724c2bb
--- /dev/null
+++ b/extensions/browser/extension_system.h
@@ -0,0 +1,131 @@
+// Copyright 2014 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_EXTENSION_SYSTEM_H_
+#define EXTENSIONS_BROWSER_EXTENSION_SYSTEM_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "extensions/common/extension.h"
+
+class ExtensionService;
+
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+class DeviceLocalAccountManagementPolicyProvider;
+}
+#endif // defined(OS_CHROMEOS)
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+
+class Blacklist;
+class ErrorConsole;
+class EventRouter;
+class Extension;
+class ExtensionWarningService;
+class InfoMap;
+class InstallVerifier;
+class LazyBackgroundTaskQueue;
+class ManagementPolicy;
+class OneShotEvent;
+class ProcessManager;
+class QuotaService;
+class RuntimeData;
+class StateStore;
+class UserScriptMaster;
+
+// ExtensionSystem manages the lifetime of many of the services used by the
+// extensions and apps system, and it handles startup and shutdown as needed.
+// Eventually, we'd like to make more of these services into
+// BrowserContextKeyedServices in their own right.
+class ExtensionSystem : public BrowserContextKeyedService {
+ public:
+ ExtensionSystem();
+ virtual ~ExtensionSystem();
+
+ // Returns the instance for the given browser context, or NULL if none.
+ static ExtensionSystem* Get(content::BrowserContext* context);
+
+ // Initializes extensions machinery.
+ // Component extensions are always enabled, external and user extensions are
+ // controlled by |extensions_enabled|.
+ virtual void InitForRegularProfile(bool extensions_enabled) = 0;
+
+ // The ExtensionService is created at startup.
+ virtual ExtensionService* extension_service() = 0;
+
+ // Per-extension data that can change during the life of the process but
+ // does not persist across restarts. Lives on UI thread. Created at startup.
+ virtual RuntimeData* runtime_data() = 0;
+
+ // The class controlling whether users are permitted to perform certain
+ // actions on extensions (install, uninstall, disable, etc.).
+ // The ManagementPolicy is created at startup.
+ virtual ManagementPolicy* management_policy() = 0;
+
+ // The UserScriptMaster is created at startup.
+ virtual UserScriptMaster* user_script_master() = 0;
+
+ // The ProcessManager is created at startup.
+ virtual ProcessManager* process_manager() = 0;
+
+ // The StateStore is created at startup.
+ virtual StateStore* state_store() = 0;
+
+ // The rules store is created at startup.
+ virtual StateStore* rules_store() = 0;
+
+ // Returns the IO-thread-accessible extension data.
+ virtual InfoMap* info_map() = 0;
+
+ // The LazyBackgroundTaskQueue is created at startup.
+ virtual LazyBackgroundTaskQueue* lazy_background_task_queue() = 0;
+
+ // The EventRouter is created at startup.
+ virtual EventRouter* event_router() = 0;
+
+ // The ExtensionWarningService is created at startup.
+ virtual ExtensionWarningService* warning_service() = 0;
+
+ // The blacklist is created at startup.
+ virtual Blacklist* blacklist() = 0;
+
+ // The ErrorConsole is created at startup.
+ virtual ErrorConsole* error_console() = 0;
+
+ // The InstallVerifier is created at startup.
+ virtual InstallVerifier* install_verifier() = 0;
+
+ // Returns the QuotaService that limits calls to certain extension functions.
+ // Lives on the UI thread. Created at startup.
+ virtual QuotaService* quota_service() = 0;
+
+ // Called by the ExtensionService that lives in this system. Gives the
+ // info map a chance to react to the load event before the EXTENSION_LOADED
+ // notification has fired. The purpose for handling this event first is to
+ // avoid race conditions by making sure URLRequestContexts learn about new
+ // extensions before anything else needs them to know.
+ virtual void RegisterExtensionWithRequestContexts(
+ const Extension* extension) {}
+
+ // Called by the ExtensionService that lives in this system. Lets the
+ // info map clean up its RequestContexts once all the listeners to the
+ // EXTENSION_UNLOADED notification have finished running.
+ virtual void UnregisterExtensionWithRequestContexts(
+ const std::string& extension_id,
+ const UnloadedExtensionInfo::Reason reason) {}
+
+ // Signaled when the extension system has completed its startup tasks.
+ virtual const OneShotEvent& ready() const = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_SYSTEM_H_
diff --git a/extensions/browser/extension_system_provider.cc b/extensions/browser/extension_system_provider.cc
new file mode 100644
index 0000000000..3cc6adb0b1
--- /dev/null
+++ b/extensions/browser/extension_system_provider.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 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/extension_system_provider.h"
+
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+
+namespace extensions {
+
+ExtensionSystemProvider::ExtensionSystemProvider(
+ const char* name,
+ BrowserContextDependencyManager* manager)
+ : BrowserContextKeyedServiceFactory(name, manager) {}
+
+ExtensionSystemProvider::~ExtensionSystemProvider() {}
+
+} // namespace extensions
diff --git a/extensions/browser/extension_system_provider.h b/extensions/browser/extension_system_provider.h
new file mode 100644
index 0000000000..45ca56c185
--- /dev/null
+++ b/extensions/browser/extension_system_provider.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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_EXTENSION_SYSTEM_PROVIDER_H_
+#define EXTENSIONS_BROWSER_EXTENSION_SYSTEM_PROVIDER_H_
+
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+class BrowserContextDependencyManager;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class ExtensionSystem;
+
+// An ExtensionSystemProvider maps a BrowserContext to its ExtensionSystem.
+// Different applications may use this to provide differing implementations
+// of ExtensionSystem.
+// TODO(yoz): Rename to ExtensionSystemFactory.
+class ExtensionSystemProvider : public BrowserContextKeyedServiceFactory {
+ public:
+ ExtensionSystemProvider(const char* name,
+ BrowserContextDependencyManager* manager);
+ virtual ~ExtensionSystemProvider();
+
+ virtual ExtensionSystem* GetForBrowserContext(
+ content::BrowserContext* context) = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_EXTENSION_SYSTEM_PROVIDER_H_
diff --git a/extensions/browser/extensions_browser_client.h b/extensions/browser/extensions_browser_client.h
index 61641a7931..08ffa586f1 100644
--- a/extensions/browser/extensions_browser_client.h
+++ b/extensions/browser/extensions_browser_client.h
@@ -5,6 +5,9 @@
#ifndef EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_CLIENT_H_
#define EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_CLIENT_H_
+#include <string>
+#include <vector>
+
#include "base/memory/scoped_ptr.h"
class CommandLine;
@@ -12,11 +15,18 @@ class PrefService;
namespace content {
class BrowserContext;
+class JavaScriptDialogManager;
+class WebContents;
}
namespace extensions {
+class ApiActivityMonitor;
class AppSorting;
+class Extension;
+class ExtensionHost;
+class ExtensionSystem;
+class ExtensionSystemProvider;
// Interface to allow the extensions module to make browser-process-specific
// queries of the embedder. Should be Set() once in the browser process.
@@ -54,11 +64,25 @@ class ExtensionsBrowserClient {
virtual content::BrowserContext* GetOffTheRecordContext(
content::BrowserContext* context) = 0;
- // Return the original "recording" context. This method returns |context| if
+ // Returns the original "recording" context. This method returns |context| if
// |context| is not incognito.
virtual content::BrowserContext* GetOriginalContext(
content::BrowserContext* context) = 0;
+ // Returns true if |context| corresponds to a guest session.
+ virtual bool IsGuestSession(content::BrowserContext* context) = 0;
+
+ // Returns true if |extension_id| can run in an incognito window.
+ virtual bool IsExtensionIncognitoEnabled(
+ const std::string& extension_id,
+ content::BrowserContext* context) const = 0;
+
+ // Returns true if |extension| can see events and data from another
+ // sub-profile (incognito to original profile, or vice versa).
+ virtual bool CanExtensionCrossIncognito(
+ const extensions::Extension* extension,
+ content::BrowserContext* context) const = 0;
+
// Returns the PrefService associated with |context|.
virtual PrefService* GetPrefServiceForContext(
content::BrowserContext* context) = 0;
@@ -67,6 +91,16 @@ class ExtensionsBrowserClient {
virtual bool DeferLoadingBackgroundHosts(
content::BrowserContext* context) const = 0;
+ virtual bool IsBackgroundPageAllowed(
+ content::BrowserContext* context) const = 0;
+
+ // Called after the hosting |web_contents| for an extension is created. The
+ // implementation may wish to add preference observers to |web_contents|.
+ virtual void OnExtensionHostCreated(content::WebContents* web_contents) = 0;
+
+ // Called after |host| creates a RenderView for an extension.
+ virtual void OnRenderViewCreatedForBackgroundPage(ExtensionHost* host) = 0;
+
// Returns true if the client version has updated since the last run. Called
// once each time the extensions system is loaded per browser_context. The
// implementation may wish to use the BrowserContext to record the current
@@ -79,6 +113,19 @@ class ExtensionsBrowserClient {
// Return true if the system is run in forced app mode.
virtual bool IsRunningInForcedAppMode() = 0;
+ // Returns the embedder's JavaScriptDialogManager or NULL if the embedder
+ // does not support JavaScript dialogs.
+ virtual content::JavaScriptDialogManager* GetJavaScriptDialogManager() = 0;
+
+ // Returns the embedder's ApiActivityMonitor for |context|. Returns NULL if
+ // the embedder does not monitor extension API activity.
+ virtual ApiActivityMonitor* GetApiActivityMonitor(
+ content::BrowserContext* context) = 0;
+
+ // Returns the factory that provides an ExtensionSystem to be returned from
+ // ExtensionSystem::Get.
+ virtual ExtensionSystemProvider* GetExtensionSystemFactory() = 0;
+
// Returns the single instance of |this|.
static ExtensionsBrowserClient* Get();
diff --git a/extensions/browser/info_map.cc b/extensions/browser/info_map.cc
index 2bff206cdd..7122eb0572 100644
--- a/extensions/browser/info_map.cc
+++ b/extensions/browser/info_map.cc
@@ -4,10 +4,10 @@
#include "extensions/browser/info_map.h"
-#include "chrome/common/extensions/extension_set.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
+#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
using content::BrowserThread;
@@ -44,6 +44,10 @@ InfoMap::InfoMap() : signin_process_id_(-1) {}
const ProcessMap& InfoMap::process_map() const { return process_map_; }
+const ProcessMap& InfoMap::worker_process_map() const {
+ return worker_process_map_;
+}
+
void InfoMap::AddExtension(const Extension* extension,
base::Time install_time,
bool incognito_enabled,
@@ -124,6 +128,19 @@ void InfoMap::UnregisterAllExtensionsInProcess(int process_id) {
process_map_.RemoveAllFromProcess(process_id);
}
+void InfoMap::RegisterExtensionWorkerProcess(const std::string& extension_id,
+ int process_id,
+ int site_instance_id) {
+ if (!worker_process_map_.Insert(extension_id, process_id, site_instance_id)) {
+ NOTREACHED() << "Duplicate extension worker process registration for: "
+ << extension_id << "," << process_id << ".";
+ }
+}
+
+void InfoMap::UnregisterExtensionWorkerProcess(int process_id) {
+ worker_process_map_.RemoveAllFromProcess(process_id);
+}
+
void InfoMap::GetExtensionsWithAPIPermissionForSecurityOrigin(
const GURL& origin,
int process_id,
diff --git a/extensions/browser/info_map.h b/extensions/browser/info_map.h
index 8d5cf6dd82..ad475068ee 100644
--- a/extensions/browser/info_map.h
+++ b/extensions/browser/info_map.h
@@ -11,9 +11,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
-#include "chrome/common/extensions/extension_set.h"
#include "extensions/browser/process_map.h"
#include "extensions/browser/quota_service.h"
+#include "extensions/common/extension_set.h"
namespace extensions {
class Extension;
@@ -30,7 +30,10 @@ class InfoMap : public base::RefCountedThreadSafe<InfoMap> {
return disabled_extensions_;
}
+ // Information about which extensions are assigned to which render processes.
const extensions::ProcessMap& process_map() const;
+ // Information about which extensions are assigned to which worker processes.
+ const extensions::ProcessMap& worker_process_map() const;
// Callback for when new extensions are loaded.
void AddExtension(const extensions::Extension* extension,
@@ -64,6 +67,14 @@ class InfoMap : public base::RefCountedThreadSafe<InfoMap> {
int site_instance_id);
void UnregisterAllExtensionsInProcess(int process_id);
+ // Adds an entry to worker_process_map_.
+ void RegisterExtensionWorkerProcess(const std::string& extension_id,
+ int process_id,
+ int site_instance_id);
+
+ // Removes an entry from worker_process_map_.
+ void UnregisterExtensionWorkerProcess(int process_id);
+
// Returns the subset of extensions which has the same |origin| in
// |process_id| with the specified |permission|.
void GetExtensionsWithAPIPermissionForSecurityOrigin(
@@ -79,6 +90,7 @@ class InfoMap : public base::RefCountedThreadSafe<InfoMap> {
extensions::APIPermission::ID permission)
const;
+ // Returns the IO thread QuotaService. Creates the instance on first call.
QuotaService* GetQuotaService();
// Keep track of the signin process, so we can restrict extension access to
@@ -88,9 +100,8 @@ class InfoMap : public base::RefCountedThreadSafe<InfoMap> {
// Notifications can be enabled/disabled in real time by the user.
void SetNotificationsDisabled(const std::string& extension_id,
- bool notifications_disabled);
- bool AreNotificationsDisabled(const std::string& extension_id)
- const;
+ bool notifications_disabled);
+ bool AreNotificationsDisabled(const std::string& extension_id) const;
private:
friend class base::RefCountedThreadSafe<InfoMap>;
@@ -113,9 +124,12 @@ class InfoMap : public base::RefCountedThreadSafe<InfoMap> {
// the IO thread.
scoped_ptr<QuotaService> quota_service_;
- // Assignment of extensions to processes.
+ // Assignment of extensions to renderer processes.
extensions::ProcessMap process_map_;
+ // Assignment of extensions to worker processes.
+ extensions::ProcessMap worker_process_map_;
+
int signin_process_id_;
};
diff --git a/extensions/browser/info_map_unittest.cc b/extensions/browser/info_map_unittest.cc
index 8eaf48851e..d01fa61efa 100644
--- a/extensions/browser/info_map_unittest.cc
+++ b/extensions/browser/info_map_unittest.cc
@@ -38,7 +38,7 @@ static scoped_refptr<Extension> CreateExtension(const std::string& name) {
base::FilePath path(FILE_PATH_LITERAL("/foo"));
#endif
- DictionaryValue manifest;
+ base::DictionaryValue manifest;
manifest.SetString(keys::kVersion, "1.0.0.0");
manifest.SetString(keys::kName, name);
@@ -61,7 +61,7 @@ static scoped_refptr<Extension> LoadManifest(const std::string& dir,
path = path.AppendASCII("extensions").AppendASCII(dir).AppendASCII(test_file);
JSONFileValueSerializer serializer(path);
- scoped_ptr<Value> result(serializer.Deserialize(NULL, NULL));
+ scoped_ptr<base::Value> result(serializer.Deserialize(NULL, NULL));
if (!result)
return NULL;
@@ -69,7 +69,7 @@ static scoped_refptr<Extension> LoadManifest(const std::string& dir,
scoped_refptr<Extension> extension =
Extension::Create(path,
Manifest::INVALID_LOCATION,
- *static_cast<DictionaryValue*>(result.get()),
+ *static_cast<base::DictionaryValue*>(result.get()),
Extension::NO_FLAGS,
&error);
EXPECT_TRUE(extension.get()) << error;
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc
index f53cdd3e96..2b38ce9ad1 100644
--- a/extensions/browser/lazy_background_task_queue.cc
+++ b/extensions/browser/lazy_background_task_queue.cc
@@ -7,8 +7,6 @@
#include "base/callback.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/notification_service.h"
@@ -16,6 +14,8 @@
#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/extension_registry.h"
+#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
@@ -44,7 +44,7 @@ bool LazyBackgroundTaskQueue::ShouldEnqueueTask(
const Extension* extension) {
DCHECK(extension);
if (BackgroundInfo::HasBackgroundPage(extension)) {
- ProcessManager* pm = ExtensionSystem::GetForBrowserContext(
+ ProcessManager* pm = ExtensionSystem::Get(
browser_context)->process_manager();
DCHECK(pm);
ExtensionHost* background_host =
@@ -73,15 +73,13 @@ void LazyBackgroundTaskQueue::AddPendingTask(
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);
+ ExtensionRegistry::Get(browser_context)->enabled_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.
- ProcessManager* pm = ExtensionSystem::GetForBrowserContext(
+ ProcessManager* pm = ExtensionSystem::Get(
browser_context)->process_manager();
pm->IncrementLazyKeepaliveCount(extension);
// Creating the background host may fail, e.g. if |profile| is incognito
@@ -129,7 +127,7 @@ void LazyBackgroundTaskQueue::ProcessPendingTasks(
// 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()->
+ ExtensionSystem::Get(browser_context)->process_manager()->
DecrementLazyKeepaliveCount(extension);
}
}
diff --git a/extensions/browser/management_policy.cc b/extensions/browser/management_policy.cc
index 8bab962fb4..50183d0488 100644
--- a/extensions/browser/management_policy.cc
+++ b/extensions/browser/management_policy.cc
@@ -25,24 +25,25 @@ ManagementPolicy::~ManagementPolicy() {
}
bool ManagementPolicy::Provider::UserMayLoad(const Extension* extension,
- string16* error) const {
+ base::string16* error) const {
return true;
}
bool ManagementPolicy::Provider::UserMayModifySettings(
- const Extension* extension, string16* error) const {
+ const Extension* extension, base::string16* error) const {
return true;
}
bool ManagementPolicy::Provider::MustRemainEnabled(const Extension* extension,
- string16* error) const {
+ base::string16* error)
+ const {
return false;
}
bool ManagementPolicy::Provider::MustRemainDisabled(
const Extension* extension,
Extension::DisableReason* reason,
- string16* error) const {
+ base::string16* error) const {
return false;
}
@@ -55,26 +56,26 @@ void ManagementPolicy::UnregisterProvider(Provider* provider) {
}
bool ManagementPolicy::UserMayLoad(const Extension* extension,
- string16* error) const {
+ base::string16* error) const {
return ApplyToProviderList(&Provider::UserMayLoad, "Installation",
true, extension, error);
}
bool ManagementPolicy::UserMayModifySettings(const Extension* extension,
- string16* error) const {
+ base::string16* error) const {
return ApplyToProviderList(&Provider::UserMayModifySettings, "Modification",
true, extension, error);
}
bool ManagementPolicy::MustRemainEnabled(const Extension* extension,
- string16* error) const {
+ base::string16* error) const {
return ApplyToProviderList(&Provider::MustRemainEnabled, "Disabling",
false, extension, error);
}
bool ManagementPolicy::MustRemainDisabled(const Extension* extension,
Extension::DisableReason* reason,
- string16* error) const {
+ base::string16* error) const {
for (ProviderList::const_iterator it = providers_.begin();
it != providers_.end(); ++it)
if ((*it)->MustRemainDisabled(extension, reason, error))
@@ -95,7 +96,7 @@ bool ManagementPolicy::ApplyToProviderList(ProviderFunction function,
const char* debug_operation_name,
bool normal_result,
const Extension* extension,
- string16* error) const {
+ base::string16* error) const {
for (ProviderList::const_iterator it = providers_.begin();
it != providers_.end(); ++it) {
const Provider* provider = *it;
diff --git a/extensions/browser/management_policy.h b/extensions/browser/management_policy.h
index ab3c9c3129..149a598fc3 100644
--- a/extensions/browser/management_policy.h
+++ b/extensions/browser/management_policy.h
@@ -52,13 +52,13 @@ class ManagementPolicy {
// Providers should return false if a user may not install the |extension|,
// or load or run it if it has already been installed.
virtual bool UserMayLoad(const Extension* extension,
- string16* error) const;
+ base::string16* error) const;
// Providers should return false if a user may not enable, disable, or
// uninstall the |extension|, or change its usage options (incognito
// permission, file access, etc.).
virtual bool UserMayModifySettings(const Extension* extension,
- string16* error) const;
+ base::string16* error) const;
// Providers should return true if the |extension| must always remain
// enabled. This is distinct from UserMayModifySettings() in that the latter
@@ -66,13 +66,13 @@ class ManagementPolicy {
// Providers implementing this method should also implement the others
// above, if they wish to completely lock in an extension.
virtual bool MustRemainEnabled(const Extension* extension,
- string16* error) const;
+ base::string16* error) const;
// Similar to MustRemainEnabled, but for whether an extension must remain
// disabled, and returns an error and/or reason if the caller needs it.
virtual bool MustRemainDisabled(const Extension* extension,
Extension::DisableReason* reason,
- string16* error) const;
+ base::string16* error) const;
private:
DISALLOW_COPY_AND_ASSIGN(Provider);
@@ -89,25 +89,25 @@ class ManagementPolicy {
// Returns true if the user is permitted to install, load, and run the given
// extension. If not, |error| may be set to an appropriate message.
- bool UserMayLoad(const Extension* extension, string16* error) const;
+ bool UserMayLoad(const Extension* extension, base::string16* error) const;
// Returns true if the user is permitted to enable, disable, or uninstall the
// given extension, or change the extension's usage options (incognito mode,
// file access, etc.). If not, |error| may be set to an appropriate message.
bool UserMayModifySettings(const Extension* extension,
- string16* error) const;
+ base::string16* error) const;
// Returns true if the extension must remain enabled at all times (e.g. a
// compoment extension). In that case, |error| may be set to an appropriate
// message.
bool MustRemainEnabled(const Extension* extension,
- string16* error) const;
+ base::string16* error) const;
// Returns true immediately if any registered provider's MustRemainDisabled
// function returns true.
bool MustRemainDisabled(const Extension* extension,
Extension::DisableReason* reason,
- string16* error) const;
+ base::string16* error) const;
// For use in testing.
void UnregisterAllProviders();
@@ -116,7 +116,8 @@ class ManagementPolicy {
private:
// This is a pointer to a function in the Provider interface, used in
// ApplyToProviderList.
- typedef bool (Provider::*ProviderFunction)(const Extension*, string16*) const;
+ typedef bool (Provider::*ProviderFunction)(const Extension*,
+ base::string16*) const;
typedef std::set<Provider*> ProviderList;
@@ -129,7 +130,7 @@ class ManagementPolicy {
const char* debug_operation_name,
bool normal_result,
const Extension* extension,
- string16* error) const;
+ base::string16* error) const;
ProviderList providers_;
diff --git a/extensions/browser/management_policy_unittest.cc b/extensions/browser/management_policy_unittest.cc
index 595ba29133..52373c135b 100644
--- a/extensions/browser/management_policy_unittest.cc
+++ b/extensions/browser/management_policy_unittest.cc
@@ -63,7 +63,7 @@ TEST_F(ManagementPolicyTest, RegisterAndUnregister) {
TEST_F(ManagementPolicyTest, UserMayLoad) {
// No providers registered.
- string16 error;
+ base::string16 error;
// The extension and location are irrelevant to the
// TestManagementPolicyProviders.
EXPECT_TRUE(policy_.UserMayLoad(NULL, &error));
@@ -92,7 +92,7 @@ TEST_F(ManagementPolicyTest, UserMayLoad) {
}
TEST_F(ManagementPolicyTest, UserMayModifySettings) {
// No providers registered.
- string16 error;
+ base::string16 error;
EXPECT_TRUE(policy_.UserMayModifySettings(NULL, &error));
EXPECT_TRUE(error.empty());
@@ -120,7 +120,7 @@ TEST_F(ManagementPolicyTest, UserMayModifySettings) {
TEST_F(ManagementPolicyTest, MustRemainEnabled) {
// No providers registered.
- string16 error;
+ base::string16 error;
EXPECT_FALSE(policy_.MustRemainEnabled(NULL, &error));
EXPECT_TRUE(error.empty());
@@ -148,7 +148,7 @@ TEST_F(ManagementPolicyTest, MustRemainEnabled) {
TEST_F(ManagementPolicyTest, MustRemainDisabled) {
// No providers registered.
- string16 error;
+ base::string16 error;
EXPECT_FALSE(policy_.MustRemainDisabled(NULL, NULL, &error));
EXPECT_TRUE(error.empty());
@@ -180,14 +180,14 @@ TEST_F(ManagementPolicyTest, MustRemainDisabled) {
TEST_F(ManagementPolicyTest, ErrorHandling) {
// The error parameter should be unchanged if no restriction was found.
std::string original_error = "Ceci est en effet une erreur.";
- string16 original_error16 = UTF8ToUTF16(original_error);
- string16 error = original_error16;
+ base::string16 original_error16 = base::UTF8ToUTF16(original_error);
+ base::string16 error = original_error16;
EXPECT_TRUE(policy_.UserMayLoad(NULL, &error));
- EXPECT_EQ(original_error, UTF16ToUTF8(error));
+ EXPECT_EQ(original_error, base::UTF16ToUTF8(error));
EXPECT_TRUE(policy_.UserMayModifySettings(NULL, &error));
- EXPECT_EQ(original_error, UTF16ToUTF8(error));
+ EXPECT_EQ(original_error, base::UTF16ToUTF8(error));
EXPECT_FALSE(policy_.MustRemainEnabled(NULL, &error));
- EXPECT_EQ(original_error, UTF16ToUTF8(error));
+ EXPECT_EQ(original_error, base::UTF16ToUTF8(error));
// Ensure no crashes if no error message was requested.
EXPECT_TRUE(policy_.UserMayLoad(NULL, NULL));
@@ -201,11 +201,11 @@ TEST_F(ManagementPolicyTest, ErrorHandling) {
// Make sure returned error is correct.
error = original_error16;
EXPECT_FALSE(policy_.UserMayLoad(NULL, &error));
- EXPECT_EQ(UTF8ToUTF16(TestProvider::expected_error()), error);
+ EXPECT_EQ(base::UTF8ToUTF16(TestProvider::expected_error()), error);
error = original_error16;
EXPECT_FALSE(policy_.UserMayModifySettings(NULL, &error));
- EXPECT_EQ(UTF8ToUTF16(TestProvider::expected_error()), error);
+ EXPECT_EQ(base::UTF8ToUTF16(TestProvider::expected_error()), error);
error = original_error16;
EXPECT_TRUE(policy_.MustRemainEnabled(NULL, &error));
- EXPECT_EQ(UTF8ToUTF16(TestProvider::expected_error()), error);
+ EXPECT_EQ(base::UTF8ToUTF16(TestProvider::expected_error()), error);
}
diff --git a/extensions/browser/pending_extension_manager.cc b/extensions/browser/pending_extension_manager.cc
index f1310dd1cd..d16b92b9df 100644
--- a/extensions/browser/pending_extension_manager.cc
+++ b/extensions/browser/pending_extension_manager.cc
@@ -65,15 +65,7 @@ bool PendingExtensionManager::Remove(const std::string& id) {
}
bool PendingExtensionManager::IsIdPending(const std::string& id) const {
- PendingExtensionList::const_iterator iter;
- for (iter = pending_extension_list_.begin();
- iter != pending_extension_list_.end();
- ++iter) {
- if (id == iter->id())
- return true;
- }
-
- return false;
+ return GetById(id) != NULL;
}
bool PendingExtensionManager::HasPendingExtensions() const {
diff --git a/extensions/browser/pref_names.cc b/extensions/browser/pref_names.cc
index 56de3397d9..76a7dc11e0 100644
--- a/extensions/browser/pref_names.cc
+++ b/extensions/browser/pref_names.cc
@@ -27,6 +27,29 @@ bool ScopeToPrefName(ExtensionPrefsScope scope, std::string* result) {
return false;
}
+const char kAlertsInitialized[] = "extensions.alerts.initialized";
+const char kAllowedInstallSites[] = "extensions.allowed_install_sites";
+const char kAllowedTypes[] = "extensions.allowed_types";
+const char kBookmarkAppCreationLaunchType[] =
+ "extensions.bookmark_app_creation_launch_type";
+const char kBrowserActionContainerWidth[] =
+ "extensions.browseractions.container.width";
+const char kExtensions[] = "extensions.settings";
+const char kInstallAllowList[] = "extensions.install.allowlist";
+const char kInstallDenyList[] = "extensions.install.denylist";
+const char kInstallForceList[] = "extensions.install.forcelist";
+const char kKnownDisabled[] = "extensions.known_disabled";
+const char kLastChromeVersion[] = "extensions.last_chrome_version";
+const char kLastUpdateCheck[] = "extensions.autoupdate.last_check";
+const char kNativeMessagingBlacklist[] = "native_messaging.blacklist";
+const char kNativeMessagingWhitelist[] = "native_messaging.whitelist";
+const char kNativeMessagingUserLevelHosts[] =
+ "native_messaging.user_level_hosts";
+const char kNextUpdateCheck[] = "extensions.autoupdate.next_check";
+const char kStorageGarbageCollect[] = "extensions.storage.garbagecollect";
+const char kToolbar[] = "extensions.toolbar";
+const char kToolbarSize[] = "extensions.toolbarsize";
+
const char kPrefPreferences[] = "preferences";
const char kPrefIncognitoPreferences[] = "incognito_preferences";
const char kPrefRegularOnlyPreferences[] = "regular_only_preferences";
diff --git a/extensions/browser/pref_names.h b/extensions/browser/pref_names.h
index f70b525b15..96afa21644 100644
--- a/extensions/browser/pref_names.h
+++ b/extensions/browser/pref_names.h
@@ -9,34 +9,111 @@
#include "extensions/browser/extension_prefs_scope.h"
-namespace extensions {
-
// Preference keys which are needed by both the ExtensionPrefs and by external
// clients, such as APIs.
+
+namespace extensions {
namespace pref_names {
// If the given |scope| is persisted, return true and populate |result| with the
-// appropriate pref name. If |scope| is not persisted, return false, and leave
-// |result| unchanged.
+// appropriate property (i.e. one of kPref*) within a kExtensions dictionary. If
+// |scope| is not persisted, return false, and leave |result| unchanged.
bool ScopeToPrefName(ExtensionPrefsScope scope, std::string* result);
-// A preference that contains any extension-controlled preferences.
+// Browser-level preferences ---------------------------------------------------
+
+// Whether we have run the extension-alert system (see ExtensionGlobalError)
+// at least once for this profile.
+extern const char kAlertsInitialized[];
+
+// The sites that are allowed to install extensions. These sites should be
+// allowed to install extensions without the scary dangerous downloads bar.
+// Also, when off-store-extension installs are disabled, these sites are exempt.
+extern const char kAllowedInstallSites[];
+
+// A list of allowed extension types. Extensions can only be installed if their
+// type is on this whitelist or alternatively on kInstallAllowList or
+// kInstallForceList.
+extern const char kAllowedTypes[];
+
+// Integer which specifies the launch type that bookmark apps are created with
+// by default.
+extern const char kBookmarkAppCreationLaunchType[];
+
+// Integer boolean representing the width (in pixels) of the container for
+// browser actions.
+extern const char kBrowserActionContainerWidth[];
+
+// Dictionary pref that keeps track of per-extension settings. The keys are
+// extension ids.
+extern const char kExtensions[];
+
+// A whitelist of extension ids the user can install: exceptions from the
+// following blacklist.
+extern const char kInstallAllowList[];
+
+// A blacklist, containing extensions the user cannot install. This list can
+// contain "*" meaning all extensions. This list should not be confused with the
+// extension blacklist, which is Google controlled.
+extern const char kInstallDenyList[];
+
+// A list containing extensions that Chrome will silently install
+// at startup time. It is a list of strings, each string contains
+// an extension ID and an update URL, delimited by a semicolon.
+// This preference is set by an admin policy, and meant to be only
+// accessed through extensions::ExternalPolicyProvider.
+extern const char kInstallForceList[];
+
+// A list of known disabled extensions IDs.
+extern const char kKnownDisabled[];
+
+// String pref for what version chrome was last time the extension prefs were
+// loaded.
+extern const char kLastChromeVersion[];
+
+// Time of the last extensions auto-update check.
+extern const char kLastUpdateCheck[];
+
+// Blacklist and whitelist for Native Messaging Hosts.
+extern const char kNativeMessagingBlacklist[];
+extern const char kNativeMessagingWhitelist[];
+
+// Flag allowing usage of Native Messaging hosts installed on user level.
+extern const char kNativeMessagingUserLevelHosts[];
+
+// Time of the next scheduled extensions auto-update checks.
+extern const char kNextUpdateCheck[];
+
+// Indicates on-disk data might have skeletal data that needs to be cleaned
+// on the next start of the browser.
+extern const char kStorageGarbageCollect[];
+
+// A preference that tracks browser action toolbar configuration. This is a list
+// object stored in the Preferences file. The extensions are stored by ID.
+extern const char kToolbar[];
+
+// Integer pref that tracks the number of browser actions visible in the browser
+// actions toolbar.
+extern const char kToolbarSize[];
+
+// Properties in kExtensions dictionaries --------------------------------------
+
+// Extension-controlled preferences.
extern const char kPrefPreferences[];
-// A preference that contains any extension-controlled incognito preferences.
+// Extension-controlled incognito preferences.
extern const char kPrefIncognitoPreferences[];
-// A preference that contains any extension-controlled regular-only preferences.
+// Extension-controlled regular-only preferences.
extern const char kPrefRegularOnlyPreferences[];
-// A preference that contains extension-set content settings.
+// Extension-set content settings.
extern const char kPrefContentSettings[];
-// A preference that contains extension-set content settings.
+// Extension-set incognito content settings.
extern const char kPrefIncognitoContentSettings[];
} // namespace pref_names
-
} // namespace extensions
#endif // EXTENSIONS_BROWSER_PREF_NAMES_H_
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 6a57d8e600..96a8b2867c 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -17,14 +17,13 @@
#include "chrome/browser/extensions/api/runtime/runtime_api.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/extension_util.h"
#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_instance.h"
@@ -33,6 +32,8 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "content/public/common/renderer_preferences.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/extension.h"
@@ -64,6 +65,22 @@ std::string GetExtensionID(RenderViewHost* render_view_host) {
return render_view_host->GetSiteInstance()->GetSiteURL().host();
}
+std::string GetExtensionIDFromFrame(
+ content::RenderFrameHost* render_frame_host) {
+ // This works for both apps and extensions because the site has been
+ // normalized to the extension URL for apps.
+ if (!render_frame_host->GetSiteInstance())
+ return std::string();
+
+ return render_frame_host->GetSiteInstance()->GetSiteURL().host();
+}
+
+bool IsFrameInExtensionHost(ExtensionHost* extension_host,
+ content::RenderFrameHost* render_frame_host) {
+ return WebContents::FromRenderFrameHost(render_frame_host) ==
+ extension_host->host_contents();
+}
+
void OnRenderViewHostUnregistered(BrowserContext* context,
RenderViewHost* render_view_host) {
content::NotificationService::current()->Notify(
@@ -85,9 +102,6 @@ class IncognitoProcessManager : public ProcessManager {
virtual SiteInstance* GetSiteInstanceForURL(const GURL& url) OVERRIDE;
private:
- // Returns true if the extension is allowed to run in incognito mode.
- bool IsIncognitoEnabled(const Extension* extension);
-
ProcessManager* original_manager_;
DISALLOW_COPY_AND_ASSIGN(IncognitoProcessManager);
@@ -113,8 +127,7 @@ class RenderViewHostDestructionObserver
explicit RenderViewHostDestructionObserver(WebContents* web_contents)
: WebContentsObserver(web_contents) {
BrowserContext* context = web_contents->GetBrowserContext();
- process_manager_ =
- ExtensionSystem::GetForBrowserContext(context)->process_manager();
+ process_manager_ = ExtensionSystem::Get(context)->process_manager();
}
friend class content::WebContentsUserData<RenderViewHostDestructionObserver>;
@@ -203,6 +216,8 @@ ProcessManager::ProcessManager(BrowserContext* context,
content::Source<BrowserContext>(original_context));
}
+ // Note: event_page_idle_time_ must be sufficiently larger (e.g. 2x) than
+ // kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals.
event_page_idle_time_ = base::TimeDelta::FromSeconds(10);
unsigned idle_time_msec = 0;
if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
@@ -246,8 +261,11 @@ ExtensionHost* ProcessManager::CreateBackgroundHost(const Extension* extension,
const GURL& url) {
// Hosted apps are taken care of from BackgroundContentsService. Ignore them
// here.
- if (extension->is_hosted_app())
+ if (extension->is_hosted_app() ||
+ !ExtensionsBrowserClient::Get()->
+ IsBackgroundPageAllowed(GetBrowserContext())) {
return NULL;
+ }
// Don't create multiple background hosts for an extension.
if (ExtensionHost* host = GetBackgroundHostForExtension(extension->id()))
@@ -296,12 +314,12 @@ const Extension* ProcessManager::GetExtensionForRenderViewHost(
if (!render_view_host->GetSiteInstance())
return NULL;
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
- GetBrowserContext())->extension_service();
- if (!service)
+ ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext());
+ if (!registry)
return NULL;
- return service->extensions()->GetByID(GetExtensionID(render_view_host));
+ return registry->enabled_extensions().GetByID(
+ GetExtensionID(render_view_host));
}
void ProcessManager::UnregisterRenderViewHost(
@@ -325,11 +343,11 @@ void ProcessManager::UnregisterRenderViewHost(
}
}
-void ProcessManager::RegisterRenderViewHost(RenderViewHost* render_view_host) {
+bool ProcessManager::RegisterRenderViewHost(RenderViewHost* render_view_host) {
const Extension* extension = GetExtensionForRenderViewHost(
render_view_host);
if (!extension)
- return;
+ return false;
WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
all_extension_views_[render_view_host] = GetViewType(web_contents);
@@ -338,6 +356,7 @@ void ProcessManager::RegisterRenderViewHost(RenderViewHost* render_view_host) {
// extension views are visible. Keepalive count balanced in
// UnregisterRenderViewHost.
IncrementLazyKeepaliveCountForView(render_view_host);
+ return true;
}
SiteInstance* ProcessManager::GetSiteInstanceForURL(const GURL& url) {
@@ -419,6 +438,12 @@ void ProcessManager::KeepaliveImpulse(const Extension* extension) {
IncrementLazyKeepaliveCount(extension);
}
}
+
+ if (!keepalive_impulse_callback_for_testing_.is_null()) {
+ ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly =
+ keepalive_impulse_callback_for_testing_;
+ callback_may_clear_callbacks_reentrantly.Run(extension->id());
+ }
}
// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse
@@ -431,8 +456,14 @@ void ProcessManager::OnKeepaliveImpulseCheck() {
for (BackgroundPageDataMap::iterator i = background_page_data_.begin();
i != background_page_data_.end();
++i) {
- if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse)
+ if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) {
DecrementLazyKeepaliveCount(i->first);
+ if (!keepalive_impulse_decrement_callback_for_testing_.is_null()) {
+ ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly =
+ keepalive_impulse_decrement_callback_for_testing_;
+ callback_may_clear_callbacks_reentrantly.Run(i->first);
+ }
+ }
i->second.previous_keepalive_impulse = i->second.keepalive_impulse;
i->second.keepalive_impulse = false;
@@ -505,17 +536,19 @@ void ProcessManager::CloseLazyBackgroundPageNow(const std::string& extension_id,
}
}
-void ProcessManager::OnNetworkRequestStarted(RenderViewHost* render_view_host) {
+void ProcessManager::OnNetworkRequestStarted(
+ content::RenderFrameHost* render_frame_host) {
ExtensionHost* host = GetBackgroundHostForExtension(
- GetExtensionID(render_view_host));
- if (host && host->render_view_host() == render_view_host)
+ GetExtensionIDFromFrame(render_frame_host));
+ if (host && IsFrameInExtensionHost(host, render_frame_host))
IncrementLazyKeepaliveCount(host->extension());
}
-void ProcessManager::OnNetworkRequestDone(RenderViewHost* render_view_host) {
+void ProcessManager::OnNetworkRequestDone(
+ content::RenderFrameHost* render_frame_host) {
ExtensionHost* host = GetBackgroundHostForExtension(
- GetExtensionID(render_view_host));
- if (host && host->render_view_host() == render_view_host)
+ GetExtensionIDFromFrame(render_frame_host));
+ if (host && IsFrameInExtensionHost(host, render_frame_host))
DecrementLazyKeepaliveCount(host->extension());
}
@@ -536,7 +569,7 @@ void ProcessManager::CancelSuspend(const Extension* extension) {
}
void ProcessManager::OnBrowserWindowReady() {
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
+ ExtensionService* service = ExtensionSystem::Get(
GetBrowserContext())->extension_service();
// On Chrome OS, a login screen is implemented as a browser.
// This browser has no extension service. In this case,
@@ -551,6 +584,16 @@ content::BrowserContext* ProcessManager::GetBrowserContext() const {
return site_instance_->GetBrowserContext();
}
+void ProcessManager::SetKeepaliveImpulseCallbackForTesting(
+ const ImpulseCallbackForTesting& callback) {
+ keepalive_impulse_callback_for_testing_ = callback;
+}
+
+void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting(
+ const ImpulseCallbackForTesting& callback) {
+ keepalive_impulse_decrement_callback_for_testing_ = callback;
+}
+
void ProcessManager::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
@@ -569,9 +612,9 @@ void ProcessManager::Observe(int type,
case chrome::NOTIFICATION_EXTENSION_LOADED: {
BrowserContext* context = content::Source<BrowserContext>(source).ptr();
- ExtensionService* service =
- ExtensionSystem::GetForBrowserContext(context)->extension_service();
- if (service->is_ready()) {
+ ExtensionSystem* system = ExtensionSystem::Get(context);
+ if (system->ready().is_signaled()) {
+ // The extension system is ready, so create the background host.
const Extension* extension =
content::Details<const Extension>(details).ptr();
CreateBackgroundHostForExtensionLoad(this, extension);
@@ -630,8 +673,9 @@ void ProcessManager::Observe(int type,
// The above will unregister a RVH when it gets swapped out with a new
// one. However we need to watch the WebContents to know when a RVH is
// deleted because the WebContents has gone away.
- RenderViewHostDestructionObserver::CreateForWebContents(contents);
- RegisterRenderViewHost(switched_details->second);
+ if (RegisterRenderViewHost(switched_details->second)) {
+ RenderViewHostDestructionObserver::CreateForWebContents(contents);
+ }
break;
}
@@ -691,14 +735,17 @@ void ProcessManager::OnDevToolsStateChanged(
}
void ProcessManager::CreateBackgroundHostsForProfileStartup() {
- if (startup_background_hosts_created_)
+ if (startup_background_hosts_created_ ||
+ !ExtensionsBrowserClient::Get()->
+ IsBackgroundPageAllowed(GetBrowserContext())) {
return;
+ }
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
- GetBrowserContext())->extension_service();
- DCHECK(service);
- for (ExtensionSet::const_iterator extension = service->extensions()->begin();
- extension != service->extensions()->end(); ++extension) {
+ const ExtensionSet& enabled_extensions =
+ ExtensionRegistry::Get(GetBrowserContext())->enabled_extensions();
+ for (ExtensionSet::const_iterator extension = enabled_extensions.begin();
+ extension != enabled_extensions.end();
+ ++extension) {
CreateBackgroundHostForExtensionLoad(this, extension->get());
RuntimeEventRouter::DispatchOnStartupEvent(GetBrowserContext(),
@@ -806,8 +853,8 @@ IncognitoProcessManager::IncognitoProcessManager(
BrowserContext* incognito_context,
BrowserContext* original_context)
: ProcessManager(incognito_context, original_context),
- original_manager_(ExtensionSystem::GetForBrowserContext(
- original_context)->process_manager()) {
+ original_manager_(
+ ExtensionSystem::Get(original_context)->process_manager()) {
DCHECK(incognito_context->IsOffTheRecord());
// The original profile will have its own ProcessManager to
@@ -823,7 +870,8 @@ IncognitoProcessManager::IncognitoProcessManager(
ExtensionHost* IncognitoProcessManager::CreateBackgroundHost(
const Extension* extension, const GURL& url) {
if (IncognitoInfo::IsSplitMode(extension)) {
- if (IsIncognitoEnabled(extension))
+ if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled(
+ extension->id(), GetBrowserContext()))
return ProcessManager::CreateBackgroundHost(extension, url);
} else {
// Do nothing. If an extension is spanning, then its original-profile
@@ -833,11 +881,10 @@ ExtensionHost* IncognitoProcessManager::CreateBackgroundHost(
}
SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
- GetBrowserContext())->extension_service();
- if (service) {
+ ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext());
+ if (registry) {
const Extension* extension =
- service->extensions()->GetExtensionOrAppByURL(url);
+ registry->enabled_extensions().GetExtensionOrAppByURL(url);
if (extension && !IncognitoInfo::IsSplitMode(extension)) {
return original_manager_->GetSiteInstanceForURL(url);
}
@@ -845,11 +892,4 @@ SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
return ProcessManager::GetSiteInstanceForURL(url);
}
-bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) {
- // Keep in sync with duplicate in extension_info_map.cc.
- ExtensionService* service = ExtensionSystem::GetForBrowserContext(
- GetBrowserContext())->extension_service();
- return extension_util::IsIncognitoEnabled(extension->id(), service);
-}
-
} // namespace extensions
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h
index fa5f2b6502..1059db3028 100644
--- a/extensions/browser/process_manager.h
+++ b/extensions/browser/process_manager.h
@@ -24,6 +24,7 @@ namespace content {
class BrowserContext;
class DevToolsAgentHost;
class RenderViewHost;
+class RenderFrameHost;
class SiteInstance;
};
@@ -104,10 +105,10 @@ class ProcessManager : public content::NotificationObserver {
// Same as above, for the Suspend message.
void OnSuspendAck(const std::string& extension_id);
- // Tracks network requests for a given RenderViewHost, used to know
+ // Tracks network requests for a given RenderFrameHost, used to know
// when network activity is idle for lazy background pages.
- void OnNetworkRequestStarted(content::RenderViewHost* render_view_host);
- void OnNetworkRequestDone(content::RenderViewHost* render_view_host);
+ void OnNetworkRequestStarted(content::RenderFrameHost* render_frame_host);
+ void OnNetworkRequestDone(content::RenderFrameHost* render_frame_host);
// Prevents |extension|'s background page from being closed and sends the
// onSuspendCanceled() event to it.
@@ -120,6 +121,14 @@ class ProcessManager : public content::NotificationObserver {
// related SiteInstances.
content::BrowserContext* GetBrowserContext() const;
+ // Sets callbacks for testing keepalive impulse behavior.
+ typedef base::Callback<void(const std::string& extension_id)>
+ ImpulseCallbackForTesting;
+ void SetKeepaliveImpulseCallbackForTesting(
+ const ImpulseCallbackForTesting& callback);
+ void SetKeepaliveImpulseDecrementCallbackForTesting(
+ const ImpulseCallbackForTesting& callback);
+
protected:
// If |context| is incognito pass the master context as |original_context|.
// Otherwise pass the same context for both.
@@ -181,7 +190,9 @@ class ProcessManager : public content::NotificationObserver {
// Potentially registers a RenderViewHost, if it is associated with an
// extension. Does nothing if this is not an extension renderer.
- void RegisterRenderViewHost(content::RenderViewHost* render_view_host);
+ // Returns true, if render_view_host was registered (it is associated
+ // with an extension).
+ bool RegisterRenderViewHost(content::RenderViewHost* render_view_host);
// Unregister RenderViewHosts and clear background page data for an extension
// which has been unloaded.
@@ -215,6 +226,9 @@ class ProcessManager : public content::NotificationObserver {
base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_;
+ ImpulseCallbackForTesting keepalive_impulse_callback_for_testing_;
+ ImpulseCallbackForTesting keepalive_impulse_decrement_callback_for_testing_;
+
base::WeakPtrFactory<ProcessManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ProcessManager);
diff --git a/extensions/browser/process_map.cc b/extensions/browser/process_map.cc
index 899940e045..3651f8af52 100644
--- a/extensions/browser/process_map.cc
+++ b/extensions/browser/process_map.cc
@@ -4,6 +4,8 @@
#include "extensions/browser/process_map.h"
+#include "extensions/browser/process_map_factory.h"
+
namespace extensions {
// Item
@@ -60,6 +62,11 @@ ProcessMap::ProcessMap() {
ProcessMap::~ProcessMap() {
}
+// static
+ProcessMap* ProcessMap::Get(content::BrowserContext* browser_context) {
+ return ProcessMapFactory::GetForBrowserContext(browser_context);
+}
+
bool ProcessMap::Insert(const std::string& extension_id, int process_id,
int site_instance_id) {
return items_.insert(Item(extension_id, process_id, site_instance_id)).second;
@@ -112,4 +119,4 @@ std::set<std::string> ProcessMap::GetExtensionsInProcess(int process_id) const {
return result;
}
-} // extensions
+} // namespace extensions
diff --git a/extensions/browser/process_map.h b/extensions/browser/process_map.h
index 780b21a587..0310651d09 100644
--- a/extensions/browser/process_map.h
+++ b/extensions/browser/process_map.h
@@ -9,6 +9,11 @@
#include <string>
#include "base/basictypes.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+
+namespace content {
+class BrowserContext;
+}
namespace extensions {
@@ -61,10 +66,14 @@ namespace extensions {
// RenderProcessHost::FromID() and check the profile of the resulting object.
//
// TODO(aa): The above warnings suggest this class could use improvement :).
-class ProcessMap {
+class ProcessMap : public BrowserContextKeyedService {
public:
ProcessMap();
- ~ProcessMap();
+ virtual ~ProcessMap();
+
+ // Returns the instance for |browser_context|. An instance is shared between
+ // an incognito and a regular context.
+ static ProcessMap* Get(content::BrowserContext* browser_context);
size_t size() const { return items_.size(); }
@@ -89,6 +98,6 @@ class ProcessMap {
DISALLOW_COPY_AND_ASSIGN(ProcessMap);
};
-} // extensions
+} // namespace extensions
#endif // EXTENSIONS_BROWSER_PROCESS_MAP_H_
diff --git a/extensions/browser/process_map_factory.cc b/extensions/browser/process_map_factory.cc
new file mode 100644
index 0000000000..1351f22636
--- /dev/null
+++ b/extensions/browser/process_map_factory.cc
@@ -0,0 +1,46 @@
+// Copyright 2014 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/process_map_factory.h"
+
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/process_map.h"
+
+using content::BrowserContext;
+
+namespace extensions {
+
+// static
+ProcessMap* ProcessMapFactory::GetForBrowserContext(BrowserContext* context) {
+ return static_cast<ProcessMap*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+ProcessMapFactory* ProcessMapFactory::GetInstance() {
+ return Singleton<ProcessMapFactory>::get();
+}
+
+ProcessMapFactory::ProcessMapFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ProcessMap",
+ BrowserContextDependencyManager::GetInstance()) {
+ // No dependencies on other services.
+}
+
+ProcessMapFactory::~ProcessMapFactory() {}
+
+BrowserContextKeyedService* ProcessMapFactory::BuildServiceInstanceFor(
+ BrowserContext* context) const {
+ return new ProcessMap;
+}
+
+BrowserContext* ProcessMapFactory::GetBrowserContextToUse(
+ BrowserContext* context) const {
+ // Redirected in incognito.
+ return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
+}
+
+} // namespace extensions
diff --git a/extensions/browser/process_map_factory.h b/extensions/browser/process_map_factory.h
new file mode 100644
index 0000000000..0a62dc75e2
--- /dev/null
+++ b/extensions/browser/process_map_factory.h
@@ -0,0 +1,42 @@
+// Copyright 2014 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_PROCESS_MAP_FACTORY_H_
+#define EXTENSIONS_BROWSER_PROCESS_MAP_FACTORY_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+namespace extensions {
+
+class ProcessMap;
+
+// Factory for ProcessMap objects. ProcessMap objects are shared between an
+// incognito browser context and its master browser context.
+class ProcessMapFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static ProcessMap* GetForBrowserContext(content::BrowserContext* context);
+
+ static ProcessMapFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<ProcessMapFactory>;
+
+ ProcessMapFactory();
+ virtual ~ProcessMapFactory();
+
+ // BrowserContextKeyedServiceFactory implementation:
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProcessMapFactory);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_PROCESS_MAP_FACTORY_H_
diff --git a/extensions/browser/quota_service.h b/extensions/browser/quota_service.h
index 8dacb959d1..7479c5535b 100644
--- a/extensions/browser/quota_service.h
+++ b/extensions/browser/quota_service.h
@@ -37,9 +37,10 @@ typedef std::list<QuotaLimitHeuristic*> QuotaLimitHeuristics;
// The QuotaService takes care that calls to certain extension
// functions do not exceed predefined quotas.
//
-// The QuotaService needs to live entirely on one thread, i.e.
-// be created, called and destroyed on the same thread, due to its use
-// of a RepeatingTimer.
+// The QuotaService needs to live entirely on one thread, i.e. be created,
+// called and destroyed on the same thread, due to its use of a RepeatingTimer.
+// It is not a BrowserContextKeyedService because instances exist on both the UI
+// and IO threads.
class QuotaService : public base::NonThreadSafe {
public:
// Some concrete heuristics (declared below) that ExtensionFunctions can
diff --git a/extensions/browser/renderer_startup_helper.cc b/extensions/browser/renderer_startup_helper.cc
new file mode 100644
index 0000000000..ab278aca9e
--- /dev/null
+++ b/extensions/browser/renderer_startup_helper.cc
@@ -0,0 +1,127 @@
+// Copyright 2014 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/renderer_startup_helper.h"
+
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/features/feature_channel.h"
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/common/extension_set.h"
+#include "extensions/common/extensions_client.h"
+#include "ui/base/webui/web_ui_util.h"
+
+using content::BrowserContext;
+
+namespace extensions {
+
+RendererStartupHelper::RendererStartupHelper(BrowserContext* browser_context)
+ : browser_context_(browser_context) {
+ DCHECK(browser_context);
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+}
+
+RendererStartupHelper::~RendererStartupHelper() {}
+
+void RendererStartupHelper::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
+ content::RenderProcessHost* process =
+ content::Source<content::RenderProcessHost>(source).ptr();
+ if (!ExtensionsBrowserClient::Get()->IsSameContext(
+ browser_context_, process->GetBrowserContext()))
+ break;
+
+ // Extensions need to know the channel for API restrictions.
+ process->Send(new ExtensionMsg_SetChannel(
+ extensions::GetCurrentChannel()));
+
+ // Platform apps need to know the system font.
+ scoped_ptr<base::DictionaryValue> fonts(new base::DictionaryValue);
+ webui::SetFontAndTextDirection(fonts.get());
+ std::string font_family, font_size;
+ fonts->GetString("fontfamily", &font_family);
+ fonts->GetString("fontsize", &font_size);
+ process->Send(new ExtensionMsg_SetSystemFont(
+ font_family, font_size));
+
+ // Valid extension function names, used to setup bindings in renderer.
+ std::vector<std::string> function_names;
+ ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names);
+ process->Send(new ExtensionMsg_SetFunctionNames(function_names));
+
+ // Scripting whitelist. This is modified by tests and must be communicated
+ // to renderers.
+ process->Send(new ExtensionMsg_SetScriptingWhitelist(
+ extensions::ExtensionsClient::Get()->GetScriptingWhitelist()));
+
+ // Loaded extensions.
+ std::vector<ExtensionMsg_Loaded_Params> loaded_extensions;
+ const ExtensionSet& extensions =
+ ExtensionRegistry::Get(browser_context_)->enabled_extensions();
+ for (ExtensionSet::const_iterator iter = extensions.begin();
+ iter != extensions.end(); ++iter) {
+ // Renderers don't need to know about themes.
+ if (!(*iter)->is_theme())
+ loaded_extensions.push_back(ExtensionMsg_Loaded_Params(iter->get()));
+ }
+ process->Send(new ExtensionMsg_Loaded(loaded_extensions));
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// static
+RendererStartupHelper* RendererStartupHelperFactory::GetForBrowserContext(
+ BrowserContext* context) {
+ return static_cast<RendererStartupHelper*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+RendererStartupHelperFactory* RendererStartupHelperFactory::GetInstance() {
+ return Singleton<RendererStartupHelperFactory>::get();
+}
+
+RendererStartupHelperFactory::RendererStartupHelperFactory()
+ : BrowserContextKeyedServiceFactory(
+ "RendererStartupHelper",
+ BrowserContextDependencyManager::GetInstance()) {
+ // No dependencies on other services.
+}
+
+RendererStartupHelperFactory::~RendererStartupHelperFactory() {}
+
+BrowserContextKeyedService*
+RendererStartupHelperFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new RendererStartupHelper(context);
+}
+
+BrowserContext* RendererStartupHelperFactory::GetBrowserContextToUse(
+ BrowserContext* context) const {
+ // Redirected in incognito.
+ return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
+}
+
+bool RendererStartupHelperFactory::ServiceIsCreatedWithBrowserContext() const {
+ return true;
+}
+
+} // namespace extensions
diff --git a/extensions/browser/renderer_startup_helper.h b/extensions/browser/renderer_startup_helper.h
new file mode 100644
index 0000000000..7fcc70f66a
--- /dev/null
+++ b/extensions/browser/renderer_startup_helper.h
@@ -0,0 +1,74 @@
+// Copyright 2014 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_RENDER_PROCESS_HELPER_H_
+#define EXTENSIONS_BROWSER_RENDER_PROCESS_HELPER_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace content {
+class BrowserContext;
+class RenderProcessHost;
+}
+
+namespace extensions {
+
+// Informs renderers about extensions-related data (channel, available
+// functions, etc.) when they start. Sends this information to both extension
+// and non-extension renderers, as the non-extension renderers may have content
+// scripts. Lives on the UI thread. Shared between incognito and non-incognito
+// browser contexts.
+class RendererStartupHelper : public BrowserContextKeyedService,
+ public content::NotificationObserver {
+ public:
+ // This class sends messages to all renderers started for |browser_context|.
+ explicit RendererStartupHelper(content::BrowserContext* browser_context);
+ virtual ~RendererStartupHelper();
+
+ // content::NotificationObserver overrides:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ content::BrowserContext* browser_context_; // Not owned.
+
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererStartupHelper);
+};
+
+// Factory for RendererStartupHelpers. Declared here because this header is
+// rarely included and it's probably cheaper to put it here than to make the
+// compiler generate another object file.
+class RendererStartupHelperFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static RendererStartupHelper* GetForBrowserContext(
+ content::BrowserContext* context);
+ static RendererStartupHelperFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<RendererStartupHelperFactory>;
+
+ RendererStartupHelperFactory();
+ virtual ~RendererStartupHelperFactory();
+
+ // BrowserContextKeyedServiceFactory implementation:
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* profile) const OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const OVERRIDE;
+ virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererStartupHelperFactory);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_RENDER_PROCESS_HELPER_H_
diff --git a/extensions/browser/runtime_data.cc b/extensions/browser/runtime_data.cc
new file mode 100644
index 0000000000..a3b1c6c4e1
--- /dev/null
+++ b/extensions/browser/runtime_data.cc
@@ -0,0 +1,76 @@
+// Copyright 2014 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/runtime_data.h"
+
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest_handlers/background_info.h"
+
+namespace extensions {
+
+RuntimeData::RuntimeData(ExtensionRegistry* registry) : registry_(registry) {
+ registry_->AddObserver(this);
+}
+
+RuntimeData::~RuntimeData() {
+ registry_->RemoveObserver(this);
+}
+
+bool RuntimeData::IsBackgroundPageReady(const Extension* extension) const {
+ if (!BackgroundInfo::HasPersistentBackgroundPage(extension))
+ return true;
+ return HasFlag(extension, BACKGROUND_PAGE_READY);
+}
+
+void RuntimeData::SetBackgroundPageReady(const Extension* extension,
+ bool value) {
+ SetFlag(extension, BACKGROUND_PAGE_READY, value);
+}
+
+bool RuntimeData::IsBeingUpgraded(const Extension* extension) const {
+ return HasFlag(extension, BEING_UPGRADED);
+}
+
+void RuntimeData::SetBeingUpgraded(const Extension* extension, bool value) {
+ SetFlag(extension, BEING_UPGRADED, value);
+}
+
+bool RuntimeData::HasUsedWebRequest(const Extension* extension) const {
+ return HasFlag(extension, HAS_USED_WEBREQUEST);
+}
+
+void RuntimeData::SetHasUsedWebRequest(const Extension* extension, bool value) {
+ SetFlag(extension, HAS_USED_WEBREQUEST, value);
+}
+
+bool RuntimeData::HasExtensionForTesting(const Extension* extension) const {
+ return extension_flags_.find(extension->id()) != extension_flags_.end();
+}
+
+void RuntimeData::ClearAll() {
+ extension_flags_.clear();
+}
+
+void RuntimeData::OnExtensionUnloaded(const Extension* extension) {
+ extension_flags_.erase(extension->id());
+}
+
+bool RuntimeData::HasFlag(const Extension* extension, RuntimeFlag flag) const {
+ ExtensionFlagsMap::const_iterator it = extension_flags_.find(extension->id());
+ if (it == extension_flags_.end())
+ return false;
+ return !!(it->second & flag);
+}
+
+void RuntimeData::SetFlag(const Extension* extension,
+ RuntimeFlag flag,
+ bool value) {
+ if (value)
+ extension_flags_[extension->id()] |= flag;
+ else
+ extension_flags_[extension->id()] &= ~flag;
+}
+
+} // namespace extensions
diff --git a/extensions/browser/runtime_data.h b/extensions/browser/runtime_data.h
new file mode 100644
index 0000000000..1b4980016a
--- /dev/null
+++ b/extensions/browser/runtime_data.h
@@ -0,0 +1,84 @@
+// Copyright 2014 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_RUNTIME_DATA_H_
+#define EXTENSIONS_BROWSER_RUNTIME_DATA_H_
+
+#include <map>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "extensions/browser/extension_registry_observer.h"
+
+namespace extensions {
+
+class Extension;
+class ExtensionRegistry;
+
+// Contains per-extension data that can change during the life of the process,
+// but does not persist across restarts. Shared between incognito and regular
+// browser contexts. Lives on the UI thread. Must be destroyed before
+// ExtensionRegistry.
+class RuntimeData : public ExtensionRegistryObserver {
+ public:
+ // Observes |registry| to clean itself up when extensions change state.
+ // |registry| must not be NULL.
+ explicit RuntimeData(ExtensionRegistry* registry);
+ virtual ~RuntimeData();
+
+ // Whether the persistent background page, if any, is ready. We don't load
+ // other components until then. If there is no background page, or if it is
+ // non-persistent (lazy), we consider it to be ready.
+ bool IsBackgroundPageReady(const Extension* extension) const;
+ void SetBackgroundPageReady(const Extension* extension, bool value);
+
+ // Getter and setter for the flag that specifies whether the extension is
+ // being upgraded.
+ bool IsBeingUpgraded(const Extension* extension) const;
+ void SetBeingUpgraded(const Extension* extension, bool value);
+
+ // Getter and setter for the flag that specifies if the extension has used
+ // the webrequest API.
+ // TODO(mpcomplete): remove. http://crbug.com/100411
+ bool HasUsedWebRequest(const Extension* extension) const;
+ void SetHasUsedWebRequest(const Extension* extension, bool value);
+
+ // Returns true if the extension is being tracked. Used only for testing.
+ bool HasExtensionForTesting(const Extension* extension) const;
+
+ // Erase runtime data for all extensions. Used only for testing. Cannot be
+ // named ClearAllForTesting due to false-positive presubmit errors.
+ void ClearAll();
+
+ // ExtensionRegistryObserver overrides. Public for testing.
+ virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE;
+
+ private:
+ // Bitmasks for runtime states.
+ enum RuntimeFlag {
+ // Set if the background page is ready.
+ BACKGROUND_PAGE_READY = 1 << 0,
+ // Set while the extension is being upgraded.
+ BEING_UPGRADED = 1 << 1,
+ // Set if the extension has used the webRequest API.
+ HAS_USED_WEBREQUEST = 1 << 2,
+ };
+
+ // Returns the setting for the flag or false if the extension isn't found.
+ bool HasFlag(const Extension* extension, RuntimeFlag flag) const;
+
+ // Sets |flag| for |extension| to |value|. Adds |extension| to the list of
+ // extensions if it isn't present.
+ void SetFlag(const Extension* extension, RuntimeFlag flag, bool value);
+
+ // Map from extension ID to the RuntimeFlags bits.
+ typedef std::map<std::string, int> ExtensionFlagsMap;
+ ExtensionFlagsMap extension_flags_;
+
+ ExtensionRegistry* registry_; // Not owned.
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_RUNTIME_DATA_H_
diff --git a/extensions/browser/runtime_data_unittest.cc b/extensions/browser/runtime_data_unittest.cc
new file mode 100644
index 0000000000..207f8aa9e0
--- /dev/null
+++ b/extensions/browser/runtime_data_unittest.cc
@@ -0,0 +1,108 @@
+// Copyright 2014 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/runtime_data.h"
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/value_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+namespace {
+
+// Creates a very simple extension.
+scoped_refptr<Extension> CreateExtension() {
+ return ExtensionBuilder()
+ .SetManifest(
+ DictionaryBuilder().Set("name", "test").Set("version", "0.1"))
+ .SetID("id1")
+ .Build();
+}
+
+// Creates a very simple extension with a background page.
+scoped_refptr<Extension> CreateExtensionWithBackgroundPage() {
+ return ExtensionBuilder()
+ .SetManifest(
+ DictionaryBuilder()
+ .Set("name", "test")
+ .Set("version", "0.1")
+ .Set("background", DictionaryBuilder().Set("page", "bg.html")))
+ .SetID("id2")
+ .Build();
+}
+
+class RuntimeDataTest : public testing::Test {
+ public:
+ RuntimeDataTest() : runtime_data_(&registry_) {}
+ virtual ~RuntimeDataTest() {}
+
+ protected:
+ ExtensionRegistry registry_;
+ RuntimeData runtime_data_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RuntimeDataTest);
+};
+
+TEST_F(RuntimeDataTest, IsBackgroundPageReady) {
+ // An extension without a background page is always considered ready.
+ scoped_refptr<Extension> no_background = CreateExtension();
+ EXPECT_TRUE(runtime_data_.IsBackgroundPageReady(no_background));
+
+ // An extension with a background page is not ready until the flag is set.
+ scoped_refptr<Extension> with_background =
+ CreateExtensionWithBackgroundPage();
+ EXPECT_FALSE(runtime_data_.IsBackgroundPageReady(with_background));
+
+ // The flag can be toggled.
+ runtime_data_.SetBackgroundPageReady(with_background, true);
+ EXPECT_TRUE(runtime_data_.IsBackgroundPageReady(with_background));
+ runtime_data_.SetBackgroundPageReady(with_background, false);
+ EXPECT_FALSE(runtime_data_.IsBackgroundPageReady(with_background));
+}
+
+TEST_F(RuntimeDataTest, IsBeingUpgraded) {
+ scoped_refptr<Extension> extension = CreateExtension();
+
+ // An extension is not being upgraded until the flag is set.
+ EXPECT_FALSE(runtime_data_.IsBeingUpgraded(extension));
+
+ // The flag can be toggled.
+ runtime_data_.SetBeingUpgraded(extension, true);
+ EXPECT_TRUE(runtime_data_.IsBeingUpgraded(extension));
+ runtime_data_.SetBeingUpgraded(extension, false);
+ EXPECT_FALSE(runtime_data_.IsBeingUpgraded(extension));
+}
+
+// TODO(mpcomplete): Remove. http://crbug.com/100411
+TEST_F(RuntimeDataTest, HasUsedWebRequest) {
+ scoped_refptr<Extension> extension = CreateExtension();
+
+ // An extension has not used web request until the flag is set.
+ EXPECT_FALSE(runtime_data_.HasUsedWebRequest(extension));
+
+ // The flag can be toggled.
+ runtime_data_.SetHasUsedWebRequest(extension, true);
+ EXPECT_TRUE(runtime_data_.HasUsedWebRequest(extension));
+ runtime_data_.SetHasUsedWebRequest(extension, false);
+ EXPECT_FALSE(runtime_data_.HasUsedWebRequest(extension));
+}
+
+// Unloading an extension stops tracking it.
+TEST_F(RuntimeDataTest, OnExtensionUnloaded) {
+ scoped_refptr<Extension> extension = CreateExtensionWithBackgroundPage();
+ runtime_data_.SetBackgroundPageReady(extension, true);
+ ASSERT_TRUE(runtime_data_.HasExtensionForTesting(extension));
+
+ runtime_data_.OnExtensionUnloaded(extension);
+ EXPECT_FALSE(runtime_data_.HasExtensionForTesting(extension));
+}
+
+} // namespace
+} // namespace extensions
diff --git a/extensions/browser/test_management_policy.cc b/extensions/browser/test_management_policy.cc
index a2c5404dd4..77ec19132f 100644
--- a/extensions/browser/test_management_policy.cc
+++ b/extensions/browser/test_management_policy.cc
@@ -14,13 +14,13 @@ TestManagementPolicyProvider::TestManagementPolicyProvider()
must_remain_enabled_(false),
must_remain_disabled_(false),
disable_reason_(Extension::DISABLE_NONE) {
- error_message_ = UTF8ToUTF16(expected_error());
+ error_message_ = base::UTF8ToUTF16(expected_error());
}
TestManagementPolicyProvider::TestManagementPolicyProvider(
int prohibited_actions) {
SetProhibitedActions(prohibited_actions);
- error_message_ = UTF8ToUTF16(expected_error());
+ error_message_ = base::UTF8ToUTF16(expected_error());
}
void TestManagementPolicyProvider::SetProhibitedActions(
@@ -41,21 +41,22 @@ std::string TestManagementPolicyProvider::GetDebugPolicyProviderName() const {
}
bool TestManagementPolicyProvider::UserMayLoad(const Extension* extension,
- string16* error) const {
+ base::string16* error) const {
if (error && !may_load_)
*error = error_message_;
return may_load_;
}
bool TestManagementPolicyProvider::UserMayModifySettings(
- const Extension* extension, string16* error) const {
+ const Extension* extension, base::string16* error) const {
if (error && !may_modify_status_)
*error = error_message_;
return may_modify_status_;
}
bool TestManagementPolicyProvider::MustRemainEnabled(const Extension* extension,
- string16* error) const {
+ base::string16* error)
+ const {
if (error && must_remain_enabled_)
*error = error_message_;
return must_remain_enabled_;
@@ -64,7 +65,7 @@ bool TestManagementPolicyProvider::MustRemainEnabled(const Extension* extension,
bool TestManagementPolicyProvider::MustRemainDisabled(
const Extension* extension,
Extension::DisableReason* reason,
- string16* error) const {
+ base::string16* error) const {
if (must_remain_disabled_) {
if (error)
*error = error_message_;
diff --git a/extensions/browser/test_management_policy.h b/extensions/browser/test_management_policy.h
index f59e015890..a96cde9df9 100644
--- a/extensions/browser/test_management_policy.h
+++ b/extensions/browser/test_management_policy.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/strings/string16.h"
-#include "chrome/browser/extensions/extension_service.h"
#include "extensions/browser/management_policy.h"
namespace extensions {
@@ -38,17 +37,17 @@ class TestManagementPolicyProvider : public ManagementPolicy::Provider {
virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
virtual bool UserMayLoad(const Extension* extension,
- string16* error) const OVERRIDE;
+ base::string16* error) const OVERRIDE;
virtual bool UserMayModifySettings(const Extension* extension,
- string16* error) const OVERRIDE;
+ base::string16* error) const OVERRIDE;
virtual bool MustRemainEnabled(const Extension* extension,
- string16* error) const OVERRIDE;
+ base::string16* error) const OVERRIDE;
virtual bool MustRemainDisabled(const Extension* extension,
Extension::DisableReason* reason,
- string16* error) const OVERRIDE;
+ base::string16* error) const OVERRIDE;
private:
bool may_load_;
@@ -57,7 +56,7 @@ class TestManagementPolicyProvider : public ManagementPolicy::Provider {
bool must_remain_disabled_;
Extension::DisableReason disable_reason_;
- string16 error_message_;
+ base::string16 error_message_;
};
} // namespace extensions
diff --git a/extensions/common/common_manifest_handlers.cc b/extensions/common/common_manifest_handlers.cc
new file mode 100644
index 0000000000..2dc14f2598
--- /dev/null
+++ b/extensions/common/common_manifest_handlers.cc
@@ -0,0 +1,34 @@
+// Copyright 2014 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/common_manifest_handlers.h"
+
+#include "extensions/common/manifest_handler.h"
+#include "extensions/common/manifest_handlers/background_info.h"
+#include "extensions/common/manifest_handlers/csp_info.h"
+#include "extensions/common/manifest_handlers/incognito_info.h"
+#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
+#include "extensions/common/manifest_handlers/offline_enabled_info.h"
+#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
+#include "extensions/common/manifest_handlers/shared_module_info.h"
+#include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
+#include "extensions/common/manifest_handlers/webview_info.h"
+
+namespace extensions {
+
+void RegisterCommonManifestHandlers() {
+ DCHECK(!ManifestHandler::IsRegistrationFinalized());
+ (new BackgroundManifestHandler)->Register();
+ (new CSPHandler(false))->Register();
+ (new CSPHandler(true))->Register();
+ (new IncognitoHandler)->Register();
+ (new KioskModeHandler)->Register();
+ (new OfflineEnabledHandler)->Register();
+ (new SandboxedPageHandler)->Register();
+ (new SharedModuleHandler)->Register();
+ (new WebAccessibleResourcesHandler)->Register();
+ (new WebviewHandler)->Register();
+}
+
+} // namespace extensions
diff --git a/extensions/common/common_manifest_handlers.h b/extensions/common/common_manifest_handlers.h
new file mode 100644
index 0000000000..4f1d7cc8f6
--- /dev/null
+++ b/extensions/common/common_manifest_handlers.h
@@ -0,0 +1,17 @@
+// Copyright 2014 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_COMMON_MANIFEST_HANDLERS_H_
+#define EXTENSIONS_COMMON_COMMON_MANIFEST_HANDLERS_H_
+
+namespace extensions {
+
+// Registers manifest handlers used by all embedders of the extensions system.
+// Should be called once in each process. Embedders may also wish to register
+// their own set of manifest handlers, such as chrome_manifest_handlers.cc.
+void RegisterCommonManifestHandlers();
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_COMMON_MANIFEST_HANDLERS_H_
diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc
index a332d7003b..dced3101be 100644
--- a/extensions/common/constants.cc
+++ b/extensions/common/constants.cc
@@ -9,6 +9,7 @@
namespace extensions {
const char kExtensionScheme[] = "chrome-extension";
+const char kExtensionResourceScheme[] = "chrome-extension-resource";
const base::FilePath::CharType kManifestFilename[] =
FILE_PATH_LITERAL("manifest.json");
diff --git a/extensions/common/constants.h b/extensions/common/constants.h
index 3113a17e9f..f55e5177b0 100644
--- a/extensions/common/constants.h
+++ b/extensions/common/constants.h
@@ -12,6 +12,9 @@ namespace extensions {
// Scheme we serve extension content from.
extern const char kExtensionScheme[];
+// Canonical schemes you can use as input to GURL.SchemeIs().
+extern const char kExtensionResourceScheme[];
+
// The name of the manifest inside an extension.
extern const base::FilePath::CharType kManifestFilename[];
diff --git a/extensions/common/error_utils.cc b/extensions/common/error_utils.cc
index bd4d32e0d2..2343c04bf7 100644
--- a/extensions/common/error_utils.cc
+++ b/extensions/common/error_utils.cc
@@ -36,31 +36,22 @@ std::string ErrorUtils::FormatErrorMessage(const std::string& format,
return ret_val;
}
-string16 ErrorUtils::FormatErrorMessageUTF16(const std::string& format,
- const std::string& s1) {
- std::string ret_val = format;
- ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1);
- return UTF8ToUTF16(ret_val);
+base::string16 ErrorUtils::FormatErrorMessageUTF16(const std::string& format,
+ const std::string& s1) {
+ return base::UTF8ToUTF16(FormatErrorMessage(format, s1));
}
-string16 ErrorUtils::FormatErrorMessageUTF16(const std::string& format,
- const std::string& s1,
- const std::string& s2) {
- std::string ret_val = format;
- ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1);
- ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s2);
- return UTF8ToUTF16(ret_val);
+base::string16 ErrorUtils::FormatErrorMessageUTF16(const std::string& format,
+ const std::string& s1,
+ const std::string& s2) {
+ return base::UTF8ToUTF16(FormatErrorMessage(format, s1, s2));
}
-string16 ErrorUtils::FormatErrorMessageUTF16(const std::string& format,
- const std::string& s1,
- const std::string& s2,
- const std::string& s3) {
- std::string ret_val = format;
- ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1);
- ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s2);
- ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s3);
- return UTF8ToUTF16(ret_val);
+base::string16 ErrorUtils::FormatErrorMessageUTF16(const std::string& format,
+ const std::string& s1,
+ const std::string& s2,
+ const std::string& s3) {
+ return base::UTF8ToUTF16(FormatErrorMessage(format, s1, s2, s3));
}
-} // namespace
+} // namespace extensions
diff --git a/extensions/common/error_utils.h b/extensions/common/error_utils.h
index c4d012ae2c..fedbd2887b 100644
--- a/extensions/common/error_utils.h
+++ b/extensions/common/error_utils.h
@@ -26,17 +26,17 @@ class ErrorUtils {
const std::string& s2,
const std::string& s3);
- static string16 FormatErrorMessageUTF16(const std::string& format,
- const std::string& s1);
+ static base::string16 FormatErrorMessageUTF16(const std::string& format,
+ const std::string& s1);
- static string16 FormatErrorMessageUTF16(const std::string& format,
- const std::string& s1,
- const std::string& s2);
+ static base::string16 FormatErrorMessageUTF16(const std::string& format,
+ const std::string& s1,
+ const std::string& s2);
- static string16 FormatErrorMessageUTF16(const std::string& format,
- const std::string& s1,
- const std::string& s2,
- const std::string& s3);
+ static base::string16 FormatErrorMessageUTF16(const std::string& format,
+ const std::string& s1,
+ const std::string& s2,
+ const std::string& s3);
};
} // namespace extensions
diff --git a/extensions/common/event_filter.cc b/extensions/common/event_filter.cc
index 70915b976d..ad954c9510 100644
--- a/extensions/common/event_filter.cc
+++ b/extensions/common/event_filter.cc
@@ -4,9 +4,13 @@
#include "extensions/common/event_filter.h"
-#include "extensions/common/matcher/url_matcher_factory.h"
+#include "components/url_matcher/url_matcher_factory.h"
#include "ipc/ipc_message.h"
+using url_matcher::URLMatcher;
+using url_matcher::URLMatcherConditionSet;
+using url_matcher::URLMatcherFactory;
+
namespace extensions {
EventFilter::EventMatcherEntry::EventMatcherEntry(
diff --git a/extensions/common/event_filter.h b/extensions/common/event_filter.h
index 6ef136cb9d..ddd0681fc8 100644
--- a/extensions/common/event_filter.h
+++ b/extensions/common/event_filter.h
@@ -9,9 +9,9 @@
#include <set>
#include "base/memory/linked_ptr.h"
+#include "components/url_matcher/url_matcher.h"
#include "extensions/common/event_filtering_info.h"
#include "extensions/common/event_matcher.h"
-#include "extensions/common/matcher/url_matcher.h"
namespace extensions {
@@ -61,9 +61,10 @@ class EventFilter {
// again on destruction. |condition_sets| should be the
// URLMatcherConditionSets that match the URL constraints specified by
// |event_matcher|.
- EventMatcherEntry(scoped_ptr<EventMatcher> event_matcher,
- URLMatcher* url_matcher,
- const URLMatcherConditionSet::Vector& condition_sets);
+ EventMatcherEntry(
+ scoped_ptr<EventMatcher> event_matcher,
+ url_matcher::URLMatcher* url_matcher,
+ const url_matcher::URLMatcherConditionSet::Vector& condition_sets);
~EventMatcherEntry();
// Prevents the removal of condition sets when this class is destroyed. We
@@ -79,8 +80,8 @@ class EventFilter {
private:
scoped_ptr<EventMatcher> event_matcher_;
// The id sets in url_matcher_ that this EventMatcher owns.
- std::vector<URLMatcherConditionSet::ID> condition_set_ids_;
- URLMatcher* url_matcher_;
+ std::vector<url_matcher::URLMatcherConditionSet::ID> condition_set_ids_;
+ url_matcher::URLMatcher* url_matcher_;
DISALLOW_COPY_AND_ASSIGN(EventMatcherEntry);
};
@@ -93,27 +94,28 @@ class EventFilter {
// Adds the list of URL filters in |matcher| to the URL matcher, having
// matches for those URLs map to |id|.
- bool CreateConditionSets(MatcherID id,
- EventMatcher* matcher,
- URLMatcherConditionSet::Vector* condition_sets);
+ bool CreateConditionSets(
+ MatcherID id,
+ EventMatcher* matcher,
+ url_matcher::URLMatcherConditionSet::Vector* condition_sets);
bool AddDictionaryAsConditionSet(
base::DictionaryValue* url_filter,
- URLMatcherConditionSet::Vector* condition_sets);
+ url_matcher::URLMatcherConditionSet::Vector* condition_sets);
- URLMatcher url_matcher_;
+ url_matcher::URLMatcher url_matcher_;
EventMatcherMultiMap event_matchers_;
// The next id to assign to an EventMatcher.
MatcherID next_id_;
// The next id to assign to a condition set passed to URLMatcher.
- URLMatcherConditionSet::ID next_condition_set_id_;
+ url_matcher::URLMatcherConditionSet::ID next_condition_set_id_;
// Maps condition set ids, which URLMatcher operates in, to event matcher
// ids, which the interface to this class operates in. As each EventFilter
// can specify many condition sets this is a many to one relationship.
- std::map<URLMatcherConditionSet::ID, MatcherID>
+ std::map<url_matcher::URLMatcherConditionSet::ID, MatcherID>
condition_set_id_to_event_matcher_id_;
// Maps from event matcher ids to the name of the event they match on.
diff --git a/extensions/common/event_filter_unittest.cc b/extensions/common/event_filter_unittest.cc
index 3f7f12b050..f95c023b67 100644
--- a/extensions/common/event_filter_unittest.cc
+++ b/extensions/common/event_filter_unittest.cc
@@ -10,6 +10,10 @@
#include "ipc/ipc_message.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::DictionaryValue;
+using base::ListValue;
+using base::Value;
+
namespace extensions {
class EventFilterUnittest : public testing::Test {
diff --git a/extensions/common/event_filtering_info.cc b/extensions/common/event_filtering_info.cc
index cc46f96916..877f2c5cab 100644
--- a/extensions/common/event_filtering_info.cc
+++ b/extensions/common/event_filtering_info.cc
@@ -46,7 +46,7 @@ scoped_ptr<base::Value> EventFilteringInfo::AsValue() const {
}
bool EventFilteringInfo::IsEmpty() const {
- return !has_url_ && service_type_.empty();
+ return !has_url_ && service_type_.empty() && !has_instance_id_;
}
} // namespace extensions
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc
index 0a67983d3a..df6ea04a61 100644
--- a/extensions/common/extension.cc
+++ b/extensions/common/extension.cc
@@ -34,7 +34,6 @@
#include "extensions/common/switches.h"
#include "extensions/common/url_pattern_set.h"
#include "grit/chromium_strings.h"
-#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "url/url_util.h"
@@ -51,7 +50,7 @@ namespace errors = manifest_errors;
namespace {
const int kModernManifestVersion = 2;
-const int kPEMOutputColumns = 65;
+const int kPEMOutputColumns = 64;
// KEY MARKERS
const char kKeyBeginHeaderMarker[] = "-----BEGIN";
@@ -103,7 +102,7 @@ scoped_refptr<Extension> Extension::Create(const base::FilePath& path,
}
// TODO(sungguk): Continue removing std::string errors and replacing
-// with string16. See http://crbug.com/71980.
+// with base::string16. See http://crbug.com/71980.
scoped_refptr<Extension> Extension::Create(const base::FilePath& path,
Manifest::Location location,
const base::DictionaryValue& value,
@@ -111,13 +110,13 @@ scoped_refptr<Extension> Extension::Create(const base::FilePath& path,
const std::string& explicit_id,
std::string* utf8_error) {
DCHECK(utf8_error);
- string16 error;
+ base::string16 error;
scoped_ptr<extensions::Manifest> manifest(
new extensions::Manifest(
location, scoped_ptr<base::DictionaryValue>(value.DeepCopy())));
if (!InitExtensionID(manifest.get(), path, explicit_id, flags, &error)) {
- *utf8_error = UTF16ToUTF8(error);
+ *utf8_error = base::UTF16ToUTF8(error);
return NULL;
}
@@ -130,7 +129,7 @@ scoped_refptr<Extension> Extension::Create(const base::FilePath& path,
extension->install_warnings_.swap(install_warnings);
if (!extension->InitFromValue(flags, &error)) {
- *utf8_error = UTF16ToUTF8(error);
+ *utf8_error = base::UTF16ToUTF8(error);
return NULL;
}
@@ -307,7 +306,8 @@ bool Extension::ShowConfigureContextMenus() const {
// options for component extension button but now there is no component
// extension with options. All other menu items like uninstall have
// no sense for component extensions.
- return location() != Manifest::COMPONENT;
+ return location() != Manifest::COMPONENT &&
+ location() != Manifest::EXTERNAL_COMPONENT;
}
bool Extension::OverlapsWithOrigin(const GURL& origin) const {
@@ -371,8 +371,7 @@ bool Extension::ShouldDisplayInExtensionSettings() const {
bool Extension::ShouldNotBeVisible() const {
// Don't show component extensions because they are only extensions as an
// implementation detail of Chrome.
- if ((location() == Manifest::COMPONENT ||
- location() == Manifest::EXTERNAL_COMPONENT) &&
+ if (extensions::Manifest::IsComponentLocation(location()) &&
!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kShowComponentExtensionOptions)) {
return true;
@@ -456,6 +455,10 @@ bool Extension::force_incognito_enabled() const {
}
void Extension::AddWebExtentPattern(const URLPattern& pattern) {
+ // Bookmark apps are permissionless.
+ if (from_bookmark())
+ return;
+
extent_.AddPattern(pattern);
}
@@ -468,7 +471,7 @@ bool Extension::InitExtensionID(extensions::Manifest* manifest,
const base::FilePath& path,
const std::string& explicit_id,
int creation_flags,
- string16* error) {
+ base::string16* error) {
if (!explicit_id.empty()) {
manifest->set_extension_id(explicit_id);
return true;
@@ -479,7 +482,7 @@ bool Extension::InitExtensionID(extensions::Manifest* manifest,
std::string public_key_bytes;
if (!manifest->GetString(keys::kPublicKey, &public_key) ||
!ParsePEMKeyBytes(public_key, &public_key_bytes)) {
- *error = ASCIIToUTF16(errors::kInvalidKey);
+ *error = base::ASCIIToUTF16(errors::kInvalidKey);
return false;
}
std::string extension_id = id_util::GenerateId(public_key_bytes);
@@ -488,7 +491,7 @@ bool Extension::InitExtensionID(extensions::Manifest* manifest,
}
if (creation_flags & REQUIRE_KEY) {
- *error = ASCIIToUTF16(errors::kInvalidKey);
+ *error = base::ASCIIToUTF16(errors::kInvalidKey);
return false;
} else {
// If there is a path, we generate the ID from it. This is useful for
@@ -521,7 +524,7 @@ Extension::Extension(const base::FilePath& path,
Extension::~Extension() {
}
-bool Extension::InitFromValue(int flags, string16* error) {
+bool Extension::InitFromValue(int flags, base::string16* error) {
DCHECK(error);
creation_flags_ = flags;
@@ -565,53 +568,53 @@ bool Extension::InitFromValue(int flags, string16* error) {
return true;
}
-bool Extension::LoadRequiredFeatures(string16* error) {
+bool Extension::LoadRequiredFeatures(base::string16* error) {
if (!LoadName(error) ||
!LoadVersion(error))
return false;
return true;
}
-bool Extension::LoadName(string16* error) {
- string16 localized_name;
+bool Extension::LoadName(base::string16* error) {
+ base::string16 localized_name;
if (!manifest_->GetString(keys::kName, &localized_name)) {
- *error = ASCIIToUTF16(errors::kInvalidName);
+ *error = base::ASCIIToUTF16(errors::kInvalidName);
return false;
}
- non_localized_name_ = UTF16ToUTF8(localized_name);
+ non_localized_name_ = base::UTF16ToUTF8(localized_name);
base::i18n::AdjustStringForLocaleDirection(&localized_name);
- name_ = UTF16ToUTF8(localized_name);
+ name_ = base::UTF16ToUTF8(localized_name);
return true;
}
-bool Extension::LoadVersion(string16* error) {
+bool Extension::LoadVersion(base::string16* error) {
std::string version_str;
if (!manifest_->GetString(keys::kVersion, &version_str)) {
- *error = ASCIIToUTF16(errors::kInvalidVersion);
+ *error = base::ASCIIToUTF16(errors::kInvalidVersion);
return false;
}
version_.reset(new Version(version_str));
if (!version_->IsValid() || version_->components().size() > 4) {
- *error = ASCIIToUTF16(errors::kInvalidVersion);
+ *error = base::ASCIIToUTF16(errors::kInvalidVersion);
return false;
}
return true;
}
-bool Extension::LoadAppFeatures(string16* error) {
+bool Extension::LoadAppFeatures(base::string16* error) {
if (!LoadExtent(keys::kWebURLs, &extent_,
errors::kInvalidWebURLs, errors::kInvalidWebURL, error)) {
return false;
}
if (manifest_->HasKey(keys::kDisplayInLauncher) &&
!manifest_->GetBoolean(keys::kDisplayInLauncher, &display_in_launcher_)) {
- *error = ASCIIToUTF16(errors::kInvalidDisplayInLauncher);
+ *error = base::ASCIIToUTF16(errors::kInvalidDisplayInLauncher);
return false;
}
if (manifest_->HasKey(keys::kDisplayInNewTabPage)) {
if (!manifest_->GetBoolean(keys::kDisplayInNewTabPage,
&display_in_new_tab_page_)) {
- *error = ASCIIToUTF16(errors::kInvalidDisplayInNewTabPage);
+ *error = base::ASCIIToUTF16(errors::kInvalidDisplayInNewTabPage);
return false;
}
} else {
@@ -625,14 +628,14 @@ bool Extension::LoadExtent(const char* key,
URLPatternSet* extent,
const char* list_error,
const char* value_error,
- string16* error) {
+ base::string16* error) {
const base::Value* temp_pattern_value = NULL;
if (!manifest_->Get(key, &temp_pattern_value))
return true;
const base::ListValue* pattern_list = NULL;
if (!temp_pattern_value->GetAsList(&pattern_list)) {
- *error = ASCIIToUTF16(list_error);
+ *error = base::ASCIIToUTF16(list_error);
return false;
}
@@ -695,7 +698,7 @@ bool Extension::LoadExtent(const char* key,
return true;
}
-bool Extension::LoadSharedFeatures(string16* error) {
+bool Extension::LoadSharedFeatures(base::string16* error) {
if (!LoadDescription(error) ||
!ManifestHandler::ParseExtension(this, error) ||
!LoadShortName(error))
@@ -704,23 +707,23 @@ bool Extension::LoadSharedFeatures(string16* error) {
return true;
}
-bool Extension::LoadDescription(string16* error) {
+bool Extension::LoadDescription(base::string16* error) {
if (manifest_->HasKey(keys::kDescription) &&
!manifest_->GetString(keys::kDescription, &description_)) {
- *error = ASCIIToUTF16(errors::kInvalidDescription);
+ *error = base::ASCIIToUTF16(errors::kInvalidDescription);
return false;
}
return true;
}
-bool Extension::LoadManifestVersion(string16* error) {
+bool Extension::LoadManifestVersion(base::string16* error) {
// Get the original value out of the dictionary so that we can validate it
// more strictly.
if (manifest_->value()->HasKey(keys::kManifestVersion)) {
int manifest_version = 1;
if (!manifest_->GetInteger(keys::kManifestVersion, &manifest_version) ||
manifest_version < 1) {
- *error = ASCIIToUTF16(errors::kInvalidManifestVersion);
+ *error = base::ASCIIToUTF16(errors::kInvalidManifestVersion);
return false;
}
}
@@ -741,17 +744,17 @@ bool Extension::LoadManifestVersion(string16* error) {
return true;
}
-bool Extension::LoadShortName(string16* error) {
+bool Extension::LoadShortName(base::string16* error) {
if (manifest_->HasKey(keys::kShortName)) {
- string16 localized_short_name;
+ base::string16 localized_short_name;
if (!manifest_->GetString(keys::kShortName, &localized_short_name) ||
localized_short_name.empty()) {
- *error = ASCIIToUTF16(errors::kInvalidShortName);
+ *error = base::ASCIIToUTF16(errors::kInvalidShortName);
return false;
}
base::i18n::AdjustStringForLocaleDirection(&localized_short_name);
- short_name_ = UTF16ToUTF8(localized_short_name);
+ short_name_ = base::UTF16ToUTF8(localized_short_name);
} else {
short_name_ = name_;
}
diff --git a/extensions/common/extension.h b/extensions/common/extension.h
index 4da7a03625..4ea11b4db8 100644
--- a/extensions/common/extension.h
+++ b/extensions/common/extension.h
@@ -90,9 +90,9 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
DISABLE_UNKNOWN_FROM_SYNC = 1 << 5,
DISABLE_PERMISSIONS_CONSENT = 1 << 6, // Unused - abandoned experiment.
DISABLE_KNOWN_DISABLED = 1 << 7,
-
- // Disabled because we could not verify the install.
- DISABLE_NOT_VERIFIED = 1 << 8,
+ DISABLE_NOT_VERIFIED = 1 << 8, // Disabled because we could not verify
+ // the install.
+ DISABLE_GREYLIST = 1 << 9
};
enum InstallType {
@@ -133,8 +133,9 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Chrome Web Store.
FROM_WEBSTORE = 1 << 3,
- // |FROM_BOOKMARK| indicates the extension was created using a mock App
- // created from a bookmark.
+ // |FROM_BOOKMARK| indicates the extension is a bookmark app which has been
+ // generated from a web page. Bookmark apps have no permissions or extent
+ // and launch the web page they are created from when run.
FROM_BOOKMARK = 1 << 4,
// |FOLLOW_SYMLINKS_ANYWHERE| means that resources can be symlinks to
@@ -341,7 +342,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
const base::FilePath& path,
const std::string& explicit_id,
int creation_flags,
- string16* error);
+ base::string16* error);
Extension(const base::FilePath& path,
scoped_ptr<extensions::Manifest> manifest);
@@ -353,28 +354,28 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// of the underlying DictionaryValue in its members. We should decide to
// either wrap the DictionaryValue and go with that only, or we should parse
// into strong types and discard the value. But doing both is bad.
- bool InitFromValue(int flags, string16* error);
+ bool InitFromValue(int flags, base::string16* error);
// The following are helpers for InitFromValue to load various features of the
// extension from the manifest.
- bool LoadRequiredFeatures(string16* error);
- bool LoadName(string16* error);
- bool LoadVersion(string16* error);
+ bool LoadRequiredFeatures(base::string16* error);
+ bool LoadName(base::string16* error);
+ bool LoadVersion(base::string16* error);
- bool LoadAppFeatures(string16* error);
+ bool LoadAppFeatures(base::string16* error);
bool LoadExtent(const char* key,
URLPatternSet* extent,
const char* list_error,
const char* value_error,
- string16* error);
+ base::string16* error);
- bool LoadSharedFeatures(string16* error);
- bool LoadDescription(string16* error);
- bool LoadManifestVersion(string16* error);
- bool LoadShortName(string16* error);
+ bool LoadSharedFeatures(base::string16* error);
+ bool LoadDescription(base::string16* error);
+ bool LoadManifestVersion(base::string16* error);
+ bool LoadShortName(base::string16* error);
- bool CheckMinimumChromeVersion(string16* error) const;
+ bool CheckMinimumChromeVersion(base::string16* error) const;
// The extension's human-readable name. Name is used for display purpose. It
// might be wrapped with unicode bidi control characters so that it is
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc
index dd68ffd09e..8e27f2b036 100644
--- a/extensions/common/extension_api.cc
+++ b/extensions/common/extension_api.cc
@@ -241,8 +241,6 @@ void ExtensionAPI::InitDefaultConfiguration() {
RegisterSchemaResource("runtime", IDR_EXTENSION_API_JSON_RUNTIME);
RegisterSchemaResource("fileBrowserHandler",
IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER);
- RegisterSchemaResource("fileBrowserPrivate",
- IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE);
RegisterSchemaResource("inputMethodPrivate",
IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE);
RegisterSchemaResource("pageAction", IDR_EXTENSION_API_JSON_PAGEACTION);
@@ -251,8 +249,6 @@ void ExtensionAPI::InitDefaultConfiguration() {
RegisterSchemaResource("processes", IDR_EXTENSION_API_JSON_PROCESSES);
RegisterSchemaResource("proxy", IDR_EXTENSION_API_JSON_PROXY);
RegisterSchemaResource("scriptBadge", IDR_EXTENSION_API_JSON_SCRIPTBADGE);
- RegisterSchemaResource("streamsPrivate",
- IDR_EXTENSION_API_JSON_STREAMSPRIVATE);
RegisterSchemaResource("ttsEngine", IDR_EXTENSION_API_JSON_TTSENGINE);
RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS);
RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES);
@@ -278,26 +274,25 @@ void ExtensionAPI::RegisterDependencyProvider(const std::string& name,
dependency_providers_[name] = provider;
}
-bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name,
+bool ExtensionAPI::IsAnyFeatureAvailableToContext(const Feature& api,
const Extension* extension,
Feature::Context context,
const GURL& url) {
FeatureProviderMap::iterator provider = dependency_providers_.find("api");
CHECK(provider != dependency_providers_.end());
- const std::vector<std::string>& features =
- provider->second->GetAllFeatureNames();
+ if (IsAvailable(api, extension, context, url).is_available())
+ return true;
// Check to see if there are any parts of this API that are allowed in this
// context.
- for (std::vector<std::string>::const_iterator i = features.begin();
- i != features.end(); ++i) {
- const std::string& feature_name = *i;
- if (feature_name != api_name && feature_name.find(api_name + ".") == 0) {
- if (IsAvailable(feature_name, extension, context, url).is_available())
- return true;
- }
+ const std::vector<Feature*> features = provider->second->GetChildren(api);
+ for (std::vector<Feature*>::const_iterator feature = features.begin();
+ feature != features.end();
+ ++feature) {
+ if (IsAvailable(**feature, extension, context, url).is_available())
+ return true;
}
- return IsAvailable(api_name, extension, context, url).is_available();
+ return false;
}
Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
@@ -306,14 +301,20 @@ Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
const GURL& url) {
Feature* feature = GetFeatureDependency(full_name);
CHECK(feature) << full_name;
+ return IsAvailable(*feature, extension, context, url);
+}
+Feature::Availability ExtensionAPI::IsAvailable(const Feature& feature,
+ const Extension* extension,
+ Feature::Context context,
+ const GURL& url) {
Feature::Availability availability =
- feature->IsAvailableToContext(extension, context, url);
+ feature.IsAvailableToContext(extension, context, url);
if (!availability.is_available())
return availability;
- for (std::set<std::string>::iterator iter = feature->dependencies().begin();
- iter != feature->dependencies().end(); ++iter) {
+ for (std::set<std::string>::iterator iter = feature.dependencies().begin();
+ iter != feature.dependencies().end(); ++iter) {
Feature::Availability dependency_availability =
IsAvailable(*iter, extension, context, url);
if (!dependency_availability.is_available())
diff --git a/extensions/common/extension_api.h b/extensions/common/extension_api.h
index 31ac97c1e8..1b2ad3edd2 100644
--- a/extensions/common/extension_api.h
+++ b/extensions/common/extension_api.h
@@ -65,10 +65,19 @@ class ExtensionAPI {
void RegisterDependencyProvider(const std::string& name,
FeatureProvider* provider);
- // Returns true if the specified API is available. |api_full_name| can be
- // either a namespace name (like "bookmarks") or a member name (like
- // "bookmarks.create"). Returns true if the feature and all of its
- // dependencies are available to the specified context.
+ // Returns true if the API feature |api| and all of its dependencies are
+ // available in |context|.
+ //
+ // Depending on the configuration of |api| (in _api_features.json), either
+ // |extension| or |url| (or both) may determine its availability, but this is
+ // up to the configuration of the individual feature.
+ Feature::Availability IsAvailable(const Feature& api,
+ const Extension* extension,
+ Feature::Context context,
+ const GURL& url);
+ // Same as the previous overload, but takes a feature name instead of an
+ // object. |api_full_name| can be either a namespace name (like "bookmarks")
+ // or a member name (like "bookmarks.create").
Feature::Availability IsAvailable(const std::string& api_full_name,
const Extension* extension,
Feature::Context context,
@@ -76,7 +85,7 @@ class ExtensionAPI {
// Determines whether an API, or any parts of that API, are available in
// |context|.
- bool IsAnyFeatureAvailableToContext(const std::string& api_name,
+ bool IsAnyFeatureAvailableToContext(const Feature& api,
const Extension* extension,
Feature::Context context,
const GURL& url);
diff --git a/extensions/common/extension_api_stub.cc b/extensions/common/extension_api_stub.cc
index e323436f32..0a2468ae78 100644
--- a/extensions/common/extension_api_stub.cc
+++ b/extensions/common/extension_api_stub.cc
@@ -29,7 +29,15 @@ Feature::Availability ExtensionAPI::IsAvailable(
return Feature::CreateAvailability(Feature::NOT_PRESENT, "");
}
-bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name,
+Feature::Availability ExtensionAPI::IsAvailable(
+ const Feature& api,
+ const Extension* extension,
+ Feature::Context context,
+ const GURL& url) {
+ return Feature::CreateAvailability(Feature::NOT_PRESENT, "");
+}
+
+bool ExtensionAPI::IsAnyFeatureAvailableToContext(const Feature& api,
const Extension* extension,
Feature::Context context,
const GURL& url) {
diff --git a/extensions/common/extension_set.cc b/extensions/common/extension_set.cc
new file mode 100644
index 0000000000..77d4491e96
--- /dev/null
+++ b/extensions/common/extension_set.cc
@@ -0,0 +1,150 @@
+// 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/extension_set.h"
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
+
+namespace extensions {
+
+ExtensionSet::const_iterator::const_iterator() {}
+
+ExtensionSet::const_iterator::const_iterator(const const_iterator& other)
+ : it_(other.it_) {
+}
+
+ExtensionSet::const_iterator::const_iterator(ExtensionMap::const_iterator it)
+ : it_(it) {
+}
+
+ExtensionSet::const_iterator::~const_iterator() {}
+
+ExtensionSet::ExtensionSet() {
+}
+
+ExtensionSet::~ExtensionSet() {
+}
+
+size_t ExtensionSet::size() const {
+ return extensions_.size();
+}
+
+bool ExtensionSet::is_empty() const {
+ return extensions_.empty();
+}
+
+bool ExtensionSet::Contains(const std::string& extension_id) const {
+ return extensions_.find(extension_id) != extensions_.end();
+}
+
+bool ExtensionSet::Insert(const scoped_refptr<const Extension>& extension) {
+ bool was_present = ContainsKey(extensions_, extension->id());
+ extensions_[extension->id()] = extension;
+ if (!was_present && !modification_callback_.is_null())
+ modification_callback_.Run(GetIDs());
+ return !was_present;
+}
+
+bool ExtensionSet::InsertAll(const ExtensionSet& extensions) {
+ size_t before = size();
+ for (ExtensionSet::const_iterator iter = extensions.begin();
+ iter != extensions.end(); ++iter) {
+ Insert(*iter);
+ }
+ return size() != before;
+}
+
+bool ExtensionSet::Remove(const std::string& id) {
+ bool was_present = extensions_.erase(id) > 0;
+ if (was_present && !modification_callback_.is_null())
+ modification_callback_.Run(GetIDs());
+ return was_present;
+}
+
+void ExtensionSet::Clear() {
+ extensions_.clear();
+}
+
+std::string ExtensionSet::GetExtensionOrAppIDByURL(const GURL& url) const {
+ if (url.SchemeIs(kExtensionScheme))
+ return url.host();
+
+ const Extension* extension = GetHostedAppByURL(url);
+ if (!extension)
+ return std::string();
+
+ return extension->id();
+}
+
+const Extension* ExtensionSet::GetExtensionOrAppByURL(const GURL& url) const {
+ if (url.SchemeIs(kExtensionScheme))
+ return GetByID(url.host());
+
+ return GetHostedAppByURL(url);
+}
+
+const Extension* ExtensionSet::GetHostedAppByURL(const GURL& url) const {
+ for (ExtensionMap::const_iterator iter = extensions_.begin();
+ iter != extensions_.end(); ++iter) {
+ if (iter->second->web_extent().MatchesURL(url))
+ return iter->second.get();
+ }
+
+ return NULL;
+}
+
+const Extension* ExtensionSet::GetHostedAppByOverlappingWebExtent(
+ const URLPatternSet& extent) const {
+ for (ExtensionMap::const_iterator iter = extensions_.begin();
+ iter != extensions_.end(); ++iter) {
+ if (iter->second->web_extent().OverlapsWith(extent))
+ return iter->second.get();
+ }
+
+ return NULL;
+}
+
+bool ExtensionSet::InSameExtent(const GURL& old_url,
+ const GURL& new_url) const {
+ return GetExtensionOrAppByURL(old_url) ==
+ GetExtensionOrAppByURL(new_url);
+}
+
+const Extension* ExtensionSet::GetByID(const std::string& id) const {
+ ExtensionMap::const_iterator i = extensions_.find(id);
+ if (i != extensions_.end())
+ return i->second.get();
+ else
+ return NULL;
+}
+
+ExtensionIdSet ExtensionSet::GetIDs() const {
+ ExtensionIdSet ids;
+ for (ExtensionMap::const_iterator it = extensions_.begin();
+ it != extensions_.end(); ++it) {
+ ids.insert(it->first);
+ }
+ return ids;
+}
+
+bool ExtensionSet::ExtensionBindingsAllowed(const GURL& url) const {
+ if (url.SchemeIs(kExtensionScheme))
+ return true;
+
+ for (ExtensionMap::const_iterator it = extensions_.begin();
+ it != extensions_.end(); ++it) {
+ if (it->second->location() == Manifest::COMPONENT &&
+ it->second->web_extent().MatchesURL(url))
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace extensions
diff --git a/extensions/common/extension_set.h b/extensions/common/extension_set.h
new file mode 100644
index 0000000000..4ba6530553
--- /dev/null
+++ b/extensions/common/extension_set.h
@@ -0,0 +1,148 @@
+// 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_EXTENSION_SET_H_
+#define EXTENSIONS_COMMON_EXTENSION_SET_H_
+
+#include <iterator>
+#include <map>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "extensions/common/extension.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+// The one true extension container. Extensions are identified by their id.
+// Only one extension can be in the set with a given ID.
+class ExtensionSet {
+ public:
+ typedef std::pair<base::FilePath, std::string> ExtensionPathAndDefaultLocale;
+ typedef std::map<std::string, scoped_refptr<const Extension> > ExtensionMap;
+ typedef base::Callback<void(const ExtensionIdSet&)>
+ ModificationCallback;
+
+ // Iteration over the values of the map (given that it's an ExtensionSet,
+ // it should iterate like a set iterator).
+ class const_iterator : public std::iterator<std::input_iterator_tag,
+ scoped_refptr<const Extension> > {
+ public:
+ const_iterator();
+ const_iterator(const const_iterator& other);
+ explicit const_iterator(ExtensionMap::const_iterator it);
+ ~const_iterator();
+ const_iterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const const_iterator old(*this);
+ ++it_;
+ return old;
+ }
+ const scoped_refptr<const Extension>& operator*() const {
+ return it_->second;
+ }
+ const scoped_refptr<const Extension>* operator->() const {
+ return &it_->second;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return it_ != other.it_;
+ }
+ bool operator==(const const_iterator& other) const {
+ return it_ == other.it_;
+ }
+
+ private:
+ ExtensionMap::const_iterator it_;
+ };
+
+ ExtensionSet();
+ ~ExtensionSet();
+
+ size_t size() const;
+ bool is_empty() const;
+
+ // Iteration support.
+ const_iterator begin() const { return const_iterator(extensions_.begin()); }
+ const_iterator end() const { return const_iterator(extensions_.end()); }
+
+ // Returns true if the set contains the specified extension.
+ bool Contains(const std::string& id) const;
+
+ // Adds the specified extension to the set. The set becomes an owner. Any
+ // previous extension with the same ID is removed.
+ // Returns true if there is no previous extension.
+ bool Insert(const scoped_refptr<const Extension>& extension);
+
+ // Copies different items from |extensions| to the current set and returns
+ // whether anything changed.
+ bool InsertAll(const ExtensionSet& extensions);
+
+ // Removes the specified extension.
+ // Returns true if the set contained the specified extnesion.
+ bool Remove(const std::string& id);
+
+ // Removes all extensions.
+ void Clear();
+
+ // Returns the extension ID, or empty if none. This includes web URLs that
+ // are part of an extension's web extent.
+ std::string GetExtensionOrAppIDByURL(const GURL& url) const;
+
+ // Returns the Extension, or NULL if none. This includes web URLs that are
+ // part of an extension's web extent.
+ // NOTE: This can return NULL if called before UpdateExtensions receives
+ // bulk extension data (e.g. if called from
+ // EventBindings::HandleContextCreated)
+ const Extension* GetExtensionOrAppByURL(const GURL& url) const;
+
+ // Returns the hosted app whose web extent contains the URL.
+ const Extension* GetHostedAppByURL(const GURL& url) const;
+
+ // Returns a hosted app that contains any URL that overlaps with the given
+ // extent, if one exists.
+ const Extension* GetHostedAppByOverlappingWebExtent(
+ const URLPatternSet& extent) const;
+
+ // Returns true if |new_url| is in the extent of the same extension as
+ // |old_url|. Also returns true if neither URL is in an app.
+ bool InSameExtent(const GURL& old_url, const GURL& new_url) const;
+
+ // Look up an Extension object by id.
+ const Extension* GetByID(const std::string& id) const;
+
+ // Gets the IDs of all extensions in the set.
+ ExtensionIdSet GetIDs() const;
+
+ // Returns true if |info| should get extension api bindings and be permitted
+ // to make api calls. Note that this is independent of what extension
+ // permissions the given extension has been granted.
+ bool ExtensionBindingsAllowed(const GURL& url) const;
+
+ void set_modification_callback(
+ const ModificationCallback& modification_callback) {
+ modification_callback_ = modification_callback;
+ }
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(ExtensionSetTest, ExtensionSet);
+
+ ExtensionMap extensions_;
+
+ // If non-null, called with the extension ids in this set after a modification
+ // occurred. This is not called on Clear() which is typically used when
+ // discarding the set (e.g., on shutdown) and we do not want to track that as
+ // a real modification.
+ ModificationCallback modification_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionSet);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_EXTENSION_SET_H_
diff --git a/extensions/common/extension_set_unittest.cc b/extensions/common/extension_set_unittest.cc
new file mode 100644
index 0000000000..75a69de5f1
--- /dev/null
+++ b/extensions/common/extension_set_unittest.cc
@@ -0,0 +1,142 @@
+// 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 "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_set.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+namespace {
+
+scoped_refptr<Extension> CreateTestExtension(const std::string& name,
+ const std::string& launch_url,
+ const std::string& extent) {
+#if defined(OS_WIN)
+ base::FilePath path(FILE_PATH_LITERAL("c:\\"));
+#else
+ base::FilePath path(FILE_PATH_LITERAL("/"));
+#endif
+ path = path.AppendASCII(name);
+
+ base::DictionaryValue manifest;
+ manifest.SetString("name", name);
+ manifest.SetString("version", "1");
+
+ if (!launch_url.empty())
+ manifest.SetString("app.launch.web_url", launch_url);
+
+ if (!extent.empty()) {
+ base::ListValue* urls = new base::ListValue();
+ manifest.Set("app.urls", urls);
+ urls->Append(new base::StringValue(extent));
+ }
+
+ std::string error;
+ scoped_refptr<Extension> extension(
+ Extension::Create(path, Manifest::INTERNAL, manifest,
+ Extension::NO_FLAGS, &error));
+ EXPECT_TRUE(extension.get()) << error;
+ return extension;
+}
+
+} // namespace
+
+TEST(ExtensionSetTest, ExtensionSet) {
+ scoped_refptr<Extension> ext1(CreateTestExtension(
+ "a", "https://chrome.google.com/launch", "https://chrome.google.com/"));
+
+ scoped_refptr<Extension> ext2(CreateTestExtension(
+ "a", "http://code.google.com/p/chromium",
+ "http://code.google.com/p/chromium/"));
+
+ scoped_refptr<Extension> ext3(CreateTestExtension(
+ "b", "http://dev.chromium.org/", "http://dev.chromium.org/"));
+
+ scoped_refptr<Extension> ext4(
+ CreateTestExtension("c", std::string(), std::string()));
+
+ ASSERT_TRUE(ext1.get() && ext2.get() && ext3.get() && ext4.get());
+
+ ExtensionSet extensions;
+
+ // Add an extension.
+ EXPECT_TRUE(extensions.Insert(ext1));
+ EXPECT_EQ(1u, extensions.size());
+ EXPECT_EQ(ext1, extensions.GetByID(ext1->id()));
+
+ // Since extension2 has same ID, it should overwrite extension1.
+ EXPECT_FALSE(extensions.Insert(ext2));
+ EXPECT_EQ(1u, extensions.size());
+ EXPECT_EQ(ext2, extensions.GetByID(ext1->id()));
+
+ // Add the other extensions.
+ EXPECT_TRUE(extensions.Insert(ext3));
+ EXPECT_TRUE(extensions.Insert(ext4));
+ EXPECT_EQ(3u, extensions.size());
+
+ // Get extension by its chrome-extension:// URL
+ EXPECT_EQ(ext2, extensions.GetExtensionOrAppByURL(
+ ext2->GetResourceURL("test.html")));
+ EXPECT_EQ(ext3, extensions.GetExtensionOrAppByURL(
+ ext3->GetResourceURL("test.html")));
+ EXPECT_EQ(ext4, extensions.GetExtensionOrAppByURL(
+ ext4->GetResourceURL("test.html")));
+
+ // Get extension by web extent.
+ EXPECT_EQ(ext2, extensions.GetExtensionOrAppByURL(
+ GURL("http://code.google.com/p/chromium/monkey")));
+ EXPECT_EQ(ext3, extensions.GetExtensionOrAppByURL(
+ GURL("http://dev.chromium.org/design-docs/")));
+ EXPECT_FALSE(extensions.GetExtensionOrAppByURL(
+ GURL("http://blog.chromium.org/")));
+
+ // Test InSameExtent().
+ EXPECT_TRUE(extensions.InSameExtent(
+ GURL("http://code.google.com/p/chromium/monkey/"),
+ GURL("http://code.google.com/p/chromium/")));
+ EXPECT_FALSE(extensions.InSameExtent(
+ GURL("http://code.google.com/p/chromium/"),
+ GURL("https://code.google.com/p/chromium/")));
+ EXPECT_FALSE(extensions.InSameExtent(
+ GURL("http://code.google.com/p/chromium/"),
+ GURL("http://dev.chromium.org/design-docs/")));
+
+ // Both of these should be NULL, which mean true for InSameExtent.
+ EXPECT_TRUE(extensions.InSameExtent(
+ GURL("http://www.google.com/"),
+ GURL("http://blog.chromium.org/")));
+
+ // Remove one of the extensions.
+ EXPECT_TRUE(extensions.Remove(ext2->id()));
+ EXPECT_EQ(2u, extensions.size());
+ EXPECT_FALSE(extensions.GetByID(ext2->id()));
+
+ // Make a union of a set with 3 more extensions (only 2 are new).
+ scoped_refptr<Extension> ext5(
+ CreateTestExtension("d", std::string(), std::string()));
+ scoped_refptr<Extension> ext6(
+ CreateTestExtension("e", std::string(), std::string()));
+ ASSERT_TRUE(ext5.get() && ext6.get());
+
+ scoped_ptr<ExtensionSet> to_add(new ExtensionSet());
+ // |ext3| is already in |extensions|, should not affect size.
+ EXPECT_TRUE(to_add->Insert(ext3));
+ EXPECT_TRUE(to_add->Insert(ext5));
+ EXPECT_TRUE(to_add->Insert(ext6));
+
+ ASSERT_TRUE(extensions.Contains(ext3->id()));
+ ASSERT_TRUE(extensions.InsertAll(*to_add));
+ EXPECT_EQ(4u, extensions.size());
+
+ ASSERT_FALSE(extensions.InsertAll(*to_add)); // Re-adding same set no-ops.
+ EXPECT_EQ(4u, extensions.size());
+}
+
+} // namespace extensions
diff --git a/extensions/common/extensions_client.cc b/extensions/common/extensions_client.cc
index ccca164a5f..89795b86e4 100644
--- a/extensions/common/extensions_client.cc
+++ b/extensions/common/extensions_client.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/basictypes.h"
+#include "base/logging.h"
#include "extensions/common/extensions_client.h"
namespace extensions {
@@ -14,6 +15,7 @@ ExtensionsClient* g_client = NULL;
} // namespace
ExtensionsClient* ExtensionsClient::Get() {
+ DCHECK(g_client);
return g_client;
}
diff --git a/extensions/common/extensions_client.h b/extensions/common/extensions_client.h
index fb6aba87ac..d309fd7e80 100644
--- a/extensions/common/extensions_client.h
+++ b/extensions/common/extensions_client.h
@@ -28,6 +28,8 @@ class ExtensionsClient {
public:
typedef std::vector<std::string> ScriptingWhitelist;
+ virtual ~ExtensionsClient() {}
+
// Initializes global state. Not done in the constructor because unit tests
// can create additional ExtensionsClients because the utility thread runs
// in-process.
diff --git a/extensions/common/feature_switch.cc b/extensions/common/feature_switch.cc
index 002446196c..1108346b62 100644
--- a/extensions/common/feature_switch.cc
+++ b/extensions/common/feature_switch.cc
@@ -20,15 +20,12 @@ class CommonSwitches {
: easy_off_store_install(
switches::kEasyOffStoreExtensionInstall,
FeatureSwitch::DEFAULT_DISABLED),
+ force_dev_mode_highlighting(
+ switches::kForceDevModeHighlighting,
+ FeatureSwitch::DEFAULT_DISABLED),
global_commands(
switches::kGlobalCommands,
FeatureSwitch::DEFAULT_DISABLED),
- script_badges(
- switches::kScriptBadges,
- FeatureSwitch::DEFAULT_DISABLED),
- script_bubble(
- switches::kScriptBubble,
- FeatureSwitch::DEFAULT_DISABLED),
prompt_for_external_extensions(
switches::kPromptForExternalExtensions,
#if defined(OS_WIN)
@@ -38,14 +35,17 @@ class CommonSwitches {
#endif
error_console(
switches::kErrorConsole,
+ FeatureSwitch::DEFAULT_DISABLED),
+ enable_override_bookmarks_ui(
+ switches::kEnableOverrideBookmarksUI,
FeatureSwitch::DEFAULT_DISABLED) {}
FeatureSwitch easy_off_store_install;
+ FeatureSwitch force_dev_mode_highlighting;
FeatureSwitch global_commands;
- FeatureSwitch script_badges;
- FeatureSwitch script_bubble;
FeatureSwitch prompt_for_external_extensions;
FeatureSwitch error_console;
+ FeatureSwitch enable_override_bookmarks_ui;
};
base::LazyInstance<CommonSwitches> g_common_switches =
@@ -53,24 +53,24 @@ base::LazyInstance<CommonSwitches> g_common_switches =
} // namespace
+FeatureSwitch* FeatureSwitch::force_dev_mode_highlighting() {
+ return &g_common_switches.Get().force_dev_mode_highlighting;
+}
FeatureSwitch* FeatureSwitch::easy_off_store_install() {
return &g_common_switches.Get().easy_off_store_install;
}
FeatureSwitch* FeatureSwitch::global_commands() {
return &g_common_switches.Get().global_commands;
}
-FeatureSwitch* FeatureSwitch::script_badges() {
- return &g_common_switches.Get().script_badges;
-}
-FeatureSwitch* FeatureSwitch::script_bubble() {
- return &g_common_switches.Get().script_bubble;
-}
FeatureSwitch* FeatureSwitch::prompt_for_external_extensions() {
return &g_common_switches.Get().prompt_for_external_extensions;
}
FeatureSwitch* FeatureSwitch::error_console() {
return &g_common_switches.Get().error_console;
}
+FeatureSwitch* FeatureSwitch::enable_override_bookmarks_ui() {
+ return &g_common_switches.Get().enable_override_bookmarks_ui;
+}
FeatureSwitch::ScopedOverride::ScopedOverride(FeatureSwitch* feature,
bool override_value)
diff --git a/extensions/common/feature_switch.h b/extensions/common/feature_switch.h
index ece1b01fd2..bbfd2c7a69 100644
--- a/extensions/common/feature_switch.h
+++ b/extensions/common/feature_switch.h
@@ -18,11 +18,11 @@ namespace extensions {
class FeatureSwitch {
public:
static FeatureSwitch* easy_off_store_install();
+ static FeatureSwitch* force_dev_mode_highlighting();
static FeatureSwitch* global_commands();
- static FeatureSwitch* script_badges();
- static FeatureSwitch* script_bubble();
static FeatureSwitch* prompt_for_external_extensions();
static FeatureSwitch* error_console();
+ static FeatureSwitch* enable_override_bookmarks_ui();
enum DefaultValue {
DEFAULT_ENABLED,
diff --git a/extensions/common/features/feature.h b/extensions/common/features/feature.h
index 0caebf6f1a..67201f07fd 100644
--- a/extensions/common/features/feature.h
+++ b/extensions/common/features/feature.h
@@ -39,6 +39,11 @@ class Feature {
// A normal web page. This should have an associated URL matching pattern.
WEB_PAGE_CONTEXT,
+
+ // A web page context which has been blessed by the user. Typically this
+ // will be via the installation of a hosted app, so this may host an
+ // extension. This is not affected by the URL matching pattern.
+ BLESSED_WEB_PAGE_CONTEXT,
};
// The location required of extensions the feature is supported in.
@@ -101,7 +106,7 @@ class Feature {
const std::string& name() const { return name_; }
void set_name(const std::string& name) { name_ = name; }
- const std::set<std::string>& dependencies() { return dependencies_; }
+ const std::set<std::string>& dependencies() const { return dependencies_; }
bool no_parent() const { return no_parent_; }
// Gets the platform the code is currently running on.
diff --git a/extensions/common/features/feature_provider.h b/extensions/common/features/feature_provider.h
index a295fe0dd2..97f94c65bf 100644
--- a/extensions/common/features/feature_provider.h
+++ b/extensions/common/features/feature_provider.h
@@ -19,13 +19,16 @@ class FeatureProvider {
virtual ~FeatureProvider() {}
// Returns the feature with the specified name.
- virtual Feature* GetFeature(const std::string& name) = 0;
+ virtual Feature* GetFeature(const std::string& name) const = 0;
// Returns the parent feature of |feature|, or NULL if there isn't one.
- virtual Feature* GetParent(Feature* feature) = 0;
+ virtual Feature* GetParent(Feature* feature) const = 0;
- // Returns all features described by this instance.
- virtual const std::vector<std::string>& GetAllFeatureNames() = 0;
+ // Returns the features inside the |parent| namespace, recursively.
+ virtual std::vector<Feature*> GetChildren(const Feature& parent) const = 0;
+
+ // Returns all features described by this instance, in asciibetical order.
+ virtual const std::vector<std::string>& GetAllFeatureNames() const = 0;
// Gets a feature provider for a specific feature type, like "permission".
static FeatureProvider* GetByName(const std::string& name);
diff --git a/extensions/common/manifest.cc b/extensions/common/manifest.cc
index bbd8c32c85..32981a3cf4 100644
--- a/extensions/common/manifest.cc
+++ b/extensions/common/manifest.cc
@@ -207,7 +207,7 @@ bool Manifest::GetString(
}
bool Manifest::GetString(
- const std::string& path, string16* out_value) const {
+ const std::string& path, base::string16* out_value) const {
return CanAccessPath(path) && value_->GetString(path, out_value);
}
diff --git a/extensions/common/manifest.h b/extensions/common/manifest.h
index f7108f88f5..a50e724c57 100644
--- a/extensions/common/manifest.h
+++ b/extensions/common/manifest.h
@@ -96,8 +96,13 @@ class Manifest {
// policy.
static inline bool IsPolicyLocation(Location location) {
return location == EXTERNAL_POLICY ||
- location == EXTERNAL_POLICY_DOWNLOAD ||
- location == EXTERNAL_COMPONENT;
+ location == EXTERNAL_POLICY_DOWNLOAD;
+ }
+
+ // Whether the |location| is an extension intended to be an internal part of
+ // Chrome.
+ static inline bool IsComponentLocation(Location location) {
+ return location == COMPONENT || location == EXTERNAL_COMPONENT;
}
// Unpacked extensions start off with file access since they are a developer
@@ -149,7 +154,7 @@ class Manifest {
bool GetBoolean(const std::string& path, bool* out_value) const;
bool GetInteger(const std::string& path, int* out_value) const;
bool GetString(const std::string& path, std::string* out_value) const;
- bool GetString(const std::string& path, string16* out_value) const;
+ bool GetString(const std::string& path, base::string16* out_value) const;
bool GetDictionary(const std::string& path,
const base::DictionaryValue** out_value) const;
bool GetList(const std::string& path,
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc
index 1f28f94ffd..f7bf1f4bc5 100644
--- a/extensions/common/manifest_constants.cc
+++ b/extensions/common/manifest_constants.cc
@@ -16,6 +16,8 @@ const char kBackgroundPage[] = "background.page";
const char kBackgroundPageLegacy[] = "background_page";
const char kBackgroundPersistent[] = "background.persistent";
const char kBackgroundScripts[] = "background.scripts";
+const char kBluetooth[] = "bluetooth";
+const char kBookmarkUI[] = "chrome_settings_overrides.bookmarks_ui";
const char kBrowserAction[] = "browser_action";
const char kChromeURLOverrides[] = "chrome_url_overrides";
const char kCommands[] = "commands";
@@ -46,9 +48,11 @@ const char kFileHandlerExtensions[] = "extensions";
const char kFileHandlerTitle[] = "title";
const char kFileHandlerTypes[] = "types";
const char kGlobal[] = "global";
+const char kHideBookmarkButton[] = "hide_bookmark_button";
const char kHomepageURL[] = "homepage_url";
const char kIcons[] = "icons";
const char kId[] = "id";
+const char kImeOptionsPage[] = "options_page";
const char kImport[] = "import";
const char kIncognito[] = "incognito";
const char kIncludeGlobs[] = "include_globs";
@@ -106,6 +110,7 @@ const char kPlugins[] = "plugins";
const char kPluginsPath[] = "path";
const char kPluginsPublic[] = "public";
const char kPublicKey[] = "key";
+const char kRemoveButton[] = "remove_button";
const char kResources[] = "resources";
const char kRequirements[] = "requirements";
const char kRunAt[] = "run_at";
@@ -158,7 +163,8 @@ const char kWebAccessibleResources[] = "web_accessible_resources";
const char kWebURLs[] = "app.urls";
const char kWebview[] = "webview";
const char kWebviewAccessibleResources[] = "accessible_resources";
-const char kWebviewPrivilegedPartitions[] = "privileged_partitions";
+const char kWebviewName[] = "name";
+const char kWebviewPartitions[] = "partitions";
} // namespace manifest_keys
@@ -217,6 +223,11 @@ const char kLaunchContainerWindow[] = "window";
// cross-platform.
namespace manifest_errors {
+const char kActiveTabPermissionNotGranted[] =
+ "The 'activeTab' permission is not in effect because this extension has "
+ "not been in invoked.";
+const char kAllURLOrActiveTabNeeded[] =
+ "Either the '<all_urls>' or 'activeTab' permission is required.";
const char kAppsNotEnabled[] =
"Apps are not enabled.";
const char kBackgroundPermissionNeeded[] =
@@ -513,6 +524,8 @@ const char kInvalidPageActionsListSize[] =
"Invalid value for 'page_actions'. There can be at most one page action.";
const char kInvalidPageActionTypeValue[] =
"Invalid value for 'page_actions[*].type', expected 'tab' or 'permanent'.";
+const char kInvalidPermissionWithDetail[] =
+ "Invalid value for 'permissions[*]': *.";
const char kInvalidPermission[] =
"Invalid value for 'permissions[*]'.";
const char kInvalidPermissions[] =
@@ -610,10 +623,12 @@ const char kInvalidWebviewAccessibleResourcesList[] =
"Invalid value for'webview.accessible_resources'.";
const char kInvalidWebviewAccessibleResource[] =
"Invalid value for 'webview.accessible_resources[*]'.";
-const char kInvalidWebviewPrivilegedPartitionList[] =
- "Invalid value for 'webview.privileged_partitions'.";
-const char kInvalidWebviewPrivilegedPartition[] =
- "Invalid value for 'webview.privileged_partitions[*]'.";
+const char kInvalidWebviewPartition[] =
+ "Invalid value for 'webview.partitions[*]'.";
+const char kInvalidWebviewPartitionName[] =
+ "Invalid value for 'webview.partitions[*].name'.";
+const char kInvalidWebviewPartitionsList[] =
+ "Invalid value for 'webview.partitions'.";
const char kInvalidWebURL[] =
"Invalid value for 'app.urls[*]': *";
const char kInvalidWebURLs[] =
@@ -628,6 +643,8 @@ const char kInsecureContentSecurityPolicy[] =
" \"'unsafe-eval'\", \"http://127.0.0.1\", \"http://localhost\", or any"
" \"https://\" or \"chrome-extension://\" origin. For more information,"
" see http://developer.chrome.com/extensions/contentSecurityPolicy.html";
+const char kKeyIsDeprecatedWithReplacement[] =
+ "Key \"*\" is deprecated. Key \"*\" should be used instead.";
const char kLaunchPathAndExtentAreExclusive[] =
"The 'app.launch.local_path' and 'app.urls' keys cannot both be set.";
const char kLaunchPathAndURLAreExclusive[] =
@@ -680,6 +697,8 @@ const char kScriptBadgeTitleIgnored[] =
"default_title specified in script_badge manifest section will not be "
"used.";
const char kUnrecognizedManifestKey[] = "Unrecognized manifest key '*'.";
+const char kUnrecognizedManifestProperty[] =
+ "Unrecognized property '*' of manifest key '*'.";
const char kWebRequestConflictsWithLazyBackground[] =
"The 'webRequest' API cannot be used with event pages.";
#if defined(OS_CHROMEOS)
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h
index f2bdaf3088..a9c39fed2a 100644
--- a/extensions/common/manifest_constants.h
+++ b/extensions/common/manifest_constants.h
@@ -18,6 +18,8 @@ extern const char kBackgroundPage[];
extern const char kBackgroundPageLegacy[];
extern const char kBackgroundPersistent[];
extern const char kBackgroundScripts[];
+extern const char kBluetooth[];
+extern const char kBookmarkUI[];
extern const char kBrowserAction[];
extern const char kBrowseURLs[];
extern const char kChromeURLOverrides[];
@@ -48,9 +50,11 @@ extern const char kFileHandlerTypes[];
extern const char kFileFilters[];
extern const char kFileBrowserHandlers[];
extern const char kGlobal[];
+extern const char kHideBookmarkButton[];
extern const char kHomepageURL[];
extern const char kIcons[];
extern const char kId[];
+extern const char kImeOptionsPage[];
extern const char kImport[];
extern const char kIncognito[];
extern const char kIncludeGlobs[];
@@ -115,6 +119,7 @@ extern const char kPlugins[];
extern const char kPluginsPath[];
extern const char kPluginsPublic[];
extern const char kPublicKey[];
+extern const char kRemoveButton[];
extern const char kResources[];
extern const char kRequirements[];
extern const char kRunAt[];
@@ -165,8 +170,9 @@ extern const char kVersion[];
extern const char kWebAccessibleResources[];
extern const char kWebURLs[];
extern const char kWebview[];
+extern const char kWebviewName[];
extern const char kWebviewAccessibleResources[];
-extern const char kWebviewPrivilegedPartitions[];
+extern const char kWebviewPartitions[];
} // namespace manifest_keys
@@ -218,11 +224,13 @@ extern const char kRunAtDocumentEnd[];
extern const char kRunAtDocumentIdle[];
extern const char kRunAtDocumentStart[];
-} // manifest_values
+} // namespace manifest_values
// Error messages returned from extension installation.
namespace manifest_errors {
+extern const char kActiveTabPermissionNotGranted[];
+extern const char kAllURLOrActiveTabNeeded[];
extern const char kAppsNotEnabled[];
extern const char kBackgroundPermissionNeeded[];
extern const char kBackgroundRequiredForPlatformApps[];
@@ -369,6 +377,7 @@ extern const char kInvalidPageActionPopupPath[];
extern const char kInvalidPageActionsList[];
extern const char kInvalidPageActionsListSize[];
extern const char kInvalidPageActionTypeValue[];
+extern const char kInvalidPermissionWithDetail[];
extern const char kInvalidPermission[];
extern const char kInvalidPermissions[];
extern const char kInvalidPermissionScheme[];
@@ -417,12 +426,14 @@ extern const char kInvalidWebAccessibleResource[];
extern const char kInvalidWebview[];
extern const char kInvalidWebviewAccessibleResourcesList[];
extern const char kInvalidWebviewAccessibleResource[];
-extern const char kInvalidWebviewPrivilegedPartitionList[];
-extern const char kInvalidWebviewPrivilegedPartition[];
+extern const char kInvalidWebviewPartition[];
+extern const char kInvalidWebviewPartitionName[];
+extern const char kInvalidWebviewPartitionsList[];
extern const char kInvalidWebURL[];
extern const char kInvalidWebURLs[];
extern const char kInvalidZipHash[];
extern const char kInsecureContentSecurityPolicy[];
+extern const char kKeyIsDeprecatedWithReplacement[];
extern const char kLaunchPathAndExtentAreExclusive[];
extern const char kLaunchPathAndURLAreExclusive[];
extern const char kLaunchURLRequired[];
@@ -445,6 +456,7 @@ extern const char kPermissionNotAllowedInManifest[];
extern const char kPermissionUnknownOrMalformed[];
extern const char kReservedMessageFound[];
extern const char kUnrecognizedManifestKey[];
+extern const char kUnrecognizedManifestProperty[];
extern const char kScriptBadgeRequiresFlag[];
extern const char kScriptBadgeIconIgnored[];
extern const char kScriptBadgeTitleIgnored[];
diff --git a/extensions/common/manifest_handler.cc b/extensions/common/manifest_handler.cc
index 4546f3283a..ff0495c30b 100644
--- a/extensions/common/manifest_handler.cc
+++ b/extensions/common/manifest_handler.cc
@@ -79,7 +79,8 @@ bool ManifestHandler::IsRegistrationFinalized() {
}
// static
-bool ManifestHandler::ParseExtension(Extension* extension, string16* error) {
+bool ManifestHandler::ParseExtension(Extension* extension,
+ base::string16* error) {
return GetRegistry()->ParseExtension(extension, error);
}
@@ -127,7 +128,7 @@ void ManifestHandlerRegistry::RegisterManifestHandler(
}
bool ManifestHandlerRegistry::ParseExtension(Extension* extension,
- string16* error) {
+ base::string16* error) {
std::map<int, ManifestHandler*> handlers_by_priority;
for (ManifestHandlerMap::iterator iter = handlers_.begin();
iter != handlers_.end(); ++iter) {
diff --git a/extensions/common/manifest_handler.h b/extensions/common/manifest_handler.h
index 90fbe84998..4c7da31eee 100644
--- a/extensions/common/manifest_handler.h
+++ b/extensions/common/manifest_handler.h
@@ -29,7 +29,7 @@ class ManifestHandler {
// Attempts to parse the extension's manifest.
// Returns true on success or false on failure; if false, |error| will
// be set to a failure message.
- virtual bool Parse(Extension* extension, string16* error) = 0;
+ virtual bool Parse(Extension* extension, base::string16* error) = 0;
// Validate that files associated with this manifest key exist.
// Validation takes place after parsing. May also append a series of
@@ -37,7 +37,7 @@ class ManifestHandler {
//
// Otherwise, returns false, and a description of the error is
// returned in |error|.
- // TODO(yoz): Change error to string16. See crbug.com/71980.
+ // TODO(yoz): Change error to base::string16. See crbug.com/71980.
virtual bool Validate(const Extension* extension,
std::string* error,
std::vector<InstallWarning>* warnings) const;
@@ -62,7 +62,7 @@ class ManifestHandler {
// for multiple keys. The global registry takes ownership of this;
// if it has an existing handler for |key|, it replaces it with this.
// Manifest handlers must be registered at process startup in
- // chrome_manifest_handlers.cc:
+ // common_manifest_handlers.cc or chrome_manifest_handlers.cc:
// (new MyManifestHandler)->Register();
void Register();
@@ -87,7 +87,7 @@ class ManifestHandler {
// Call Parse on all registered manifest handlers that should parse
// this extension.
- static bool ParseExtension(Extension* extension, string16* error);
+ static bool ParseExtension(Extension* extension, base::string16* error);
// Call Validate on all registered manifest handlers for this extension.
static bool ValidateExtension(const Extension* extension,
@@ -132,7 +132,7 @@ class ManifestHandlerRegistry {
void RegisterManifestHandler(const std::string& key,
linked_ptr<ManifestHandler> handler);
- bool ParseExtension(Extension* extension, string16* error);
+ bool ParseExtension(Extension* extension, base::string16* error);
bool ValidateExtension(const Extension* extension,
std::string* error,
std::vector<InstallWarning>* warnings);
diff --git a/extensions/common/manifest_handler_unittest.cc b/extensions/common/manifest_handler_unittest.cc
index 9a3a29298b..1da6b408a4 100644
--- a/extensions/common/manifest_handler_unittest.cc
+++ b/extensions/common/manifest_handler_unittest.cc
@@ -83,7 +83,7 @@ class ManifestHandlerTest : public testing::Test {
: name_(name), keys_(keys), prereqs_(prereqs), watcher_(watcher) {
}
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE {
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE {
watcher_->Record(name_);
return true;
}
@@ -111,8 +111,8 @@ class ManifestHandlerTest : public testing::Test {
ParsingWatcher* watcher)
: TestManifestHandler(name, keys, prereqs, watcher) {
}
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE {
- *error = ASCIIToUTF16(name_);
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE {
+ *error = base::ASCIIToUTF16(name_);
return false;
}
};
@@ -141,7 +141,7 @@ class ManifestHandlerTest : public testing::Test {
keys_(keys) {
}
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE {
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE {
return true;
}
diff --git a/extensions/common/manifest_handlers/background_info.cc b/extensions/common/manifest_handlers/background_info.cc
index 1ec404eaea..c7aee9053a 100644
--- a/extensions/common/manifest_handlers/background_info.cc
+++ b/extensions/common/manifest_handlers/background_info.cc
@@ -20,6 +20,7 @@
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
+using base::ASCIIToUTF16;
using base::DictionaryValue;
namespace extensions {
@@ -93,7 +94,7 @@ bool BackgroundInfo::HasLazyBackgroundPage(const Extension* extension) {
return GetBackgroundInfo(extension).has_lazy_background_page();
}
-bool BackgroundInfo::Parse(const Extension* extension, string16* error) {
+bool BackgroundInfo::Parse(const Extension* extension, base::string16* error) {
const std::string& bg_scripts_key = extension->is_platform_app() ?
keys::kPlatformAppBackgroundScripts : keys::kBackgroundScripts;
if (!LoadBackgroundScripts(extension, bg_scripts_key, error) ||
@@ -107,7 +108,7 @@ bool BackgroundInfo::Parse(const Extension* extension, string16* error) {
bool BackgroundInfo::LoadBackgroundScripts(const Extension* extension,
const std::string& key,
- string16* error) {
+ base::string16* error) {
const base::Value* background_scripts_value = NULL;
if (!extension->manifest()->Get(key, &background_scripts_value))
return true;
@@ -135,7 +136,7 @@ bool BackgroundInfo::LoadBackgroundScripts(const Extension* extension,
bool BackgroundInfo::LoadBackgroundPage(const Extension* extension,
const std::string& key,
- string16* error) {
+ base::string16* error) {
const base::Value* background_page_value = NULL;
if (!extension->manifest()->Get(key, &background_page_value))
return true;
@@ -180,7 +181,7 @@ bool BackgroundInfo::LoadBackgroundPage(const Extension* extension,
}
bool BackgroundInfo::LoadBackgroundPage(const Extension* extension,
- string16* error) {
+ base::string16* error) {
if (extension->is_platform_app()) {
return LoadBackgroundPage(
extension, keys::kPlatformAppBackgroundPage, error);
@@ -194,7 +195,7 @@ bool BackgroundInfo::LoadBackgroundPage(const Extension* extension,
}
bool BackgroundInfo::LoadBackgroundPersistent(const Extension* extension,
- string16* error) {
+ base::string16* error) {
if (extension->is_platform_app()) {
is_persistent_ = false;
return true;
@@ -219,7 +220,7 @@ bool BackgroundInfo::LoadBackgroundPersistent(const Extension* extension,
}
bool BackgroundInfo::LoadAllowJSAccess(const Extension* extension,
- string16* error) {
+ base::string16* error) {
const base::Value* allow_js_access = NULL;
if (!extension->manifest()->Get(keys::kBackgroundAllowJsAccess,
&allow_js_access))
@@ -240,7 +241,8 @@ BackgroundManifestHandler::BackgroundManifestHandler() {
BackgroundManifestHandler::~BackgroundManifestHandler() {
}
-bool BackgroundManifestHandler::Parse(Extension* extension, string16* error) {
+bool BackgroundManifestHandler::Parse(Extension* extension,
+ base::string16* error) {
scoped_ptr<BackgroundInfo> info(new BackgroundInfo);
if (!info->Parse(extension, error))
return false;
@@ -274,7 +276,7 @@ bool BackgroundManifestHandler::Validate(
extension->GetResource(background_scripts[i]).GetFilePath())) {
*error = l10n_util::GetStringFUTF8(
IDS_EXTENSION_LOAD_BACKGROUND_SCRIPT_FAILED,
- UTF8ToUTF16(background_scripts[i]));
+ base::UTF8ToUTF16(background_scripts[i]));
return false;
}
}
diff --git a/extensions/common/manifest_handlers/background_info.h b/extensions/common/manifest_handlers/background_info.h
index 113c341c31..e9e360e696 100644
--- a/extensions/common/manifest_handlers/background_info.h
+++ b/extensions/common/manifest_handlers/background_info.h
@@ -41,18 +41,19 @@ class BackgroundInfo : public Extension::ManifestData {
return has_background_page() && !is_persistent_;
}
- bool Parse(const Extension* extension, string16* error);
+ bool Parse(const Extension* extension, base::string16* error);
private:
bool LoadBackgroundScripts(const Extension* extension,
const std::string& key,
- string16* error);
+ base::string16* error);
bool LoadBackgroundPage(const Extension* extension,
const std::string& key,
- string16* error);
- bool LoadBackgroundPage(const Extension* extension, string16* error);
- bool LoadBackgroundPersistent(const Extension* extension, string16* error);
- bool LoadAllowJSAccess(const Extension* extension, string16* error);
+ base::string16* error);
+ bool LoadBackgroundPage(const Extension* extension, base::string16* error);
+ bool LoadBackgroundPersistent(const Extension* extension,
+ base::string16* error);
+ bool LoadAllowJSAccess(const Extension* extension, base::string16* error);
// Optional URL to a master page of which a single instance should be always
// loaded in the background.
@@ -82,7 +83,7 @@ class BackgroundManifestHandler : public ManifestHandler {
BackgroundManifestHandler();
virtual ~BackgroundManifestHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
virtual bool Validate(const Extension* extension,
std::string* error,
std::vector<InstallWarning>* warnings) const OVERRIDE;
diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc
index 79f531a4f7..2fd74fb76b 100644
--- a/extensions/common/manifest_handlers/csp_info.cc
+++ b/extensions/common/manifest_handlers/csp_info.cc
@@ -77,7 +77,7 @@ CSPHandler::CSPHandler(bool is_platform_app)
CSPHandler::~CSPHandler() {
}
-bool CSPHandler::Parse(Extension* extension, string16* error) {
+bool CSPHandler::Parse(Extension* extension, base::string16* error) {
const std::string key = Keys()[0];
if (!extension->manifest()->HasPath(key)) {
if (extension->manifest_version() >= 2) {
@@ -97,17 +97,17 @@ bool CSPHandler::Parse(Extension* extension, string16* error) {
std::string content_security_policy;
if (!extension->manifest()->GetString(key, &content_security_policy)) {
- *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
+ *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
return false;
}
if (!ContentSecurityPolicyIsLegal(content_security_policy)) {
- *error = ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
+ *error = base::ASCIIToUTF16(errors::kInvalidContentSecurityPolicy);
return false;
}
if (extension->manifest_version() >= 2 &&
!ContentSecurityPolicyIsSecure(content_security_policy,
extension->GetType())) {
- *error = ASCIIToUTF16(errors::kInsecureContentSecurityPolicy);
+ *error = base::ASCIIToUTF16(errors::kInsecureContentSecurityPolicy);
return false;
}
diff --git a/extensions/common/manifest_handlers/csp_info.h b/extensions/common/manifest_handlers/csp_info.h
index c0ac884520..7b5b25d13e 100644
--- a/extensions/common/manifest_handlers/csp_info.h
+++ b/extensions/common/manifest_handlers/csp_info.h
@@ -38,7 +38,7 @@ class CSPHandler : public ManifestHandler {
explicit CSPHandler(bool is_platform_app);
virtual ~CSPHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
virtual bool AlwaysParseForType(Manifest::Type type) const OVERRIDE;
private:
diff --git a/extensions/common/manifest_handlers/incognito_info.cc b/extensions/common/manifest_handlers/incognito_info.cc
index b57a8a633d..02c3b28a52 100644
--- a/extensions/common/manifest_handlers/incognito_info.cc
+++ b/extensions/common/manifest_handlers/incognito_info.cc
@@ -34,7 +34,7 @@ IncognitoHandler::IncognitoHandler() {
IncognitoHandler::~IncognitoHandler() {
}
-bool IncognitoHandler::Parse(Extension* extension, string16* error) {
+bool IncognitoHandler::Parse(Extension* extension, base::string16* error) {
if (!extension->manifest()->HasKey(keys::kIncognito)) {
// Extensions and Chrome apps default to spanning mode.
// Hosted and legacy packaged apps default to split mode.
@@ -48,7 +48,7 @@ bool IncognitoHandler::Parse(Extension* extension, string16* error) {
bool split_mode = false;
std::string incognito_string;
if (!extension->manifest()->GetString(keys::kIncognito, &incognito_string)) {
- *error = ASCIIToUTF16(manifest_errors::kInvalidIncognitoBehavior);
+ *error = base::ASCIIToUTF16(manifest_errors::kInvalidIncognitoBehavior);
return false;
}
@@ -57,7 +57,7 @@ bool IncognitoHandler::Parse(Extension* extension, string16* error) {
else if (incognito_string != manifest_values::kIncognitoSpanning) {
// If incognito_string == kIncognitoSpanning, it is valid and
// split_mode remains false.
- *error = ASCIIToUTF16(manifest_errors::kInvalidIncognitoBehavior);
+ *error = base::ASCIIToUTF16(manifest_errors::kInvalidIncognitoBehavior);
return false;
}
diff --git a/extensions/common/manifest_handlers/incognito_info.h b/extensions/common/manifest_handlers/incognito_info.h
index cd44934a93..3650883c46 100644
--- a/extensions/common/manifest_handlers/incognito_info.h
+++ b/extensions/common/manifest_handlers/incognito_info.h
@@ -29,7 +29,7 @@ class IncognitoHandler : public ManifestHandler {
IncognitoHandler();
virtual ~IncognitoHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
virtual bool AlwaysParseForType(Manifest::Type type) const OVERRIDE;
private:
diff --git a/extensions/common/manifest_handlers/kiosk_mode_info.cc b/extensions/common/manifest_handlers/kiosk_mode_info.cc
index 92f406b012..f5d36afbef 100644
--- a/extensions/common/manifest_handlers/kiosk_mode_info.cc
+++ b/extensions/common/manifest_handlers/kiosk_mode_info.cc
@@ -44,7 +44,7 @@ KioskModeHandler::KioskModeHandler() {
KioskModeHandler::~KioskModeHandler() {
}
-bool KioskModeHandler::Parse(Extension* extension, string16* error) {
+bool KioskModeHandler::Parse(Extension* extension, base::string16* error) {
const Manifest* manifest = extension->manifest();
DCHECK(manifest->HasKey(keys::kKioskEnabled) ||
manifest->HasKey(keys::kKioskOnly));
@@ -52,19 +52,20 @@ bool KioskModeHandler::Parse(Extension* extension, string16* error) {
bool kiosk_enabled = false;
if (manifest->HasKey(keys::kKioskEnabled) &&
!manifest->GetBoolean(keys::kKioskEnabled, &kiosk_enabled)) {
- *error = ASCIIToUTF16(manifest_errors::kInvalidKioskEnabled);
+ *error = base::ASCIIToUTF16(manifest_errors::kInvalidKioskEnabled);
return false;
}
bool kiosk_only = false;
if (manifest->HasKey(keys::kKioskOnly) &&
!manifest->GetBoolean(keys::kKioskOnly, &kiosk_only)) {
- *error = ASCIIToUTF16(manifest_errors::kInvalidKioskOnly);
+ *error = base::ASCIIToUTF16(manifest_errors::kInvalidKioskOnly);
return false;
}
if (kiosk_only && !kiosk_enabled) {
- *error = ASCIIToUTF16(manifest_errors::kInvalidKioskOnlyButNotEnabled);
+ *error = base::ASCIIToUTF16(
+ manifest_errors::kInvalidKioskOnlyButNotEnabled);
return false;
}
diff --git a/extensions/common/manifest_handlers/kiosk_mode_info.h b/extensions/common/manifest_handlers/kiosk_mode_info.h
index e98fa31559..9cf57e9c3c 100644
--- a/extensions/common/manifest_handlers/kiosk_mode_info.h
+++ b/extensions/common/manifest_handlers/kiosk_mode_info.h
@@ -40,7 +40,7 @@ class KioskModeHandler : public ManifestHandler {
KioskModeHandler();
virtual ~KioskModeHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
private:
virtual const std::vector<std::string> Keys() const OVERRIDE;
diff --git a/extensions/common/manifest_handlers/offline_enabled_info.cc b/extensions/common/manifest_handlers/offline_enabled_info.cc
index 7cf1835d40..1d1f8b1540 100644
--- a/extensions/common/manifest_handlers/offline_enabled_info.cc
+++ b/extensions/common/manifest_handlers/offline_enabled_info.cc
@@ -35,7 +35,7 @@ OfflineEnabledHandler::OfflineEnabledHandler() {
OfflineEnabledHandler::~OfflineEnabledHandler() {
}
-bool OfflineEnabledHandler::Parse(Extension* extension, string16* error) {
+bool OfflineEnabledHandler::Parse(Extension* extension, base::string16* error) {
if (!extension->manifest()->HasKey(keys::kOfflineEnabled)) {
// Only platform apps default to being enabled offline, and we should only
// attempt parsing without a key present if it is a platform app.
@@ -49,7 +49,7 @@ bool OfflineEnabledHandler::Parse(Extension* extension, string16* error) {
if (!extension->manifest()->GetBoolean(keys::kOfflineEnabled,
&offline_enabled)) {
- *error = ASCIIToUTF16(manifest_errors::kInvalidOfflineEnabled);
+ *error = base::ASCIIToUTF16(manifest_errors::kInvalidOfflineEnabled);
return false;
}
diff --git a/extensions/common/manifest_handlers/offline_enabled_info.h b/extensions/common/manifest_handlers/offline_enabled_info.h
index e9b4f35d10..55aa837c6b 100644
--- a/extensions/common/manifest_handlers/offline_enabled_info.h
+++ b/extensions/common/manifest_handlers/offline_enabled_info.h
@@ -31,7 +31,7 @@ class OfflineEnabledHandler : public ManifestHandler {
OfflineEnabledHandler();
virtual ~OfflineEnabledHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
virtual bool AlwaysParseForType(Manifest::Type type) const OVERRIDE;
private:
diff --git a/extensions/common/manifest_handlers/requirements_info.cc b/extensions/common/manifest_handlers/requirements_info.cc
index aaf30dd1fe..a775324c88 100644
--- a/extensions/common/manifest_handlers/requirements_info.cc
+++ b/extensions/common/manifest_handlers/requirements_info.cc
@@ -60,7 +60,7 @@ bool RequirementsHandler::AlwaysParseForType(Manifest::Type type) const {
return true;
}
-bool RequirementsHandler::Parse(Extension* extension, string16* error) {
+bool RequirementsHandler::Parse(Extension* extension, base::string16* error) {
scoped_ptr<RequirementsInfo> requirements(
new RequirementsInfo(extension->manifest()));
@@ -72,7 +72,7 @@ bool RequirementsHandler::Parse(Extension* extension, string16* error) {
const base::DictionaryValue* requirements_value = NULL;
if (!extension->manifest()->GetDictionary(keys::kRequirements,
&requirements_value)) {
- *error = ASCIIToUTF16(errors::kInvalidRequirements);
+ *error = base::ASCIIToUTF16(errors::kInvalidRequirements);
return false;
}
@@ -129,7 +129,7 @@ bool RequirementsHandler::Parse(Extension* extension, string16* error) {
}
}
} else {
- *error = ASCIIToUTF16(errors::kInvalidRequirements);
+ *error = base::ASCIIToUTF16(errors::kInvalidRequirements);
return false;
}
}
diff --git a/extensions/common/manifest_handlers/requirements_info.h b/extensions/common/manifest_handlers/requirements_info.h
index adc128bdb2..37dbfb98b4 100644
--- a/extensions/common/manifest_handlers/requirements_info.h
+++ b/extensions/common/manifest_handlers/requirements_info.h
@@ -32,7 +32,7 @@ class RequirementsHandler : public ManifestHandler {
RequirementsHandler();
virtual ~RequirementsHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
virtual bool AlwaysParseForType(Manifest::Type type) const OVERRIDE;
diff --git a/extensions/common/manifest_handlers/sandboxed_page_info.cc b/extensions/common/manifest_handlers/sandboxed_page_info.cc
index a225a709a2..2471e93467 100644
--- a/extensions/common/manifest_handlers/sandboxed_page_info.cc
+++ b/extensions/common/manifest_handlers/sandboxed_page_info.cc
@@ -61,12 +61,12 @@ SandboxedPageHandler::SandboxedPageHandler() {
SandboxedPageHandler::~SandboxedPageHandler() {
}
-bool SandboxedPageHandler::Parse(Extension* extension, string16* error) {
+bool SandboxedPageHandler::Parse(Extension* extension, base::string16* error) {
scoped_ptr<SandboxedPageInfo> sandboxed_info(new SandboxedPageInfo);
const base::ListValue* list_value = NULL;
if (!extension->manifest()->GetList(keys::kSandboxedPages, &list_value)) {
- *error = ASCIIToUTF16(errors::kInvalidSandboxedPagesList);
+ *error = base::ASCIIToUTF16(errors::kInvalidSandboxedPagesList);
return false;
}
@@ -93,7 +93,7 @@ bool SandboxedPageHandler::Parse(Extension* extension, string16* error) {
if (!extension->manifest()->GetString(
keys::kSandboxedPagesCSP,
&sandboxed_info->content_security_policy)) {
- *error = ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP);
+ *error = base::ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP);
return false;
}
@@ -101,7 +101,7 @@ bool SandboxedPageHandler::Parse(Extension* extension, string16* error) {
sandboxed_info->content_security_policy) ||
!csp_validator::ContentSecurityPolicyIsSandboxed(
sandboxed_info->content_security_policy, extension->GetType())) {
- *error = ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP);
+ *error = base::ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP);
return false;
}
} else {
diff --git a/extensions/common/manifest_handlers/sandboxed_page_info.h b/extensions/common/manifest_handlers/sandboxed_page_info.h
index 936973e9c7..9dbc9a6290 100644
--- a/extensions/common/manifest_handlers/sandboxed_page_info.h
+++ b/extensions/common/manifest_handlers/sandboxed_page_info.h
@@ -44,7 +44,7 @@ class SandboxedPageHandler : public ManifestHandler {
SandboxedPageHandler();
virtual ~SandboxedPageHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
private:
virtual const std::vector<std::string> Keys() const OVERRIDE;
diff --git a/extensions/common/manifest_handlers/shared_module_info.cc b/extensions/common/manifest_handlers/shared_module_info.cc
index 09df879b73..5f44160992 100644
--- a/extensions/common/manifest_handlers/shared_module_info.cc
+++ b/extensions/common/manifest_handlers/shared_module_info.cc
@@ -105,26 +105,27 @@ const std::vector<SharedModuleInfo::ImportInfo>& SharedModuleInfo::GetImports(
return GetSharedModuleInfo(extension).imports_;
}
-bool SharedModuleInfo::Parse(const Extension* extension, string16* error) {
+bool SharedModuleInfo::Parse(const Extension* extension,
+ base::string16* error) {
bool has_import = extension->manifest()->HasKey(keys::kImport);
bool has_export = extension->manifest()->HasKey(keys::kExport);
if (!has_import && !has_export)
return true;
if (has_import && has_export) {
- *error = ASCIIToUTF16(errors::kInvalidImportAndExport);
+ *error = base::ASCIIToUTF16(errors::kInvalidImportAndExport);
return false;
}
if (has_export) {
const base::DictionaryValue* export_value = NULL;
if (!extension->manifest()->GetDictionary(keys::kExport, &export_value)) {
- *error = ASCIIToUTF16(errors::kInvalidExport);
+ *error = base::ASCIIToUTF16(errors::kInvalidExport);
return false;
}
const base::ListValue* resources_list = NULL;
if (!export_value->GetList(keys::kResources, &resources_list)) {
- *error = ASCIIToUTF16(errors::kInvalidExportResources);
+ *error = base::ASCIIToUTF16(errors::kInvalidExportResources);
return false;
}
for (size_t i = 0; i < resources_list->GetSize(); ++i) {
@@ -148,13 +149,13 @@ bool SharedModuleInfo::Parse(const Extension* extension, string16* error) {
if (has_import) {
const base::ListValue* import_list = NULL;
if (!extension->manifest()->GetList(keys::kImport, &import_list)) {
- *error = ASCIIToUTF16(errors::kInvalidImport);
+ *error = base::ASCIIToUTF16(errors::kInvalidImport);
return false;
}
for (size_t i = 0; i < import_list->GetSize(); ++i) {
const base::DictionaryValue* import_entry = NULL;
if (!import_list->GetDictionary(i, &import_entry)) {
- *error = ASCIIToUTF16(errors::kInvalidImport);
+ *error = base::ASCIIToUTF16(errors::kInvalidImport);
return false;
}
std::string extension_id;
@@ -193,7 +194,7 @@ SharedModuleHandler::SharedModuleHandler() {
SharedModuleHandler::~SharedModuleHandler() {
}
-bool SharedModuleHandler::Parse(Extension* extension, string16* error) {
+bool SharedModuleHandler::Parse(Extension* extension, base::string16* error) {
scoped_ptr<SharedModuleInfo> info(new SharedModuleInfo);
if (!info->Parse(extension, error))
return false;
diff --git a/extensions/common/manifest_handlers/shared_module_info.h b/extensions/common/manifest_handlers/shared_module_info.h
index db51594b07..4240ed7a81 100644
--- a/extensions/common/manifest_handlers/shared_module_info.h
+++ b/extensions/common/manifest_handlers/shared_module_info.h
@@ -19,7 +19,7 @@ class SharedModuleInfo : public Extension::ManifestData {
SharedModuleInfo();
virtual ~SharedModuleInfo();
- bool Parse(const Extension* extension, string16* error);
+ bool Parse(const Extension* extension, base::string16* error);
struct ImportInfo {
std::string extension_id;
@@ -57,7 +57,7 @@ class SharedModuleHandler : public ManifestHandler {
SharedModuleHandler();
virtual ~SharedModuleHandler();
- virtual bool Parse(Extension* extension, string16* error) OVERRIDE;
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
virtual bool Validate(const Extension* extension,
std::string* error,
std::vector<InstallWarning>* warnings) const OVERRIDE;
diff --git a/extensions/common/manifest_handlers/web_accessible_resources_info.cc b/extensions/common/manifest_handlers/web_accessible_resources_info.cc
new file mode 100644
index 0000000000..8da6bf5c7a
--- /dev/null
+++ b/extensions/common/manifest_handlers/web_accessible_resources_info.cc
@@ -0,0 +1,99 @@
+// Copyright 2014 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/manifest_handlers/web_accessible_resources_info.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/manifest_constants.h"
+
+namespace extensions {
+
+namespace keys = manifest_keys;
+namespace errors = manifest_errors;
+
+namespace {
+
+const WebAccessibleResourcesInfo* GetResourcesInfo(const Extension* extension) {
+ return static_cast<WebAccessibleResourcesInfo*>(
+ extension->GetManifestData(keys::kWebAccessibleResources));
+}
+
+} // namespace
+
+WebAccessibleResourcesInfo::WebAccessibleResourcesInfo() {
+}
+
+WebAccessibleResourcesInfo::~WebAccessibleResourcesInfo() {
+}
+
+// static
+bool WebAccessibleResourcesInfo::IsResourceWebAccessible(
+ const Extension* extension,
+ const std::string& relative_path) {
+ // For old manifest versions which do not specify web_accessible_resources
+ // we always allow resource loads.
+ if (extension->manifest_version() < 2 &&
+ !WebAccessibleResourcesInfo::HasWebAccessibleResources(extension))
+ return true;
+
+ const WebAccessibleResourcesInfo* info = GetResourcesInfo(extension);
+ return info &&
+ extension->ResourceMatches(
+ info->web_accessible_resources_, relative_path);
+}
+
+// static
+bool WebAccessibleResourcesInfo::HasWebAccessibleResources(
+ const Extension* extension) {
+ const WebAccessibleResourcesInfo* info = GetResourcesInfo(extension);
+ return info && info->web_accessible_resources_.size() > 0;
+}
+
+WebAccessibleResourcesHandler::WebAccessibleResourcesHandler() {
+}
+
+WebAccessibleResourcesHandler::~WebAccessibleResourcesHandler() {
+}
+
+bool WebAccessibleResourcesHandler::Parse(Extension* extension,
+ base::string16* error) {
+ scoped_ptr<WebAccessibleResourcesInfo> info(new WebAccessibleResourcesInfo);
+ const base::ListValue* list_value = NULL;
+ if (!extension->manifest()->GetList(keys::kWebAccessibleResources,
+ &list_value)) {
+ *error = base::ASCIIToUTF16(errors::kInvalidWebAccessibleResourcesList);
+ return false;
+ }
+ for (size_t i = 0; i < list_value->GetSize(); ++i) {
+ std::string relative_path;
+ if (!list_value->GetString(i, &relative_path)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidWebAccessibleResource, base::IntToString(i));
+ return false;
+ }
+ URLPattern pattern(URLPattern::SCHEME_EXTENSION);
+ if (pattern.Parse(extension->url().spec()) != URLPattern::PARSE_SUCCESS) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidURLPatternError, extension->url().spec());
+ return false;
+ }
+ while (relative_path[0] == '/')
+ relative_path = relative_path.substr(1, relative_path.length() - 1);
+ pattern.SetPath(pattern.path() + relative_path);
+ info->web_accessible_resources_.AddPattern(pattern);
+ }
+ extension->SetManifestData(keys::kWebAccessibleResources, info.release());
+ return true;
+}
+
+const std::vector<std::string> WebAccessibleResourcesHandler::Keys() const {
+ return SingleKey(keys::kWebAccessibleResources);
+}
+
+} // namespace extensions
diff --git a/extensions/common/manifest_handlers/web_accessible_resources_info.h b/extensions/common/manifest_handlers/web_accessible_resources_info.h
new file mode 100644
index 0000000000..2d0ed81e6b
--- /dev/null
+++ b/extensions/common/manifest_handlers/web_accessible_resources_info.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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_MANIFEST_HANDLERS_WEB_ACCESSIBLE_RESOURCES_INFO_H_
+#define EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_ACCESSIBLE_RESOURCES_INFO_H_
+
+#include <string>
+
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest_handler.h"
+
+namespace extensions {
+
+// A structure to hold the web accessible extension resources
+// that may be specified in the manifest of an extension using
+// "web_accessible_resources" key.
+struct WebAccessibleResourcesInfo : public Extension::ManifestData {
+ // Define out of line constructor/destructor to please Clang.
+ WebAccessibleResourcesInfo();
+ virtual ~WebAccessibleResourcesInfo();
+
+ // Returns true if the specified resource is web accessible.
+ static bool IsResourceWebAccessible(const Extension* extension,
+ const std::string& relative_path);
+
+ // Returns true when 'web_accessible_resources' are defined for the extension.
+ static bool HasWebAccessibleResources(const Extension* extension);
+
+ // Optional list of web accessible extension resources.
+ URLPatternSet web_accessible_resources_;
+};
+
+// Parses the "web_accessible_resources" manifest key.
+class WebAccessibleResourcesHandler : public ManifestHandler {
+ public:
+ WebAccessibleResourcesHandler();
+ virtual ~WebAccessibleResourcesHandler();
+
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
+
+ private:
+ virtual const std::vector<std::string> Keys() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(WebAccessibleResourcesHandler);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEB_ACCESSIBLE_RESOURCES_INFO_H_
diff --git a/extensions/common/manifest_handlers/webview_info.cc b/extensions/common/manifest_handlers/webview_info.cc
new file mode 100644
index 0000000000..3b30bbe421
--- /dev/null
+++ b/extensions/common/manifest_handlers/webview_info.cc
@@ -0,0 +1,182 @@
+// Copyright 2014 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/manifest_handlers/webview_info.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/manifest_constants.h"
+
+namespace extensions {
+
+namespace keys = extensions::manifest_keys;
+namespace errors = extensions::manifest_errors;
+
+namespace {
+
+const WebviewInfo* GetResourcesInfo(
+ const Extension& extension) {
+ return static_cast<WebviewInfo*>(
+ extension.GetManifestData(keys::kWebviewAccessibleResources));
+}
+
+} // namespace
+
+// A PartitionItem represents a set of accessible resources given a partition
+// ID pattern.
+class PartitionItem {
+ public:
+ explicit PartitionItem(const std::string& partition_pattern)
+ : partition_pattern_(partition_pattern) {
+ }
+
+ virtual ~PartitionItem() {
+ }
+
+ bool Matches(const std::string& partition_id) const {
+ return MatchPattern(partition_id, partition_pattern_);
+ }
+
+ // Adds a pattern to the set. Returns true if a new pattern was inserted,
+ // false if the pattern was already in the set.
+ bool AddPattern(const URLPattern& pattern) {
+ return accessible_resources_.AddPattern(pattern);
+ }
+
+ const URLPatternSet& accessible_resources() const {
+ return accessible_resources_;
+ }
+ private:
+ // A pattern string that matches partition IDs.
+ const std::string partition_pattern_;
+ // A URL pattern set of resources accessible to the given
+ // |partition_pattern_|.
+ URLPatternSet accessible_resources_;
+};
+
+
+WebviewInfo::WebviewInfo() {
+}
+
+WebviewInfo::~WebviewInfo() {
+}
+
+// static
+bool WebviewInfo::IsResourceWebviewAccessible(
+ const Extension* extension,
+ const std::string& partition_id,
+ const std::string& relative_path) {
+ if (!extension)
+ return false;
+
+ const WebviewInfo* info = GetResourcesInfo(*extension);
+ if (!info)
+ return false;
+
+ for (size_t i = 0; i < info->partition_items_.size(); ++i) {
+ const PartitionItem* const item = info->partition_items_[i];
+ if (item->Matches(partition_id) &&
+ extension->ResourceMatches(item->accessible_resources(),
+ relative_path)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void WebviewInfo::AddPartitionItem(scoped_ptr<PartitionItem> item) {
+ partition_items_.push_back(item.release());
+}
+
+WebviewHandler::WebviewHandler() {
+}
+
+WebviewHandler::~WebviewHandler() {
+}
+
+bool WebviewHandler::Parse(Extension* extension, base::string16* error) {
+ scoped_ptr<WebviewInfo> info(new WebviewInfo());
+
+ const base::DictionaryValue* dict_value = NULL;
+ if (!extension->manifest()->GetDictionary(keys::kWebview,
+ &dict_value)) {
+ *error = base::ASCIIToUTF16(errors::kInvalidWebview);
+ return false;
+ }
+
+ const base::ListValue* partition_list = NULL;
+ if (!dict_value->GetList(keys::kWebviewPartitions, &partition_list)) {
+ *error = base::ASCIIToUTF16(errors::kInvalidWebviewPartitionsList);
+ return false;
+ }
+
+ // The partition list must have at least one entry.
+ if (partition_list->GetSize() == 0) {
+ *error = base::ASCIIToUTF16(errors::kInvalidWebviewPartitionsList);
+ return false;
+ }
+
+ for (size_t i = 0; i < partition_list->GetSize(); ++i) {
+ const base::DictionaryValue* partition = NULL;
+ if (!partition_list->GetDictionary(i, &partition)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidWebviewPartition, base::IntToString(i));
+ return false;
+ }
+
+ std::string partition_pattern;
+ if (!partition->GetString(keys::kWebviewName, &partition_pattern)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidWebviewPartitionName, base::IntToString(i));
+ return false;
+ }
+
+ const base::ListValue* url_list = NULL;
+ if (!partition->GetList(keys::kWebviewAccessibleResources,
+ &url_list)) {
+ *error = base::ASCIIToUTF16(
+ errors::kInvalidWebviewAccessibleResourcesList);
+ return false;
+ }
+
+ // The URL list should have at least one entry.
+ if (url_list->GetSize() == 0) {
+ *error = base::ASCIIToUTF16(
+ errors::kInvalidWebviewAccessibleResourcesList);
+ return false;
+ }
+
+ scoped_ptr<PartitionItem> partition_item(
+ new PartitionItem(partition_pattern));
+
+ for (size_t i = 0; i < url_list->GetSize(); ++i) {
+ std::string relative_path;
+ if (!url_list->GetString(i, &relative_path)) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidWebviewAccessibleResource, base::IntToString(i));
+ return false;
+ }
+ URLPattern pattern(URLPattern::SCHEME_EXTENSION,
+ Extension::GetResourceURL(extension->url(),
+ relative_path).spec());
+ partition_item->AddPattern(pattern);
+ }
+ info->AddPartitionItem(partition_item.Pass());
+ }
+
+ extension->SetManifestData(keys::kWebviewAccessibleResources, info.release());
+ return true;
+}
+
+const std::vector<std::string> WebviewHandler::Keys() const {
+ return SingleKey(keys::kWebview);
+}
+
+} // namespace extensions
diff --git a/extensions/common/manifest_handlers/webview_info.h b/extensions/common/manifest_handlers/webview_info.h
new file mode 100644
index 0000000000..dcdb400c71
--- /dev/null
+++ b/extensions/common/manifest_handlers/webview_info.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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_MANIFEST_HANDLERS_WEBVIEW_INFO_H_
+#define EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEBVIEW_INFO_H_
+
+#include <string>
+
+#include "base/memory/scoped_vector.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest_handler.h"
+
+namespace extensions {
+
+class PartitionItem;
+
+// A class to hold the <webview> accessible extension resources
+// that may be specified in the manifest of an extension using the
+// "webview" key.
+class WebviewInfo : public Extension::ManifestData {
+ public:
+ // Define out of line constructor/destructor to please Clang.
+ WebviewInfo();
+ virtual ~WebviewInfo();
+
+ // Returns true if the specified resource is web accessible.
+ static bool IsResourceWebviewAccessible(const Extension* extension,
+ const std::string& partition_id,
+ const std::string& relative_path);
+
+ void AddPartitionItem(scoped_ptr<PartitionItem> item);
+
+ private:
+ ScopedVector<PartitionItem> partition_items_;
+};
+
+// Parses the "webview" manifest key.
+class WebviewHandler : public ManifestHandler {
+ public:
+ WebviewHandler();
+ virtual ~WebviewHandler();
+
+ virtual bool Parse(Extension* extension, base::string16* error) OVERRIDE;
+
+ private:
+ virtual const std::vector<std::string> Keys() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(WebviewHandler);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_MANIFEST_HANDLERS_WEBVIEW_INFO_H_
diff --git a/extensions/common/matcher/OWNERS b/extensions/common/matcher/OWNERS
deleted file mode 100644
index d5f125f04e..0000000000
--- a/extensions/common/matcher/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-battre@chromium.org
diff --git a/extensions/common/matcher/regex_set_matcher.cc b/extensions/common/matcher/regex_set_matcher.cc
deleted file mode 100644
index 24d99efa3f..0000000000
--- a/extensions/common/matcher/regex_set_matcher.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2012 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/matcher/regex_set_matcher.h"
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "extensions/common/matcher/substring_set_matcher.h"
-#include "third_party/re2/re2/filtered_re2.h"
-#include "third_party/re2/re2/re2.h"
-
-namespace extensions {
-
-RegexSetMatcher::RegexSetMatcher() {}
-
-RegexSetMatcher::~RegexSetMatcher() {
- DeleteSubstringPatterns();
-}
-
-void RegexSetMatcher::AddPatterns(
- const std::vector<const StringPattern*>& regex_list) {
- if (regex_list.empty())
- return;
- for (size_t i = 0; i < regex_list.size(); ++i) {
- regexes_[regex_list[i]->id()] = regex_list[i];
- }
-
- RebuildMatcher();
-}
-
-void RegexSetMatcher::ClearPatterns() {
- regexes_.clear();
- RebuildMatcher();
-}
-
-bool RegexSetMatcher::Match(const std::string& text,
- std::set<StringPattern::ID>* matches) const {
- size_t old_number_of_matches = matches->size();
- if (regexes_.empty())
- return false;
- if (!filtered_re2_.get()) {
- LOG(ERROR) << "RegexSetMatcher was not initialized";
- return false;
- }
-
- // FilteredRE2 expects lowercase for prefiltering, but we still
- // match case-sensitively.
- std::vector<RE2ID> atoms(FindSubstringMatches(
- StringToLowerASCII(text)));
-
- std::vector<RE2ID> re2_ids;
- filtered_re2_->AllMatches(text, atoms, &re2_ids);
-
- for (size_t i = 0; i < re2_ids.size(); ++i) {
- StringPattern::ID id = re2_id_map_[re2_ids[i]];
- matches->insert(id);
- }
- return old_number_of_matches != matches->size();
-}
-
-bool RegexSetMatcher::IsEmpty() const {
- return regexes_.empty();
-}
-
-std::vector<RegexSetMatcher::RE2ID> RegexSetMatcher::FindSubstringMatches(
- const std::string& text) const {
- std::set<int> atoms_set;
- substring_matcher_->Match(text, &atoms_set);
- return std::vector<RE2ID>(atoms_set.begin(), atoms_set.end());
-}
-
-void RegexSetMatcher::RebuildMatcher() {
- re2_id_map_.clear();
- filtered_re2_.reset(new re2::FilteredRE2());
- if (regexes_.empty())
- return;
-
- for (RegexMap::iterator it = regexes_.begin(); it != regexes_.end(); ++it) {
- RE2ID re2_id;
- RE2::ErrorCode error = filtered_re2_->Add(
- it->second->pattern(), RE2::DefaultOptions, &re2_id);
- if (error == RE2::NoError) {
- DCHECK_EQ(static_cast<RE2ID>(re2_id_map_.size()), re2_id);
- re2_id_map_.push_back(it->first);
- } else {
- // Unparseable regexes should have been rejected already in
- // URLMatcherFactory::CreateURLMatchesCondition.
- LOG(ERROR) << "Could not parse regex (id=" << it->first << ", "
- << it->second->pattern() << ")";
- }
- }
-
- std::vector<std::string> strings_to_match;
- filtered_re2_->Compile(&strings_to_match);
-
- substring_matcher_.reset(new SubstringSetMatcher);
- DeleteSubstringPatterns();
- // Build SubstringSetMatcher from |strings_to_match|.
- // SubstringSetMatcher doesn't own its strings.
- for (size_t i = 0; i < strings_to_match.size(); ++i) {
- substring_patterns_.push_back(
- new StringPattern(strings_to_match[i], i));
- }
- substring_matcher_->RegisterPatterns(substring_patterns_);
-}
-
-void RegexSetMatcher::DeleteSubstringPatterns() {
- STLDeleteElements(&substring_patterns_);
-}
-
-} // namespace extensions
diff --git a/extensions/common/matcher/regex_set_matcher.h b/extensions/common/matcher/regex_set_matcher.h
deleted file mode 100644
index 906ab9ca3e..0000000000
--- a/extensions/common/matcher/regex_set_matcher.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2012 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_MATCHER_REGEX_SET_MATCHER_H_
-#define EXTENSIONS_COMMON_MATCHER_REGEX_SET_MATCHER_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "extensions/common/matcher/string_pattern.h"
-#include "extensions/common/matcher/substring_set_matcher.h"
-
-namespace re2 {
-class FilteredRE2;
-}
-
-namespace extensions {
-
-// Efficiently matches URLs against a collection of regular expressions,
-// using FilteredRE2 to reduce the number of regexes that must be matched
-// by pre-filtering with substring matching. See:
-// http://swtch.com/~rsc/regexp/regexp3.html#analysis
-class RegexSetMatcher {
- public:
- RegexSetMatcher();
- virtual ~RegexSetMatcher();
-
- // Adds the regex patterns in |regex_list| to the matcher. Also rebuilds
- // the FilteredRE2 matcher; thus, for efficiency, prefer adding multiple
- // patterns at once.
- // Ownership of the patterns remains with the caller.
- void AddPatterns(const std::vector<const StringPattern*>& regex_list);
-
- // Removes all regex patterns.
- void ClearPatterns();
-
- // Appends the IDs of regular expressions in our set that match the |text|
- // to |matches|.
- bool Match(const std::string& text,
- std::set<StringPattern::ID>* matches) const;
-
- bool IsEmpty() const;
-
- private:
- typedef int RE2ID;
- typedef std::map<StringPattern::ID, const StringPattern*> RegexMap;
- typedef std::vector<StringPattern::ID> RE2IDMap;
-
- // Use Aho-Corasick SubstringSetMatcher to find which literal patterns
- // match the |text|.
- std::vector<RE2ID> FindSubstringMatches(const std::string& text) const;
-
- // Rebuild FilteredRE2 from scratch. Needs to be called whenever
- // our set of regexes changes.
- // TODO(yoz): investigate if it could be done incrementally;
- // apparently not supported by FilteredRE2.
- void RebuildMatcher();
-
- // Clean up StringPatterns in |substring_patterns_|.
- void DeleteSubstringPatterns();
-
- // Mapping of regex StringPattern::IDs to regexes.
- RegexMap regexes_;
- // Mapping of RE2IDs from FilteredRE2 (which are assigned in order)
- // to regex StringPattern::IDs.
- RE2IDMap re2_id_map_;
-
- scoped_ptr<re2::FilteredRE2> filtered_re2_;
- scoped_ptr<SubstringSetMatcher> substring_matcher_;
-
- // The substring patterns from FilteredRE2, which are used in
- // |substring_matcher_| but whose lifetime is managed here.
- std::vector<const StringPattern*> substring_patterns_;
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_REGEX_SET_MATCHER_H_
diff --git a/extensions/common/matcher/regex_set_matcher_unittest.cc b/extensions/common/matcher/regex_set_matcher_unittest.cc
deleted file mode 100644
index 49d312a140..0000000000
--- a/extensions/common/matcher/regex_set_matcher_unittest.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2012 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/matcher/regex_set_matcher.h"
-
-#include <set>
-
-#include "base/stl_util.h"
-#include "url/gurl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using extensions::StringPattern;
-using extensions::RegexSetMatcher;
-
-TEST(RegexSetMatcherTest, MatchRegexes) {
- StringPattern pattern_1("ab.*c", 42);
- StringPattern pattern_2("f*f", 17);
- StringPattern pattern_3("c(ar|ra)b|brac", 239);
- std::vector<const StringPattern*> regexes;
- regexes.push_back(&pattern_1);
- regexes.push_back(&pattern_2);
- regexes.push_back(&pattern_3);
- RegexSetMatcher matcher;
- matcher.AddPatterns(regexes);
-
- std::set<StringPattern::ID> result1;
- matcher.Match("http://abracadabra.com", &result1);
- EXPECT_EQ(2U, result1.size());
- EXPECT_TRUE(ContainsKey(result1, 42));
- EXPECT_TRUE(ContainsKey(result1, 239));
-
- std::set<StringPattern::ID> result2;
- matcher.Match("https://abfffffffffffffffffffffffffffffff.fi/cf", &result2);
- EXPECT_EQ(2U, result2.size());
- EXPECT_TRUE(ContainsKey(result2, 17));
- EXPECT_TRUE(ContainsKey(result2, 42));
-
- std::set<StringPattern::ID> result3;
- matcher.Match("http://nothing.com/", &result3);
- EXPECT_EQ(0U, result3.size());
-}
-
-TEST(RegexSetMatcherTest, CaseSensitivity) {
- StringPattern pattern_1("AAA", 51);
- StringPattern pattern_2("aaA", 57);
- std::vector<const StringPattern*> regexes;
- regexes.push_back(&pattern_1);
- regexes.push_back(&pattern_2);
- RegexSetMatcher matcher;
- matcher.AddPatterns(regexes);
-
- std::set<StringPattern::ID> result1;
- matcher.Match("http://aaa.net/", &result1);
- EXPECT_EQ(0U, result1.size());
-
- std::set<StringPattern::ID> result2;
- matcher.Match("http://aaa.net/quaaACK", &result2);
- EXPECT_EQ(1U, result2.size());
- EXPECT_TRUE(ContainsKey(result2, 57));
-}
diff --git a/extensions/common/matcher/string_pattern.cc b/extensions/common/matcher/string_pattern.cc
deleted file mode 100644
index 4e5c350c45..0000000000
--- a/extensions/common/matcher/string_pattern.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 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/matcher/string_pattern.h"
-
-namespace extensions {
-
-StringPattern::StringPattern(const std::string& pattern,
- StringPattern::ID id)
- : pattern_(pattern), id_(id) {}
-
-StringPattern::~StringPattern() {}
-
-bool StringPattern::operator<(const StringPattern& rhs) const {
- if (id_ != rhs.id_) return id_ < rhs.id_;
- return pattern_ < rhs.pattern_;
-}
-
-} // namespace extensions
diff --git a/extensions/common/matcher/string_pattern.h b/extensions/common/matcher/string_pattern.h
deleted file mode 100644
index 1781b03283..0000000000
--- a/extensions/common/matcher/string_pattern.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 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_MATCHER_STRING_PATTERN_H_
-#define EXTENSIONS_COMMON_MATCHER_STRING_PATTERN_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-
-namespace extensions {
-
-// An individual pattern of a substring or regex matcher. A pattern consists of
-// a string (interpreted as individual bytes, no character encoding) and an
-// identifier.
-// IDs are returned to the caller of SubstringSetMatcher::Match() or
-// RegexMatcher::MatchURL() to help the caller to figure out what
-// patterns matched a string. All patterns registered to a matcher
-// need to contain unique IDs.
-class StringPattern {
- public:
- typedef int ID;
-
- StringPattern(const std::string& pattern, ID id);
- ~StringPattern();
- const std::string& pattern() const { return pattern_; }
- ID id() const { return id_; }
-
- bool operator<(const StringPattern& rhs) const;
-
- private:
- std::string pattern_;
- ID id_;
-
- DISALLOW_COPY_AND_ASSIGN(StringPattern);
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_STRING_PATTERN_H_
diff --git a/extensions/common/matcher/string_pattern_unittest.cc b/extensions/common/matcher/string_pattern_unittest.cc
deleted file mode 100644
index 6e7e4bfbcf..0000000000
--- a/extensions/common/matcher/string_pattern_unittest.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2012 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/matcher/string_pattern.h"
-
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-using extensions::StringPattern;
-
-TEST(StringPatternTest, StringPattern) {
- StringPattern r1("Test", 2);
- EXPECT_EQ("Test", r1.pattern());
- EXPECT_EQ(2, r1.id());
-
- EXPECT_FALSE(r1 < r1);
- StringPattern r2("Test", 3);
- EXPECT_TRUE(r1 < r2);
- StringPattern r3("ZZZZ", 2);
- EXPECT_TRUE(r1 < r3);
-}
diff --git a/extensions/common/matcher/substring_set_matcher.cc b/extensions/common/matcher/substring_set_matcher.cc
deleted file mode 100644
index 91ac718b04..0000000000
--- a/extensions/common/matcher/substring_set_matcher.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright (c) 2012 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/matcher/substring_set_matcher.h"
-
-#include <algorithm>
-#include <queue>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-
-namespace extensions {
-
-namespace {
-
-// Compare StringPattern instances based on their string patterns.
-bool ComparePatterns(const StringPattern* a, const StringPattern* b) {
- return a->pattern() < b->pattern();
-}
-
-// Given the set of patterns, compute how many nodes will the corresponding
-// Aho-Corasick tree have. Note that |patterns| need to be sorted.
-uint32 TreeSize(const std::vector<const StringPattern*>& patterns) {
- uint32 result = 1u; // 1 for the root node.
- if (patterns.empty())
- return result;
-
- std::vector<const StringPattern*>::const_iterator last = patterns.begin();
- std::vector<const StringPattern*>::const_iterator current = last + 1;
- // For the first pattern, each letter is a label of an edge to a new node.
- result += (*last)->pattern().size();
-
- // For the subsequent patterns, only count the edges which were not counted
- // yet. For this it suffices to test against the previous pattern, because the
- // patterns are sorted.
- for (; current != patterns.end(); ++last, ++current) {
- const std::string& last_pattern = (*last)->pattern();
- const std::string& current_pattern = (*current)->pattern();
- const uint32 prefix_bound =
- std::min(last_pattern.size(), current_pattern.size());
-
- uint32 common_prefix = 0;
- while (common_prefix < prefix_bound &&
- last_pattern[common_prefix] == current_pattern[common_prefix])
- ++common_prefix;
- result += current_pattern.size() - common_prefix;
- }
- return result;
-}
-
-} // namespace
-
-//
-// SubstringSetMatcher
-//
-
-SubstringSetMatcher::SubstringSetMatcher() {
- RebuildAhoCorasickTree(SubstringPatternVector());
-}
-
-SubstringSetMatcher::~SubstringSetMatcher() {}
-
-void SubstringSetMatcher::RegisterPatterns(
- const std::vector<const StringPattern*>& patterns) {
- RegisterAndUnregisterPatterns(patterns,
- std::vector<const StringPattern*>());
-}
-
-void SubstringSetMatcher::UnregisterPatterns(
- const std::vector<const StringPattern*>& patterns) {
- RegisterAndUnregisterPatterns(std::vector<const StringPattern*>(),
- patterns);
-}
-
-void SubstringSetMatcher::RegisterAndUnregisterPatterns(
- const std::vector<const StringPattern*>& to_register,
- const std::vector<const StringPattern*>& to_unregister) {
- // Register patterns.
- for (std::vector<const StringPattern*>::const_iterator i =
- to_register.begin(); i != to_register.end(); ++i) {
- DCHECK(patterns_.find((*i)->id()) == patterns_.end());
- patterns_[(*i)->id()] = *i;
- }
-
- // Unregister patterns
- for (std::vector<const StringPattern*>::const_iterator i =
- to_unregister.begin(); i != to_unregister.end(); ++i) {
- patterns_.erase((*i)->id());
- }
-
- // Now we compute the total number of tree nodes needed.
- SubstringPatternVector sorted_patterns;
- sorted_patterns.resize(patterns_.size());
-
- size_t next = 0;
- for (SubstringPatternMap::const_iterator i = patterns_.begin();
- i != patterns_.end();
- ++i, ++next) {
- sorted_patterns[next] = i->second;
- }
-
- std::sort(sorted_patterns.begin(), sorted_patterns.end(), ComparePatterns);
- tree_.reserve(TreeSize(sorted_patterns));
-
- RebuildAhoCorasickTree(sorted_patterns);
-}
-
-bool SubstringSetMatcher::Match(const std::string& text,
- std::set<StringPattern::ID>* matches) const {
- const size_t old_number_of_matches = matches->size();
-
- // Handle patterns matching the empty string.
- matches->insert(tree_[0].matches().begin(), tree_[0].matches().end());
-
- uint32 current_node = 0;
- for (std::string::const_iterator i = text.begin(); i != text.end(); ++i) {
- uint32 edge_from_current = tree_[current_node].GetEdge(*i);
- while (edge_from_current == AhoCorasickNode::kNoSuchEdge &&
- current_node != 0) {
- current_node = tree_[current_node].failure();
- edge_from_current = tree_[current_node].GetEdge(*i);
- }
- if (edge_from_current != AhoCorasickNode::kNoSuchEdge) {
- current_node = edge_from_current;
- matches->insert(tree_[current_node].matches().begin(),
- tree_[current_node].matches().end());
- } else {
- DCHECK_EQ(0u, current_node);
- }
- }
-
- return old_number_of_matches != matches->size();
-}
-
-bool SubstringSetMatcher::IsEmpty() const {
- // An empty tree consists of only the root node.
- return patterns_.empty() && tree_.size() == 1u;
-}
-
-void SubstringSetMatcher::RebuildAhoCorasickTree(
- const SubstringPatternVector& sorted_patterns) {
- tree_.clear();
-
- // Initialize root note of tree.
- AhoCorasickNode root;
- root.set_failure(0);
- tree_.push_back(root);
-
- // Insert all patterns.
- for (SubstringPatternVector::const_iterator i = sorted_patterns.begin();
- i != sorted_patterns.end();
- ++i) {
- InsertPatternIntoAhoCorasickTree(*i);
- }
-
- CreateFailureEdges();
-}
-
-void SubstringSetMatcher::InsertPatternIntoAhoCorasickTree(
- const StringPattern* pattern) {
- const std::string& text = pattern->pattern();
- const std::string::const_iterator text_end = text.end();
-
- // Iterators on the tree and the text.
- uint32 current_node = 0;
- std::string::const_iterator i = text.begin();
-
- // Follow existing paths for as long as possible.
- while (i != text_end) {
- uint32 edge_from_current = tree_[current_node].GetEdge(*i);
- if (edge_from_current == AhoCorasickNode::kNoSuchEdge)
- break;
- current_node = edge_from_current;
- ++i;
- }
-
- // Create new nodes if necessary.
- while (i != text_end) {
- tree_.push_back(AhoCorasickNode());
- tree_[current_node].SetEdge(*i, tree_.size() - 1);
- current_node = tree_.size() - 1;
- ++i;
- }
-
- // Register match.
- tree_[current_node].AddMatch(pattern->id());
-}
-
-void SubstringSetMatcher::CreateFailureEdges() {
- typedef AhoCorasickNode::Edges Edges;
-
- std::queue<uint32> queue;
-
- AhoCorasickNode& root = tree_[0];
- root.set_failure(0);
- const Edges& root_edges = root.edges();
- for (Edges::const_iterator e = root_edges.begin(); e != root_edges.end();
- ++e) {
- const uint32& leads_to = e->second;
- tree_[leads_to].set_failure(0);
- queue.push(leads_to);
- }
-
- while (!queue.empty()) {
- AhoCorasickNode& current_node = tree_[queue.front()];
- queue.pop();
- for (Edges::const_iterator e = current_node.edges().begin();
- e != current_node.edges().end(); ++e) {
- const char& edge_label = e->first;
- const uint32& leads_to = e->second;
- queue.push(leads_to);
-
- uint32 failure = current_node.failure();
- uint32 edge_from_failure = tree_[failure].GetEdge(edge_label);
- while (edge_from_failure == AhoCorasickNode::kNoSuchEdge &&
- failure != 0) {
- failure = tree_[failure].failure();
- edge_from_failure = tree_[failure].GetEdge(edge_label);
- }
-
- const uint32 follow_in_case_of_failure =
- edge_from_failure != AhoCorasickNode::kNoSuchEdge
- ? edge_from_failure
- : 0;
- tree_[leads_to].set_failure(follow_in_case_of_failure);
- tree_[leads_to].AddMatches(tree_[follow_in_case_of_failure].matches());
- }
- }
-}
-
-const uint32 SubstringSetMatcher::AhoCorasickNode::kNoSuchEdge = ~0;
-
-SubstringSetMatcher::AhoCorasickNode::AhoCorasickNode()
- : failure_(kNoSuchEdge) {}
-
-SubstringSetMatcher::AhoCorasickNode::~AhoCorasickNode() {}
-
-SubstringSetMatcher::AhoCorasickNode::AhoCorasickNode(
- const SubstringSetMatcher::AhoCorasickNode& other)
- : edges_(other.edges_),
- failure_(other.failure_),
- matches_(other.matches_) {}
-
-SubstringSetMatcher::AhoCorasickNode&
-SubstringSetMatcher::AhoCorasickNode::operator=(
- const SubstringSetMatcher::AhoCorasickNode& other) {
- edges_ = other.edges_;
- failure_ = other.failure_;
- matches_ = other.matches_;
- return *this;
-}
-
-uint32 SubstringSetMatcher::AhoCorasickNode::GetEdge(char c) const {
- Edges::const_iterator i = edges_.find(c);
- return i == edges_.end() ? kNoSuchEdge : i->second;
-}
-
-void SubstringSetMatcher::AhoCorasickNode::SetEdge(char c, uint32 node) {
- edges_[c] = node;
-}
-
-void SubstringSetMatcher::AhoCorasickNode::AddMatch(StringPattern::ID id) {
- matches_.insert(id);
-}
-
-void SubstringSetMatcher::AhoCorasickNode::AddMatches(
- const SubstringSetMatcher::AhoCorasickNode::Matches& matches) {
- matches_.insert(matches.begin(), matches.end());
-}
-
-} // namespace extensions
diff --git a/extensions/common/matcher/substring_set_matcher.h b/extensions/common/matcher/substring_set_matcher.h
deleted file mode 100644
index 610efc0fc2..0000000000
--- a/extensions/common/matcher/substring_set_matcher.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2012 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_MATCHER_SUBSTRING_SET_MATCHER_H_
-#define EXTENSIONS_COMMON_MATCHER_SUBSTRING_SET_MATCHER_H_
-
-#include <limits>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "extensions/common/matcher/string_pattern.h"
-
-namespace extensions {
-
-// Class that store a set of string patterns and can find for a string S,
-// which string patterns occur in S.
-class SubstringSetMatcher {
- public:
- SubstringSetMatcher();
- ~SubstringSetMatcher();
-
- // Registers all |patterns|. The ownership remains with the caller.
- // The same pattern cannot be registered twice and each pattern needs to have
- // a unique ID.
- // Ownership of the patterns remains with the caller.
- void RegisterPatterns(const std::vector<const StringPattern*>& patterns);
-
- // Unregisters the passed |patterns|.
- void UnregisterPatterns(const std::vector<const StringPattern*>& patterns);
-
- // Analogous to RegisterPatterns and UnregisterPatterns but executes both
- // operations in one step, which is cheaper in the execution.
- void RegisterAndUnregisterPatterns(
- const std::vector<const StringPattern*>& to_register,
- const std::vector<const StringPattern*>& to_unregister);
-
- // Matches |text| against all registered StringPatterns. Stores the IDs
- // of matching patterns in |matches|. |matches| is not cleared before adding
- // to it.
- bool Match(const std::string& text,
- std::set<StringPattern::ID>* matches) const;
-
- // Returns true if this object retains no allocated data. Only for debugging.
- bool IsEmpty() const;
-
- private:
- // A node of an Aho Corasick Tree. This is implemented according to
- // http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
- //
- // The algorithm is based on the idea of building a trie of all registered
- // patterns. Each node of the tree is annotated with a set of pattern
- // IDs that are used to report matches.
- //
- // The root of the trie represents an empty match. If we were looking whether
- // any registered pattern matches a text at the beginning of the text (i.e.
- // whether any pattern is a prefix of the text), we could just follow
- // nodes in the trie according to the matching characters in the text.
- // E.g., if text == "foobar", we would follow the trie from the root node
- // to its child labeled 'f', from there to child 'o', etc. In this process we
- // would report all pattern IDs associated with the trie nodes as matches.
- //
- // As we are not looking for all prefix matches but all substring matches,
- // this algorithm would need to compare text.substr(0), text.substr(1), ...
- // against the trie, which is in O(|text|^2).
- //
- // The Aho Corasick algorithm improves this runtime by using failure edges.
- // In case we have found a partial match of length k in the text
- // (text[i, ..., i + k - 1]) in the trie starting at the root and ending at
- // a node at depth k, but cannot find a match in the trie for character
- // text[i + k] at depth k + 1, we follow a failure edge. This edge
- // corresponds to the longest proper suffix of text[i, ..., i + k - 1] that
- // is a prefix of any registered pattern.
- //
- // If your brain thinks "Forget it, let's go shopping.", don't worry.
- // Take a nap and read an introductory text on the Aho Corasick algorithm.
- // It will make sense. Eventually.
- class AhoCorasickNode {
- public:
- // Key: label of the edge, value: node index in |tree_| of parent class.
- typedef std::map<char, uint32> Edges;
- typedef std::set<StringPattern::ID> Matches;
-
- static const uint32 kNoSuchEdge; // Represents an invalid node index.
-
- AhoCorasickNode();
- ~AhoCorasickNode();
- AhoCorasickNode(const AhoCorasickNode& other);
- AhoCorasickNode& operator=(const AhoCorasickNode& other);
-
- uint32 GetEdge(char c) const;
- void SetEdge(char c, uint32 node);
- const Edges& edges() const { return edges_; }
-
- uint32 failure() const { return failure_; }
- void set_failure(uint32 failure) { failure_ = failure; }
-
- void AddMatch(StringPattern::ID id);
- void AddMatches(const Matches& matches);
- const Matches& matches() const { return matches_; }
-
- private:
- // Outgoing edges of current node.
- Edges edges_;
-
- // Node index that failure edge leads to.
- uint32 failure_;
-
- // Identifiers of matches.
- Matches matches_;
- };
-
- typedef std::map<StringPattern::ID, const StringPattern*> SubstringPatternMap;
- typedef std::vector<const StringPattern*> SubstringPatternVector;
-
- // |sorted_patterns| is a copy of |patterns_| sorted by the pattern string.
- void RebuildAhoCorasickTree(const SubstringPatternVector& sorted_patterns);
-
- // Inserts a path for |pattern->pattern()| into the tree and adds
- // |pattern->id()| to the set of matches. Ownership of |pattern| remains with
- // the caller.
- void InsertPatternIntoAhoCorasickTree(const StringPattern* pattern);
- void CreateFailureEdges();
-
- // Set of all registered StringPatterns. Used to regenerate the
- // Aho-Corasick tree in case patterns are registered or unregistered.
- SubstringPatternMap patterns_;
-
- // The nodes of a Aho-Corasick tree.
- std::vector<AhoCorasickNode> tree_;
-
- DISALLOW_COPY_AND_ASSIGN(SubstringSetMatcher);
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_SUBSTRING_SET_MATCHER_H_
diff --git a/extensions/common/matcher/substring_set_matcher_unittest.cc b/extensions/common/matcher/substring_set_matcher_unittest.cc
deleted file mode 100644
index fde65bf2dc..0000000000
--- a/extensions/common/matcher/substring_set_matcher_unittest.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2012 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/matcher/substring_set_matcher.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-using extensions::StringPattern;
-using extensions::SubstringSetMatcher;
-
-namespace {
-void TestOnePattern(const std::string& test_string,
- const std::string& pattern,
- bool is_match) {
- std::string test =
- "TestOnePattern(" + test_string + ", " + pattern + ", " +
- (is_match ? "1" : "0") + ")";
- std::vector<const StringPattern*> patterns;
- StringPattern substring_pattern(pattern, 1);
- patterns.push_back(&substring_pattern);
- SubstringSetMatcher matcher;
- matcher.RegisterPatterns(patterns);
- std::set<int> matches;
- matcher.Match(test_string, &matches);
-
- size_t expected_matches = (is_match ? 1 : 0);
- EXPECT_EQ(expected_matches, matches.size()) << test;
- EXPECT_EQ(is_match, matches.find(1) != matches.end()) << test;
-}
-
-void TestTwoPatterns(const std::string& test_string,
- const std::string& pattern_1,
- const std::string& pattern_2,
- bool is_match_1,
- bool is_match_2) {
- std::string test =
- "TestTwoPatterns(" + test_string + ", " + pattern_1 + ", " + pattern_2 +
- ", " + (is_match_1 ? "1" : "0") + ", " + (is_match_2 ? "1" : "0") + ")";
- StringPattern substring_pattern_1(pattern_1, 1);
- StringPattern substring_pattern_2(pattern_2, 2);
- // In order to make sure that the order in which patterns are registered
- // does not make any difference we try both permutations.
- for (int permutation = 0; permutation < 2; ++permutation) {
- std::vector<const StringPattern*> patterns;
- if (permutation == 0) {
- patterns.push_back(&substring_pattern_1);
- patterns.push_back(&substring_pattern_2);
- } else {
- patterns.push_back(&substring_pattern_2);
- patterns.push_back(&substring_pattern_1);
- }
- SubstringSetMatcher matcher;
- matcher.RegisterPatterns(patterns);
- std::set<int> matches;
- matcher.Match(test_string, &matches);
-
- size_t expected_matches = (is_match_1 ? 1 : 0) + (is_match_2 ? 1 : 0);
- EXPECT_EQ(expected_matches, matches.size()) << test;
- EXPECT_EQ(is_match_1, matches.find(1) != matches.end()) << test;
- EXPECT_EQ(is_match_2, matches.find(2) != matches.end()) << test;
- }
-}
-}
-
-TEST(SubstringSetMatcherTest, TestMatcher) {
- // Test overlapping patterns
- // String abcde
- // Pattern 1 bc
- // Pattern 2 cd
- TestTwoPatterns("abcde", "bc", "cd", true, true);
-
- // Test subpatterns - part 1
- // String abcde
- // Pattern 1 bc
- // Pattern 2 b
- TestTwoPatterns("abcde", "bc", "b", true, true);
-
- // Test subpatterns - part 2
- // String abcde
- // Pattern 1 bc
- // Pattern 2 c
- TestTwoPatterns("abcde", "bc", "c", true, true);
-
- // Test identical matches
- // String abcde
- // Pattern 1 abcde
- TestOnePattern("abcde", "abcde", true);
-
- // Test multiple matches
- // String aaaaa
- // Pattern 1 a
- TestOnePattern("abcde", "a", true);
-
- // Test matches at beginning and end
- // String abcde
- // Pattern 1 ab
- // Pattern 2 de
- TestTwoPatterns("abcde", "ab", "de", true, true);
-
- // Test duplicate patterns with different IDs
- // String abcde
- // Pattern 1 bc
- // Pattern 2 bc
- TestTwoPatterns("abcde", "bc", "bc", true, true);
-
- // Test non-match
- // String abcde
- // Pattern 1 fg
- TestOnePattern("abcde", "fg", false);
-
- // Test empty pattern and too long pattern
- // String abcde
- // Pattern 1
- // Pattern 2 abcdef
- TestTwoPatterns("abcde", std::string(), "abcdef", true, false);
-}
-
-TEST(SubstringSetMatcherTest, RegisterAndRemove) {
- SubstringSetMatcher matcher;
-
- StringPattern pattern_1("a", 1);
- StringPattern pattern_2("b", 2);
- StringPattern pattern_3("c", 3);
-
- std::vector<const StringPattern*> patterns;
- patterns.push_back(&pattern_1);
- matcher.RegisterPatterns(patterns);
-
- patterns.clear();
- patterns.push_back(&pattern_2);
- patterns.push_back(&pattern_3);
- matcher.RegisterPatterns(patterns);
-
- std::set<int> matches;
- matcher.Match("abd", &matches);
- EXPECT_EQ(2u, matches.size());
- EXPECT_TRUE(matches.end() != matches.find(1));
- EXPECT_TRUE(matches.end() != matches.find(2));
-
- patterns.clear();
- patterns.push_back(&pattern_2);
- matcher.UnregisterPatterns(patterns);
-
- matches.clear();
- matcher.Match("abd", &matches);
- EXPECT_EQ(1u, matches.size());
- EXPECT_TRUE(matches.end() != matches.find(1));
- EXPECT_TRUE(matches.end() == matches.find(2));
-
- patterns.clear();
- patterns.push_back(&pattern_1);
- patterns.push_back(&pattern_3);
- matcher.UnregisterPatterns(patterns);
- EXPECT_TRUE(matcher.IsEmpty());
-}
-
-TEST(SubstringSetMatcherTest, TestEmptyMatcher) {
- SubstringSetMatcher matcher;
- std::set<int> matches;
- matcher.Match("abd", &matches);
- EXPECT_TRUE(matches.empty());
-}
diff --git a/extensions/common/matcher/url_matcher.cc b/extensions/common/matcher/url_matcher.cc
deleted file mode 100644
index 5a1d876cc6..0000000000
--- a/extensions/common/matcher/url_matcher.cc
+++ /dev/null
@@ -1,881 +0,0 @@
-// Copyright (c) 2012 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/matcher/url_matcher.h"
-
-#include <algorithm>
-#include <iterator>
-
-#include "base/logging.h"
-#include "content/public/common/url_constants.h"
-#include "url/gurl.h"
-#include "url/url_canon.h"
-
-namespace extensions {
-
-// This set of classes implement a mapping of URL Component Patterns, such as
-// host_prefix, host_suffix, host_equals, ..., etc., to StringPatterns
-// for use in substring comparisons.
-//
-// The idea of this mapping is to reduce the problem of comparing many
-// URL Component Patterns against one URL to the problem of searching many
-// substrings in one string:
-//
-// ---------------------- -----------------
-// | URL Query operator | ----translate----> | StringPattern |
-// ---------------------- -----------------
-// ^
-// |
-// compare
-// |
-// v
-// ---------------------- -----------------
-// | URL to compare | | |
-// | to all URL Query | ----translate----> | String |
-// | operators | | |
-// ---------------------- -----------------
-//
-// The reason for this problem reduction is that there are efficient algorithms
-// for searching many substrings in one string (see Aho-Corasick algorithm).
-//
-// Additionally, some of the same pieces are reused to implement regular
-// expression comparisons. The FilteredRE2 implementation for matching many
-// regular expressions against one string uses prefiltering, in which a set
-// of substrings (derived from the regexes) are first searched for, to reduce
-// the number of regular expressions to test; the prefiltering step also
-// uses Aho-Corasick.
-//
-// Case 1: {host,path,query}_{prefix,suffix,equals} searches.
-// ==========================================================
-//
-// For searches in this class, we normalize URLs as follows:
-//
-// Step 1:
-// Remove scheme, port and segment from URL:
-// -> http://www.example.com:8080/index.html?search=foo#first_match becomes
-// www.example.com/index.html?search=foo
-//
-// We remove the scheme and port number because they can be checked later
-// in a secondary filter step. We remove the segment (the #... part) because
-// this is not guaranteed to be ASCII-7 encoded.
-//
-// Step 2:
-// Translate URL to String and add the following position markers:
-// - BU = Beginning of URL
-// - ED = End of Domain
-// - EP = End of Path
-// - EU = End of URL
-// Furthermore, the hostname is canonicalized to start with a ".".
-//
-// Position markers are represented as characters >127, which are therefore
-// guaranteed not to be part of the ASCII-7 encoded URL character set.
-//
-// -> www.example.com/index.html?search=foo becomes
-// BU .www.example.com ED /index.html EP ?search=foo EU
-//
-// -> www.example.com/index.html becomes
-// BU .www.example.com ED /index.html EP EU
-//
-// Step 3:
-// Translate URL Component Patterns as follows:
-//
-// host_prefix(prefix) = BU add_missing_dot_prefix(prefix)
-// -> host_prefix("www.example") = BU .www.example
-//
-// host_suffix(suffix) = suffix ED
-// -> host_suffix("example.com") = example.com ED
-// -> host_suffix(".example.com") = .example.com ED
-//
-// host_equals(domain) = BU add_missing_dot_prefix(domain) ED
-// -> host_equals("www.example.com") = BU .www.example.com ED
-//
-// Similarly for path query parameters ({path, query}_{prefix, suffix, equals}).
-//
-// With this, we can search the StringPatterns in the normalized URL.
-//
-//
-// Case 2: url_{prefix,suffix,equals,contains} searches.
-// =====================================================
-//
-// Step 1: as above, except that
-// - the scheme is not removed
-// - the port is not removed if it is specified and does not match the default
-// port for the given scheme.
-//
-// Step 2:
-// Translate URL to String and add the following position markers:
-// - BU = Beginning of URL
-// - EU = End of URL
-//
-// -> http://www.example.com:8080/index.html?search=foo#first_match becomes
-// BU http://www.example.com:8080/index.html?search=foo EU
-// -> http://www.example.com:80/index.html?search=foo#first_match becomes
-// BU http://www.example.com/index.html?search=foo EU
-//
-// url_prefix(prefix) = BU prefix
-// -> url_prefix("http://www.example") = BU http://www.example
-//
-// url_contains(substring) = substring
-// -> url_contains("index") = index
-//
-//
-// Case 3: {host,path,query}_contains searches.
-// ============================================
-//
-// These kinds of searches are not supported directly but can be derived
-// by a combination of a url_contains() query followed by an explicit test:
-//
-// host_contains(str) = url_contains(str) followed by test whether str occurs
-// in host component of original URL.
-// -> host_contains("example.co") = example.co
-// followed by gurl.host().find("example.co");
-//
-// [similarly for path_contains and query_contains].
-//
-//
-// Regular expression matching (url_matches searches)
-// ==================================================
-//
-// This class also supports matching regular expressions (RE2 syntax)
-// against full URLs, which are transformed as in case 2.
-
-namespace {
-
-bool IsRegexCriterion(URLMatcherCondition::Criterion criterion) {
- return criterion == URLMatcherCondition::URL_MATCHES;
-}
-
-bool IsOriginAndPathRegexCriterion(URLMatcherCondition::Criterion criterion) {
- return criterion == URLMatcherCondition::ORIGIN_AND_PATH_MATCHES;
-}
-
-} // namespace
-
-//
-// URLMatcherCondition
-//
-
-URLMatcherCondition::URLMatcherCondition()
- : criterion_(HOST_PREFIX),
- string_pattern_(NULL) {}
-
-URLMatcherCondition::~URLMatcherCondition() {}
-
-URLMatcherCondition::URLMatcherCondition(
- Criterion criterion,
- const StringPattern* string_pattern)
- : criterion_(criterion),
- string_pattern_(string_pattern) {}
-
-URLMatcherCondition::URLMatcherCondition(const URLMatcherCondition& rhs)
- : criterion_(rhs.criterion_),
- string_pattern_(rhs.string_pattern_) {}
-
-URLMatcherCondition& URLMatcherCondition::operator=(
- const URLMatcherCondition& rhs) {
- criterion_ = rhs.criterion_;
- string_pattern_ = rhs.string_pattern_;
- return *this;
-}
-
-bool URLMatcherCondition::operator<(const URLMatcherCondition& rhs) const {
- if (criterion_ < rhs.criterion_) return true;
- if (criterion_ > rhs.criterion_) return false;
- if (string_pattern_ != NULL && rhs.string_pattern_ != NULL)
- return *string_pattern_ < *rhs.string_pattern_;
- if (string_pattern_ == NULL && rhs.string_pattern_ != NULL) return true;
- // Either string_pattern_ != NULL && rhs.string_pattern_ == NULL,
- // or both are NULL.
- return false;
-}
-
-bool URLMatcherCondition::IsFullURLCondition() const {
- // For these criteria the SubstringMatcher needs to be executed on the
- // GURL that is canonicalized with
- // URLMatcherConditionFactory::CanonicalizeURLForFullSearches.
- switch (criterion_) {
- case HOST_CONTAINS:
- case PATH_CONTAINS:
- case QUERY_CONTAINS:
- case URL_PREFIX:
- case URL_SUFFIX:
- case URL_CONTAINS:
- case URL_EQUALS:
- return true;
- default:
- break;
- }
- return false;
-}
-
-bool URLMatcherCondition::IsRegexCondition() const {
- return IsRegexCriterion(criterion_);
-}
-
-bool URLMatcherCondition::IsOriginAndPathRegexCondition() const {
- return IsOriginAndPathRegexCriterion(criterion_);
-}
-
-bool URLMatcherCondition::IsMatch(
- const std::set<StringPattern::ID>& matching_patterns,
- const GURL& url) const {
- DCHECK(string_pattern_);
- if (!ContainsKey(matching_patterns, string_pattern_->id()))
- return false;
- // The criteria HOST_CONTAINS, PATH_CONTAINS, QUERY_CONTAINS are based on
- // a substring match on the raw URL. In case of a match, we need to verify
- // that the match was found in the correct component of the URL.
- switch (criterion_) {
- case HOST_CONTAINS:
- return url.host().find(string_pattern_->pattern()) !=
- std::string::npos;
- case PATH_CONTAINS:
- return url.path().find(string_pattern_->pattern()) !=
- std::string::npos;
- case QUERY_CONTAINS:
- return url.query().find(string_pattern_->pattern()) !=
- std::string::npos;
- default:
- break;
- }
- return true;
-}
-
-//
-// URLMatcherConditionFactory
-//
-
-namespace {
-// These are symbols that are not contained in 7-bit ASCII used in GURLs.
-const char kBeginningOfURL[] = {static_cast<char>(-1), 0};
-const char kEndOfDomain[] = {static_cast<char>(-2), 0};
-const char kEndOfPath[] = {static_cast<char>(-3), 0};
-const char kEndOfURL[] = {static_cast<char>(-4), 0};
-} // namespace
-
-URLMatcherConditionFactory::URLMatcherConditionFactory() : id_counter_(0) {}
-
-URLMatcherConditionFactory::~URLMatcherConditionFactory() {
- STLDeleteElements(&substring_pattern_singletons_);
- STLDeleteElements(&regex_pattern_singletons_);
- STLDeleteElements(&origin_and_path_regex_pattern_singletons_);
-}
-
-std::string URLMatcherConditionFactory::CanonicalizeURLForComponentSearches(
- const GURL& url) const {
- return kBeginningOfURL + CanonicalizeHostname(url.host()) + kEndOfDomain +
- url.path() + kEndOfPath +
- (url.has_query() ? "?" + url.query() : std::string()) + kEndOfURL;
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateHostPrefixCondition(
- const std::string& prefix) {
- return CreateCondition(URLMatcherCondition::HOST_PREFIX,
- kBeginningOfURL + CanonicalizeHostname(prefix));
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateHostSuffixCondition(
- const std::string& suffix) {
- return CreateCondition(URLMatcherCondition::HOST_SUFFIX,
- suffix + kEndOfDomain);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateHostContainsCondition(
- const std::string& str) {
- return CreateCondition(URLMatcherCondition::HOST_CONTAINS, str);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateHostEqualsCondition(
- const std::string& str) {
- return CreateCondition(URLMatcherCondition::HOST_EQUALS,
- kBeginningOfURL + CanonicalizeHostname(str) + kEndOfDomain);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreatePathPrefixCondition(
- const std::string& prefix) {
- return CreateCondition(URLMatcherCondition::PATH_PREFIX,
- kEndOfDomain + prefix);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreatePathSuffixCondition(
- const std::string& suffix) {
- return CreateCondition(URLMatcherCondition::PATH_SUFFIX, suffix + kEndOfPath);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreatePathContainsCondition(
- const std::string& str) {
- return CreateCondition(URLMatcherCondition::PATH_CONTAINS, str);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreatePathEqualsCondition(
- const std::string& str) {
- return CreateCondition(URLMatcherCondition::PATH_EQUALS,
- kEndOfDomain + str + kEndOfPath);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateQueryPrefixCondition(
- const std::string& prefix) {
- std::string pattern;
- if (!prefix.empty() && prefix[0] == '?')
- pattern = kEndOfPath + prefix;
- else
- pattern = kEndOfPath + ('?' + prefix);
-
- return CreateCondition(URLMatcherCondition::QUERY_PREFIX, pattern);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateQuerySuffixCondition(
- const std::string& suffix) {
- if (!suffix.empty() && suffix[0] == '?') {
- return CreateQueryEqualsCondition(suffix);
- } else {
- return CreateCondition(URLMatcherCondition::QUERY_SUFFIX,
- suffix + kEndOfURL);
- }
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateQueryContainsCondition(
- const std::string& str) {
- if (!str.empty() && str[0] == '?')
- return CreateQueryPrefixCondition(str);
- else
- return CreateCondition(URLMatcherCondition::QUERY_CONTAINS, str);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateQueryEqualsCondition(
- const std::string& str) {
- std::string pattern;
- if (!str.empty() && str[0] == '?')
- pattern = kEndOfPath + str + kEndOfURL;
- else
- pattern = kEndOfPath + ('?' + str) + kEndOfURL;
-
- return CreateCondition(URLMatcherCondition::QUERY_EQUALS, pattern);
-}
-
-URLMatcherCondition
- URLMatcherConditionFactory::CreateHostSuffixPathPrefixCondition(
- const std::string& host_suffix,
- const std::string& path_prefix) {
- return CreateCondition(URLMatcherCondition::HOST_SUFFIX_PATH_PREFIX,
- host_suffix + kEndOfDomain + path_prefix);
-}
-
-URLMatcherCondition
-URLMatcherConditionFactory::CreateHostEqualsPathPrefixCondition(
- const std::string& host,
- const std::string& path_prefix) {
- return CreateCondition(URLMatcherCondition::HOST_EQUALS_PATH_PREFIX,
- kBeginningOfURL + CanonicalizeHostname(host) + kEndOfDomain +
- path_prefix);
-}
-
-std::string URLMatcherConditionFactory::CanonicalizeURLForFullSearches(
- const GURL& url) const {
- GURL::Replacements replacements;
- replacements.ClearPassword();
- replacements.ClearUsername();
- replacements.ClearRef();
- // Clear port if it is implicit from scheme.
- if (url.has_port()) {
- const std::string& port = url.scheme();
- if (url_canon::DefaultPortForScheme(port.c_str(), port.size()) ==
- url.EffectiveIntPort()) {
- replacements.ClearPort();
- }
- }
- return kBeginningOfURL + url.ReplaceComponents(replacements).spec() +
- kEndOfURL;
-}
-
-static std::string CanonicalizeURLForRegexSearchesHelper(
- const GURL& url,
- bool clear_query) {
- GURL::Replacements replacements;
- replacements.ClearPassword();
- replacements.ClearUsername();
- replacements.ClearRef();
- if (clear_query)
- replacements.ClearQuery();
- // Clear port if it is implicit from scheme.
- if (url.has_port()) {
- const std::string& port = url.scheme();
- if (url_canon::DefaultPortForScheme(port.c_str(), port.size()) ==
- url.EffectiveIntPort()) {
- replacements.ClearPort();
- }
- }
- return url.ReplaceComponents(replacements).spec();
-}
-
-std::string URLMatcherConditionFactory::CanonicalizeURLForRegexSearches(
- const GURL& url) const {
- return CanonicalizeURLForRegexSearchesHelper(url, false);
-}
-
-std::string
-URLMatcherConditionFactory::CanonicalizeURLForOriginAndPathRegexSearches(
- const GURL& url) const {
- return CanonicalizeURLForRegexSearchesHelper(url, true);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateURLPrefixCondition(
- const std::string& prefix) {
- return CreateCondition(URLMatcherCondition::URL_PREFIX,
- kBeginningOfURL + prefix);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateURLSuffixCondition(
- const std::string& suffix) {
- return CreateCondition(URLMatcherCondition::URL_SUFFIX, suffix + kEndOfURL);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateURLContainsCondition(
- const std::string& str) {
- return CreateCondition(URLMatcherCondition::URL_CONTAINS, str);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateURLEqualsCondition(
- const std::string& str) {
- return CreateCondition(URLMatcherCondition::URL_EQUALS,
- kBeginningOfURL + str + kEndOfURL);
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateURLMatchesCondition(
- const std::string& regex) {
- return CreateCondition(URLMatcherCondition::URL_MATCHES, regex);
-}
-
-URLMatcherCondition
-URLMatcherConditionFactory::CreateOriginAndPathMatchesCondition(
- const std::string& regex) {
- return CreateCondition(URLMatcherCondition::ORIGIN_AND_PATH_MATCHES, regex);
-}
-
-void URLMatcherConditionFactory::ForgetUnusedPatterns(
- const std::set<StringPattern::ID>& used_patterns) {
- PatternSingletons::iterator i = substring_pattern_singletons_.begin();
- while (i != substring_pattern_singletons_.end()) {
- if (ContainsKey(used_patterns, (*i)->id())) {
- ++i;
- } else {
- delete *i;
- substring_pattern_singletons_.erase(i++);
- }
- }
- i = regex_pattern_singletons_.begin();
- while (i != regex_pattern_singletons_.end()) {
- if (ContainsKey(used_patterns, (*i)->id())) {
- ++i;
- } else {
- delete *i;
- regex_pattern_singletons_.erase(i++);
- }
- }
- i = origin_and_path_regex_pattern_singletons_.begin();
- while (i != origin_and_path_regex_pattern_singletons_.end()) {
- if (ContainsKey(used_patterns, (*i)->id())) {
- ++i;
- } else {
- delete *i;
- origin_and_path_regex_pattern_singletons_.erase(i++);
- }
- }
-}
-
-bool URLMatcherConditionFactory::IsEmpty() const {
- return substring_pattern_singletons_.empty() &&
- regex_pattern_singletons_.empty() &&
- origin_and_path_regex_pattern_singletons_.empty();
-}
-
-URLMatcherCondition URLMatcherConditionFactory::CreateCondition(
- URLMatcherCondition::Criterion criterion,
- const std::string& pattern) {
- StringPattern search_pattern(pattern, 0);
- PatternSingletons* pattern_singletons = NULL;
- if (IsRegexCriterion(criterion))
- pattern_singletons = &regex_pattern_singletons_;
- else if (IsOriginAndPathRegexCriterion(criterion))
- pattern_singletons = &origin_and_path_regex_pattern_singletons_;
- else
- pattern_singletons = &substring_pattern_singletons_;
-
- PatternSingletons::const_iterator iter =
- pattern_singletons->find(&search_pattern);
-
- if (iter != pattern_singletons->end()) {
- return URLMatcherCondition(criterion, *iter);
- } else {
- StringPattern* new_pattern =
- new StringPattern(pattern, id_counter_++);
- pattern_singletons->insert(new_pattern);
- return URLMatcherCondition(criterion, new_pattern);
- }
-}
-
-std::string URLMatcherConditionFactory::CanonicalizeHostname(
- const std::string& hostname) const {
- if (!hostname.empty() && hostname[0] == '.')
- return hostname;
- else
- return "." + hostname;
-}
-
-bool URLMatcherConditionFactory::StringPatternPointerCompare::operator()(
- StringPattern* lhs,
- StringPattern* rhs) const {
- if (lhs == NULL && rhs != NULL) return true;
- if (lhs != NULL && rhs != NULL)
- return lhs->pattern() < rhs->pattern();
- // Either both are NULL or only rhs is NULL.
- return false;
-}
-
-//
-// URLMatcherSchemeFilter
-//
-
-URLMatcherSchemeFilter::URLMatcherSchemeFilter(const std::string& filter)
- : filters_(1) {
- filters_.push_back(filter);
-}
-
-URLMatcherSchemeFilter::URLMatcherSchemeFilter(
- const std::vector<std::string>& filters)
- : filters_(filters) {}
-
-URLMatcherSchemeFilter::~URLMatcherSchemeFilter() {}
-
-bool URLMatcherSchemeFilter::IsMatch(const GURL& url) const {
- return std::find(filters_.begin(), filters_.end(), url.scheme()) !=
- filters_.end();
-}
-
-//
-// URLMatcherPortFilter
-//
-
-URLMatcherPortFilter::URLMatcherPortFilter(
- const std::vector<URLMatcherPortFilter::Range>& ranges)
- : ranges_(ranges) {}
-
-URLMatcherPortFilter::~URLMatcherPortFilter() {}
-
-bool URLMatcherPortFilter::IsMatch(const GURL& url) const {
- int port = url.EffectiveIntPort();
- for (std::vector<Range>::const_iterator i = ranges_.begin();
- i != ranges_.end(); ++i) {
- if (i->first <= port && port <= i->second)
- return true;
- }
- return false;
-}
-
-// static
-URLMatcherPortFilter::Range URLMatcherPortFilter::CreateRange(int from,
- int to) {
- return Range(from, to);
-}
-
-// static
-URLMatcherPortFilter::Range URLMatcherPortFilter::CreateRange(int port) {
- return Range(port, port);
-}
-
-//
-// URLMatcherConditionSet
-//
-
-URLMatcherConditionSet::~URLMatcherConditionSet() {}
-
-URLMatcherConditionSet::URLMatcherConditionSet(
- ID id,
- const Conditions& conditions)
- : id_(id),
- conditions_(conditions) {}
-
-URLMatcherConditionSet::URLMatcherConditionSet(
- ID id,
- const Conditions& conditions,
- scoped_ptr<URLMatcherSchemeFilter> scheme_filter,
- scoped_ptr<URLMatcherPortFilter> port_filter)
- : id_(id),
- conditions_(conditions),
- scheme_filter_(scheme_filter.Pass()),
- port_filter_(port_filter.Pass()) {}
-
-bool URLMatcherConditionSet::IsMatch(
- const std::set<StringPattern::ID>& matching_patterns,
- const GURL& url) const {
- for (Conditions::const_iterator i = conditions_.begin();
- i != conditions_.end(); ++i) {
- if (!i->IsMatch(matching_patterns, url))
- return false;
- }
- if (scheme_filter_.get() && !scheme_filter_->IsMatch(url))
- return false;
- if (port_filter_.get() && !port_filter_->IsMatch(url))
- return false;
- return true;
-}
-
-//
-// URLMatcher
-//
-
-URLMatcher::URLMatcher() {}
-
-URLMatcher::~URLMatcher() {}
-
-void URLMatcher::AddConditionSets(
- const URLMatcherConditionSet::Vector& condition_sets) {
- for (URLMatcherConditionSet::Vector::const_iterator i =
- condition_sets.begin(); i != condition_sets.end(); ++i) {
- DCHECK(url_matcher_condition_sets_.find((*i)->id()) ==
- url_matcher_condition_sets_.end());
- url_matcher_condition_sets_[(*i)->id()] = *i;
- }
- UpdateInternalDatastructures();
-}
-
-void URLMatcher::RemoveConditionSets(
- const std::vector<URLMatcherConditionSet::ID>& condition_set_ids) {
- for (std::vector<URLMatcherConditionSet::ID>::const_iterator i =
- condition_set_ids.begin(); i != condition_set_ids.end(); ++i) {
- DCHECK(url_matcher_condition_sets_.find(*i) !=
- url_matcher_condition_sets_.end());
- url_matcher_condition_sets_.erase(*i);
- }
- UpdateInternalDatastructures();
-}
-
-void URLMatcher::ClearUnusedConditionSets() {
- UpdateConditionFactory();
-}
-
-std::set<URLMatcherConditionSet::ID> URLMatcher::MatchURL(
- const GURL& url) const {
- // Find all IDs of StringPatterns that match |url|.
- // See URLMatcherConditionFactory for the canonicalization of URLs and the
- // distinction between full url searches and url component searches.
- std::set<StringPattern::ID> matches;
- if (!full_url_matcher_.IsEmpty()) {
- full_url_matcher_.Match(
- condition_factory_.CanonicalizeURLForFullSearches(url), &matches);
- }
- if (!url_component_matcher_.IsEmpty()) {
- url_component_matcher_.Match(
- condition_factory_.CanonicalizeURLForComponentSearches(url), &matches);
- }
- if (!regex_set_matcher_.IsEmpty()) {
- regex_set_matcher_.Match(
- condition_factory_.CanonicalizeURLForRegexSearches(url), &matches);
- }
- if (!origin_and_path_regex_set_matcher_.IsEmpty()) {
- origin_and_path_regex_set_matcher_.Match(
- condition_factory_.CanonicalizeURLForOriginAndPathRegexSearches(url),
- &matches);
- }
-
- // Calculate all URLMatcherConditionSets for which all URLMatcherConditions
- // were fulfilled.
- std::set<URLMatcherConditionSet::ID> result;
- for (std::set<StringPattern::ID>::const_iterator i = matches.begin();
- i != matches.end(); ++i) {
- // For each URLMatcherConditionSet there is exactly one condition
- // registered in substring_match_triggers_. This means that the following
- // logic tests each URLMatcherConditionSet exactly once if it can be
- // completely fulfilled.
- StringPatternTriggers::const_iterator triggered_condition_sets_iter =
- substring_match_triggers_.find(*i);
- if (triggered_condition_sets_iter == substring_match_triggers_.end())
- continue; // Not all substring matches are triggers for a condition set.
- const std::set<URLMatcherConditionSet::ID>& condition_sets =
- triggered_condition_sets_iter->second;
- for (std::set<URLMatcherConditionSet::ID>::const_iterator j =
- condition_sets.begin(); j != condition_sets.end(); ++j) {
- URLMatcherConditionSets::const_iterator condition_set_iter =
- url_matcher_condition_sets_.find(*j);
- DCHECK(condition_set_iter != url_matcher_condition_sets_.end());
- if (condition_set_iter->second->IsMatch(matches, url))
- result.insert(*j);
- }
- }
-
- return result;
-}
-
-bool URLMatcher::IsEmpty() const {
- return condition_factory_.IsEmpty() &&
- url_matcher_condition_sets_.empty() &&
- substring_match_triggers_.empty() &&
- full_url_matcher_.IsEmpty() &&
- url_component_matcher_.IsEmpty() &&
- regex_set_matcher_.IsEmpty() &&
- origin_and_path_regex_set_matcher_.IsEmpty() &&
- registered_full_url_patterns_.empty() &&
- registered_url_component_patterns_.empty();
-}
-
-void URLMatcher::UpdateSubstringSetMatcher(bool full_url_conditions) {
- // The purpose of |full_url_conditions| is just that we need to execute
- // the same logic once for Full URL searches and once for URL Component
- // searches (see URLMatcherConditionFactory).
-
- // Determine which patterns need to be registered when this function
- // terminates.
- std::set<const StringPattern*> new_patterns;
- for (URLMatcherConditionSets::const_iterator condition_set_iter =
- url_matcher_condition_sets_.begin();
- condition_set_iter != url_matcher_condition_sets_.end();
- ++condition_set_iter) {
- const URLMatcherConditionSet::Conditions& conditions =
- condition_set_iter->second->conditions();
- for (URLMatcherConditionSet::Conditions::const_iterator condition_iter =
- conditions.begin(); condition_iter != conditions.end();
- ++condition_iter) {
- // If we are called to process Full URL searches, ignore others, and
- // vice versa. (Regex conditions are updated in UpdateRegexSetMatcher.)
- if (!condition_iter->IsRegexCondition() &&
- !condition_iter->IsOriginAndPathRegexCondition() &&
- full_url_conditions == condition_iter->IsFullURLCondition())
- new_patterns.insert(condition_iter->string_pattern());
- }
- }
-
- // This is the set of patterns that were registered before this function
- // is called.
- std::set<const StringPattern*>& registered_patterns =
- full_url_conditions ? registered_full_url_patterns_
- : registered_url_component_patterns_;
-
- // Add all patterns that are in new_patterns but not in registered_patterns.
- std::vector<const StringPattern*> patterns_to_register =
- base::STLSetDifference<std::vector<const StringPattern*> >(
- new_patterns, registered_patterns);
-
- // Remove all patterns that are in registered_patterns but not in
- // new_patterns.
- std::vector<const StringPattern*> patterns_to_unregister =
- base::STLSetDifference<std::vector<const StringPattern*> >(
- registered_patterns, new_patterns);
-
- // Update the SubstringSetMatcher.
- SubstringSetMatcher& url_matcher =
- full_url_conditions ? full_url_matcher_ : url_component_matcher_;
- url_matcher.RegisterAndUnregisterPatterns(patterns_to_register,
- patterns_to_unregister);
-
- // Update the set of registered_patterns for the next time this function
- // is being called.
- registered_patterns.swap(new_patterns);
-}
-
-void URLMatcher::UpdateRegexSetMatcher() {
- std::vector<const StringPattern*> new_patterns;
- std::vector<const StringPattern*> new_origin_and_path_patterns;
-
- for (URLMatcherConditionSets::const_iterator condition_set_iter =
- url_matcher_condition_sets_.begin();
- condition_set_iter != url_matcher_condition_sets_.end();
- ++condition_set_iter) {
- const URLMatcherConditionSet::Conditions& conditions =
- condition_set_iter->second->conditions();
- for (URLMatcherConditionSet::Conditions::const_iterator condition_iter =
- conditions.begin(); condition_iter != conditions.end();
- ++condition_iter) {
- if (condition_iter->IsRegexCondition()) {
- new_patterns.push_back(condition_iter->string_pattern());
- } else if (condition_iter->IsOriginAndPathRegexCondition()) {
- new_origin_and_path_patterns.push_back(
- condition_iter->string_pattern());
- }
- }
- }
-
- // Start over from scratch. We can't really do better than this, since the
- // FilteredRE2 backend doesn't support incremental updates.
- regex_set_matcher_.ClearPatterns();
- regex_set_matcher_.AddPatterns(new_patterns);
- origin_and_path_regex_set_matcher_.ClearPatterns();
- origin_and_path_regex_set_matcher_.AddPatterns(new_origin_and_path_patterns);
-}
-
-void URLMatcher::UpdateTriggers() {
- // Count substring pattern frequencies.
- std::map<StringPattern::ID, size_t> substring_pattern_frequencies;
- for (URLMatcherConditionSets::const_iterator condition_set_iter =
- url_matcher_condition_sets_.begin();
- condition_set_iter != url_matcher_condition_sets_.end();
- ++condition_set_iter) {
- const URLMatcherConditionSet::Conditions& conditions =
- condition_set_iter->second->conditions();
- for (URLMatcherConditionSet::Conditions::const_iterator condition_iter =
- conditions.begin(); condition_iter != conditions.end();
- ++condition_iter) {
- const StringPattern* pattern = condition_iter->string_pattern();
- substring_pattern_frequencies[pattern->id()]++;
- }
- }
-
- // Update trigger conditions: Determine for each URLMatcherConditionSet which
- // URLMatcherCondition contains a StringPattern that occurs least
- // frequently in this URLMatcher. We assume that this condition is very
- // specific and occurs rarely in URLs. If a match occurs for this
- // URLMatcherCondition, we want to test all other URLMatcherCondition in the
- // respective URLMatcherConditionSet as well to see whether the entire
- // URLMatcherConditionSet is considered matching.
- substring_match_triggers_.clear();
- for (URLMatcherConditionSets::const_iterator condition_set_iter =
- url_matcher_condition_sets_.begin();
- condition_set_iter != url_matcher_condition_sets_.end();
- ++condition_set_iter) {
- const URLMatcherConditionSet::Conditions& conditions =
- condition_set_iter->second->conditions();
- if (conditions.empty())
- continue;
- URLMatcherConditionSet::Conditions::const_iterator condition_iter =
- conditions.begin();
- StringPattern::ID trigger = condition_iter->string_pattern()->id();
- // We skip the first element in the following loop.
- ++condition_iter;
- for (; condition_iter != conditions.end(); ++condition_iter) {
- StringPattern::ID current_id =
- condition_iter->string_pattern()->id();
- if (substring_pattern_frequencies[trigger] >
- substring_pattern_frequencies[current_id]) {
- trigger = current_id;
- }
- }
- substring_match_triggers_[trigger].insert(condition_set_iter->second->id());
- }
-}
-
-void URLMatcher::UpdateConditionFactory() {
- std::set<StringPattern::ID> used_patterns;
- for (URLMatcherConditionSets::const_iterator condition_set_iter =
- url_matcher_condition_sets_.begin();
- condition_set_iter != url_matcher_condition_sets_.end();
- ++condition_set_iter) {
- const URLMatcherConditionSet::Conditions& conditions =
- condition_set_iter->second->conditions();
- for (URLMatcherConditionSet::Conditions::const_iterator condition_iter =
- conditions.begin(); condition_iter != conditions.end();
- ++condition_iter) {
- used_patterns.insert(condition_iter->string_pattern()->id());
- }
- }
- condition_factory_.ForgetUnusedPatterns(used_patterns);
-}
-
-void URLMatcher::UpdateInternalDatastructures() {
- UpdateSubstringSetMatcher(false);
- UpdateSubstringSetMatcher(true);
- UpdateRegexSetMatcher();
- UpdateTriggers();
- UpdateConditionFactory();
-}
-
-} // namespace extensions
diff --git a/extensions/common/matcher/url_matcher.h b/extensions/common/matcher/url_matcher.h
deleted file mode 100644
index d93a606701..0000000000
--- a/extensions/common/matcher/url_matcher.h
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright (c) 2012 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_MATCHER_URL_MATCHER_H_
-#define EXTENSIONS_COMMON_MATCHER_URL_MATCHER_H_
-
-#include <set>
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "extensions/common/matcher/regex_set_matcher.h"
-#include "extensions/common/matcher/substring_set_matcher.h"
-
-class GURL;
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace extensions {
-
-// This class represents a single URL matching condition, e.g. a match on the
-// host suffix or the containment of a string in the query component of a GURL.
-//
-// The difference from a simple StringPattern is that this also supports
-// checking whether the {Host, Path, Query} of a URL contains a string. The
-// reduction of URL matching conditions to StringPatterns conducted by
-// URLMatcherConditionFactory is not capable of expressing that alone.
-//
-// Also supported is matching regular expressions against the URL (URL_MATCHES).
-class URLMatcherCondition {
- public:
- enum Criterion {
- HOST_PREFIX,
- HOST_SUFFIX,
- HOST_CONTAINS,
- HOST_EQUALS,
- PATH_PREFIX,
- PATH_SUFFIX,
- PATH_CONTAINS,
- PATH_EQUALS,
- QUERY_PREFIX,
- QUERY_SUFFIX,
- QUERY_CONTAINS,
- QUERY_EQUALS,
- HOST_SUFFIX_PATH_PREFIX,
- HOST_EQUALS_PATH_PREFIX,
- URL_PREFIX,
- URL_SUFFIX,
- URL_CONTAINS,
- URL_EQUALS,
- URL_MATCHES,
- ORIGIN_AND_PATH_MATCHES, // Matches the URL minus its query string.
- };
-
- URLMatcherCondition();
- ~URLMatcherCondition();
- URLMatcherCondition(Criterion criterion,
- const StringPattern* substring_pattern);
- URLMatcherCondition(const URLMatcherCondition& rhs);
- URLMatcherCondition& operator=(const URLMatcherCondition& rhs);
- bool operator<(const URLMatcherCondition& rhs) const;
-
- Criterion criterion() const { return criterion_; }
- const StringPattern* string_pattern() const {
- return string_pattern_;
- }
-
- // Returns whether this URLMatcherCondition needs to be executed on a
- // full URL rather than the individual components (see
- // URLMatcherConditionFactory).
- bool IsFullURLCondition() const;
-
- // Returns whether this URLMatcherCondition is a regular expression to be
- // handled by a regex matcher instead of a substring matcher.
- bool IsRegexCondition() const;
-
- // Returns whether this URLMatcherCondition is a regular expression that shall
- // be evaluated on the URL without the query parameter.
- bool IsOriginAndPathRegexCondition() const;
-
- // Returns whether this condition is fulfilled according to
- // |matching_patterns| and |url|.
- bool IsMatch(const std::set<StringPattern::ID>& matching_patterns,
- const GURL& url) const;
-
- private:
- // |criterion_| and |string_pattern_| describe together what property a URL
- // needs to fulfill to be considered a match.
- Criterion criterion_;
-
- // This is the StringPattern that is used in a SubstringSetMatcher.
- const StringPattern* string_pattern_;
-};
-
-// Class to map the problem of finding {host, path, query} {prefixes, suffixes,
-// containments, and equality} in GURLs to the substring matching problem.
-//
-// Say, you want to check whether the path of a URL starts with "/index.html".
-// This class preprocesses a URL like "www.google.com/index.html" into something
-// like "www.google.com|/index.html". After preprocessing, you can search for
-// "|/index.html" in the string and see that this candidate URL actually has
-// a path that starts with "/index.html". On the contrary,
-// "www.google.com/images/index.html" would be normalized to
-// "www.google.com|/images/index.html". It is easy to see that it contains
-// "/index.html" but the path of the URL does not start with "/index.html".
-//
-// This preprocessing is important if you want to match a URL against many
-// patterns because it reduces the matching to a "discover all substrings
-// of a dictionary in a text" problem, which can be solved very efficiently
-// by the Aho-Corasick algorithm.
-//
-// IMPORTANT: The URLMatcherConditionFactory owns the StringPattern
-// referenced by created URLMatcherConditions. Therefore, it must outlive
-// all created URLMatcherCondition and the SubstringSetMatcher.
-class URLMatcherConditionFactory {
- public:
- URLMatcherConditionFactory();
- ~URLMatcherConditionFactory();
-
- // Canonicalizes a URL for "Create{Host,Path,Query}*Condition" searches.
- std::string CanonicalizeURLForComponentSearches(const GURL& url) const;
-
- // Factory methods for various condition types.
- //
- // Note that these methods fill the pattern_singletons_. If you create
- // conditions and don't register them to a URLMatcher, they will continue to
- // consume memory. You need to call ForgetUnusedPatterns() or
- // URLMatcher::ClearUnusedConditionSets() in this case.
- URLMatcherCondition CreateHostPrefixCondition(const std::string& prefix);
- URLMatcherCondition CreateHostSuffixCondition(const std::string& suffix);
- URLMatcherCondition CreateHostContainsCondition(const std::string& str);
- URLMatcherCondition CreateHostEqualsCondition(const std::string& str);
-
- URLMatcherCondition CreatePathPrefixCondition(const std::string& prefix);
- URLMatcherCondition CreatePathSuffixCondition(const std::string& suffix);
- URLMatcherCondition CreatePathContainsCondition(const std::string& str);
- URLMatcherCondition CreatePathEqualsCondition(const std::string& str);
-
- URLMatcherCondition CreateQueryPrefixCondition(const std::string& prefix);
- URLMatcherCondition CreateQuerySuffixCondition(const std::string& suffix);
- URLMatcherCondition CreateQueryContainsCondition(const std::string& str);
- URLMatcherCondition CreateQueryEqualsCondition(const std::string& str);
-
- // This covers the common case, where you don't care whether a domain
- // "foobar.com" is expressed as "foobar.com" or "www.foobar.com", and it
- // should be followed by a given |path_prefix|.
- URLMatcherCondition CreateHostSuffixPathPrefixCondition(
- const std::string& host_suffix,
- const std::string& path_prefix);
- URLMatcherCondition CreateHostEqualsPathPrefixCondition(
- const std::string& host,
- const std::string& path_prefix);
-
- // Canonicalizes a URL for "CreateURL*Condition" searches.
- std::string CanonicalizeURLForFullSearches(const GURL& url) const;
-
- // Canonicalizes a URL for "CreateURLMatchesCondition" searches.
- std::string CanonicalizeURLForRegexSearches(const GURL& url) const;
- // Canonicalizes a URL for "CreateOriginAndPathMatchesCondition" searches.
- std::string CanonicalizeURLForOriginAndPathRegexSearches(
- const GURL& url) const;
-
- URLMatcherCondition CreateURLPrefixCondition(const std::string& prefix);
- URLMatcherCondition CreateURLSuffixCondition(const std::string& suffix);
- URLMatcherCondition CreateURLContainsCondition(const std::string& str);
- URLMatcherCondition CreateURLEqualsCondition(const std::string& str);
-
- URLMatcherCondition CreateURLMatchesCondition(const std::string& regex);
- URLMatcherCondition CreateOriginAndPathMatchesCondition(
- const std::string& regex);
-
- // Removes all patterns from |pattern_singletons_| that are not listed in
- // |used_patterns|. These patterns are not referenced any more and get
- // freed.
- void ForgetUnusedPatterns(
- const std::set<StringPattern::ID>& used_patterns);
-
- // Returns true if this object retains no allocated data. Only for debugging.
- bool IsEmpty() const;
-
- private:
- // Creates a URLMatcherCondition according to the parameters passed.
- // The URLMatcherCondition will refer to a StringPattern that is
- // owned by |pattern_singletons_|.
- URLMatcherCondition CreateCondition(URLMatcherCondition::Criterion criterion,
- const std::string& pattern);
-
- // Prepends a "." to the hostname if it does not start with one.
- std::string CanonicalizeHostname(const std::string& hostname) const;
-
- // Counter that ensures that all created StringPatterns have unique IDs.
- // Note that substring patterns and regex patterns will use different IDs.
- int id_counter_;
-
- // This comparison considers only the pattern() value of the
- // StringPatterns.
- struct StringPatternPointerCompare {
- bool operator()(StringPattern* lhs, StringPattern* rhs) const;
- };
- // Set to ensure that we generate only one StringPattern for each content
- // of StringPattern::pattern().
- typedef std::set<StringPattern*, StringPatternPointerCompare>
- PatternSingletons;
- PatternSingletons substring_pattern_singletons_;
- PatternSingletons regex_pattern_singletons_;
- PatternSingletons origin_and_path_regex_pattern_singletons_;
-
- DISALLOW_COPY_AND_ASSIGN(URLMatcherConditionFactory);
-};
-
-// This class represents a filter for the URL scheme to be hooked up into a
-// URLMatcherConditionSet.
-class URLMatcherSchemeFilter {
- public:
- explicit URLMatcherSchemeFilter(const std::string& filter);
- explicit URLMatcherSchemeFilter(const std::vector<std::string>& filters);
- ~URLMatcherSchemeFilter();
- bool IsMatch(const GURL& url) const;
-
- private:
- std::vector<std::string> filters_;
-
- DISALLOW_COPY_AND_ASSIGN(URLMatcherSchemeFilter);
-};
-
-// This class represents a filter for port numbers to be hooked up into a
-// URLMatcherConditionSet.
-class URLMatcherPortFilter {
- public:
- // Boundaries of a port range (both ends are included).
- typedef std::pair<int, int> Range;
- explicit URLMatcherPortFilter(const std::vector<Range>& ranges);
- ~URLMatcherPortFilter();
- bool IsMatch(const GURL& url) const;
-
- // Creates a port range [from, to]; both ends are included.
- static Range CreateRange(int from, int to);
- // Creates a port range containing a single port.
- static Range CreateRange(int port);
-
- private:
- std::vector<Range> ranges_;
-
- DISALLOW_COPY_AND_ASSIGN(URLMatcherPortFilter);
-};
-
-// This class represents a set of conditions that all need to match on a
-// given URL in order to be considered a match.
-class URLMatcherConditionSet : public base::RefCounted<URLMatcherConditionSet> {
- public:
- typedef int ID;
- typedef std::set<URLMatcherCondition> Conditions;
- typedef std::vector<scoped_refptr<URLMatcherConditionSet> > Vector;
-
- // Matches if all conditions in |conditions| are fulfilled.
- URLMatcherConditionSet(ID id, const Conditions& conditions);
-
- // Matches if all conditions in |conditions|, |scheme_filter| and
- // |port_filter| are fulfilled. |scheme_filter| and |port_filter| may be NULL,
- // in which case, no restrictions are imposed on the scheme/port of a URL.
- URLMatcherConditionSet(ID id, const Conditions& conditions,
- scoped_ptr<URLMatcherSchemeFilter> scheme_filter,
- scoped_ptr<URLMatcherPortFilter> port_filter);
-
- ID id() const { return id_; }
- const Conditions& conditions() const { return conditions_; }
-
- bool IsMatch(const std::set<StringPattern::ID>& matching_patterns,
- const GURL& url) const;
-
- private:
- friend class base::RefCounted<URLMatcherConditionSet>;
- ~URLMatcherConditionSet();
- ID id_;
- Conditions conditions_;
- scoped_ptr<URLMatcherSchemeFilter> scheme_filter_;
- scoped_ptr<URLMatcherPortFilter> port_filter_;
-
- DISALLOW_COPY_AND_ASSIGN(URLMatcherConditionSet);
-};
-
-// This class allows matching one URL against a large set of
-// URLMatcherConditionSets at the same time.
-class URLMatcher {
- public:
- URLMatcher();
- ~URLMatcher();
-
- // Adds new URLMatcherConditionSet to this URL Matcher. Each condition set
- // must have a unique ID.
- // This is an expensive operation as it triggers pre-calculations on the
- // currently registered condition sets. Do not call this operation many
- // times with a single condition set in each call.
- void AddConditionSets(const URLMatcherConditionSet::Vector& condition_sets);
-
- // Removes the listed condition sets. All |condition_set_ids| must be
- // currently registered. This function should be called with large batches
- // of |condition_set_ids| at a time to improve performance.
- void RemoveConditionSets(
- const std::vector<URLMatcherConditionSet::ID>& condition_set_ids);
-
- // Removes all unused condition sets from the ConditionFactory.
- void ClearUnusedConditionSets();
-
- // Returns the IDs of all URLMatcherConditionSet that match to this |url|.
- std::set<URLMatcherConditionSet::ID> MatchURL(const GURL& url) const;
-
- // Returns the URLMatcherConditionFactory that must be used to create
- // URLMatcherConditionSets for this URLMatcher.
- URLMatcherConditionFactory* condition_factory() {
- return &condition_factory_;
- }
-
- // Returns true if this object retains no allocated data. Only for debugging.
- bool IsEmpty() const;
-
- private:
- void UpdateSubstringSetMatcher(bool full_url_conditions);
- void UpdateRegexSetMatcher();
- void UpdateTriggers();
- void UpdateConditionFactory();
- void UpdateInternalDatastructures();
-
- URLMatcherConditionFactory condition_factory_;
-
- // Maps the ID of a URLMatcherConditionSet to the respective
- // URLMatcherConditionSet.
- typedef std::map<URLMatcherConditionSet::ID,
- scoped_refptr<URLMatcherConditionSet> >
- URLMatcherConditionSets;
- URLMatcherConditionSets url_matcher_condition_sets_;
-
- // Maps a StringPattern ID to the URLMatcherConditions that need to
- // be triggered in case of a StringPattern match.
- typedef std::map<StringPattern::ID, std::set<URLMatcherConditionSet::ID> >
- StringPatternTriggers;
- StringPatternTriggers substring_match_triggers_;
-
- SubstringSetMatcher full_url_matcher_;
- SubstringSetMatcher url_component_matcher_;
- RegexSetMatcher regex_set_matcher_;
- RegexSetMatcher origin_and_path_regex_set_matcher_;
- std::set<const StringPattern*> registered_full_url_patterns_;
- std::set<const StringPattern*> registered_url_component_patterns_;
-
- DISALLOW_COPY_AND_ASSIGN(URLMatcher);
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_URL_MATCHER_H_
diff --git a/extensions/common/matcher/url_matcher_constants.cc b/extensions/common/matcher/url_matcher_constants.cc
deleted file mode 100644
index 5b23dea09a..0000000000
--- a/extensions/common/matcher/url_matcher_constants.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 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/matcher/url_matcher_constants.h"
-
-namespace extensions {
-namespace url_matcher_constants {
-
-// Keys of dictionaries for URL constraints
-const char kPortsKey[] = "ports";
-const char kSchemesKey[] = "schemes";
-const char kHostContainsKey[] = "hostContains";
-const char kHostEqualsKey[] = "hostEquals";
-const char kHostPrefixKey[] = "hostPrefix";
-const char kHostSuffixKey[] = "hostSuffix";
-const char kHostSuffixPathPrefixKey[] = "hostSuffixPathPrefix";
-const char kOriginAndPathMatchesKey[] = "originAndPathMatches";
-const char kPathContainsKey[] = "pathContains";
-const char kPathEqualsKey[] = "pathEquals";
-const char kPathPrefixKey[] = "pathPrefix";
-const char kPathSuffixKey[] = "pathSuffix";
-const char kQueryContainsKey[] = "queryContains";
-const char kQueryEqualsKey[] = "queryEquals";
-const char kQueryPrefixKey[] = "queryPrefix";
-const char kQuerySuffixKey[] = "querySuffix";
-const char kURLContainsKey[] = "urlContains";
-const char kURLEqualsKey[] = "urlEquals";
-const char kURLMatchesKey[] = "urlMatches";
-const char kURLPrefixKey[] = "urlPrefix";
-const char kURLSuffixKey[] = "urlSuffix";
-
-} // namespace url_matcher_constants
-} // namespace extensions
diff --git a/extensions/common/matcher/url_matcher_constants.h b/extensions/common/matcher/url_matcher_constants.h
deleted file mode 100644
index 0618a52157..0000000000
--- a/extensions/common/matcher/url_matcher_constants.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Constants used for the URLMatcher component of the Declarative API.
-
-#ifndef EXTENSIONS_COMMON_MATCHER_URL_MATCHER_CONSTANTS_H_
-#define EXTENSIONS_COMMON_MATCHER_URL_MATCHER_CONSTANTS_H_
-
-namespace extensions {
-namespace url_matcher_constants {
-
-// Keys of dictionaries for URL constraints
-extern const char kPortsKey[];
-extern const char kSchemesKey[];
-extern const char kHostContainsKey[];
-extern const char kHostEqualsKey[];
-extern const char kHostPrefixKey[];
-extern const char kHostSuffixKey[];
-extern const char kHostSuffixPathPrefixKey[];
-extern const char kOriginAndPathMatchesKey[];
-extern const char kPathContainsKey[];
-extern const char kPathEqualsKey[];
-extern const char kPathPrefixKey[];
-extern const char kPathSuffixKey[];
-extern const char kQueryContainsKey[];
-extern const char kQueryEqualsKey[];
-extern const char kQueryPrefixKey[];
-extern const char kQuerySuffixKey[];
-extern const char kURLContainsKey[];
-extern const char kURLEqualsKey[];
-extern const char kURLMatchesKey[];
-extern const char kURLPrefixKey[];
-extern const char kURLSuffixKey[];
-
-} // namespace url_matcher_constants
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_URL_MATCHER_CONSTANTS_H_
diff --git a/extensions/common/matcher/url_matcher_factory.cc b/extensions/common/matcher/url_matcher_factory.cc
deleted file mode 100644
index 6eec2e6ab1..0000000000
--- a/extensions/common/matcher/url_matcher_factory.cc
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright (c) 2012 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/matcher/url_matcher_factory.h"
-
-#include <algorithm>
-#include <cctype>
-
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "extensions/common/error_utils.h"
-#include "extensions/common/matcher/url_matcher_constants.h"
-#include "extensions/common/matcher/url_matcher_helpers.h"
-#include "third_party/re2/re2/re2.h"
-
-namespace helpers = extensions::url_matcher_helpers;
-namespace keys = extensions::url_matcher_constants;
-
-namespace {
-// Error messages:
-const char kInvalidPortRanges[] = "Invalid port ranges in UrlFilter.";
-const char kVectorOfStringsExpected[] =
- "UrlFilter attribute '*' expected a vector of strings as parameter.";
-const char kUnknownURLFilterAttribute[] =
- "Unknown attribute '*' in UrlFilter.";
-const char kAttributeExpectedString[] =
- "UrlFilter attribute '*' expected a string value.";
-const char kUnparseableRegexString[] =
- "Could not parse regular expression '*': *";
-const char kLowerCaseExpected[] = "* values need to be in lower case.";
-
-// Registry for all factory methods of extensions::URLMatcherConditionFactory
-// that allows translating string literals from the extension API into
-// the corresponding factory method to be called.
-class URLMatcherConditionFactoryMethods {
- public:
- URLMatcherConditionFactoryMethods() {
- typedef extensions::URLMatcherConditionFactory F;
- factory_methods_[keys::kHostContainsKey] = &F::CreateHostContainsCondition;
- factory_methods_[keys::kHostEqualsKey] = &F::CreateHostEqualsCondition;
- factory_methods_[keys::kHostPrefixKey] = &F::CreateHostPrefixCondition;
- factory_methods_[keys::kHostSuffixKey] = &F::CreateHostSuffixCondition;
- factory_methods_[keys::kOriginAndPathMatchesKey] =
- &F::CreateOriginAndPathMatchesCondition;
- factory_methods_[keys::kPathContainsKey] = &F::CreatePathContainsCondition;
- factory_methods_[keys::kPathEqualsKey] = &F::CreatePathEqualsCondition;
- factory_methods_[keys::kPathPrefixKey] = &F::CreatePathPrefixCondition;
- factory_methods_[keys::kPathSuffixKey] = &F::CreatePathSuffixCondition;
- factory_methods_[keys::kQueryContainsKey] =
- &F::CreateQueryContainsCondition;
- factory_methods_[keys::kQueryEqualsKey] = &F::CreateQueryEqualsCondition;
- factory_methods_[keys::kQueryPrefixKey] = &F::CreateQueryPrefixCondition;
- factory_methods_[keys::kQuerySuffixKey] = &F::CreateQuerySuffixCondition;
- factory_methods_[keys::kURLContainsKey] = &F::CreateURLContainsCondition;
- factory_methods_[keys::kURLEqualsKey] = &F::CreateURLEqualsCondition;
- factory_methods_[keys::kURLPrefixKey] = &F::CreateURLPrefixCondition;
- factory_methods_[keys::kURLSuffixKey] = &F::CreateURLSuffixCondition;
- factory_methods_[keys::kURLMatchesKey] = &F::CreateURLMatchesCondition;
- }
-
- // Returns whether a factory method for the specified |pattern_type| (e.g.
- // "host_suffix") is known.
- bool Contains(const std::string& pattern_type) const {
- return factory_methods_.find(pattern_type) != factory_methods_.end();
- }
-
- // Creates a URLMatcherCondition instance from |url_matcher_condition_factory|
- // of the given |pattern_type| (e.g. "host_suffix") for the given
- // |pattern_value| (e.g. "example.com").
- // The |pattern_type| needs to be known to this class (see Contains()) or
- // a CHECK is triggered.
- extensions::URLMatcherCondition Call(
- extensions::URLMatcherConditionFactory* url_matcher_condition_factory,
- const std::string& pattern_type,
- const std::string& pattern_value) const {
- FactoryMethods::const_iterator i = factory_methods_.find(pattern_type);
- CHECK(i != factory_methods_.end());
- const FactoryMethod& method = i->second;
- return (url_matcher_condition_factory->*method)(pattern_value);
- }
-
- private:
- typedef extensions::URLMatcherCondition
- (extensions::URLMatcherConditionFactory::* FactoryMethod)
- (const std::string& prefix);
- typedef std::map<std::string, FactoryMethod> FactoryMethods;
-
- FactoryMethods factory_methods_;
-
- DISALLOW_COPY_AND_ASSIGN(URLMatcherConditionFactoryMethods);
-};
-
-static base::LazyInstance<URLMatcherConditionFactoryMethods>
- g_url_matcher_condition_factory_methods = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-namespace extensions {
-
-// static
-scoped_refptr<URLMatcherConditionSet>
-URLMatcherFactory::CreateFromURLFilterDictionary(
- URLMatcherConditionFactory* url_matcher_condition_factory,
- const base::DictionaryValue* url_filter_dict,
- URLMatcherConditionSet::ID id,
- std::string* error) {
- scoped_ptr<URLMatcherSchemeFilter> url_matcher_schema_filter;
- scoped_ptr<URLMatcherPortFilter> url_matcher_port_filter;
- URLMatcherConditionSet::Conditions url_matcher_conditions;
-
- for (base::DictionaryValue::Iterator iter(*url_filter_dict);
- !iter.IsAtEnd(); iter.Advance()) {
- const std::string& condition_attribute_name = iter.key();
- const Value& condition_attribute_value = iter.value();
- if (IsURLMatcherConditionAttribute(condition_attribute_name)) {
- // Handle {host, path, ...}{Prefix, Suffix, Contains, Equals}.
- URLMatcherCondition url_matcher_condition =
- CreateURLMatcherCondition(
- url_matcher_condition_factory,
- condition_attribute_name,
- &condition_attribute_value,
- error);
- if (!error->empty())
- return scoped_refptr<URLMatcherConditionSet>(NULL);
- url_matcher_conditions.insert(url_matcher_condition);
- } else if (condition_attribute_name == keys::kSchemesKey) {
- // Handle scheme.
- url_matcher_schema_filter = CreateURLMatcherScheme(
- &condition_attribute_value, error);
- if (!error->empty())
- return scoped_refptr<URLMatcherConditionSet>(NULL);
- } else if (condition_attribute_name == keys::kPortsKey) {
- // Handle ports.
- url_matcher_port_filter = CreateURLMatcherPorts(
- &condition_attribute_value, error);
- if (!error->empty())
- return scoped_refptr<URLMatcherConditionSet>(NULL);
- } else {
- // Handle unknown attributes.
- *error = ErrorUtils::FormatErrorMessage(
- kUnknownURLFilterAttribute,
- condition_attribute_name);
- return scoped_refptr<URLMatcherConditionSet>(NULL);
- }
- }
-
- // As the URL is the preliminary matching criterion that triggers the tests
- // for the remaining condition attributes, we insert an empty URL match if
- // no other url match conditions were specified. Such an empty URL is always
- // matched.
- if (url_matcher_conditions.empty()) {
- url_matcher_conditions.insert(
- url_matcher_condition_factory->CreateHostPrefixCondition(
- std::string()));
- }
-
- scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set(
- new URLMatcherConditionSet(id, url_matcher_conditions,
- url_matcher_schema_filter.Pass(), url_matcher_port_filter.Pass()));
- return url_matcher_condition_set;
-}
-
-// static
-bool URLMatcherFactory::IsURLMatcherConditionAttribute(
- const std::string& condition_attribute_name) {
- return g_url_matcher_condition_factory_methods.Get().Contains(
- condition_attribute_name);
-}
-
-namespace {
-
-// Returns true if some alphabetic characters in this string are upper case.
-bool ContainsUpperCase(const std::string& str) {
- return std::find_if(str.begin(), str.end(), ::isupper) != str.end();
-}
-
-} // namespace
-
-// static
-URLMatcherCondition URLMatcherFactory::CreateURLMatcherCondition(
- URLMatcherConditionFactory* url_matcher_condition_factory,
- const std::string& condition_attribute_name,
- const base::Value* value,
- std::string* error) {
- std::string str_value;
- if (!value->GetAsString(&str_value)) {
- *error = ErrorUtils::FormatErrorMessage(kAttributeExpectedString,
- condition_attribute_name);
- return URLMatcherCondition();
- }
- if (condition_attribute_name == keys::kHostContainsKey ||
- condition_attribute_name == keys::kHostPrefixKey ||
- condition_attribute_name == keys::kHostSuffixKey ||
- condition_attribute_name == keys::kHostEqualsKey) {
- if (ContainsUpperCase(str_value)) {
- *error = ErrorUtils::FormatErrorMessage(kLowerCaseExpected,
- "Host");
- return URLMatcherCondition();
- }
- }
-
- // Test regular expressions for validity.
- if (condition_attribute_name == keys::kURLMatchesKey ||
- condition_attribute_name == keys::kOriginAndPathMatchesKey) {
- re2::RE2 regex(str_value);
- if (!regex.ok()) {
- *error = ErrorUtils::FormatErrorMessage(kUnparseableRegexString,
- str_value, regex.error());
- return URLMatcherCondition();
- }
- }
- return g_url_matcher_condition_factory_methods.Get().Call(
- url_matcher_condition_factory, condition_attribute_name, str_value);
-}
-
-// static
-scoped_ptr<URLMatcherSchemeFilter> URLMatcherFactory::CreateURLMatcherScheme(
- const base::Value* value,
- std::string* error) {
- std::vector<std::string> schemas;
- if (!helpers::GetAsStringVector(value, &schemas)) {
- *error = ErrorUtils::FormatErrorMessage(kVectorOfStringsExpected,
- keys::kSchemesKey);
- return scoped_ptr<URLMatcherSchemeFilter>();
- }
- for (std::vector<std::string>::const_iterator it = schemas.begin();
- it != schemas.end(); ++it) {
- if (ContainsUpperCase(*it)) {
- *error = ErrorUtils::FormatErrorMessage(kLowerCaseExpected,
- "Scheme");
- return scoped_ptr<URLMatcherSchemeFilter>();
- }
- }
- return scoped_ptr<URLMatcherSchemeFilter>(
- new URLMatcherSchemeFilter(schemas));
-}
-
-// static
-scoped_ptr<URLMatcherPortFilter> URLMatcherFactory::CreateURLMatcherPorts(
- const base::Value* value,
- std::string* error) {
- std::vector<URLMatcherPortFilter::Range> ranges;
- const base::ListValue* value_list = NULL;
- if (!value->GetAsList(&value_list)) {
- *error = kInvalidPortRanges;
- return scoped_ptr<URLMatcherPortFilter>();
- }
-
- for (ListValue::const_iterator i = value_list->begin();
- i != value_list->end(); ++i) {
- Value* entry = *i;
- int port = 0;
- base::ListValue* range = NULL;
- if (entry->GetAsInteger(&port)) {
- ranges.push_back(URLMatcherPortFilter::CreateRange(port));
- } else if (entry->GetAsList(&range)) {
- int from = 0, to = 0;
- if (range->GetSize() != 2u ||
- !range->GetInteger(0, &from) ||
- !range->GetInteger(1, &to)) {
- *error = kInvalidPortRanges;
- return scoped_ptr<URLMatcherPortFilter>();
- }
- ranges.push_back(URLMatcherPortFilter::CreateRange(from, to));
- } else {
- *error = kInvalidPortRanges;
- return scoped_ptr<URLMatcherPortFilter>();
- }
- }
-
- return scoped_ptr<URLMatcherPortFilter>(new URLMatcherPortFilter(ranges));
-}
-
-} // namespace extensions
diff --git a/extensions/common/matcher/url_matcher_factory.h b/extensions/common/matcher/url_matcher_factory.h
deleted file mode 100644
index 7c5be6832d..0000000000
--- a/extensions/common/matcher/url_matcher_factory.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2012 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_MATCHER_URL_MATCHER_FACTORY_H_
-#define EXTENSIONS_COMMON_MATCHER_URL_MATCHER_FACTORY_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "extensions/common/matcher/url_matcher.h"
-
-namespace base {
-class DictionaryValue;
-class Value;
-}
-
-namespace extensions {
-
-class URLMatcherFactory {
- public:
- // Creates a URLMatcherConditionSet from a UrlFilter dictionary as defined in
- // the declarative API. |url_fetcher_dict| contains the dictionary passed
- // by the extension, |id| is the identifier assigned to the created
- // URLMatcherConditionSet. In case of an error, |error| is set to contain
- // an error message.
- //
- // Note: In case this function fails or if you don't register the
- // URLMatcherConditionSet to the URLMatcher, you need to call
- // URLMatcher::ClearUnusedConditionSets() on the URLMatcher that owns this
- // URLMatcherFactory. Otherwise you leak memory.
- static scoped_refptr<URLMatcherConditionSet> CreateFromURLFilterDictionary(
- URLMatcherConditionFactory* url_matcher_condition_factory,
- const base::DictionaryValue* url_filter_dict,
- URLMatcherConditionSet::ID id,
- std::string* error);
-
- private:
- // Returns whether a condition attribute with name |condition_attribute_name|
- // needs to be handled by the URLMatcher.
- static bool IsURLMatcherConditionAttribute(
- const std::string& condition_attribute_name);
-
- // Factory method of for URLMatcherConditions.
- static URLMatcherCondition CreateURLMatcherCondition(
- URLMatcherConditionFactory* url_matcher_condition_factory,
- const std::string& condition_attribute_name,
- const base::Value* value,
- std::string* error);
-
- static scoped_ptr<URLMatcherSchemeFilter> CreateURLMatcherScheme(
- const base::Value* value, std::string* error);
-
- static scoped_ptr<URLMatcherPortFilter> CreateURLMatcherPorts(
- const base::Value* value, std::string* error);
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(URLMatcherFactory);
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_URL_MATCHER_FACTORY_H_
diff --git a/extensions/common/matcher/url_matcher_factory_unittest.cc b/extensions/common/matcher/url_matcher_factory_unittest.cc
deleted file mode 100644
index 733e1b8a94..0000000000
--- a/extensions/common/matcher/url_matcher_factory_unittest.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright (c) 2012 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/matcher/url_matcher_factory.h"
-
-#include "base/basictypes.h"
-#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "extensions/common/matcher/url_matcher_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace extensions {
-
-namespace keys = url_matcher_constants;
-
-TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) {
- URLMatcher matcher;
-
- std::string error;
- scoped_refptr<URLMatcherConditionSet> result;
-
- // Invalid key: {"invalid": "foobar"}
- DictionaryValue invalid_condition;
- invalid_condition.SetString("invalid", "foobar");
-
- // Invalid value type: {"hostSuffix": []}
- DictionaryValue invalid_condition2;
- invalid_condition2.Set(keys::kHostSuffixKey, new ListValue);
-
- // Invalid regex value: {"urlMatches": "*"}
- DictionaryValue invalid_condition3;
- invalid_condition3.SetString(keys::kURLMatchesKey, "*");
-
- // Invalid regex value: {"originAndPathMatches": "*"}
- DictionaryValue invalid_condition4;
- invalid_condition4.SetString(keys::kOriginAndPathMatchesKey, "*");
-
- // Valid values:
- // {
- // "port_range": [80, [1000, 1010]],
- // "schemes": ["http"],
- // "hostSuffix": "example.com"
- // "hostPrefix": "www"
- // }
-
- // Port range: Allow 80;1000-1010.
- ListValue* port_range = new ListValue();
- port_range->Append(Value::CreateIntegerValue(1000));
- port_range->Append(Value::CreateIntegerValue(1010));
- ListValue* port_ranges = new ListValue();
- port_ranges->Append(Value::CreateIntegerValue(80));
- port_ranges->Append(port_range);
-
- ListValue* scheme_list = new ListValue();
- scheme_list->Append(Value::CreateStringValue("http"));
-
- DictionaryValue valid_condition;
- valid_condition.SetString(keys::kHostSuffixKey, "example.com");
- valid_condition.SetString(keys::kHostPrefixKey, "www");
- valid_condition.Set(keys::kPortsKey, port_ranges);
- valid_condition.Set(keys::kSchemesKey, scheme_list);
-
- // Test wrong condition name passed.
- error.clear();
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), &invalid_condition, 1, &error);
- EXPECT_FALSE(error.empty());
- EXPECT_FALSE(result.get());
-
- // Test wrong datatype in hostSuffix.
- error.clear();
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), &invalid_condition2, 2, &error);
- EXPECT_FALSE(error.empty());
- EXPECT_FALSE(result.get());
-
- // Test invalid regex in urlMatches.
- error.clear();
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), &invalid_condition3, 3, &error);
- EXPECT_FALSE(error.empty());
- EXPECT_FALSE(result.get());
-
- error.clear();
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), &invalid_condition4, 4, &error);
- EXPECT_FALSE(error.empty());
- EXPECT_FALSE(result.get());
-
- // Test success.
- error.clear();
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), &valid_condition, 100, &error);
- EXPECT_EQ("", error);
- ASSERT_TRUE(result.get());
-
- URLMatcherConditionSet::Vector conditions;
- conditions.push_back(result);
- matcher.AddConditionSets(conditions);
-
- EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com")).size());
- EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:80")).size());
- EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:1000")).size());
- // Wrong scheme.
- EXPECT_EQ(0u, matcher.MatchURL(GURL("https://www.example.com:80")).size());
- // Wrong port.
- EXPECT_EQ(0u, matcher.MatchURL(GURL("http://www.example.com:81")).size());
- // Unfulfilled host prefix.
- EXPECT_EQ(0u, matcher.MatchURL(GURL("http://mail.example.com:81")).size());
-}
-
-// Using upper case letters for scheme and host values is currently an error.
-// See more context at http://crbug.com/160702#c6 .
-TEST(URLMatcherFactoryTest, UpperCase) {
- URLMatcher matcher;
- std::string error;
- scoped_refptr<URLMatcherConditionSet> result;
-
- // {"hostContains": "exaMple"}
- DictionaryValue invalid_condition1;
- invalid_condition1.SetString(keys::kHostContainsKey, "exaMple");
-
- // {"hostSuffix": ".Com"}
- DictionaryValue invalid_condition2;
- invalid_condition2.SetString(keys::kHostSuffixKey, ".Com");
-
- // {"hostPrefix": "WWw."}
- DictionaryValue invalid_condition3;
- invalid_condition3.SetString(keys::kHostPrefixKey, "WWw.");
-
- // {"hostEquals": "WWW.example.Com"}
- DictionaryValue invalid_condition4;
- invalid_condition4.SetString(keys::kHostEqualsKey, "WWW.example.Com");
-
- // {"scheme": ["HTTP"]}
- ListValue* scheme_list = new ListValue();
- scheme_list->Append(Value::CreateStringValue("HTTP"));
- DictionaryValue invalid_condition5;
- invalid_condition5.Set(keys::kSchemesKey, scheme_list);
-
- const DictionaryValue* invalid_conditions[] = {
- &invalid_condition1,
- &invalid_condition2,
- &invalid_condition3,
- &invalid_condition4,
- &invalid_condition5
- };
-
- for (size_t i = 0; i < arraysize(invalid_conditions); ++i) {
- error.clear();
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), invalid_conditions[i], 1, &error);
- EXPECT_FALSE(error.empty()) << "in iteration " << i;
- EXPECT_FALSE(result.get()) << "in iteration " << i;
- }
-}
-
-// This class wraps a case sensitivity test for a single UrlFilter condition.
-class UrlConditionCaseTest {
- public:
- // The condition is identified by the key |condition_key|. If that key is
- // associated with string values, then |use_list_of_strings| should be false,
- // if the key is associated with list-of-string values, then
- // |use_list_of_strings| should be true. In |url| is the URL to test against.
- UrlConditionCaseTest(const char* condition_key,
- bool use_list_of_strings,
- const std::string& expected_value,
- const std::string& incorrect_case_value,
- bool case_sensitive,
- bool lower_case_enforced,
- const GURL& url)
- : condition_key_(condition_key),
- use_list_of_strings_(use_list_of_strings),
- expected_value_(expected_value),
- incorrect_case_value_(incorrect_case_value),
- expected_result_for_wrong_case_(ExpectedResult(case_sensitive,
- lower_case_enforced)),
- url_(url) {}
-
- ~UrlConditionCaseTest() {}
-
- // Match the condition against |url_|. Checks via EXPECT_* macros that
- // |expected_value_| matches always, and that |incorrect_case_value_| matches
- // iff |case_sensitive_| is false.
- void Test() const;
-
- private:
- enum ResultType { OK, NOT_FULFILLED, CREATE_FAILURE };
-
- // What is the expected result of |CheckCondition| if a wrong-case |value|
- // containing upper case letters is supplied.
- static ResultType ExpectedResult(bool case_sensitive,
- bool lower_case_enforced) {
- if (lower_case_enforced)
- return CREATE_FAILURE;
- if (case_sensitive)
- return NOT_FULFILLED;
- return OK;
- }
-
- // Test the condition |condition_key_| = |value| against |url_|.
- // Check, via EXPECT_* macros, that either the condition cannot be constructed
- // at all, or that the condition is not fulfilled, or that it is fulfilled,
- // depending on the value of |expected_result|.
- void CheckCondition(const std::string& value,
- ResultType expected_result) const;
-
- const char* condition_key_;
- const bool use_list_of_strings_;
- const std::string& expected_value_;
- const std::string& incorrect_case_value_;
- const ResultType expected_result_for_wrong_case_;
- const GURL& url_;
-
- // Allow implicit copy and assign, because a public copy constructor is
- // needed, but never used (!), for the definition of arrays of this class.
-};
-
-void UrlConditionCaseTest::Test() const {
- CheckCondition(expected_value_, OK);
- CheckCondition(incorrect_case_value_, expected_result_for_wrong_case_);
-}
-
-void UrlConditionCaseTest::CheckCondition(
- const std::string& value,
- UrlConditionCaseTest::ResultType expected_result) const {
- DictionaryValue condition;
- if (use_list_of_strings_) {
- ListValue* list = new ListValue();
- list->Append(Value::CreateStringValue(value));
- condition.SetWithoutPathExpansion(condition_key_, list);
- } else {
- condition.SetStringWithoutPathExpansion(condition_key_, value);
- }
-
- URLMatcher matcher;
- std::string error;
- scoped_refptr<URLMatcherConditionSet> result;
-
- result = URLMatcherFactory::CreateFromURLFilterDictionary(
- matcher.condition_factory(), &condition, 1, &error);
- if (expected_result == CREATE_FAILURE) {
- EXPECT_FALSE(error.empty());
- EXPECT_FALSE(result.get());
- return;
- }
- EXPECT_EQ("", error);
- ASSERT_TRUE(result.get());
-
- URLMatcherConditionSet::Vector conditions;
- conditions.push_back(result);
- matcher.AddConditionSets(conditions);
- EXPECT_EQ((expected_result == OK ? 1u : 0u), matcher.MatchURL(url_).size())
- << "while matching condition " << condition_key_ << " with value "
- << value << " against url " << url_;
-}
-
-// This tests that the UrlFilter handles case sensitivity on various parts of
-// URLs correctly.
-TEST(URLMatcherFactoryTest, CaseSensitivity) {
- const std::string kScheme("https");
- const std::string kSchemeUpper("HTTPS");
- const std::string kHost("www.example.com");
- const std::string kHostUpper("WWW.EXAMPLE.COM");
- const std::string kPath("/path");
- const std::string kPathUpper("/PATH");
- const std::string kQuery("?option=value&A=B");
- const std::string kQueryUpper("?OPTION=VALUE&A=B");
- const std::string kUrl(kScheme + "://" + kHost + ":1234" + kPath + kQuery);
- const std::string kUrlUpper(
- kSchemeUpper + "://" + kHostUpper + ":1234" + kPathUpper + kQueryUpper);
- const GURL url(kUrl);
- // Note: according to RFC 3986, and RFC 1034, schema and host, respectively
- // should be case insensitive. See crbug.com/160702#6 for why we still
- // require them to be case sensitive in UrlFilter, and enforce lower case.
- const bool kIsSchemeLowerCaseEnforced = true;
- const bool kIsHostLowerCaseEnforced = true;
- const bool kIsPathLowerCaseEnforced = false;
- const bool kIsQueryLowerCaseEnforced = false;
- const bool kIsUrlLowerCaseEnforced = false;
- const bool kIsSchemeCaseSensitive = true;
- const bool kIsHostCaseSensitive = true;
- const bool kIsPathCaseSensitive = true;
- const bool kIsQueryCaseSensitive = true;
- const bool kIsUrlCaseSensitive = kIsSchemeCaseSensitive ||
- kIsHostCaseSensitive ||
- kIsPathCaseSensitive ||
- kIsQueryCaseSensitive;
-
- const UrlConditionCaseTest case_tests[] = {
- UrlConditionCaseTest(keys::kSchemesKey, true, kScheme, kSchemeUpper,
- kIsSchemeCaseSensitive, kIsSchemeLowerCaseEnforced,
- url),
- UrlConditionCaseTest(keys::kHostContainsKey, false, kHost, kHostUpper,
- kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kHostEqualsKey, false, kHost, kHostUpper,
- kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kHostPrefixKey, false, kHost, kHostUpper,
- kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kHostSuffixKey, false, kHost, kHostUpper,
- kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kPathContainsKey, false, kPath, kPathUpper,
- kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kPathEqualsKey, false, kPath, kPathUpper,
- kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kPathPrefixKey, false, kPath, kPathUpper,
- kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kPathSuffixKey, false, kPath, kPathUpper,
- kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kQueryContainsKey, false, kQuery, kQueryUpper,
- kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kQueryEqualsKey, false, kQuery, kQueryUpper,
- kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kQueryPrefixKey, false, kQuery, kQueryUpper,
- kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kQuerySuffixKey, false, kQuery, kQueryUpper,
- kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
- // Excluding kURLMatchesKey because case sensitivity can be specified in the
- // RE2 expression.
- UrlConditionCaseTest(keys::kURLContainsKey, false, kUrl, kUrlUpper,
- kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kURLEqualsKey, false, kUrl, kUrlUpper,
- kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kURLPrefixKey, false, kUrl, kUrlUpper,
- kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
- UrlConditionCaseTest(keys::kURLSuffixKey, false, kUrl, kUrlUpper,
- kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(case_tests); ++i) {
- SCOPED_TRACE(base::StringPrintf("Iteration: %" PRIuS, i));
- case_tests[i].Test();
- }
-}
-
-} // namespace extensions
diff --git a/extensions/common/matcher/url_matcher_helpers.cc b/extensions/common/matcher/url_matcher_helpers.cc
deleted file mode 100644
index e4832cc18a..0000000000
--- a/extensions/common/matcher/url_matcher_helpers.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 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/matcher/url_matcher_helpers.h"
-
-#include "base/values.h"
-
-namespace extensions {
-namespace url_matcher_helpers {
-
-// Converts a ValueList |value| of strings into a vector. Returns true if
-// successful.
-bool GetAsStringVector(const base::Value* value,
- std::vector<std::string>* out) {
- const ListValue* value_as_list = 0;
- if (!value->GetAsList(&value_as_list))
- return false;
-
- size_t number_types = value_as_list->GetSize();
- for (size_t i = 0; i < number_types; ++i) {
- std::string item;
- if (!value_as_list->GetString(i, &item))
- return false;
- out->push_back(item);
- }
- return true;
-}
-
-} // namespace url_matcher_helpers
-} // namespace extensions
diff --git a/extensions/common/matcher/url_matcher_helpers.h b/extensions/common/matcher/url_matcher_helpers.h
deleted file mode 100644
index 57bd2997ce..0000000000
--- a/extensions/common/matcher/url_matcher_helpers.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Helper functions used for URLMatcher and Declarative APIs.
-
-#ifndef EXTENSIONS_COMMON_MATCHER_URL_MATCHER_HELPERS_H_
-#define EXTENSIONS_COMMON_MATCHER_URL_MATCHER_HELPERS_H_
-
-#include <string>
-#include <vector>
-
-namespace base {
-class Value;
-}
-
-namespace extensions {
-namespace url_matcher_helpers {
-
-// Converts a ValueList |value| of strings into a vector. Returns true if
-// successful.
-bool GetAsStringVector(const base::Value* value, std::vector<std::string>* out);
-
-} // namespace declarative_helpers
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_MATCHER_URL_MATCHER_HELPERS_H_
diff --git a/extensions/common/matcher/url_matcher_unittest.cc b/extensions/common/matcher/url_matcher_unittest.cc
deleted file mode 100644
index 29b7c890df..0000000000
--- a/extensions/common/matcher/url_matcher_unittest.cc
+++ /dev/null
@@ -1,682 +0,0 @@
-// Copyright (c) 2012 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/matcher/url_matcher.h"
-
-#include "base/strings/string_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace extensions {
-
-//
-// URLMatcherCondition
-//
-
-TEST(URLMatcherConditionTest, Constructors) {
- StringPattern pattern("example.com", 1);
- URLMatcherCondition m1(URLMatcherCondition::HOST_SUFFIX, &pattern);
- EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX, m1.criterion());
- EXPECT_EQ(&pattern, m1.string_pattern());
-
- URLMatcherCondition m2;
- m2 = m1;
- EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX, m2.criterion());
- EXPECT_EQ(&pattern, m2.string_pattern());
-
- URLMatcherCondition m3(m1);
- EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX, m3.criterion());
- EXPECT_EQ(&pattern, m3.string_pattern());
-}
-
-TEST(URLMatcherSchemeFilter, TestMatching) {
- URLMatcherSchemeFilter filter1("https");
- std::vector<std::string> filter2_content;
- filter2_content.push_back("http");
- filter2_content.push_back("https");
- URLMatcherSchemeFilter filter2(filter2_content);
-
- GURL matching_url("https://www.foobar.com");
- GURL non_matching_url("http://www.foobar.com");
- EXPECT_TRUE(filter1.IsMatch(matching_url));
- EXPECT_FALSE(filter1.IsMatch(non_matching_url));
- EXPECT_TRUE(filter2.IsMatch(matching_url));
- EXPECT_TRUE(filter2.IsMatch(non_matching_url));
-}
-
-TEST(URLMatcherPortFilter, TestMatching) {
- std::vector<URLMatcherPortFilter::Range> ranges;
- ranges.push_back(URLMatcherPortFilter::CreateRange(80, 90));
- ranges.push_back(URLMatcherPortFilter::CreateRange(8080));
- URLMatcherPortFilter filter(ranges);
- EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com")));
- EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:80")));
- EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:81")));
- EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:90")));
- EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:8080")));
- EXPECT_FALSE(filter.IsMatch(GURL("http://www.example.com:79")));
- EXPECT_FALSE(filter.IsMatch(GURL("http://www.example.com:91")));
- EXPECT_FALSE(filter.IsMatch(GURL("https://www.example.com")));
-}
-
-TEST(URLMatcherConditionTest, IsFullURLCondition) {
- StringPattern pattern("example.com", 1);
- EXPECT_FALSE(URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX,
- &pattern).IsFullURLCondition());
-
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::HOST_CONTAINS,
- &pattern).IsFullURLCondition());
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::PATH_CONTAINS,
- &pattern).IsFullURLCondition());
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::QUERY_CONTAINS,
- &pattern).IsFullURLCondition());
-
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_PREFIX,
- &pattern).IsFullURLCondition());
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_SUFFIX,
- &pattern).IsFullURLCondition());
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_CONTAINS,
- &pattern).IsFullURLCondition());
- EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_EQUALS,
- &pattern).IsFullURLCondition());
-}
-
-TEST(URLMatcherConditionTest, IsMatch) {
- GURL url1("http://www.example.com/www.foobar.com/index.html");
- GURL url2("http://www.foobar.com/example.com/index.html");
-
- StringPattern pattern("example.com", 1);
- URLMatcherCondition m1(URLMatcherCondition::HOST_SUFFIX, &pattern);
-
- std::set<StringPattern::ID> matching_patterns;
-
- // matches = {0} --> matcher did not indicate that m1 was a match.
- matching_patterns.insert(0);
- EXPECT_FALSE(m1.IsMatch(matching_patterns, url1));
-
- // matches = {0, 1} --> matcher did indicate that m1 was a match.
- matching_patterns.insert(1);
- EXPECT_TRUE(m1.IsMatch(matching_patterns, url1));
-
- // For m2 we use a HOST_CONTAINS test, which requires a post-validation
- // whether the match reported by the SubstringSetMatcher occurs really
- // in the correct url component.
- URLMatcherCondition m2(URLMatcherCondition::HOST_CONTAINS, &pattern);
- EXPECT_TRUE(m2.IsMatch(matching_patterns, url1));
- EXPECT_FALSE(m2.IsMatch(matching_patterns, url2));
-}
-
-TEST(URLMatcherConditionTest, Comparison) {
- StringPattern p1("foobar.com", 1);
- StringPattern p2("foobar.com", 2);
- // The first component of each test is expected to be < than the second.
- URLMatcherCondition test_smaller[][2] = {
- {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
- URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX, &p1)},
- {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
- URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p2)},
- {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, NULL),
- URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p2)},
- {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
- URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX, NULL)},
- };
- for (size_t i = 0; i < arraysize(test_smaller); ++i) {
- EXPECT_TRUE(test_smaller[i][0] < test_smaller[i][1])
- << "Test " << i << " of test_smaller failed";
- EXPECT_FALSE(test_smaller[i][1] < test_smaller[i][0])
- << "Test " << i << " of test_smaller failed";
- }
- URLMatcherCondition test_equal[][2] = {
- {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
- URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1)},
- {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, NULL),
- URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, NULL)},
- };
- for (size_t i = 0; i < arraysize(test_equal); ++i) {
- EXPECT_FALSE(test_equal[i][0] < test_equal[i][1])
- << "Test " << i << " of test_equal failed";
- EXPECT_FALSE(test_equal[i][1] < test_equal[i][0])
- << "Test " << i << " of test_equal failed";
- }
-}
-
-//
-// URLMatcherConditionFactory
-//
-
-namespace {
-
-bool Matches(const URLMatcherCondition& condition, std::string text) {
- return text.find(condition.string_pattern()->pattern()) !=
- std::string::npos;
-}
-
-} // namespace
-
-TEST(URLMatcherConditionFactoryTest, GURLCharacterSet) {
- // GURL guarantees that neither domain, nor path, nor query may contain
- // non ASCII-7 characters. We test this here, because a change to this
- // guarantee breaks this implementation horribly.
- GURL url("http://www.föö.com/föö?föö#föö");
- EXPECT_TRUE(IsStringASCII(url.host()));
- EXPECT_TRUE(IsStringASCII(url.path()));
- EXPECT_TRUE(IsStringASCII(url.query()));
- EXPECT_FALSE(IsStringASCII(url.ref()));
-}
-
-TEST(URLMatcherConditionFactoryTest, Criteria) {
- URLMatcherConditionFactory factory;
- EXPECT_EQ(URLMatcherCondition::HOST_PREFIX,
- factory.CreateHostPrefixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX,
- factory.CreateHostSuffixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::HOST_CONTAINS,
- factory.CreateHostContainsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::HOST_EQUALS,
- factory.CreateHostEqualsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::PATH_PREFIX,
- factory.CreatePathPrefixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::PATH_SUFFIX,
- factory.CreatePathSuffixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::PATH_CONTAINS,
- factory.CreatePathContainsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::PATH_EQUALS,
- factory.CreatePathEqualsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::QUERY_PREFIX,
- factory.CreateQueryPrefixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::QUERY_SUFFIX,
- factory.CreateQuerySuffixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::QUERY_CONTAINS,
- factory.CreateQueryContainsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::QUERY_EQUALS,
- factory.CreateQueryEqualsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX_PATH_PREFIX,
- factory.CreateHostSuffixPathPrefixCondition("foo",
- "bar").criterion());
- EXPECT_EQ(URLMatcherCondition::HOST_EQUALS_PATH_PREFIX,
- factory.CreateHostEqualsPathPrefixCondition("foo",
- "bar").criterion());
- EXPECT_EQ(URLMatcherCondition::URL_PREFIX,
- factory.CreateURLPrefixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::URL_SUFFIX,
- factory.CreateURLSuffixCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::URL_CONTAINS,
- factory.CreateURLContainsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::URL_EQUALS,
- factory.CreateURLEqualsCondition("foo").criterion());
- EXPECT_EQ(URLMatcherCondition::URL_MATCHES,
- factory.CreateURLMatchesCondition("foo").criterion());
-}
-
-TEST(URLMatcherConditionFactoryTest, TestSingletonProperty) {
- URLMatcherConditionFactory factory;
- URLMatcherCondition c1 = factory.CreateHostEqualsCondition("www.google.com");
- URLMatcherCondition c2 = factory.CreateHostEqualsCondition("www.google.com");
- EXPECT_EQ(c1.criterion(), c2.criterion());
- EXPECT_EQ(c1.string_pattern(), c2.string_pattern());
- URLMatcherCondition c3 = factory.CreateHostEqualsCondition("www.google.de");
- EXPECT_EQ(c2.criterion(), c3.criterion());
- EXPECT_NE(c2.string_pattern(), c3.string_pattern());
- EXPECT_NE(c2.string_pattern()->id(), c3.string_pattern()->id());
- EXPECT_NE(c2.string_pattern()->pattern(),
- c3.string_pattern()->pattern());
- URLMatcherCondition c4 = factory.CreateURLMatchesCondition("www.google.com");
- URLMatcherCondition c5 = factory.CreateURLContainsCondition("www.google.com");
- // Regex patterns and substring patterns do not share IDs.
- EXPECT_EQ(c5.string_pattern()->pattern(), c4.string_pattern()->pattern());
- EXPECT_NE(c5.string_pattern(), c4.string_pattern());
- EXPECT_NE(c5.string_pattern()->id(), c4.string_pattern()->id());
-
- // Check that all StringPattern singletons are freed if we call
- // ForgetUnusedPatterns.
- StringPattern::ID old_id_1 = c1.string_pattern()->id();
- StringPattern::ID old_id_4 = c4.string_pattern()->id();
- factory.ForgetUnusedPatterns(std::set<StringPattern::ID>());
- EXPECT_TRUE(factory.IsEmpty());
- URLMatcherCondition c6 = factory.CreateHostEqualsCondition("www.google.com");
- EXPECT_NE(old_id_1, c6.string_pattern()->id());
- URLMatcherCondition c7 = factory.CreateURLMatchesCondition("www.google.com");
- EXPECT_NE(old_id_4, c7.string_pattern()->id());
-}
-
-TEST(URLMatcherConditionFactoryTest, TestComponentSearches) {
- GURL gurl("https://www.google.com:1234/webhp?sourceid=chrome-instant&ie=UTF-8"
- "&ion=1#hl=en&output=search&sclient=psy-ab&q=chrome%20is%20awesome");
- URLMatcherConditionFactory factory;
- std::string url = factory.CanonicalizeURLForComponentSearches(gurl);
-
- // Test host component.
- EXPECT_TRUE(Matches(factory.CreateHostPrefixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreateHostPrefixCondition("www.goog"), url));
- EXPECT_TRUE(
- Matches(factory.CreateHostPrefixCondition("www.google.com"), url));
- EXPECT_TRUE(
- Matches(factory.CreateHostPrefixCondition(".www.google.com"), url));
- EXPECT_FALSE(Matches(factory.CreateHostPrefixCondition("google.com"), url));
- EXPECT_FALSE(
- Matches(factory.CreateHostPrefixCondition("www.google.com/"), url));
- EXPECT_FALSE(Matches(factory.CreateHostPrefixCondition("webhp"), url));
-
- EXPECT_TRUE(Matches(factory.CreateHostSuffixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreateHostSuffixCondition("com"), url));
- EXPECT_TRUE(Matches(factory.CreateHostSuffixCondition(".com"), url));
- EXPECT_TRUE(
- Matches(factory.CreateHostSuffixCondition("www.google.com"), url));
- EXPECT_TRUE(
- Matches(factory.CreateHostSuffixCondition(".www.google.com"), url));
- EXPECT_FALSE(Matches(factory.CreateHostSuffixCondition("www"), url));
- EXPECT_FALSE(
- Matches(factory.CreateHostSuffixCondition("www.google.com/"), url));
- EXPECT_FALSE(Matches(factory.CreateHostSuffixCondition("webhp"), url));
-
- EXPECT_FALSE(Matches(factory.CreateHostEqualsCondition(std::string()), url));
- EXPECT_FALSE(Matches(factory.CreateHostEqualsCondition("www"), url));
- EXPECT_TRUE(
- Matches(factory.CreateHostEqualsCondition("www.google.com"), url));
- EXPECT_FALSE(
- Matches(factory.CreateHostEqualsCondition("www.google.com/"), url));
-
-
- // Test path component.
- EXPECT_TRUE(Matches(factory.CreatePathPrefixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreatePathPrefixCondition("/web"), url));
- EXPECT_TRUE(Matches(factory.CreatePathPrefixCondition("/webhp"), url));
- EXPECT_FALSE(Matches(factory.CreatePathPrefixCondition("webhp"), url));
- EXPECT_FALSE(Matches(factory.CreatePathPrefixCondition("/webhp?"), url));
- EXPECT_FALSE(Matches(factory.CreatePathPrefixCondition("?sourceid"), url));
-
- EXPECT_TRUE(Matches(factory.CreatePathSuffixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreatePathSuffixCondition("webhp"), url));
- EXPECT_TRUE(Matches(factory.CreatePathSuffixCondition("/webhp"), url));
- EXPECT_FALSE(Matches(factory.CreatePathSuffixCondition("/web"), url));
- EXPECT_FALSE(Matches(factory.CreatePathSuffixCondition("/webhp?"), url));
-
- EXPECT_TRUE(Matches(factory.CreatePathEqualsCondition("/webhp"), url));
- EXPECT_FALSE(Matches(factory.CreatePathEqualsCondition("webhp"), url));
- EXPECT_FALSE(Matches(factory.CreatePathEqualsCondition("/webhp?"), url));
- EXPECT_FALSE(
- Matches(factory.CreatePathEqualsCondition("www.google.com"), url));
-
-
- // Test query component.
- EXPECT_TRUE(Matches(factory.CreateQueryPrefixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreateQueryPrefixCondition("sourceid"), url));
- // The '?' at the beginning is just ignored.
- EXPECT_TRUE(Matches(factory.CreateQueryPrefixCondition("?sourceid"), url));
-
- EXPECT_TRUE(Matches(factory.CreateQuerySuffixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreateQuerySuffixCondition("ion=1"), url));
- EXPECT_FALSE(Matches(factory.CreateQuerySuffixCondition("www"), url));
- // "Suffix" condition + pattern starting with '?' = "equals" condition.
- EXPECT_FALSE(Matches(factory.CreateQuerySuffixCondition(
- "?sourceid=chrome-instant&ie=UTF-8&ion="), url));
- EXPECT_TRUE(Matches(factory.CreateQuerySuffixCondition(
- "?sourceid=chrome-instant&ie=UTF-8&ion=1"), url));
-
- EXPECT_FALSE(Matches(factory.CreateQueryEqualsCondition(
- "?sourceid=chrome-instant&ie=UTF-8&ion="), url));
- EXPECT_FALSE(Matches(factory.CreateQueryEqualsCondition(
- "sourceid=chrome-instant&ie=UTF-8&ion="), url));
- EXPECT_TRUE(Matches(factory.CreateQueryEqualsCondition(
- "sourceid=chrome-instant&ie=UTF-8&ion=1"), url));
- // The '?' at the beginning is just ignored.
- EXPECT_TRUE(Matches(factory.CreateQueryEqualsCondition(
- "?sourceid=chrome-instant&ie=UTF-8&ion=1"), url));
- EXPECT_FALSE(
- Matches(factory.CreateQueryEqualsCondition("www.google.com"), url));
-
-
- // Test adjacent components
- EXPECT_TRUE(Matches(factory.CreateHostSuffixPathPrefixCondition(
- "google.com", "/webhp"), url));
- EXPECT_TRUE(Matches(
- factory.CreateHostSuffixPathPrefixCondition(std::string(), "/webhp"),
- url));
- EXPECT_TRUE(Matches(
- factory.CreateHostSuffixPathPrefixCondition("google.com", std::string()),
- url));
- EXPECT_FALSE(Matches(
- factory.CreateHostSuffixPathPrefixCondition("www", std::string()), url));
-
- EXPECT_TRUE(Matches(factory.CreateHostEqualsPathPrefixCondition(
- "www.google.com", "/webhp"), url));
- EXPECT_FALSE(Matches(
- factory.CreateHostEqualsPathPrefixCondition(std::string(), "/webhp"),
- url));
- EXPECT_TRUE(Matches(factory.CreateHostEqualsPathPrefixCondition(
- "www.google.com", std::string()),
- url));
- EXPECT_FALSE(Matches(
- factory.CreateHostEqualsPathPrefixCondition("google.com", std::string()),
- url));
-}
-
-TEST(URLMatcherConditionFactoryTest, TestFullSearches) {
- // The Port 443 is stripped because it is the default port for https.
- GURL gurl("https://www.google.com:443/webhp?sourceid=chrome-instant&ie=UTF-8"
- "&ion=1#hl=en&output=search&sclient=psy-ab&q=chrome%20is%20awesome");
- URLMatcherConditionFactory factory;
- std::string url = factory.CanonicalizeURLForFullSearches(gurl);
-
- EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(std::string()), url));
- EXPECT_TRUE(
- Matches(factory.CreateURLPrefixCondition("https://www.goog"), url));
- EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(
- "https://www.google.com"), url));
- EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(
- "https://www.google.com/webhp?"), url));
- EXPECT_FALSE(Matches(factory.CreateURLPrefixCondition(
- "http://www.google.com"), url));
- EXPECT_FALSE(Matches(factory.CreateURLPrefixCondition("webhp"), url));
-
- EXPECT_TRUE(Matches(factory.CreateURLSuffixCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreateURLSuffixCondition("ion=1"), url));
- EXPECT_FALSE(Matches(factory.CreateURLSuffixCondition("www"), url));
-
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition(std::string()), url));
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("www.goog"), url));
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("webhp"), url));
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("?"), url));
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("sourceid"), url));
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("ion=1"), url));
- EXPECT_FALSE(Matches(factory.CreateURLContainsCondition(".www.goog"), url));
- EXPECT_FALSE(Matches(factory.CreateURLContainsCondition("foobar"), url));
- EXPECT_FALSE(Matches(factory.CreateURLContainsCondition("search"), url));
- EXPECT_FALSE(Matches(factory.CreateURLContainsCondition(":443"), url));
-
- EXPECT_TRUE(Matches(factory.CreateURLEqualsCondition(
- "https://www.google.com/webhp?sourceid=chrome-instant&ie=UTF-8&ion=1"),
- url));
- EXPECT_FALSE(
- Matches(factory.CreateURLEqualsCondition("https://www.google.com"), url));
-
- // Same as above but this time with a non-standard port.
- gurl = GURL("https://www.google.com:1234/webhp?sourceid=chrome-instant&"
- "ie=UTF-8&ion=1#hl=en&output=search&sclient=psy-ab&q=chrome%20is%20"
- "awesome");
- url = factory.CanonicalizeURLForFullSearches(gurl);
- EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(
- "https://www.google.com:1234/webhp?"), url));
- EXPECT_TRUE(Matches(factory.CreateURLContainsCondition(":1234"), url));
-}
-
-//
-// URLMatcherConditionSet
-//
-
-TEST(URLMatcherConditionSetTest, Constructor) {
- URLMatcherConditionFactory factory;
- URLMatcherCondition m1 = factory.CreateHostSuffixCondition("example.com");
- URLMatcherCondition m2 = factory.CreatePathContainsCondition("foo");
-
- std::set<URLMatcherCondition> conditions;
- conditions.insert(m1);
- conditions.insert(m2);
-
- scoped_refptr<URLMatcherConditionSet> condition_set(
- new URLMatcherConditionSet(1, conditions));
- EXPECT_EQ(1, condition_set->id());
- EXPECT_EQ(2u, condition_set->conditions().size());
-}
-
-TEST(URLMatcherConditionSetTest, Matching) {
- GURL url1("http://www.example.com/foo?bar=1");
- GURL url2("http://foo.example.com/index.html");
- GURL url3("http://www.example.com:80/foo?bar=1");
- GURL url4("http://www.example.com:8080/foo?bar=1");
-
- URLMatcherConditionFactory factory;
- URLMatcherCondition m1 = factory.CreateHostSuffixCondition("example.com");
- URLMatcherCondition m2 = factory.CreatePathContainsCondition("foo");
-
- std::set<URLMatcherCondition> conditions;
- conditions.insert(m1);
- conditions.insert(m2);
-
- scoped_refptr<URLMatcherConditionSet> condition_set(
- new URLMatcherConditionSet(1, conditions));
- EXPECT_EQ(1, condition_set->id());
- EXPECT_EQ(2u, condition_set->conditions().size());
-
- std::set<StringPattern::ID> matching_patterns;
- matching_patterns.insert(m1.string_pattern()->id());
- EXPECT_FALSE(condition_set->IsMatch(matching_patterns, url1));
-
- matching_patterns.insert(m2.string_pattern()->id());
- EXPECT_TRUE(condition_set->IsMatch(matching_patterns, url1));
- EXPECT_FALSE(condition_set->IsMatch(matching_patterns, url2));
-
- // Test scheme filters.
- scoped_refptr<URLMatcherConditionSet> condition_set2(
- new URLMatcherConditionSet(1,
- conditions,
- scoped_ptr<URLMatcherSchemeFilter>(
- new URLMatcherSchemeFilter("https")),
- scoped_ptr<URLMatcherPortFilter>()));
- EXPECT_FALSE(condition_set2->IsMatch(matching_patterns, url1));
- scoped_refptr<URLMatcherConditionSet> condition_set3(
- new URLMatcherConditionSet(1,
- conditions,
- scoped_ptr<URLMatcherSchemeFilter>(
- new URLMatcherSchemeFilter("http")),
- scoped_ptr<URLMatcherPortFilter>()));
- EXPECT_TRUE(condition_set3->IsMatch(matching_patterns, url1));
-
- // Test port filters.
- std::vector<URLMatcherPortFilter::Range> ranges;
- ranges.push_back(URLMatcherPortFilter::CreateRange(80));
- scoped_ptr<URLMatcherPortFilter> filter(new URLMatcherPortFilter(ranges));
- scoped_refptr<URLMatcherConditionSet> condition_set4(
- new URLMatcherConditionSet(
- 1, conditions, scoped_ptr<URLMatcherSchemeFilter>(), filter.Pass()));
- EXPECT_TRUE(condition_set4->IsMatch(matching_patterns, url1));
- EXPECT_TRUE(condition_set4->IsMatch(matching_patterns, url3));
- EXPECT_FALSE(condition_set4->IsMatch(matching_patterns, url4));
-
- // Test regex patterns.
- matching_patterns.clear();
- URLMatcherCondition r1 = factory.CreateURLMatchesCondition("/fo?oo");
- std::set<URLMatcherCondition> regex_conditions;
- regex_conditions.insert(r1);
- scoped_refptr<URLMatcherConditionSet> condition_set5(
- new URLMatcherConditionSet(1, regex_conditions));
- EXPECT_FALSE(condition_set5->IsMatch(matching_patterns, url1));
- matching_patterns.insert(r1.string_pattern()->id());
- EXPECT_TRUE(condition_set5->IsMatch(matching_patterns, url1));
-
- regex_conditions.insert(m1);
- scoped_refptr<URLMatcherConditionSet> condition_set6(
- new URLMatcherConditionSet(1, regex_conditions));
- EXPECT_FALSE(condition_set6->IsMatch(matching_patterns, url1));
- matching_patterns.insert(m1.string_pattern()->id());
- EXPECT_TRUE(condition_set6->IsMatch(matching_patterns, url1));
-
- matching_patterns.clear();
- regex_conditions.clear();
- URLMatcherCondition r2 = factory.CreateOriginAndPathMatchesCondition("b[a]r");
- regex_conditions.insert(r2);
- scoped_refptr<URLMatcherConditionSet> condition_set7(
- new URLMatcherConditionSet(1, regex_conditions));
- EXPECT_FALSE(condition_set7->IsMatch(matching_patterns, url1));
- matching_patterns.insert(r2.string_pattern()->id());
- EXPECT_TRUE(condition_set7->IsMatch(matching_patterns, url1));
-}
-
-
-//
-// URLMatcher
-//
-
-TEST(URLMatcherTest, FullTest) {
- GURL url1("http://www.example.com/foo?bar=1");
- GURL url2("http://foo.example.com/index.html");
-
- URLMatcher matcher;
- URLMatcherConditionFactory* factory = matcher.condition_factory();
-
- // First insert.
- URLMatcherConditionSet::Conditions conditions1;
- conditions1.insert(factory->CreateHostSuffixCondition("example.com"));
- conditions1.insert(factory->CreatePathContainsCondition("foo"));
-
- const int kConditionSetId1 = 1;
- URLMatcherConditionSet::Vector insert1;
- insert1.push_back(make_scoped_refptr(
- new URLMatcherConditionSet(kConditionSetId1, conditions1)));
- matcher.AddConditionSets(insert1);
- EXPECT_EQ(1u, matcher.MatchURL(url1).size());
- EXPECT_EQ(0u, matcher.MatchURL(url2).size());
-
- // Second insert.
- URLMatcherConditionSet::Conditions conditions2;
- conditions2.insert(factory->CreateHostSuffixCondition("example.com"));
-
- const int kConditionSetId2 = 2;
- URLMatcherConditionSet::Vector insert2;
- insert2.push_back(make_scoped_refptr(
- new URLMatcherConditionSet(kConditionSetId2, conditions2)));
- matcher.AddConditionSets(insert2);
- EXPECT_EQ(2u, matcher.MatchURL(url1).size());
- EXPECT_EQ(1u, matcher.MatchURL(url2).size());
-
- // This should be the cached singleton.
- int patternId1 = factory->CreateHostSuffixCondition(
- "example.com").string_pattern()->id();
-
- // Third insert.
- URLMatcherConditionSet::Conditions conditions3;
- conditions3.insert(factory->CreateHostSuffixCondition("example.com"));
- conditions3.insert(factory->CreateURLMatchesCondition("x.*[0-9]"));
-
- const int kConditionSetId3 = 3;
- URLMatcherConditionSet::Vector insert3;
- insert3.push_back(make_scoped_refptr(
- new URLMatcherConditionSet(kConditionSetId3, conditions3)));
- matcher.AddConditionSets(insert3);
- EXPECT_EQ(3u, matcher.MatchURL(url1).size());
- EXPECT_EQ(1u, matcher.MatchURL(url2).size());
-
- // Removal of third insert.
- std::vector<URLMatcherConditionSet::ID> remove3;
- remove3.push_back(kConditionSetId3);
- matcher.RemoveConditionSets(remove3);
- EXPECT_EQ(2u, matcher.MatchURL(url1).size());
- EXPECT_EQ(1u, matcher.MatchURL(url2).size());
-
- // Removal of second insert.
- std::vector<URLMatcherConditionSet::ID> remove2;
- remove2.push_back(kConditionSetId2);
- matcher.RemoveConditionSets(remove2);
- EXPECT_EQ(1u, matcher.MatchURL(url1).size());
- EXPECT_EQ(0u, matcher.MatchURL(url2).size());
-
- // Removal of first insert.
- std::vector<URLMatcherConditionSet::ID> remove1;
- remove1.push_back(kConditionSetId1);
- matcher.RemoveConditionSets(remove1);
- EXPECT_EQ(0u, matcher.MatchURL(url1).size());
- EXPECT_EQ(0u, matcher.MatchURL(url2).size());
-
- EXPECT_TRUE(matcher.IsEmpty());
-
- // The cached singleton in matcher.condition_factory_ should be destroyed to
- // free memory.
- int patternId2 = factory->CreateHostSuffixCondition(
- "example.com").string_pattern()->id();
- // If patternId1 and patternId2 are different that indicates that
- // matcher.condition_factory_ does not leak memory by holding onto
- // unused patterns.
- EXPECT_NE(patternId1, patternId2);
-}
-
-TEST(URLMatcherTest, TestComponentsImplyContains) {
- // Due to a different implementation of component (prefix, suffix and equals)
- // and *Contains conditions we need to check that when a pattern matches a
- // given part of a URL as equal, prefix or suffix, it also matches it in the
- // "contains" test.
- GURL url("https://www.google.com:1234/webhp?test=val&a=b");
-
- URLMatcher matcher;
- URLMatcherConditionFactory* factory = matcher.condition_factory();
-
- URLMatcherConditionSet::Conditions conditions;
-
- // First insert all the matching equals => contains pairs.
- conditions.insert(factory->CreateHostEqualsCondition("www.google.com"));
- conditions.insert(factory->CreateHostContainsCondition("www.google.com"));
-
- conditions.insert(factory->CreateHostPrefixCondition("www."));
- conditions.insert(factory->CreateHostContainsCondition("www."));
-
- conditions.insert(factory->CreateHostSuffixCondition("com"));
- conditions.insert(factory->CreateHostContainsCondition("com"));
-
- conditions.insert(factory->CreatePathEqualsCondition("/webhp"));
- conditions.insert(factory->CreatePathContainsCondition("/webhp"));
-
- conditions.insert(factory->CreatePathPrefixCondition("/we"));
- conditions.insert(factory->CreatePathContainsCondition("/we"));
-
- conditions.insert(factory->CreatePathSuffixCondition("hp"));
- conditions.insert(factory->CreatePathContainsCondition("hp"));
-
- conditions.insert(factory->CreateQueryEqualsCondition("test=val&a=b"));
- conditions.insert(factory->CreateQueryContainsCondition("test=val&a=b"));
-
- conditions.insert(factory->CreateQueryPrefixCondition("test=v"));
- conditions.insert(factory->CreateQueryContainsCondition("test=v"));
-
- conditions.insert(factory->CreateQuerySuffixCondition("l&a=b"));
- conditions.insert(factory->CreateQueryContainsCondition("l&a=b"));
-
- // The '?' for equality is just ignored.
- conditions.insert(factory->CreateQueryEqualsCondition("?test=val&a=b"));
- // Due to '?' the condition created here is a prefix-testing condition.
- conditions.insert(factory->CreateQueryContainsCondition("?test=val&a=b"));
-
- const int kConditionSetId = 1;
- URLMatcherConditionSet::Vector insert;
- insert.push_back(make_scoped_refptr(
- new URLMatcherConditionSet(kConditionSetId, conditions)));
- matcher.AddConditionSets(insert);
- EXPECT_EQ(1u, matcher.MatchURL(url).size());
-}
-
-// Check that matches in everything but the query are found.
-TEST(URLMatcherTest, TestOriginAndPathRegExPositive) {
- GURL url("https://www.google.com:1234/webhp?test=val&a=b");
-
- URLMatcher matcher;
- URLMatcherConditionFactory* factory = matcher.condition_factory();
-
- URLMatcherConditionSet::Conditions conditions;
-
- conditions.insert(factory->CreateOriginAndPathMatchesCondition("w..hp"));
- const int kConditionSetId = 1;
- URLMatcherConditionSet::Vector insert;
- insert.push_back(make_scoped_refptr(
- new URLMatcherConditionSet(kConditionSetId, conditions)));
- matcher.AddConditionSets(insert);
- EXPECT_EQ(1u, matcher.MatchURL(url).size());
-}
-
-// Check that matches in the query are ignored.
-TEST(URLMatcherTest, TestOriginAndPathRegExNegative) {
- GURL url("https://www.google.com:1234/webhp?test=val&a=b");
-
- URLMatcher matcher;
- URLMatcherConditionFactory* factory = matcher.condition_factory();
-
- URLMatcherConditionSet::Conditions conditions;
-
- conditions.insert(factory->CreateOriginAndPathMatchesCondition("val"));
- const int kConditionSetId = 1;
- URLMatcherConditionSet::Vector insert;
- insert.push_back(make_scoped_refptr(
- new URLMatcherConditionSet(kConditionSetId, conditions)));
- matcher.AddConditionSets(insert);
- EXPECT_EQ(0u, matcher.MatchURL(url).size());
-}
-
-} // namespace extensions
diff --git a/extensions/common/one_shot_event.cc b/extensions/common/one_shot_event.cc
index 318acad5c6..28f91cb206 100644
--- a/extensions/common/one_shot_event.cc
+++ b/extensions/common/one_shot_event.cc
@@ -31,6 +31,9 @@ OneShotEvent::OneShotEvent() : signaled_(false) {
// immediately move it to another thread.
thread_checker_.DetachFromThread();
}
+OneShotEvent::OneShotEvent(bool signaled) : signaled_(signaled) {
+ thread_checker_.DetachFromThread();
+}
OneShotEvent::~OneShotEvent() {}
void OneShotEvent::Post(const tracked_objects::Location& from_here,
diff --git a/extensions/common/one_shot_event.h b/extensions/common/one_shot_event.h
index 17ab5c88f7..9baa152d2c 100644
--- a/extensions/common/one_shot_event.h
+++ b/extensions/common/one_shot_event.h
@@ -35,6 +35,11 @@ namespace extensions {
class OneShotEvent {
public:
OneShotEvent();
+ // Use the following constructor to create an already signaled event. This is
+ // useful if you construct the event on a different thread from where it is
+ // used, in which case it is not possible to call Signal() just after
+ // construction.
+ explicit OneShotEvent(bool signaled);
~OneShotEvent();
// True if Signal has been called. This function is mostly for
diff --git a/extensions/common/permissions/api_permission.cc b/extensions/common/permissions/api_permission.cc
index f183ed29f8..95728fa1cf 100644
--- a/extensions/common/permissions/api_permission.cc
+++ b/extensions/common/permissions/api_permission.cc
@@ -37,21 +37,19 @@ class SimpleAPIPermission : public APIPermission {
}
virtual bool Contains(const APIPermission* rhs) const OVERRIDE {
- CHECK(info() == rhs->info());
+ CHECK_EQ(info(), rhs->info());
return true;
}
virtual bool Equal(const APIPermission* rhs) const OVERRIDE {
- if (this == rhs)
- return true;
- CHECK(info() == rhs->info());
+ if (this != rhs)
+ CHECK_EQ(info(), rhs->info());
return true;
}
- virtual bool FromValue(const base::Value* value) OVERRIDE {
- if (value)
- return false;
- return true;
+ virtual bool FromValue(const base::Value* value,
+ std::string* /*error*/) OVERRIDE {
+ return (value == NULL);
}
virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
@@ -63,17 +61,17 @@ class SimpleAPIPermission : public APIPermission {
}
virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE {
- CHECK(info() == rhs->info());
+ CHECK_EQ(info(), rhs->info());
return NULL;
}
virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE {
- CHECK(info() == rhs->info());
+ CHECK_EQ(info(), rhs->info());
return new SimpleAPIPermission(info());
}
virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE {
- CHECK(info() == rhs->info());
+ CHECK_EQ(info(), rhs->info());
return new SimpleAPIPermission(info());
}
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index b234af1454..aaf1d6efa4 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -40,14 +40,10 @@ class APIPermission {
kAdView,
kAlarms,
kAlwaysOnTopWindows,
- kAppCurrentWindowInternal,
- kAppRuntime,
- kAppWindow,
kAudio,
kAudioCapture,
kAutoTestPrivate,
kBackground,
- kBluetooth,
kBookmark,
kBookmarkManagerPrivate,
kBrailleDisplayPrivate,
@@ -93,8 +89,10 @@ class APIPermission {
kFullscreen,
kGcm,
kGeolocation,
+ kHid,
kHistory,
kHomepage,
+ kHotwordPrivate,
kIdentity,
kIdentityPrivate,
kIdltest,
@@ -126,13 +124,13 @@ class APIPermission {
kProxy,
kPushMessaging,
kImageWriterPrivate,
+ kReadingListPrivate,
kRtcPrivate,
kSearchProvider,
kSerial,
kSessions,
kSignedInDevices,
kSocket,
- kSocketsUdp,
kStartupPages,
kStorage,
kStreamsPrivate,
@@ -207,8 +205,9 @@ class APIPermission {
// Returns true if |rhs| is equal to this.
virtual bool Equal(const APIPermission* rhs) const = 0;
- // Parses the APIPermission from |value|. Returns false if error happens.
- virtual bool FromValue(const base::Value* value) = 0;
+ // Parses the APIPermission from |value|. Returns false if an error happens
+ // and optionally set |error| if |error| is not NULL.
+ virtual bool FromValue(const base::Value* value, std::string* error) = 0;
// Stores this into a new created |value|.
virtual scoped_ptr<base::Value> ToValue() const = 0;
@@ -311,8 +310,7 @@ class APIPermissionInfo {
}
private:
- // Instances should only be constructed from within a
- // PermissionsInfo::Delegate.
+ // Instances should only be constructed from within a PermissionsProvider.
friend class ChromeAPIPermissions;
// Implementations of APIPermission will want to get the permission message,
// but this class's implementation should be hidden from everyone else.
diff --git a/extensions/common/permissions/api_permission_set.cc b/extensions/common/permissions/api_permission_set.cc
index 0ed7769e08..fbbfdc028d 100644
--- a/extensions/common/permissions/api_permission_set.cc
+++ b/extensions/common/permissions/api_permission_set.cc
@@ -23,7 +23,7 @@ bool CreateAPIPermission(
const base::Value* permission_value,
APIPermissionSet::ParseSource source,
APIPermissionSet* api_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions) {
const APIPermissionInfo* permission_info =
@@ -41,10 +41,19 @@ bool CreateAPIPermission(
return false;
}
- if (!permission->FromValue(permission_value)) {
+ std::string error_details;
+ if (!permission->FromValue(permission_value, &error_details)) {
if (error) {
- *error = ErrorUtils::FormatErrorMessageUTF16(
- errors::kInvalidPermission, permission_info->name());
+ if (error_details.empty()) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidPermission,
+ permission_info->name());
+ } else {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidPermissionWithDetail,
+ permission_info->name(),
+ error_details);
+ }
return false;
}
LOG(WARNING) << "Parse permission failed.";
@@ -66,7 +75,7 @@ bool ParseChildPermissions(const std::string& base_name,
const base::Value* permission_value,
APIPermissionSet::ParseSource source,
APIPermissionSet* api_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions) {
if (permission_value) {
const base::ListValue* permissions;
@@ -112,6 +121,7 @@ bool ParseChildPermissions(const std::string& base_name,
void APIPermissionSet::insert(APIPermission::ID id) {
const APIPermissionInfo* permission_info =
PermissionsInfo::GetInstance()->GetByID(id);
+ DCHECK(permission_info);
insert(permission_info->CreateAPIPermission());
}
@@ -124,7 +134,7 @@ bool APIPermissionSet::ParseFromJSON(
const base::ListValue* permissions,
APIPermissionSet::ParseSource source,
APIPermissionSet* api_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions) {
for (size_t i = 0; i < permissions->GetSize(); ++i) {
std::string permission_str;
diff --git a/extensions/common/permissions/api_permission_set.h b/extensions/common/permissions/api_permission_set.h
index c5dd248391..4db19f6818 100644
--- a/extensions/common/permissions/api_permission_set.h
+++ b/extensions/common/permissions/api_permission_set.h
@@ -54,7 +54,7 @@ class APIPermissionSet : public BaseSetOperators<APIPermissionSet> {
const base::ListValue* permissions,
ParseSource source,
APIPermissionSet* api_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions);
void AddImpliedPermissions();
diff --git a/extensions/common/permissions/api_permission_set_unittest.cc b/extensions/common/permissions/api_permission_set_unittest.cc
index 85f8ccc87f..abeb9ab0cb 100644
--- a/extensions/common/permissions/api_permission_set_unittest.cc
+++ b/extensions/common/permissions/api_permission_set_unittest.cc
@@ -48,9 +48,7 @@ TEST(APIPermissionSetTest, CreateUnion) {
value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
// Union with an empty set.
@@ -83,9 +81,7 @@ TEST(APIPermissionSetTest, CreateUnion) {
scoped_ptr<base::ListValue> value(new base::ListValue());
value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
value->Append(new base::StringValue("udp-send-to::8899"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
apis2.insert(permission);
@@ -101,9 +97,7 @@ TEST(APIPermissionSetTest, CreateUnion) {
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
value->Append(new base::StringValue("udp-send-to::8899"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
// Insert a new socket permission which will replace the old one.
expected_apis.insert(permission);
@@ -140,9 +134,7 @@ TEST(APIPermissionSetTest, CreateIntersection) {
value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
apis1.insert(permission);
@@ -168,9 +160,7 @@ TEST(APIPermissionSetTest, CreateIntersection) {
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
value->Append(new base::StringValue("udp-send-to::8899"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
apis2.insert(permission);
@@ -180,9 +170,7 @@ TEST(APIPermissionSetTest, CreateIntersection) {
scoped_ptr<base::ListValue> value(new base::ListValue());
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
expected_apis.insert(permission);
@@ -218,9 +206,7 @@ TEST(APIPermissionSetTest, CreateDifference) {
value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
apis1.insert(permission);
@@ -238,9 +224,7 @@ TEST(APIPermissionSetTest, CreateDifference) {
scoped_ptr<base::ListValue> value(new base::ListValue());
value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
value->Append(new base::StringValue("udp-send-to::8899"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
apis2.insert(permission);
@@ -250,9 +234,7 @@ TEST(APIPermissionSetTest, CreateDifference) {
scoped_ptr<base::ListValue> value(new base::ListValue());
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
expected_apis.insert(permission);
@@ -286,9 +268,7 @@ TEST(APIPermissionSetTest, IPC) {
value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
value->Append(new base::StringValue("udp-bind::8080"));
value->Append(new base::StringValue("udp-send-to::8888"));
- if (!permission->FromValue(value.get())) {
- NOTREACHED();
- }
+ ASSERT_TRUE(permission->FromValue(value.get(), NULL));
}
apis.insert(permission);
diff --git a/extensions/common/permissions/manifest_permission_set.cc b/extensions/common/permissions/manifest_permission_set.cc
index 821159f6a2..fecb611dbe 100644
--- a/extensions/common/permissions/manifest_permission_set.cc
+++ b/extensions/common/permissions/manifest_permission_set.cc
@@ -24,7 +24,7 @@ bool CreateManifestPermission(
const std::string& permission_name,
const base::Value* permission_value,
ManifestPermissionSet* manifest_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions) {
scoped_ptr<ManifestPermission> permission(
@@ -60,7 +60,7 @@ namespace extensions {
bool ManifestPermissionSet::ParseFromJSON(
const base::ListValue* permissions,
ManifestPermissionSet* manifest_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions) {
for (size_t i = 0; i < permissions->GetSize(); ++i) {
std::string permission_name;
diff --git a/extensions/common/permissions/manifest_permission_set.h b/extensions/common/permissions/manifest_permission_set.h
index e9683bc7e9..4b1ffe0238 100644
--- a/extensions/common/permissions/manifest_permission_set.h
+++ b/extensions/common/permissions/manifest_permission_set.h
@@ -38,7 +38,7 @@ class ManifestPermissionSet : public BaseSetOperators<ManifestPermissionSet> {
static bool ParseFromJSON(
const base::ListValue* permissions,
ManifestPermissionSet* manifest_permissions,
- string16* error,
+ base::string16* error,
std::vector<std::string>* unhandled_permissions);
};
diff --git a/extensions/common/permissions/permission_message.cc b/extensions/common/permissions/permission_message.cc
index 1b11a37a36..bc2008e058 100644
--- a/extensions/common/permissions/permission_message.cc
+++ b/extensions/common/permissions/permission_message.cc
@@ -10,13 +10,15 @@ namespace extensions {
//
PermissionMessage::PermissionMessage(
- PermissionMessage::ID id, const string16& message)
+ PermissionMessage::ID id, const base::string16& message)
: id_(id),
message_(message) {
}
PermissionMessage::PermissionMessage(
- PermissionMessage::ID id, const string16& message, const string16& details)
+ PermissionMessage::ID id,
+ const base::string16& message,
+ const base::string16& details)
: id_(id),
message_(message),
details_(details) {
diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h
index 82b516298d..9c3fe7ec1c 100644
--- a/extensions/common/permissions/permission_message.h
+++ b/extensions/common/permissions/permission_message.h
@@ -31,6 +31,7 @@ class PermissionMessage {
kManagement,
kDebugger,
kDesktopCapture,
+ kHid,
kHosts1,
kHosts2,
kHosts3,
@@ -79,14 +80,17 @@ class PermissionMessage {
kStartupPages,
kMediaGalleriesAllGalleriesDelete,
kScreenlockPrivate,
+ kOverrideBookmarksUI,
kEnumBoundary,
};
COMPILE_ASSERT(PermissionMessage::kNone > PermissionMessage::kUnknown,
kNone_not_greater_than_kUnknown);
// Creates the corresponding permission message.
- PermissionMessage(ID id, const string16& message);
- PermissionMessage(ID id, const string16& message, const string16& details);
+ PermissionMessage(ID id, const base::string16& message);
+ PermissionMessage(ID id,
+ const base::string16& message,
+ const base::string16& details);
~PermissionMessage();
// Gets the id of the permission message, which can be used in UMA
@@ -95,12 +99,12 @@ class PermissionMessage {
// Gets a localized message describing this permission. Please note that
// the message will be empty for message types TYPE_NONE and TYPE_UNKNOWN.
- const string16& message() const { return message_; }
+ const base::string16& message() const { return message_; }
// Gets a localized message describing the details for this permission. Please
// note that the message will be empty for message types TYPE_NONE and
// TYPE_UNKNOWN.
- const string16& details() const { return details_; }
+ const base::string16& details() const { return details_; }
// Comparator to work with std::set.
bool operator<(const PermissionMessage& that) const {
@@ -113,8 +117,8 @@ class PermissionMessage {
private:
ID id_;
- string16 message_;
- string16 details_;
+ base::string16 message_;
+ base::string16 details_;
};
typedef std::vector<PermissionMessage> PermissionMessages;
diff --git a/extensions/common/permissions/permission_message_provider.h b/extensions/common/permissions/permission_message_provider.h
index 7f682e3e5d..ab8b49e677 100644
--- a/extensions/common/permissions/permission_message_provider.h
+++ b/extensions/common/permissions/permission_message_provider.h
@@ -33,14 +33,14 @@ class PermissionMessageProvider {
// Gets the localized permission messages that represent this set (represented
// as strings). The set of permission messages shown varies by extension type.
- virtual std::vector<string16> GetWarningMessages(
+ virtual std::vector<base::string16> GetWarningMessages(
const PermissionSet* permissions,
Manifest::Type extension_type) const = 0;
// Gets the localized permission details for messages that represent this set
// (represented as strings). The set of permission messages shown varies by
// extension type.
- virtual std::vector<string16> GetWarningMessagesDetails(
+ virtual std::vector<base::string16> GetWarningMessagesDetails(
const PermissionSet* permissions,
Manifest::Type extension_type) const = 0;
diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc
index 8ec1cbedd0..fd32d4e83d 100644
--- a/extensions/common/permissions/permission_set.cc
+++ b/extensions/common/permissions/permission_set.cc
@@ -180,6 +180,7 @@ bool PermissionSet::HasAPIPermission(
bool PermissionSet::HasAPIPermission(const std::string& permission_name) const {
const APIPermissionInfo* permission =
PermissionsInfo::GetInstance()->GetByName(permission_name);
+ // Ensure our PermissionsProvider is aware of this permission.
CHECK(permission) << permission_name;
return (permission && apis_.count(permission->id()));
}
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc
index f43d1d7743..43a6004fd3 100644
--- a/extensions/common/permissions/permissions_data.cc
+++ b/extensions/common/permissions/permissions_data.cc
@@ -65,7 +65,7 @@ bool CanSpecifyHostPermission(const Extension* extension,
const URLPattern& pattern,
const APIPermissionSet& permissions) {
if (!pattern.match_all_urls() &&
- pattern.MatchesScheme(chrome::kChromeUIScheme)) {
+ pattern.MatchesScheme(content::kChromeUIScheme)) {
URLPatternSet chrome_scheme_hosts = ExtensionsClient::Get()->
GetPermittedChromeSchemeHosts(extension, permissions);
if (chrome_scheme_hosts.ContainsPattern(pattern))
@@ -95,7 +95,7 @@ bool ParseHelper(Extension* extension,
const char* key,
APIPermissionSet* api_permissions,
URLPatternSet* host_permissions,
- string16* error) {
+ base::string16* error) {
if (!extension->manifest()->HasKey(key))
return true;
@@ -152,7 +152,7 @@ bool ParseHelper(Extension* extension,
if (iter->id() == APIPermission::kExperimental) {
if (!CanSpecifyExperimentalPermission(extension)) {
- *error = ASCIIToUTF16(errors::kExperimentalFlagRequired);
+ *error = base::ASCIIToUTF16(errors::kExperimentalFlagRequired);
return false;
}
}
@@ -183,14 +183,14 @@ bool ParseHelper(Extension* extension,
// to match all paths.
pattern.SetPath("/*");
int valid_schemes = pattern.valid_schemes();
- if (pattern.MatchesScheme(chrome::kFileScheme) &&
+ if (pattern.MatchesScheme(content::kFileScheme) &&
!PermissionsData::CanExecuteScriptEverywhere(extension)) {
extension->set_wants_file_access(true);
if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS))
valid_schemes &= ~URLPattern::SCHEME_FILE;
}
- if (pattern.scheme() != chrome::kChromeUIScheme &&
+ if (pattern.scheme() != content::kChromeUIScheme &&
!PermissionsData::CanExecuteScriptEverywhere(extension)) {
// Keep chrome:// in allowed schemes only if it's explicitly requested
// or CanExecuteScriptEverywhere is true. If the
@@ -429,11 +429,11 @@ PermissionMessages PermissionsData::GetPermissionMessages(
}
// static
-std::vector<string16> PermissionsData::GetPermissionMessageStrings(
+std::vector<base::string16> PermissionsData::GetPermissionMessageStrings(
const Extension* extension) {
base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
if (ShouldSkipPermissionWarnings(extension)) {
- return std::vector<string16>();
+ return std::vector<base::string16>();
} else {
return PermissionMessageProvider::Get()->GetWarningMessages(
GetActivePermissions(extension), extension->GetType());
@@ -441,11 +441,11 @@ std::vector<string16> PermissionsData::GetPermissionMessageStrings(
}
// static
-std::vector<string16> PermissionsData::GetPermissionMessageDetailsStrings(
+std::vector<base::string16> PermissionsData::GetPermissionMessageDetailsStrings(
const Extension* extension) {
base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
if (ShouldSkipPermissionWarnings(extension)) {
- return std::vector<string16>();
+ return std::vector<base::string16>();
} else {
return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
GetActivePermissions(extension), extension->GetType());
@@ -476,7 +476,7 @@ bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension,
}
if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) {
- if (document_url.SchemeIs(chrome::kChromeUIScheme) &&
+ if (document_url.SchemeIs(content::kChromeUIScheme) &&
!can_execute_everywhere) {
if (error)
*error = errors::kCannotAccessChromeUrl;
@@ -537,31 +537,34 @@ bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
// static
bool PermissionsData::CanCaptureVisiblePage(const Extension* extension,
- const GURL& page_url,
int tab_id,
std::string* error) {
+ scoped_refptr<const PermissionSet> active_permissions =
+ GetActivePermissions(extension);
+ const URLPattern all_urls(URLPattern::SCHEME_ALL,
+ URLPattern::kAllUrlsPattern);
+ if (active_permissions->explicit_hosts().ContainsPattern(all_urls))
+ return true;
+
if (tab_id >= 0) {
scoped_refptr<const PermissionSet> tab_permissions =
GetTabSpecificPermissions(extension, tab_id);
- if (tab_permissions.get() &&
- tab_permissions->explicit_hosts().MatchesSecurityOrigin(page_url)) {
+ if (tab_permissions &&
+ tab_permissions->HasAPIPermission(APIPermission::kTab)) {
return true;
}
+ if (error)
+ *error = errors::kActiveTabPermissionNotGranted;
+ return false;
}
- if (HasHostPermission(extension, page_url) ||
- page_url.GetOrigin() == extension->url()) {
- return true;
- }
-
- if (error) {
- *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
- page_url.spec());
- }
+ if (error)
+ *error = errors::kAllURLOrActiveTabNeeded;
return false;
}
-bool PermissionsData::ParsePermissions(Extension* extension, string16* error) {
+bool PermissionsData::ParsePermissions(Extension* extension,
+ base::string16* error) {
initial_required_permissions_.reset(new InitialPermissions);
if (!ParseHelper(extension,
keys::kPermissions,
@@ -571,18 +574,6 @@ bool PermissionsData::ParsePermissions(Extension* extension, string16* error) {
return false;
}
- // TODO(jeremya/kalman) do this via the features system by exposing the
- // app.window API to platform apps, with no dependency on any permissions.
- // See http://crbug.com/120069.
- if (extension->is_platform_app()) {
- initial_required_permissions_->api_permissions.insert(
- APIPermission::kAppCurrentWindowInternal);
- initial_required_permissions_->api_permissions.insert(
- APIPermission::kAppRuntime);
- initial_required_permissions_->api_permissions.insert(
- APIPermission::kAppWindow);
- }
-
initial_optional_permissions_.reset(new InitialPermissions);
if (!ParseHelper(extension,
keys::kOptionalPermissions,
diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h
index 72b9d247f6..ee1715df6c 100644
--- a/extensions/common/permissions/permissions_data.h
+++ b/extensions/common/permissions/permissions_data.h
@@ -141,13 +141,13 @@ class PermissionsData {
// Returns the full list of permission messages that the given |extension|
// should display at install time. The messages are returned as strings
// for convenience.
- static std::vector<string16> GetPermissionMessageStrings(
+ static std::vector<base::string16> GetPermissionMessageStrings(
const Extension* extension);
// Returns the full list of permission details for messages that the given
// |extension| should display at install time. The messages are returned as
// strings for convenience.
- static std::vector<string16> GetPermissionMessageDetailsStrings(
+ static std::vector<base::string16> GetPermissionMessageDetailsStrings(
const Extension* extension);
// Returns true if the given |extension| can execute script on a page. If a
@@ -174,12 +174,11 @@ class PermissionsData {
// is restricted to the extension's host permissions as well as the
// extension page itself.
static bool CanCaptureVisiblePage(const Extension* extension,
- const GURL& page_url,
int tab_id,
std::string* error);
// Parse the permissions of a given extension in the initialization process.
- bool ParsePermissions(Extension* extension, string16* error);
+ bool ParsePermissions(Extension* extension, base::string16* error);
// Ensure manifest handlers provide their custom manifest permissions.
void InitializeManifestPermissions(Extension* extension);
diff --git a/extensions/common/permissions/permissions_data_unittest.cc b/extensions/common/permissions/permissions_data_unittest.cc
index 3ea4856a51..fda57f9dae 100644
--- a/extensions/common/permissions/permissions_data_unittest.cc
+++ b/extensions/common/permissions/permissions_data_unittest.cc
@@ -24,6 +24,7 @@
#include "extensions/common/url_pattern_set.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::UTF16ToUTF8;
using content::SocketPermissionRequest;
using extension_test_util::LoadManifest;
using extension_test_util::LoadManifestUnchecked;
@@ -130,9 +131,11 @@ TEST(ExtensionPermissionsTest, SocketPermissions) {
Manifest::INTERNAL, Extension::NO_FLAGS,
&error);
EXPECT_TRUE(extension.get() == NULL);
- ASSERT_EQ(ErrorUtils::FormatErrorMessage(
- manifest_errors::kInvalidPermission, "socket"),
- error);
+ std::string expected_error_msg_header = ErrorUtils::FormatErrorMessage(
+ manifest_errors::kInvalidPermissionWithDetail,
+ "socket",
+ "NULL or empty permission list");
+ EXPECT_EQ(expected_error_msg_header, error);
extension = LoadManifest("socket_permissions", "socket2.json");
EXPECT_TRUE(CheckSocketPermission(extension,
@@ -153,7 +156,7 @@ TEST(ExtensionPermissionsTest, SocketPermissions) {
TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyAPIPermissions) {
scoped_refptr<Extension> extension;
extension = LoadManifest("permissions", "many-apis.json");
- std::vector<string16> warnings =
+ std::vector<base::string16> warnings =
PermissionsData::GetPermissionMessageStrings(extension.get());
ASSERT_EQ(6u, warnings.size());
EXPECT_EQ("Access your data on api.flickr.com",
@@ -169,9 +172,9 @@ TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyAPIPermissions) {
TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyHostsPermissions) {
scoped_refptr<Extension> extension;
extension = LoadManifest("permissions", "more-than-3-hosts.json");
- std::vector<string16> warnings =
+ std::vector<base::string16> warnings =
PermissionsData::GetPermissionMessageStrings(extension.get());
- std::vector<string16> warnings_details =
+ std::vector<base::string16> warnings_details =
PermissionsData::GetPermissionMessageDetailsStrings(extension.get());
ASSERT_EQ(1u, warnings.size());
ASSERT_EQ(1u, warnings_details.size());
@@ -186,7 +189,7 @@ TEST(ExtensionPermissionsTest, GetPermissionMessages_LocationApiPermission) {
"location-api.json",
Manifest::COMPONENT,
Extension::NO_FLAGS);
- std::vector<string16> warnings =
+ std::vector<base::string16> warnings =
PermissionsData::GetPermissionMessageStrings(extension.get());
ASSERT_EQ(1u, warnings.size());
EXPECT_EQ("Detect your physical location", UTF16ToUTF8(warnings[0]));
@@ -195,7 +198,7 @@ TEST(ExtensionPermissionsTest, GetPermissionMessages_LocationApiPermission) {
TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyHosts) {
scoped_refptr<Extension> extension;
extension = LoadManifest("permissions", "many-hosts.json");
- std::vector<string16> warnings =
+ std::vector<base::string16> warnings =
PermissionsData::GetPermissionMessageStrings(extension.get());
ASSERT_EQ(1u, warnings.size());
EXPECT_EQ("Access your data on encrypted.google.com and www.google.com",
@@ -205,7 +208,7 @@ TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyHosts) {
TEST(ExtensionPermissionsTest, GetPermissionMessages_Plugins) {
scoped_refptr<Extension> extension;
extension = LoadManifest("permissions", "plugins.json");
- std::vector<string16> warnings =
+ std::vector<base::string16> warnings =
PermissionsData::GetPermissionMessageStrings(extension.get());
// We don't parse the plugins key on Chrome OS, so it should not ask for any
// permissions.
@@ -247,8 +250,13 @@ class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
bool AllowedScript(const Extension* extension, const GURL& url,
const GURL& top_url) {
+ return AllowedScript(extension, url, top_url, -1);
+ }
+
+ bool AllowedScript(const Extension* extension, const GURL& url,
+ const GURL& top_url, int tab_id) {
return PermissionsData::CanExecuteScriptOnPage(
- extension, url, top_url, -1, NULL, -1, NULL);
+ extension, url, top_url, tab_id, NULL, -1, NULL);
}
bool BlockedScript(const Extension* extension, const GURL& url,
@@ -265,7 +273,7 @@ class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
return (PermissionsData::CanExecuteScriptOnPage(
extension, url, url, tab_id, NULL, -1, NULL) &&
PermissionsData::CanCaptureVisiblePage(
- extension, url, tab_id, NULL));
+ extension, tab_id, NULL));
}
bool CaptureOnly(const Extension* extension, const GURL& url) {
@@ -275,7 +283,18 @@ class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
bool CaptureOnly(const Extension* extension, const GURL& url, int tab_id) {
return !PermissionsData::CanExecuteScriptOnPage(
extension, url, url, tab_id, NULL, -1, NULL) &&
- PermissionsData::CanCaptureVisiblePage(extension, url, tab_id, NULL);
+ PermissionsData::CanCaptureVisiblePage(extension, tab_id, NULL);
+ }
+
+ bool ScriptOnly(const Extension* extension, const GURL& url,
+ const GURL& top_url) {
+ return ScriptOnly(extension, url, top_url, -1);
+ }
+
+ bool ScriptOnly(const Extension* extension, const GURL& url,
+ const GURL& top_url, int tab_id) {
+ return AllowedScript(extension, url, top_url, tab_id) &&
+ !PermissionsData::CanCaptureVisiblePage(extension, tab_id, NULL);
}
bool Blocked(const Extension* extension, const GURL& url) {
@@ -286,10 +305,10 @@ class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
return !(PermissionsData::CanExecuteScriptOnPage(
extension, url, url, tab_id, NULL, -1, NULL) ||
PermissionsData::CanCaptureVisiblePage(
- extension, url, tab_id, NULL));
+ extension, tab_id, NULL));
}
- bool AllowedExclusivelyOnTab(
+ bool ScriptAllowedExclusivelyOnTab(
const Extension* extension,
const std::set<GURL>& allowed_urls,
int tab_id) {
@@ -297,7 +316,7 @@ class ExtensionScriptAndCaptureVisibleTest : public testing::Test {
for (std::set<GURL>::iterator it = urls_.begin(); it != urls_.end(); ++it) {
const GURL& url = *it;
if (allowed_urls.count(url))
- result &= Allowed(extension, url, tab_id);
+ result &= AllowedScript(extension, url, url, tab_id);
else
result &= Blocked(extension, url, tab_id);
}
@@ -332,11 +351,11 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
EXPECT_TRUE(Allowed(extension.get(), http_url));
EXPECT_TRUE(Allowed(extension.get(), https_url));
- EXPECT_TRUE(Blocked(extension.get(), file_url));
- EXPECT_TRUE(Blocked(extension.get(), settings_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
EXPECT_TRUE(CaptureOnly(extension.get(), favicon_url));
- EXPECT_TRUE(Blocked(extension.get(), about_url));
- EXPECT_TRUE(Blocked(extension.get(), extension_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
// Test access to iframed content.
GURL within_extension_url = extension->GetResourceURL("page.html");
@@ -355,8 +374,8 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
// Test * for scheme, which implies just the http/https schemes.
extension = LoadManifestStrict("script_and_capture",
"extension_wildcard.json");
- EXPECT_TRUE(Allowed(extension.get(), http_url));
- EXPECT_TRUE(Allowed(extension.get(), https_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), https_url, https_url));
EXPECT_TRUE(Blocked(extension.get(), settings_url));
EXPECT_TRUE(Blocked(extension.get(), about_url));
EXPECT_TRUE(Blocked(extension.get(), file_url));
@@ -386,7 +405,7 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
extension = LoadManifestStrict("script_and_capture",
"extension_chrome_favicon_wildcard.json");
EXPECT_TRUE(Blocked(extension.get(), settings_url));
- EXPECT_TRUE(CaptureOnly(extension.get(), favicon_url));
+ EXPECT_TRUE(Blocked(extension.get(), favicon_url));
EXPECT_TRUE(Blocked(extension.get(), about_url));
EXPECT_TRUE(PermissionsData::HasHostPermission(extension.get(), favicon_url));
@@ -410,7 +429,7 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) {
extension = LoadManifest("script_and_capture",
"extension_component_google.json", Manifest::COMPONENT,
Extension::NO_FLAGS);
- EXPECT_TRUE(Allowed(extension.get(), http_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
EXPECT_TRUE(Blocked(extension.get(), https_url));
EXPECT_TRUE(Blocked(extension.get(), file_url));
EXPECT_TRUE(Blocked(extension.get(), settings_url));
@@ -432,11 +451,11 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
"extension_regular_all.json");
EXPECT_TRUE(Allowed(extension.get(), http_url));
EXPECT_TRUE(Allowed(extension.get(), https_url));
- EXPECT_TRUE(Blocked(extension.get(), file_url));
- EXPECT_TRUE(Blocked(extension.get(), settings_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
EXPECT_TRUE(Allowed(extension.get(), favicon_url)); // chrome:// requested
- EXPECT_TRUE(Blocked(extension.get(), about_url));
- EXPECT_TRUE(Blocked(extension.get(), extension_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
+ EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
// Test access to iframed content.
GURL within_extension_url = extension->GetResourceURL("page.html");
@@ -455,8 +474,8 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
// Test * for scheme, which implies just the http/https schemes.
extension = LoadManifestStrict("script_and_capture",
"extension_wildcard.json");
- EXPECT_TRUE(Allowed(extension.get(), http_url));
- EXPECT_TRUE(Allowed(extension.get(), https_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), https_url, https_url));
EXPECT_TRUE(Blocked(extension.get(), settings_url));
EXPECT_TRUE(Blocked(extension.get(), about_url));
EXPECT_TRUE(Blocked(extension.get(), file_url));
@@ -475,16 +494,16 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
EXPECT_FALSE(extension.get() == NULL);
EXPECT_TRUE(Blocked(extension.get(), http_url));
EXPECT_TRUE(Blocked(extension.get(), https_url));
- EXPECT_TRUE(Allowed(extension.get(), settings_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), settings_url, settings_url));
EXPECT_TRUE(Blocked(extension.get(), about_url));
EXPECT_TRUE(Blocked(extension.get(), file_url));
- EXPECT_TRUE(Allowed(extension.get(), favicon_url)); // chrome:// requested
+ EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url, favicon_url));
// Having chrome://favicon/* should not give you chrome://*
extension = LoadManifestStrict("script_and_capture",
"extension_chrome_favicon_wildcard.json");
EXPECT_TRUE(Blocked(extension.get(), settings_url));
- EXPECT_TRUE(Allowed(extension.get(), favicon_url)); // chrome:// requested
+ EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url, favicon_url));
EXPECT_TRUE(Blocked(extension.get(), about_url));
EXPECT_TRUE(PermissionsData::HasHostPermission(extension.get(), favicon_url));
@@ -508,7 +527,7 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) {
extension = LoadManifest("script_and_capture",
"extension_component_google.json", Manifest::COMPONENT,
Extension::NO_FLAGS);
- EXPECT_TRUE(Allowed(extension.get(), http_url));
+ EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url));
EXPECT_TRUE(Blocked(extension.get(), https_url));
EXPECT_TRUE(Blocked(extension.get(), file_url));
EXPECT_TRUE(Blocked(extension.get(), settings_url));
@@ -532,9 +551,9 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) {
std::set<GURL> no_urls;
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 0));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 1));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 2));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
URLPatternSet allowed_hosts;
allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL,
@@ -557,17 +576,17 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) {
->explicit_hosts());
}
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), allowed_urls, 0));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 1));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 2));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), allowed_urls, 0));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
PermissionsData::ClearTabSpecificPermissions(extension.get(), 0);
EXPECT_FALSE(PermissionsData::GetTabSpecificPermissions(extension.get(), 0)
.get());
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 0));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 1));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 2));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
std::set<GURL> more_allowed_urls = allowed_urls;
more_allowed_urls.insert(https_url);
@@ -596,25 +615,27 @@ TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) {
->explicit_hosts());
}
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), allowed_urls, 0));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 2));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), allowed_urls, 0));
+ EXPECT_TRUE(
+ ScriptAllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
PermissionsData::ClearTabSpecificPermissions(extension.get(), 0);
EXPECT_FALSE(PermissionsData::GetTabSpecificPermissions(extension.get(), 0)
.get());
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 0));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 2));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
+ EXPECT_TRUE(
+ ScriptAllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
PermissionsData::ClearTabSpecificPermissions(extension.get(), 1);
EXPECT_FALSE(PermissionsData::GetTabSpecificPermissions(extension.get(), 1)
.get());
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 0));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 1));
- EXPECT_TRUE(AllowedExclusivelyOnTab(extension.get(), no_urls, 2));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1));
+ EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2));
}
} // namespace extensions
diff --git a/extensions/common/permissions/permissions_info.cc b/extensions/common/permissions/permissions_info.cc
index bac3d9c18e..e4684aa522 100644
--- a/extensions/common/permissions/permissions_info.cc
+++ b/extensions/common/permissions/permissions_info.cc
@@ -64,7 +64,6 @@ bool PermissionsInfo::HasChildPermissions(const std::string& name) const {
PermissionsInfo::PermissionsInfo()
: hosted_app_permission_count_(0),
permission_count_(0) {
- DCHECK(ExtensionsClient::Get());
InitializeWithProvider(ExtensionsClient::Get()->GetPermissionsProvider());
}
diff --git a/extensions/common/stack_frame_unittest.cc b/extensions/common/stack_frame_unittest.cc
index 7dad047309..ddd92aec59 100644
--- a/extensions/common/stack_frame_unittest.cc
+++ b/extensions/common/stack_frame_unittest.cc
@@ -21,18 +21,18 @@ void AssertStackFrameValid(const std::string& text,
size_t column,
const std::string& source,
const std::string& function) {
- base::string16 utf16_text = UTF8ToUTF16(text);
+ base::string16 utf16_text = base::UTF8ToUTF16(text);
scoped_ptr<StackFrame> frame = StackFrame::CreateFromText(utf16_text);
ASSERT_TRUE(frame.get()) << "Failed to create frame from '" << text << "'";
EXPECT_EQ(line, frame->line_number());
EXPECT_EQ(column, frame->column_number());
- EXPECT_EQ(UTF8ToUTF16(source), frame->source());
- EXPECT_EQ(UTF8ToUTF16(function), frame->function());
+ EXPECT_EQ(base::UTF8ToUTF16(source), frame->source());
+ EXPECT_EQ(base::UTF8ToUTF16(function), frame->function());
}
void AssertStackFrameInvalid(const std::string& text) {
- base::string16 utf16_text = UTF8ToUTF16(text);
+ base::string16 utf16_text = base::UTF8ToUTF16(text);
scoped_ptr<StackFrame> frame = StackFrame::CreateFromText(utf16_text);
ASSERT_FALSE(frame.get()) << "Errantly created frame from '" << text << "'";
}
diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc
index 5d50344671..9a1a91956b 100644
--- a/extensions/common/switches.cc
+++ b/extensions/common/switches.cc
@@ -9,7 +9,7 @@ namespace extensions {
namespace switches {
// Allows non-https URL for background_page for hosted apps.
-const char kAllowHTTPBackgroundPage[] = "allow-http-background-page";
+const char kAllowHTTPBackgroundPage[] = "allow-http-background-page";
// Allows the browser to load extensions that lack a modern manifest when that
// would otherwise be forbidden.
@@ -30,23 +30,32 @@ const char kEasyOffStoreExtensionInstall[] = "easy-off-store-extension-install";
const char kEnableExperimentalExtensionApis[] =
"enable-experimental-extension-apis";
+// Enables extensions to hide bookmarks UI elements.
+const char kEnableOverrideBookmarksUI[] = "enable-override-bookmarks-ui";
+
// Allows the ErrorConsole to collect runtime and manifest errors, and display
// them in the chrome:extensions page.
const char kErrorConsole[] = "error-console";
// The time in milliseconds that an extension event page can be idle before it
// is shut down.
-const char kEventPageIdleTime[] = "event-page-idle-time";
+const char kEventPageIdleTime[] = "event-page-idle-time";
// The time in milliseconds that an extension event page has between being
// notified of its impending unload and that unload happening.
-const char kEventPageSuspendingTime[] = "event-page-unloading-time";
+const char kEventPageSuspendingTime[] = "event-page-unloading-time";
+
+// Marks a renderer as extension process.
+const char kExtensionProcess[] = "extension-process";
// Enables extensions running scripts on chrome:// URLs.
// Extensions still need to explicitly request access to chrome:// URLs in the
// manifest.
const char kExtensionsOnChromeURLs[] = "extensions-on-chrome-urls";
+// Whether to force developer mode extensions highlighting.
+const char kForceDevModeHighlighting[] = "force-dev-mode-highlighting";
+
// Enables setting global commands through the Extensions Commands API.
const char kGlobalCommands[] = "global-commands";
@@ -54,13 +63,6 @@ const char kGlobalCommands[] = "global-commands";
// Default is yes.
const char kPromptForExternalExtensions[] = "prompt-for-external-extensions";
-// Enables or disables extension scripts badges in the location bar.
-const char kScriptBadges[] = "script-badges";
-
-// Enable or diable the "script bubble" icon in the URL bar that tells you how
-// many extensions are running scripts on a page.
-const char kScriptBubble[] = "script-bubble";
-
// Makes component extensions appear in chrome://settings/extensions.
const char kShowComponentExtensionOptions[] =
"show-component-extension-options";
diff --git a/extensions/common/switches.h b/extensions/common/switches.h
index 75f384366f..6f08870b54 100644
--- a/extensions/common/switches.h
+++ b/extensions/common/switches.h
@@ -16,14 +16,15 @@ extern const char kAllowLegacyExtensionManifests[];
extern const char kAllowScriptingGallery[];
extern const char kEasyOffStoreExtensionInstall[];
extern const char kEnableExperimentalExtensionApis[];
+extern const char kEnableOverrideBookmarksUI[];
extern const char kErrorConsole[];
extern const char kEventPageIdleTime[];
extern const char kEventPageSuspendingTime[];
+extern const char kExtensionProcess[];
extern const char kExtensionsOnChromeURLs[];
+extern const char kForceDevModeHighlighting[];
extern const char kGlobalCommands[];
extern const char kPromptForExternalExtensions[];
-extern const char kScriptBadges[];
-extern const char kScriptBubble[];
extern const char kShowComponentExtensionOptions[];
} // namespace switches
diff --git a/extensions/common/test_util.cc b/extensions/common/test_util.cc
new file mode 100644
index 0000000000..4d3164ffe1
--- /dev/null
+++ b/extensions/common/test_util.cc
@@ -0,0 +1,31 @@
+// Copyright 2014 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/test_util.h"
+
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/value_builder.h"
+
+namespace extensions {
+namespace test_util {
+
+ExtensionBuilder& BuildExtension(ExtensionBuilder& builder) {
+ return builder
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "Test extension")
+ .Set("version", "1.0")
+ .Set("manifest_version", 2));
+}
+
+scoped_refptr<Extension> CreateExtensionWithID(const std::string& id) {
+ return ExtensionBuilder()
+ .SetManifest(
+ DictionaryBuilder().Set("name", "test").Set("version", "0.1"))
+ .SetID(id)
+ .Build();
+}
+
+} // namespace test_util
+} // namespace extensions
diff --git a/extensions/common/test_util.h b/extensions/common/test_util.h
new file mode 100644
index 0000000000..e38b28fda4
--- /dev/null
+++ b/extensions/common/test_util.h
@@ -0,0 +1,27 @@
+// Copyright 2014 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_TEST_UTIL_H_
+#define EXTENSIONS_COMMON_TEST_UTIL_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+
+namespace extensions {
+class Extension;
+class ExtensionBuilder;
+
+namespace test_util {
+
+// Adds an extension manifest to a builder.
+ExtensionBuilder& BuildExtension(ExtensionBuilder& builder);
+
+// Return a very simple extension with a given |id|.
+scoped_refptr<Extension> CreateExtensionWithID(const std::string& id);
+
+} // namespace test_util
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_TEST_UTIL_H_
diff --git a/extensions/common/url_pattern.cc b/extensions/common/url_pattern.cc
index 5326f431ba..477d3ddf08 100644
--- a/extensions/common/url_pattern.cc
+++ b/extensions/common/url_pattern.cc
@@ -22,11 +22,11 @@ namespace {
const char* kValidSchemes[] = {
content::kHttpScheme,
content::kHttpsScheme,
- chrome::kFileScheme,
+ content::kFileScheme,
content::kFtpScheme,
- chrome::kChromeUIScheme,
+ content::kChromeUIScheme,
extensions::kExtensionScheme,
- chrome::kFileSystemScheme,
+ content::kFileSystemScheme,
};
const int kValidSchemeMasks[] = {
@@ -128,8 +128,9 @@ URLPattern::URLPattern(int valid_schemes, const std::string& pattern)
match_all_urls_(false),
match_subdomains_(false),
port_("*") {
- if (PARSE_SUCCESS != Parse(pattern))
- NOTREACHED() << "URLPattern is invalid: " << pattern;
+ ParseResult result = Parse(pattern);
+ if (PARSE_SUCCESS != result)
+ NOTREACHED() << "URLPattern invalid: " << pattern << " result " << result;
}
URLPattern::~URLPattern() {
@@ -191,7 +192,7 @@ URLPattern::ParseResult URLPattern::Parse(const std::string& pattern) {
if (!standard_scheme) {
path_start_pos = host_start_pos;
- } else if (scheme_ == chrome::kFileScheme) {
+ } else if (scheme_ == content::kFileScheme) {
size_t host_end_pos = pattern.find(kPathSeparator, host_start_pos);
if (host_end_pos == std::string::npos) {
// Allow hostname omission.
@@ -425,7 +426,7 @@ const std::string& URLPattern::GetAsString() const {
std::string spec = scheme_ +
(standard_scheme ? content::kStandardSchemeSeparator : ":");
- if (scheme_ != chrome::kFileScheme && standard_scheme) {
+ if (scheme_ != content::kFileScheme && standard_scheme) {
if (match_subdomains_) {
spec += "*";
if (!host_.empty())
@@ -492,7 +493,7 @@ bool URLPattern::MatchesAllSchemes(
bool URLPattern::MatchesSecurityOriginHelper(const GURL& test) const {
// Ignore hostname if scheme is file://.
- if (scheme_ != chrome::kFileScheme && !MatchesHost(test))
+ if (scheme_ != content::kFileScheme && !MatchesHost(test))
return false;
if (!MatchesPortPattern(base::IntToString(test.EffectiveIntPort())))
diff --git a/extensions/common/url_pattern_set.cc b/extensions/common/url_pattern_set.cc
index db5b4eb7c4..118f9ee31e 100644
--- a/extensions/common/url_pattern_set.cc
+++ b/extensions/common/url_pattern_set.cc
@@ -183,10 +183,10 @@ bool URLPatternSet::OverlapsWith(const URLPatternSet& other) const {
}
scoped_ptr<base::ListValue> URLPatternSet::ToValue() const {
- scoped_ptr<ListValue> value(new ListValue);
+ scoped_ptr<base::ListValue> value(new base::ListValue);
for (URLPatternSet::const_iterator i = patterns_.begin();
i != patterns_.end(); ++i)
- value->AppendIfNotPresent(Value::CreateStringValue(i->GetAsString()));
+ value->AppendIfNotPresent(new base::StringValue(i->GetAsString()));
return value.Pass();
}
@@ -206,7 +206,7 @@ bool URLPatternSet::Populate(const std::vector<std::string>& patterns,
}
return false;
}
- if (!allow_file_access && pattern.MatchesScheme(chrome::kFileScheme)) {
+ if (!allow_file_access && pattern.MatchesScheme(content::kFileScheme)) {
pattern.SetValidSchemes(
pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
}
diff --git a/extensions/common/value_builder.cc b/extensions/common/value_builder.cc
index c32679e326..0b25745432 100644
--- a/extensions/common/value_builder.cc
+++ b/extensions/common/value_builder.cc
@@ -34,7 +34,7 @@ DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
}
DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
- const string16& in_value) {
+ const base::string16& in_value) {
dict_->SetWithoutPathExpansion(path, new base::StringValue(in_value));
return *this;
}
@@ -79,7 +79,7 @@ ListBuilder& ListBuilder::Append(const std::string& in_value) {
return *this;
}
-ListBuilder& ListBuilder::Append(const string16& in_value) {
+ListBuilder& ListBuilder::Append(const base::string16& in_value) {
list_->Append(new base::StringValue(in_value));
return *this;
}
diff --git a/extensions/common/value_builder.h b/extensions/common/value_builder.h
index 77b0d73dfc..bcb40aa51a 100644
--- a/extensions/common/value_builder.h
+++ b/extensions/common/value_builder.h
@@ -59,7 +59,8 @@ class DictionaryBuilder {
DictionaryBuilder& Set(const std::string& path, int in_value);
DictionaryBuilder& Set(const std::string& path, double in_value);
DictionaryBuilder& Set(const std::string& path, const std::string& in_value);
- DictionaryBuilder& Set(const std::string& path, const string16& in_value);
+ DictionaryBuilder& Set(const std::string& path,
+ const base::string16& in_value);
DictionaryBuilder& Set(const std::string& path, DictionaryBuilder& in_value);
DictionaryBuilder& Set(const std::string& path, ListBuilder& in_value);
@@ -87,7 +88,7 @@ class ListBuilder {
ListBuilder& Append(int in_value);
ListBuilder& Append(double in_value);
ListBuilder& Append(const std::string& in_value);
- ListBuilder& Append(const string16& in_value);
+ ListBuilder& Append(const base::string16& in_value);
ListBuilder& Append(DictionaryBuilder& in_value);
ListBuilder& Append(ListBuilder& in_value);
diff --git a/extensions/common/view_type.h b/extensions/common/view_type.h
index 6030e6ca92..3815da0884 100644
--- a/extensions/common/view_type.h
+++ b/extensions/common/view_type.h
@@ -14,6 +14,8 @@ namespace extensions {
// data.
enum ViewType {
VIEW_TYPE_INVALID,
+ // TODO(jamescook): Rename this to VIEW_TYPE_APP_WINDOW after figuring out
+ // if the strings can be changed. http://crbug.com/344067
VIEW_TYPE_APP_SHELL,
VIEW_TYPE_BACKGROUND_CONTENTS,
VIEW_TYPE_EXTENSION_BACKGROUND_PAGE,
@@ -26,6 +28,7 @@ enum ViewType {
VIEW_TYPE_PANEL,
VIEW_TYPE_TAB_CONTENTS,
VIEW_TYPE_VIRTUAL_KEYBOARD,
+ VIEW_TYPE_LAST = VIEW_TYPE_VIRTUAL_KEYBOARD
};
// Constant strings corresponding to the Type enumeration values. Used
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 96a0075357..1045e535d1 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -11,19 +11,24 @@
'target_name': 'extensions_common',
'type': 'static_library',
'dependencies': [
+ '../third_party/re2/re2.gyp:re2',
# TODO(benwells): figure out what to do with the api target and
# api resources compiled into the chrome resource bundle.
# http://crbug.com/162530
'../chrome/chrome_resources.gyp:chrome_resources',
+ # TODO(jamescook|derat): Pull strings into extensions module.
+ '../chrome/chrome_resources.gyp:chrome_strings',
'../chrome/common/extensions/api/api.gyp:api',
+ '../components/components.gyp:url_matcher',
'../content/content.gyp:content_common',
- '../third_party/re2/re2.gyp:re2',
],
'include_dirs': [
'..',
'<(INTERMEDIATE_DIR)',
],
'sources': [
+ 'common/common_manifest_handlers.cc',
+ 'common/common_manifest_handlers.h',
'common/crx_file.cc',
'common/crx_file.h',
'common/csp_validator.cc',
@@ -47,6 +52,8 @@
'common/extension_paths.h',
'common/extension_resource.cc',
'common/extension_resource.h',
+ 'common/extension_set.cc',
+ 'common/extension_set.h',
'common/extension_urls.cc',
'common/extension_urls.h',
'common/extensions_client.cc',
@@ -85,20 +92,10 @@
'common/manifest_handlers/sandboxed_page_info.h',
'common/manifest_handlers/shared_module_info.cc',
'common/manifest_handlers/shared_module_info.h',
- 'common/matcher/regex_set_matcher.cc',
- 'common/matcher/regex_set_matcher.h',
- 'common/matcher/string_pattern.cc',
- 'common/matcher/string_pattern.h',
- 'common/matcher/substring_set_matcher.cc',
- 'common/matcher/substring_set_matcher.h',
- 'common/matcher/url_matcher.cc',
- 'common/matcher/url_matcher.h',
- 'common/matcher/url_matcher_constants.cc',
- 'common/matcher/url_matcher_constants.h',
- 'common/matcher/url_matcher_factory.cc',
- 'common/matcher/url_matcher_factory.h',
- 'common/matcher/url_matcher_helpers.cc',
- 'common/matcher/url_matcher_helpers.h',
+ 'common/manifest_handlers/web_accessible_resources_info.cc',
+ 'common/manifest_handlers/web_accessible_resources_info.h',
+ 'common/manifest_handlers/webview_info.cc',
+ 'common/manifest_handlers/webview_info.h',
'common/one_shot_event.cc',
'common/one_shot_event.h',
'common/permissions/api_permission.cc',
@@ -170,16 +167,42 @@
'sources': [
'browser/admin_policy.cc',
'browser/admin_policy.h',
+ 'browser/api_activity_monitor.h',
'browser/app_sorting.h',
+ 'browser/blacklist_state.h',
+ 'browser/error_map.cc',
+ 'browser/error_map.h',
'browser/event_listener_map.cc',
'browser/event_listener_map.h',
'browser/event_router.cc',
'browser/event_router.h',
- 'browser/extension_prefs_scope.h',
'browser/extension_error.cc',
'browser/extension_error.h',
'browser/extension_function.cc',
'browser/extension_function.h',
+ 'browser/extension_message_filter.cc',
+ 'browser/extension_message_filter.h',
+ 'browser/extension_pref_store.cc',
+ 'browser/extension_pref_store.h',
+ 'browser/extension_pref_value_map.cc',
+ 'browser/extension_pref_value_map_factory.cc',
+ 'browser/extension_pref_value_map_factory.h',
+ 'browser/extension_pref_value_map.h',
+ 'browser/extension_prefs.cc',
+ 'browser/extension_prefs.h',
+ 'browser/extension_prefs_factory.cc',
+ 'browser/extension_prefs_factory.h',
+ 'browser/extension_prefs_scope.h',
+ 'browser/extension_registry.cc',
+ 'browser/extension_registry.h',
+ 'browser/extension_registry_factory.cc',
+ 'browser/extension_registry_factory.h',
+ 'browser/extension_registry_observer.h',
+ 'browser/extension_scoped_prefs.h',
+ 'browser/extension_system.cc',
+ 'browser/extension_system.h',
+ 'browser/extension_system_provider.cc',
+ 'browser/extension_system_provider.h',
'browser/extensions_browser_client.cc',
'browser/extensions_browser_client.h',
'browser/external_provider_interface.h',
@@ -203,8 +226,14 @@
'browser/process_manager.h',
'browser/process_map.cc',
'browser/process_map.h',
+ 'browser/process_map_factory.cc',
+ 'browser/process_map_factory.h',
'browser/quota_service.cc',
'browser/quota_service.h',
+ 'browser/renderer_startup_helper.cc',
+ 'browser/renderer_startup_helper.h',
+ 'browser/runtime_data.cc',
+ 'browser/runtime_data.h',
'browser/update_observer.h',
'browser/view_type_utils.cc',
'browser/view_type_utils.h',
@@ -212,5 +241,29 @@
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
},
+ {
+ 'target_name': 'extensions_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'extensions_browser',
+ 'extensions_common',
+ '../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'browser/test_management_policy.cc',
+ 'browser/test_management_policy.h',
+ 'common/extension_builder.cc',
+ 'common/extension_builder.h',
+ 'common/test_util.cc',
+ 'common/test_util.h',
+ 'common/value_builder.cc',
+ 'common/value_builder.h',
+ ],
+ # Disable c4267 warnings until we fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
]
}