| 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..8f70db12c08352922c149649d81a67dbb56233db
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/external_install_ui.cc
|
| @@ -0,0 +1,297 @@
|
| +// 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;
|
| +
|
| + 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
|
|
|