Index: chrome/browser/extensions/external_install_ui.cc |
diff --git a/chrome/browser/extensions/external_install_ui.cc b/chrome/browser/extensions/external_install_ui.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b28aaa796f84aae73f77ddfc53f4ed9ae098ab1c |
--- /dev/null |
+++ b/chrome/browser/extensions/external_install_ui.cc |
@@ -0,0 +1,299 @@ |
+// 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 "chrome/browser/extensions/external_install_ui.h" |
+ |
+#include <string> |
+ |
+#include "base/bind.h" |
+#include "base/lazy_instance.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "base/metrics/histogram.h" |
+#include "base/utf_string_conversions.h" |
+#include "chrome/app/chrome_command_ids.h" |
+#include "chrome/browser/extensions/extension_install_prompt.h" |
+#include "chrome/browser/extensions/extension_service.h" |
+#include "chrome/browser/extensions/extension_uninstall_dialog.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/global_error/global_error.h" |
+#include "chrome/browser/ui/global_error/global_error_service.h" |
+#include "chrome/browser/ui/global_error/global_error_service_factory.h" |
+#include "chrome/common/chrome_notification_types.h" |
+#include "chrome/common/extensions/extension.h" |
+#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_observer.h" |
+#include "content/public/browser/notification_registrar.h" |
+#include "content/public/browser/notification_source.h" |
+#include "grit/chromium_strings.h" |
+#include "grit/generated_resources.h" |
+#include "grit/theme_resources.h" |
+#include "ui/base/l10n/l10n_util.h" |
+ |
+namespace extensions { |
+ |
+static const int kMenuCommandId = IDC_EXTERNAL_EXTENSION_ALERT; |
+ |
+// ExternalInstallDialogDelegate -------------------------------------------- |
+ |
+// TODO(mpcomplete): Get rid of the refcounting on this class, or document |
+// why it's necessary. Will do after refactoring to merge back with |
+// ExtensionDisabledDialogDelegate. |
+class ExternalInstallDialogDelegate |
+ : public ExtensionInstallPrompt::Delegate, |
+ public base::RefCountedThreadSafe<ExternalInstallDialogDelegate> { |
+ public: |
+ ExternalInstallDialogDelegate(Browser* browser, |
+ ExtensionService* service, |
+ const Extension* extension); |
+ |
+ private: |
+ friend class base::RefCountedThreadSafe<ExternalInstallDialogDelegate>; |
+ |
+ virtual ~ExternalInstallDialogDelegate(); |
+ |
+ // ExtensionInstallPrompt::Delegate: |
+ virtual void InstallUIProceed() OVERRIDE; |
+ virtual void InstallUIAbort(bool user_initiated) OVERRIDE; |
+ |
+ // The UI for showing the install dialog when enabling. |
+ scoped_ptr<ExtensionInstallPrompt> install_ui_; |
+ |
+ ExtensionService* service_; |
+ const Extension* extension_; |
+}; |
+ |
+ExternalInstallDialogDelegate::ExternalInstallDialogDelegate( |
+ Browser* browser, |
+ ExtensionService* service, |
+ const Extension* extension) |
+ : service_(service), extension_(extension) { |
+ AddRef(); // Balanced in Proceed or Abort. |
+ |
+ install_ui_.reset(chrome::CreateExtensionInstallPromptWithBrowser(browser)); |
+ install_ui_->ConfirmExternalInstall(this, extension_); |
+} |
+ |
+ExternalInstallDialogDelegate::~ExternalInstallDialogDelegate() { |
+} |
+ |
+void ExternalInstallDialogDelegate::InstallUIProceed() { |
+ service_->GrantPermissionsAndEnableExtension( |
+ extension_, install_ui_->record_oauth2_grant()); |
+ Release(); |
+} |
+ |
+void ExternalInstallDialogDelegate::InstallUIAbort(bool user_initiated) { |
+ service_->UninstallExtension(extension_->id(), false, NULL); |
+ Release(); |
+} |
+ |
+static void ShowExternalInstallDialog(ExtensionService* service, |
+ Browser* browser, |
+ const Extension* extension) { |
+ // This object manages its own lifetime. |
+ new ExternalInstallDialogDelegate(browser, service, extension); |
+} |
+ |
+// ExternalInstallGlobalError ----------------------------------------------- |
+ |
+class ExternalInstallGlobalError : public GlobalError, |
+ public content::NotificationObserver { |
+ public: |
+ ExternalInstallGlobalError(ExtensionService* service, |
+ const Extension* extension); |
+ virtual ~ExternalInstallGlobalError(); |
+ |
+ const Extension* extension() const { return extension_; } |
+ |
+ // GlobalError implementation. |
+ virtual bool HasBadge() OVERRIDE; |
+ virtual int GetBadgeResourceID() OVERRIDE; |
+ virtual bool HasMenuItem() OVERRIDE; |
+ virtual int MenuItemCommandID() OVERRIDE; |
+ virtual string16 MenuItemLabel() OVERRIDE; |
+ virtual int MenuItemIconResourceID() OVERRIDE; |
+ virtual void ExecuteMenuItem(Browser* browser) OVERRIDE; |
+ virtual bool HasBubbleView() OVERRIDE; |
+ virtual string16 GetBubbleViewTitle() OVERRIDE; |
+ virtual string16 GetBubbleViewMessage() OVERRIDE; |
+ virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; |
+ virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE; |
+ virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; |
+ virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; |
+ virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; |
+ |
+ // content::NotificationObserver implementation. |
+ virtual void Observe(int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) OVERRIDE; |
+ |
+ private: |
+ ExtensionService* service_; |
+ const Extension* extension_; |
+ |
+ // How the user responded to the error; used for metrics. |
+ enum UserResponse { |
+ IGNORED, |
+ REENABLE, |
+ UNINSTALL, |
+ USER_RESPONSE_BUCKET_BOUNDARY |
+ }; |
+ UserResponse user_response_; |
+ |
+ content::NotificationRegistrar registrar_; |
+}; |
+ |
+ExternalInstallGlobalError::ExternalInstallGlobalError( |
+ ExtensionService* service, |
+ const Extension* extension) |
+ : service_(service), |
+ extension_(extension), |
+ user_response_(IGNORED) { |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
+ content::Source<Profile>(service->profile())); |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
+ content::Source<Profile>(service->profile())); |
+} |
+ |
+ExternalInstallGlobalError::~ExternalInstallGlobalError() { |
+ HISTOGRAM_ENUMERATION("Extensions.ExternalInstallUIUserResponse", |
+ user_response_, USER_RESPONSE_BUCKET_BOUNDARY); |
+} |
+ |
+bool ExternalInstallGlobalError::HasBadge() { |
+ return true; |
+} |
+ |
+int ExternalInstallGlobalError::GetBadgeResourceID() { |
+ return IDR_UPDATE_BADGE_EXTENSION; |
+} |
+ |
+bool ExternalInstallGlobalError::HasMenuItem() { |
+ return true; |
+} |
+ |
+int ExternalInstallGlobalError::MenuItemCommandID() { |
+ return kMenuCommandId; |
+} |
+ |
+int ExternalInstallGlobalError::MenuItemIconResourceID() { |
+ return IDR_UPDATE_MENU_EXTENSION; |
+} |
+ |
+string16 ExternalInstallGlobalError::MenuItemLabel() { |
+ return l10n_util::GetStringFUTF16(IDS_EXTENSION_EXTERNAL_INSTALL_ALERT, |
+ UTF8ToUTF16(extension_->name())); |
+} |
+ |
+void ExternalInstallGlobalError::ExecuteMenuItem(Browser* browser) { |
+ ShowExternalInstallDialog(service_, browser, extension_); |
+} |
+ |
+bool ExternalInstallGlobalError::HasBubbleView() { |
+ return false; |
+} |
+ |
+string16 ExternalInstallGlobalError::GetBubbleViewTitle() { |
+ return string16(); |
+} |
+ |
+string16 ExternalInstallGlobalError::GetBubbleViewMessage() { |
+ return string16(); |
+} |
+ |
+string16 ExternalInstallGlobalError::GetBubbleViewAcceptButtonLabel() { |
+ return string16(); |
+} |
+ |
+string16 ExternalInstallGlobalError::GetBubbleViewCancelButtonLabel() { |
+ return string16(); |
+} |
+ |
+void ExternalInstallGlobalError::OnBubbleViewDidClose(Browser* browser) { |
+ NOTREACHED(); |
+} |
+ |
+void ExternalInstallGlobalError::BubbleViewAcceptButtonPressed( |
+ Browser* browser) { |
+ NOTREACHED(); |
+} |
+ |
+void ExternalInstallGlobalError::BubbleViewCancelButtonPressed( |
+ Browser* browser) { |
+ NOTREACHED(); |
+} |
+ |
+void ExternalInstallGlobalError::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ const Extension* extension = NULL; |
+ // The error is invalidated if the extension has been reloaded |
+ // or unloaded. |
+ if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { |
+ extension = content::Details<const Extension>(details).ptr(); |
+ } else { |
+ DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_UNLOADED, type); |
+ extensions::UnloadedExtensionInfo* info = |
+ content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); |
+ extension = info->extension; |
+ } |
+ if (extension == extension_) { |
+ GlobalErrorService* error_service = |
+ GlobalErrorServiceFactory::GetForProfile(service_->profile()); |
+ error_service->RemoveGlobalError(this); |
+ |
+ // We only check for new external installs on startup, so these |
+ // notifications are guaranteed to be user-initiated. |
+ if (type == chrome::NOTIFICATION_EXTENSION_LOADED) |
+ user_response_ = REENABLE; |
+ else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) |
+ user_response_ = UNINSTALL; |
+ |
+ // This call deletes us (via Add/RemoveExternalInstallError). |
Yoyo Zhou
2012/10/17 00:23:55
This comment seems to be no longer accurate.
Matt Perry
2012/10/17 00:35:20
Done.
|
+ service_->AcknowledgeExternalExtension(extension_->id()); |
+ |
+ delete this; |
+ } |
+} |
+ |
+// Public interface --------------------------------------------------------- |
+ |
+bool AddExternalInstallError(ExtensionService* service, |
+ const Extension* extension) { |
+ GlobalErrorService* error_service = |
+ GlobalErrorServiceFactory::GetForProfile(service->profile()); |
+ GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( |
+ kMenuCommandId); |
+ if (error) |
+ return false; |
+ |
+ error_service->AddGlobalError( |
+ new ExternalInstallGlobalError(service, extension)); |
+ return true; |
+} |
+ |
+void RemoveExternalInstallError(ExtensionService* service) { |
+ GlobalErrorService* error_service = |
+ GlobalErrorServiceFactory::GetForProfile(service->profile()); |
+ GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( |
+ kMenuCommandId); |
+ if (error) { |
+ error_service->RemoveGlobalError(error); |
+ delete error; |
+ } |
+} |
+ |
+bool HasExternalInstallError(ExtensionService* service) { |
+ GlobalErrorService* error_service = |
+ GlobalErrorServiceFactory::GetForProfile(service->profile()); |
+ GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( |
+ kMenuCommandId); |
+ return !!error; |
+} |
+ |
+} // namespace extensions |