summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 22:52:49 +0000
committerjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 22:52:49 +0000
commitfe2dd774543cb94fb60feb94df60444fd5b73c34 (patch)
tree8dc1c91f4744debb680e94160c7015a441a81aba /chrome
parent47317494db5a0041f8a32ce4a654f8209166e96e (diff)
downloadchromium_src-fe2dd774543cb94fb60feb94df60444fd5b73c34.zip
chromium_src-fe2dd774543cb94fb60feb94df60444fd5b73c34.tar.gz
chromium_src-fe2dd774543cb94fb60feb94df60444fd5b73c34.tar.bz2
Add histograms to track permission use in extensions.
Updates the disabled extension prompt to use the new re-enable prompt text. BUG=42672, 37963 TEST=about:histograms/Extensions Review URL: http://codereview.chromium.org/6626024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82177 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/crx_installer.cc5
-rw-r--r--chrome/browser/extensions/extension_disabled_infobar_delegate.cc5
-rw-r--r--chrome/browser/extensions/extension_install_ui.cc3
-rw-r--r--chrome/browser/extensions/extension_service.cc36
-rw-r--r--chrome/browser/extensions/extension_service.h7
-rw-r--r--chrome/browser/extensions/extension_webstore_private_api.cc2
-rw-r--r--chrome/browser/ui/webui/app_launcher_handler.cc5
-rw-r--r--chrome/common/extensions/extension.cc208
-rw-r--r--chrome/common/extensions/extension.h89
-rw-r--r--chrome/common/extensions/extension_unittest.cc19
10 files changed, 290 insertions, 89 deletions
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index d234ed0..234546f 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -400,6 +400,11 @@ void CrxInstaller::InstallUIProceed() {
}
void CrxInstaller::InstallUIAbort() {
+ // Technically, this can be called for other reasons than the user hitting
+ // cancel, but they're rare.
+ ExtensionService::RecordPermissionMessagesHistogram(
+ extension_, "Extensions.Permissions_InstallCancel");
+
// Kill the theme loading bubble.
NotificationService* service = NotificationService::current();
service->Notify(NotificationType::NO_THEME_DETECTED,
diff --git a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc
index dc46f00..e334fd2 100644
--- a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc
+++ b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc
@@ -54,7 +54,7 @@ ExtensionDisabledDialogDelegate::ExtensionDisabledDialogDelegate(
AddRef(); // Balanced in Proceed or Abort.
install_ui_.reset(new ExtensionInstallUI(profile));
- install_ui_->ConfirmInstall(this, extension_);
+ install_ui_->ConfirmReEnable(this, extension_);
}
ExtensionDisabledDialogDelegate::~ExtensionDisabledDialogDelegate() {
@@ -66,6 +66,9 @@ void ExtensionDisabledDialogDelegate::InstallUIProceed() {
}
void ExtensionDisabledDialogDelegate::InstallUIAbort() {
+ ExtensionService::RecordPermissionMessagesHistogram(
+ extension_, "Extensions.Permissions_ReEnableCancel");
+
// Do nothing. The extension will remain disabled.
Release();
}
diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc
index ba1f144..bfed0be 100644
--- a/chrome/browser/extensions/extension_install_ui.cc
+++ b/chrome/browser/extensions/extension_install_ui.cc
@@ -203,7 +203,8 @@ void ExtensionInstallUI::OnImageLoaded(
Source<ExtensionInstallUI>(this),
NotificationService::NoDetails());
- std::vector<string16> warnings = extension_->GetPermissionMessages();
+ std::vector<string16> warnings =
+ extension_->GetPermissionMessageStrings();
ShowExtensionInstallDialog(
profile_, delegate_, extension_, &icon_, warnings, prompt_type_);
break;
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 37ed6a2..f6b9583 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -671,6 +671,8 @@ bool ExtensionService::UninstallExtension(const std::string& extension_id,
UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType",
extension->GetType(), 100);
+ RecordPermissionMessagesHistogram(
+ extension, "Extensions.Permissions_Uninstall");
// Also copy the extension identifier since the reference might have been
// obtained via Extension::id().
@@ -800,6 +802,8 @@ void ExtensionService::GrantPermissions(const Extension* extension) {
void ExtensionService::GrantPermissionsAndEnableExtension(
const Extension* extension) {
CHECK(extension);
+ RecordPermissionMessagesHistogram(
+ extension, "Extensions.Permissions_ReEnable");
GrantPermissions(extension);
extension_prefs_->SetDidExtensionEscalatePermissions(extension, false);
EnableExtension(extension->id());
@@ -985,6 +989,9 @@ void ExtensionService::LoadAllExtensions() {
++page_action_count;
if ((*ex)->browser_action() != NULL)
++browser_action_count;
+
+ RecordPermissionMessagesHistogram(
+ ex->get(), "Extensions.Permissions_Load");
}
UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp", app_count);
UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count);
@@ -998,6 +1005,29 @@ void ExtensionService::LoadAllExtensions() {
browser_action_count);
}
+// static
+void ExtensionService::RecordPermissionMessagesHistogram(
+ const Extension* e, const char* histogram) {
+ // Since this is called from multiple sources, and since the Histogram macros
+ // use statics, we need to manually lookup the Histogram ourselves.
+ base::Histogram* counter = base::LinearHistogram::FactoryGet(
+ histogram,
+ 1,
+ Extension::PermissionMessage::ID_ENUM_BOUNDARY,
+ Extension::PermissionMessage::ID_ENUM_BOUNDARY + 1,
+ base::Histogram::kUmaTargetedHistogramFlag);
+
+ std::vector<Extension::PermissionMessage> permissions =
+ e->GetPermissionMessages();
+ if (permissions.empty()) {
+ counter->Add(Extension::PermissionMessage::ID_NONE);
+ } else {
+ std::vector<Extension::PermissionMessage>::iterator it;
+ for (it = permissions.begin(); it != permissions.end(); ++it)
+ counter->Add(it->message_id());
+ }
+}
+
void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info,
bool write_to_prefs) {
std::string error;
@@ -1651,6 +1681,10 @@ void ExtensionService::DisableIfPrivilegeIncrease(const Extension* extension) {
// Extension has changed permissions significantly. Disable it. A
// notification should be sent by the caller.
if (is_privilege_increase) {
+ if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) {
+ RecordPermissionMessagesHistogram(
+ extension, "Extensions.Permissions_AutoDisable");
+ }
extension_prefs_->SetExtensionState(extension, Extension::DISABLED);
extension_prefs_->SetDidExtensionEscalatePermissions(extension, true);
}
@@ -1722,6 +1756,8 @@ void ExtensionService::OnExtensionInstalled(const Extension* extension) {
UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType",
extension->GetType(), 100);
+ RecordPermissionMessagesHistogram(
+ extension, "Extensions.Permissions_Install");
ShownSectionsHandler::OnExtensionInstalled(profile_->GetPrefs(), extension);
extension_prefs_->OnExtensionInstalled(
extension, initial_enable ? Extension::ENABLED : Extension::DISABLED,
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 600d12a..2eb5e4f 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -452,6 +452,13 @@ class ExtensionService
// Gets the set of loaded app ids. Component apps are not included.
ExtensionIdSet GetAppIds() const;
+ // Record a histogram using the PermissionMessage enum values for each
+ // permission in |e|.
+ // NOTE: If this is ever called with high frequency, the implementation may
+ // need to be made more efficient.
+ static void RecordPermissionMessagesHistogram(
+ const Extension* e, const char* histogram);
+
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
friend class DeleteTask<ExtensionService>;
diff --git a/chrome/browser/extensions/extension_webstore_private_api.cc b/chrome/browser/extensions/extension_webstore_private_api.cc
index ff8b374..8f042a3 100644
--- a/chrome/browser/extensions/extension_webstore_private_api.cc
+++ b/chrome/browser/extensions/extension_webstore_private_api.cc
@@ -364,7 +364,7 @@ void BeginInstallWithManifestFunction::OnParseSuccess(
this,
dummy_extension_.get(),
&icon_,
- dummy_extension_->GetPermissionMessages(),
+ dummy_extension_->GetPermissionMessageStrings(),
ExtensionInstallUI::INSTALL_PROMPT);
// Control flow finishes up in InstallUIProceed or InstallUIAbort.
diff --git a/chrome/browser/ui/webui/app_launcher_handler.cc b/chrome/browser/ui/webui/app_launcher_handler.cc
index 67ee56c..95621d5 100644
--- a/chrome/browser/ui/webui/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/app_launcher_handler.cc
@@ -585,6 +585,11 @@ void AppLauncherHandler::ExtensionDialogAccepted() {
}
void AppLauncherHandler::ExtensionDialogCanceled() {
+ const Extension* extension =
+ extensions_service_->GetExtensionById(extension_id_prompting_, true);
+ ExtensionService::RecordPermissionMessagesHistogram(
+ extension, "Extensions.Permissions_ReEnableCancel");
+
extension_id_prompting_ = "";
}
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index e3e2122..741628d 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -98,6 +98,9 @@ bool IsBaseCrxKey(const std::string& key) {
return false;
}
+// Constant used to represent an undefined l10n message id.
+const int kUndefinedMessageId = -1;
+
// Names of API modules that do not require a permission.
const char kBrowserActionModuleName[] = "browserAction";
const char kBrowserActionsModuleName[] = "browserActions";
@@ -142,7 +145,8 @@ class ExtensionConfig {
return Singleton<ExtensionConfig>::get();
}
- int GetPermissionMessageId(const std::string& permission) {
+ Extension::PermissionMessage::MessageId GetPermissionMessageId(
+ const std::string& permission) {
return Extension::kPermissions[permission_map_[permission]].message_id;
}
@@ -281,25 +285,25 @@ const char Extension::kWebstorePrivatePermission[] = "webstorePrivate";
// See ExtensionsTest.PermissionMessages for an explanation of each
// exception.
const Extension::Permission Extension::kPermissions[] = {
- { kBackgroundPermission, 0 },
- { kBookmarkPermission, IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS },
- { kChromeosInfoPrivatePermissions, 0},
- { kContentSettingsPermission, 0 },
- { kContextMenusPermission, 0 },
- { kCookiePermission, 0 },
- { kDebuggerPermission, IDS_EXTENSION_PROMPT_WARNING_DEBUGGER },
- { kExperimentalPermission, 0 },
- { kFileBrowserHandlerPermission, 0 },
- { kFileBrowserPrivatePermission, 0 },
- { kGeolocationPermission, IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION },
- { kIdlePermission, 0 },
- { kHistoryPermission, IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY },
- { kManagementPermission, IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT },
- { kNotificationPermission, 0 },
- { kProxyPermission, 0 },
- { kTabPermission, IDS_EXTENSION_PROMPT_WARNING_TABS },
- { kUnlimitedStoragePermission, 0 },
- { kWebstorePrivatePermission, 0 },
+ { kBackgroundPermission, PermissionMessage::ID_NONE },
+ { kBookmarkPermission, PermissionMessage::ID_BOOKMARKS },
+ { kChromeosInfoPrivatePermissions, PermissionMessage::ID_NONE },
+ { kContentSettingsPermission, PermissionMessage::ID_NONE },
+ { kContextMenusPermission, PermissionMessage::ID_NONE },
+ { kCookiePermission, PermissionMessage::ID_NONE },
+ { kDebuggerPermission, PermissionMessage::ID_DEBUGGER },
+ { kExperimentalPermission, PermissionMessage::ID_NONE },
+ { kFileBrowserHandlerPermission, PermissionMessage::ID_NONE },
+ { kFileBrowserPrivatePermission, PermissionMessage::ID_NONE },
+ { kGeolocationPermission, PermissionMessage::ID_GEOLOCATION },
+ { kIdlePermission, PermissionMessage::ID_NONE },
+ { kHistoryPermission, PermissionMessage::ID_BROWSING_HISTORY },
+ { kManagementPermission, PermissionMessage::ID_MANAGEMENT },
+ { kNotificationPermission, PermissionMessage::ID_NONE },
+ { kProxyPermission, PermissionMessage::ID_NONE },
+ { kTabPermission, PermissionMessage::ID_TABS },
+ { kUnlimitedStoragePermission, PermissionMessage::ID_NONE },
+ { kWebstorePrivatePermission, PermissionMessage::ID_NONE }
};
const size_t Extension::kNumPermissions =
arraysize(Extension::kPermissions);
@@ -332,6 +336,83 @@ const int Extension::kValidHostPermissionSchemes =
UserScript::kValidUserScriptSchemes | URLPattern::SCHEME_CHROMEUI;
//
+// PermissionMessage
+//
+
+// static
+Extension::PermissionMessage Extension::PermissionMessage::CreateFromMessageId(
+ Extension::PermissionMessage::MessageId message_id) {
+ DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
+ if (message_id <= ID_NONE)
+ return PermissionMessage(message_id, string16());
+
+ string16 message = l10n_util::GetStringUTF16(kMessageIds[message_id]);
+ return PermissionMessage(message_id, message);
+}
+
+// static
+Extension::PermissionMessage Extension::PermissionMessage::CreateFromHostList(
+ const std::vector<std::string> hosts) {
+ CHECK(hosts.size() > 0);
+
+ MessageId message_id;
+ string16 message;
+ switch (hosts.size()) {
+ case 1:
+ message_id = ID_HOSTS_1;
+ message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
+ UTF8ToUTF16(hosts[0]));
+ break;
+ case 2:
+ message_id = ID_HOSTS_2;
+ message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
+ UTF8ToUTF16(hosts[0]),
+ UTF8ToUTF16(hosts[1]));
+ break;
+ case 3:
+ message_id = ID_HOSTS_3;
+ message = l10n_util::GetStringFUTF16(kMessageIds[message_id],
+ UTF8ToUTF16(hosts[0]),
+ UTF8ToUTF16(hosts[1]),
+ UTF8ToUTF16(hosts[2]));
+ break;
+ default:
+ message_id = ID_HOSTS_4_OR_MORE;
+ message = l10n_util::GetStringFUTF16(
+ kMessageIds[message_id],
+ UTF8ToUTF16(hosts[0]),
+ UTF8ToUTF16(hosts[1]),
+ base::IntToString16(hosts.size() - 2));
+ break;
+ }
+
+ return PermissionMessage(message_id, message);
+}
+
+Extension::PermissionMessage::PermissionMessage(
+ Extension::PermissionMessage::MessageId message_id, string16 message)
+ : message_id_(message_id),
+ message_(message) {
+}
+
+const int Extension::PermissionMessage::kMessageIds[] = {
+ kUndefinedMessageId, // "unknown"
+ kUndefinedMessageId, // "none"
+ IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS,
+ IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION,
+ IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY,
+ IDS_EXTENSION_PROMPT_WARNING_TABS,
+ IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
+ IDS_EXTENSION_PROMPT_WARNING_DEBUGGER,
+ IDS_EXTENSION_PROMPT_WARNING_1_HOST,
+ IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
+ IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
+ IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
+ IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS,
+ IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS
+};
+
+//
// Extension
//
@@ -365,11 +446,6 @@ GURL Extension::GalleryUpdateUrl(bool secure) {
}
// static
-int Extension::GetPermissionMessageId(const std::string& permission) {
- return ExtensionConfig::GetInstance()->GetPermissionMessageId(permission);
-}
-
-// static
Extension::Location Extension::GetHigherPriorityLocation(
Extension::Location loc1, Extension::Location loc2) {
if (loc1 == loc2)
@@ -386,31 +462,54 @@ Extension::Location Extension::GetHigherPriorityLocation(
return (loc1_rank > loc2_rank ? loc1 : loc2 );
}
-std::vector<string16> Extension::GetPermissionMessages() const {
- std::vector<string16> messages;
+// static
+Extension::PermissionMessage::MessageId Extension::GetPermissionMessageId(
+ const std::string& permission) {
+ return ExtensionConfig::GetInstance()->GetPermissionMessageId(permission);
+}
+
+Extension::PermissionMessages Extension::GetPermissionMessages() const {
+ PermissionMessages messages;
if (!plugins().empty()) {
- messages.push_back(
- l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS));
+ messages.push_back(PermissionMessage::CreateFromMessageId(
+ PermissionMessage::ID_FULL_ACCESS));
return messages;
}
- string16 host_msg = GetHostPermissionMessage();
- if (!host_msg.empty())
- messages.push_back(host_msg);
+ if (HasEffectiveAccessToAllHosts()) {
+ messages.push_back(PermissionMessage::CreateFromMessageId(
+ PermissionMessage::ID_HOSTS_ALL));
+ } else {
+ std::vector<std::string> hosts = GetDistinctHostsForDisplay(
+ GetEffectiveHostPermissions().patterns());
+ if (!hosts.empty())
+ messages.push_back(PermissionMessage::CreateFromHostList(hosts));
+ }
- std::set<string16> simple_msgs = GetSimplePermissionMessages();
+ std::set<PermissionMessage> simple_msgs = GetSimplePermissionMessages();
messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end());
return messages;
}
-std::set<string16> Extension::GetSimplePermissionMessages() const {
- std::set<string16> messages;
+std::vector<string16> Extension::GetPermissionMessageStrings() const {
+ std::vector<string16> messages;
+ PermissionMessages permissions = GetPermissionMessages();
+ for (PermissionMessages::const_iterator i = permissions.begin();
+ i != permissions.end(); ++i)
+ messages.push_back(i->message());
+ return messages;
+}
+
+std::set<Extension::PermissionMessage>
+ Extension::GetSimplePermissionMessages() const {
+ std::set<PermissionMessage> messages;
std::set<std::string>::const_iterator i;
for (i = api_permissions().begin(); i != api_permissions().end(); ++i) {
- int message_id = GetPermissionMessageId(*i);
- if (message_id)
- messages.insert(l10n_util::GetStringUTF16(message_id));
+ PermissionMessage::MessageId message_id = GetPermissionMessageId(*i);
+ DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
+ if (message_id > PermissionMessage::ID_NONE)
+ messages.insert(PermissionMessage::CreateFromMessageId(message_id));
}
return messages;
}
@@ -503,36 +602,6 @@ std::vector<std::string> Extension::GetDistinctHosts(
return distinct_hosts;
}
-string16 Extension::GetHostPermissionMessage() const {
- if (HasEffectiveAccessToAllHosts())
- return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS);
-
- std::vector<std::string> hosts = GetDistinctHostsForDisplay(
- GetEffectiveHostPermissions().patterns());
-
- if (hosts.size() == 1) {
- return l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
- UTF8ToUTF16(hosts[0]));
- } else if (hosts.size() == 2) {
- return l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
- UTF8ToUTF16(hosts[0]),
- UTF8ToUTF16(hosts[1]));
- } else if (hosts.size() == 3) {
- return l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
- UTF8ToUTF16(hosts[0]),
- UTF8ToUTF16(hosts[1]),
- UTF8ToUTF16(hosts[2]));
- } else if (hosts.size() >= 4) {
- return l10n_util::GetStringFUTF16(
- IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS,
- UTF8ToUTF16(hosts[0]),
- UTF8ToUTF16(hosts[1]),
- base::IntToString16(hosts.size() - 2));
- }
-
- return string16();
-}
-
FilePath Extension::MaybeNormalizePath(const FilePath& path) {
#if defined(OS_WIN)
// Normalize any drive letter to upper-case. We do this for consistency with
@@ -1522,7 +1591,8 @@ bool Extension::IsPrivilegeIncrease(const bool granted_full_access,
size_t new_api_count = 0;
for (std::set<std::string>::iterator i = new_apis_only.begin();
i != new_apis_only.end(); ++i) {
- if (GetPermissionMessageId(*i))
+ DCHECK_GT(PermissionMessage::ID_NONE, PermissionMessage::ID_UNKNOWN);
+ if (GetPermissionMessageId(*i) > PermissionMessage::ID_NONE)
new_api_count++;
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index a164317..d08f17e 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -118,11 +118,77 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
std::string gender;
};
+ // When prompting the user to install or approve permissions, we display
+ // messages describing the effects of the permissions and not the permissions
+ // themselves. Each PermissionMessage represents one of the messages that is
+ // shown to the user.
+ class PermissionMessage {
+ public:
+ // Do not reorder or add new enumerations in this list. If you need to add a
+ // new enum, add it just prior to ID_ENUM_BOUNDARY and enter its l10n
+ // message in kMessageIds.
+ enum MessageId {
+ ID_UNKNOWN,
+ ID_NONE,
+ ID_BOOKMARKS,
+ ID_GEOLOCATION,
+ ID_BROWSING_HISTORY,
+ ID_TABS,
+ ID_MANAGEMENT,
+ ID_DEBUGGER,
+ ID_HOSTS_1,
+ ID_HOSTS_2,
+ ID_HOSTS_3,
+ ID_HOSTS_4_OR_MORE,
+ ID_HOSTS_ALL,
+ ID_FULL_ACCESS,
+ ID_ENUM_BOUNDARY
+ };
+
+ // Creates a permission message with the given |message_id| and initializes
+ // its message to the appropriate value.
+ static PermissionMessage CreateFromMessageId(MessageId message_id);
+
+ // Creates the corresponding permission message for a list of hosts. This
+ // method exists because the hosts are presented as one message that depends
+ // on what and how many hosts there are.
+ static PermissionMessage CreateFromHostList(
+ const std::vector<std::string> hosts);
+
+ // Gets the id of the permission message, which can be used in UMA
+ // histograms.
+ MessageId message_id() const { return message_id_; }
+
+ // 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_; }
+
+ // Comparator to work with std::set.
+ bool operator<(const PermissionMessage& that) const {
+ return message_id_ < that.message_id_;
+ }
+
+ private:
+ PermissionMessage(MessageId message_id, string16 message_);
+
+ // The index of the id in the array is its enum value. The first two values
+ // are non-existent message ids to act as placeholders for "unknown" and
+ // "none".
+ // Note: Do not change the order of the items in this list since they
+ // are used in a histogram. The order must match the MessageId order.
+ static const int kMessageIds[];
+
+ MessageId message_id_;
+ string16 message_;
+ };
+
+ typedef std::vector<PermissionMessage> PermissionMessages;
+
// A permission is defined by its |name| (what is used in the manifest),
// and the |message_id| that's used by install/update UI.
struct Permission {
const char* const name;
- const int message_id;
+ const PermissionMessage::MessageId message_id;
};
enum InitFromValueFlags {
@@ -160,17 +226,24 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Return the update url used by gallery/webstore extensions.
static GURL GalleryUpdateUrl(bool secure);
- // The install message id for |permission|. Returns 0 if none exists.
- static int GetPermissionMessageId(const std::string& permission);
-
// Given two install sources, return the one which should take priority
// over the other. If an extension is installed from two sources A and B,
// its install source should be set to GetHigherPriorityLocation(A, B).
static Location GetHigherPriorityLocation(Location loc1, Location loc2);
+ // Get's the install message id for |permission|. Returns
+ // MessageId::TYPE_NONE if none exists.
+ static PermissionMessage::MessageId GetPermissionMessageId(
+ const std::string& permission);
+
// Returns the full list of permission messages that this extension
// should display at install time.
- std::vector<string16> GetPermissionMessages() const;
+ PermissionMessages GetPermissionMessages() const;
+
+ // Returns the full list of permission messages that this extension
+ // should display at install time. The messages are returned as strings
+ // for convenience.
+ std::vector<string16> GetPermissionMessageStrings() const;
// Returns the distinct hosts that should be displayed in the install UI
// for the URL patterns |list|. This discards some of the detail that is
@@ -680,11 +753,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// NOTE: This only includes messages related to permissions declared in the
// "permissions" key in the manifest. Permissions implied from other features
// of the manifest, like plugins and content scripts are not included.
- std::set<string16> GetSimplePermissionMessages() const;
-
- // The permission message displayed related to the host permissions for
- // this extension.
- string16 GetHostPermissionMessage() const;
+ std::set<PermissionMessage> GetSimplePermissionMessages() const;
// Cached images for this extension. This should only be touched on the UI
// thread.
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 131f144..591d4ced 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -1034,13 +1034,18 @@ TEST(ExtensionTest, PermissionMessages) {
skip.insert(Extension::kFileBrowserPrivatePermission);
skip.insert(Extension::kChromeosInfoPrivatePermissions);
+ const Extension::PermissionMessage::MessageId ID_NONE =
+ Extension::PermissionMessage::ID_NONE;
+
for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
- int message_id = Extension::kPermissions[i].message_id;
- std::string name = Extension::kPermissions[i].name;
- if (skip.count(name))
- EXPECT_EQ(0, message_id) << "unexpected message_id for " << name;
- else
- EXPECT_NE(0, message_id) << "missing message_id for " << name;
+ Extension::Permission permission = Extension::kPermissions[i];
+ if (skip.count(permission.name)) {
+ EXPECT_EQ(ID_NONE, permission.message_id)
+ << "unexpected message_id for " << permission.name;
+ } else {
+ EXPECT_NE(ID_NONE, permission.message_id)
+ << "missing message_id for " << permission.name;
+ }
}
}
@@ -1204,7 +1209,7 @@ TEST(ExtensionTest, ApiPermissions) {
TEST(ExtensionTest, GetHostPermissionMessages_ManyHosts) {
scoped_refptr<Extension> extension;
extension = LoadManifest("permissions", "many-hosts.json");
- std::vector<string16> warnings = extension->GetPermissionMessages();
+ std::vector<string16> warnings = extension->GetPermissionMessageStrings();
ASSERT_EQ(1u, warnings.size());
EXPECT_EQ("Your data on www.google.com and encrypted.google.com",
UTF16ToUTF8(warnings[0]));