diff options
author | jstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-19 22:52:49 +0000 |
---|---|---|
committer | jstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-19 22:52:49 +0000 |
commit | fe2dd774543cb94fb60feb94df60444fd5b73c34 (patch) | |
tree | 8dc1c91f4744debb680e94160c7015a441a81aba /chrome | |
parent | 47317494db5a0041f8a32ce4a654f8209166e96e (diff) | |
download | chromium_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.cc | 5 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_disabled_infobar_delegate.cc | 5 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_install_ui.cc | 3 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service.cc | 36 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service.h | 7 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_webstore_private_api.cc | 2 | ||||
-rw-r--r-- | chrome/browser/ui/webui/app_launcher_handler.cc | 5 | ||||
-rw-r--r-- | chrome/common/extensions/extension.cc | 208 | ||||
-rw-r--r-- | chrome/common/extensions/extension.h | 89 | ||||
-rw-r--r-- | chrome/common/extensions/extension_unittest.cc | 19 |
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])); |