1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Use of this source code is governed by a BSD-style license that can be 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// found in the LICENSE file. 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/extensions/external_install_ui.h" 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <string> 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/bind.h" 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/lazy_instance.h" 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/memory/ref_counted.h" 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/memory/scoped_ptr.h" 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/message_loop/message_loop.h" 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/metrics/histogram.h" 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/strings/utf_string_conversions.h" 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/app/chrome_command_ids.h" 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/chrome_notification_types.h" 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/extensions/extension_install_prompt.h" 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/extensions/extension_install_ui.h" 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/extensions/extension_service.h" 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/extensions/extension_uninstall_dialog.h" 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/profiles/profile.h" 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/ui/browser.h" 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/ui/browser_finder.h" 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/ui/global_error/global_error.h" 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/ui/global_error/global_error_service.h" 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/ui/global_error/global_error_service_factory.h" 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/browser/ui/host_desktop.h" 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/common/extensions/extension_constants.h" 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "chrome/common/extensions/manifest_url_handler.h" 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/notification_details.h" 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/notification_observer.h" 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/notification_registrar.h" 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/notification_source.h" 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "extensions/common/extension.h" 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "grit/chromium_strings.h" 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "grit/generated_resources.h" 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "grit/theme_resources.h" 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ui/base/l10n/l10n_util.h" 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ui/gfx/image/image.h" 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ui/gfx/image/image_skia_operations.h" 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ui/gfx/size.h" 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace extensions { 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace { 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Whether the external extension can use the streamlined bubble install flow. 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool UseBubbleInstall(const Extension* extension, bool is_new_profile) { 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ManifestURL::UpdatesFromGallery(extension) && !is_new_profile; 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // namespace 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const int kMenuCommandId = IDC_EXTERNAL_EXTENSION_ALERT; 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ExternalInstallGlobalError; 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// TODO(mpcomplete): Get rid of the refcounting on this class, or document 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// why it's necessary. Will do after refactoring to merge back with 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ExtensionDisabledDialogDelegate. 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ExternalInstallDialogDelegate 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org : public ExtensionInstallPrompt::Delegate, 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public base::RefCountedThreadSafe<ExternalInstallDialogDelegate> { 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ExternalInstallDialogDelegate(Browser* browser, 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ExtensionService* service, 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const Extension* extension, 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool use_global_error); 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Browser* browser() { return browser_; } 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org private: 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org friend class base::RefCountedThreadSafe<ExternalInstallDialogDelegate>; 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org friend class ExternalInstallGlobalError; 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ~ExternalInstallDialogDelegate(); 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // ExtensionInstallPrompt::Delegate: 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void InstallUIProceed() OVERRIDE; 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void InstallUIAbort(bool user_initiated) OVERRIDE; 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The UI for showing the install dialog when enabling. 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org scoped_ptr<ExtensionInstallPrompt> install_ui_; 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Browser* browser_; 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org base::WeakPtr<ExtensionService> service_weak_; 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const std::string extension_id_; 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Only shows a menu item, no bubble. Clicking the menu item shows 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// an external install dialog. 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ExternalInstallMenuAlert : public GlobalErrorWithStandardBubble, 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public content::NotificationObserver { 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ExternalInstallMenuAlert(ExtensionService* service, 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const Extension* extension); 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ~ExternalInstallMenuAlert(); 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const Extension* extension() const { return extension_; } 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // GlobalError implementation. 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual Severity GetSeverity() OVERRIDE; 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual bool HasMenuItem() OVERRIDE; 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual int MenuItemCommandID() OVERRIDE; 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 MenuItemLabel() OVERRIDE; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void ExecuteMenuItem(Browser* browser) OVERRIDE; 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual bool HasBubbleView() OVERRIDE; 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 GetBubbleViewTitle() OVERRIDE; 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual std::vector<base::string16> GetBubbleViewMessages() OVERRIDE; 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 GetBubbleViewCancelButtonLabel() OVERRIDE; 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // content::NotificationObserver implementation. 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void Observe(int type, 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const content::NotificationSource& source, 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const content::NotificationDetails& details) OVERRIDE; 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org protected: 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ExtensionService* service_; 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const Extension* extension_; 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org content::NotificationRegistrar registrar_; 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Shows a menu item and a global error bubble, replacing the install dialog. 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ExternalInstallGlobalError : public ExternalInstallMenuAlert { 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ExternalInstallGlobalError(ExtensionService* service, 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const Extension* extension, 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ExternalInstallDialogDelegate* delegate, 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const ExtensionInstallPrompt::Prompt& prompt); 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ~ExternalInstallGlobalError(); 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void ExecuteMenuItem(Browser* browser) OVERRIDE; 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual bool HasBubbleView() OVERRIDE; 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual gfx::Image GetBubbleViewIcon() OVERRIDE; 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 GetBubbleViewTitle() OVERRIDE; 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual std::vector<base::string16> GetBubbleViewMessages() OVERRIDE; 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual base::string16 GetBubbleViewCancelButtonLabel() OVERRIDE; 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org protected: 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Ref-counted, but needs to be disposed of if we are dismissed without 150 // having been clicked (perhaps because the user enabled the extension 151 // manually). 152 ExternalInstallDialogDelegate* delegate_; 153 const ExtensionInstallPrompt::Prompt* prompt_; 154}; 155 156static void CreateExternalInstallGlobalError( 157 base::WeakPtr<ExtensionService> service, 158 const std::string& extension_id, 159 const ExtensionInstallPrompt::ShowParams& show_params, 160 ExtensionInstallPrompt::Delegate* prompt_delegate, 161 const ExtensionInstallPrompt::Prompt& prompt) { 162 if (!service.get()) 163 return; 164 const Extension* extension = service->GetInstalledExtension(extension_id); 165 if (!extension) 166 return; 167 GlobalErrorService* error_service = 168 GlobalErrorServiceFactory::GetForProfile(service->profile()); 169 if (error_service->GetGlobalErrorByMenuItemCommandID(kMenuCommandId)) 170 return; 171 172 ExternalInstallDialogDelegate* delegate = 173 static_cast<ExternalInstallDialogDelegate*>(prompt_delegate); 174 ExternalInstallGlobalError* error_bubble = new ExternalInstallGlobalError( 175 service.get(), extension, delegate, prompt); 176 error_service->AddGlobalError(error_bubble); 177 // Show bubble immediately if possible. 178 if (delegate->browser()) 179 error_bubble->ShowBubbleView(delegate->browser()); 180} 181 182static void ShowExternalInstallDialog( 183 ExtensionService* service, 184 Browser* browser, 185 const Extension* extension) { 186 // This object manages its own lifetime. 187 new ExternalInstallDialogDelegate(browser, service, extension, false); 188} 189 190// ExternalInstallDialogDelegate -------------------------------------------- 191 192ExternalInstallDialogDelegate::ExternalInstallDialogDelegate( 193 Browser* browser, 194 ExtensionService* service, 195 const Extension* extension, 196 bool use_global_error) 197 : browser_(browser), 198 service_weak_(service->AsWeakPtr()), 199 extension_id_(extension->id()) { 200 AddRef(); // Balanced in Proceed or Abort. 201 202 install_ui_.reset( 203 ExtensionInstallUI::CreateInstallPromptWithBrowser(browser)); 204 205 const ExtensionInstallPrompt::ShowDialogCallback callback = 206 use_global_error ? 207 base::Bind(&CreateExternalInstallGlobalError, 208 service_weak_, extension_id_) : 209 ExtensionInstallPrompt::GetDefaultShowDialogCallback(); 210 install_ui_->ConfirmExternalInstall(this, extension, callback); 211} 212 213ExternalInstallDialogDelegate::~ExternalInstallDialogDelegate() { 214} 215 216void ExternalInstallDialogDelegate::InstallUIProceed() { 217 if (!service_weak_.get()) 218 return; 219 const Extension* extension = 220 service_weak_->GetInstalledExtension(extension_id_); 221 if (!extension) 222 return; 223 service_weak_->GrantPermissionsAndEnableExtension(extension); 224 Release(); 225} 226 227void ExternalInstallDialogDelegate::InstallUIAbort(bool user_initiated) { 228 if (!service_weak_.get()) 229 return; 230 const Extension* extension = 231 service_weak_->GetInstalledExtension(extension_id_); 232 if (!extension) 233 return; 234 service_weak_->UninstallExtension(extension_id_, false, NULL); 235 Release(); 236} 237 238// ExternalInstallMenuAlert ------------------------------------------------- 239 240ExternalInstallMenuAlert::ExternalInstallMenuAlert( 241 ExtensionService* service, 242 const Extension* extension) 243 : service_(service), 244 extension_(extension) { 245 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 246 content::Source<Profile>(service->profile())); 247 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_REMOVED, 248 content::Source<Profile>(service->profile())); 249} 250 251ExternalInstallMenuAlert::~ExternalInstallMenuAlert() { 252} 253 254GlobalError::Severity ExternalInstallMenuAlert::GetSeverity() { 255 return SEVERITY_LOW; 256} 257 258bool ExternalInstallMenuAlert::HasMenuItem() { 259 return true; 260} 261 262int ExternalInstallMenuAlert::MenuItemCommandID() { 263 return kMenuCommandId; 264} 265 266base::string16 ExternalInstallMenuAlert::MenuItemLabel() { 267 int id = -1; 268 if (extension_->is_app()) 269 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_APP; 270 else if (extension_->is_theme()) 271 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_THEME; 272 else 273 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_EXTENSION; 274 return l10n_util::GetStringFUTF16(id, UTF8ToUTF16(extension_->name())); 275} 276 277void ExternalInstallMenuAlert::ExecuteMenuItem(Browser* browser) { 278 ShowExternalInstallDialog(service_, browser, extension_); 279} 280 281bool ExternalInstallMenuAlert::HasBubbleView() { 282 return false; 283} 284base::string16 ExternalInstallMenuAlert::GetBubbleViewTitle() { 285 return base::string16(); 286} 287 288std::vector<base::string16> ExternalInstallMenuAlert::GetBubbleViewMessages() { 289 return std::vector<base::string16>(); 290} 291 292base::string16 ExternalInstallMenuAlert::GetBubbleViewAcceptButtonLabel() { 293 return base::string16(); 294} 295 296base::string16 ExternalInstallMenuAlert::GetBubbleViewCancelButtonLabel() { 297 return base::string16(); 298} 299 300void ExternalInstallMenuAlert::OnBubbleViewDidClose(Browser* browser) { 301 NOTREACHED(); 302} 303 304void ExternalInstallMenuAlert::BubbleViewAcceptButtonPressed( 305 Browser* browser) { 306 NOTREACHED(); 307} 308 309void ExternalInstallMenuAlert::BubbleViewCancelButtonPressed( 310 Browser* browser) { 311 NOTREACHED(); 312} 313 314void ExternalInstallMenuAlert::Observe( 315 int type, 316 const content::NotificationSource& source, 317 const content::NotificationDetails& details) { 318 // The error is invalidated if the extension has been loaded or removed. 319 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED || 320 type == chrome::NOTIFICATION_EXTENSION_REMOVED); 321 const Extension* extension = content::Details<const Extension>(details).ptr(); 322 if (extension != extension_) 323 return; 324 GlobalErrorService* error_service = 325 GlobalErrorServiceFactory::GetForProfile(service_->profile()); 326 error_service->RemoveGlobalError(this); 327 service_->AcknowledgeExternalExtension(extension_->id()); 328 delete this; 329} 330 331// ExternalInstallGlobalError ----------------------------------------------- 332 333ExternalInstallGlobalError::ExternalInstallGlobalError( 334 ExtensionService* service, 335 const Extension* extension, 336 ExternalInstallDialogDelegate* delegate, 337 const ExtensionInstallPrompt::Prompt& prompt) 338 : ExternalInstallMenuAlert(service, extension), 339 delegate_(delegate), 340 prompt_(&prompt) { 341} 342 343ExternalInstallGlobalError::~ExternalInstallGlobalError() { 344 if (delegate_) 345 delegate_->Release(); 346} 347 348void ExternalInstallGlobalError::ExecuteMenuItem(Browser* browser) { 349 ShowBubbleView(browser); 350} 351 352bool ExternalInstallGlobalError::HasBubbleView() { 353 return true; 354} 355 356gfx::Image ExternalInstallGlobalError::GetBubbleViewIcon() { 357 if (prompt_->icon().IsEmpty()) 358 return GlobalErrorWithStandardBubble::GetBubbleViewIcon(); 359 // Scale icon to a reasonable size. 360 return gfx::Image(gfx::ImageSkiaOperations::CreateResizedImage( 361 *prompt_->icon().ToImageSkia(), 362 skia::ImageOperations::RESIZE_BEST, 363 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, 364 extension_misc::EXTENSION_ICON_SMALL))); 365} 366 367base::string16 ExternalInstallGlobalError::GetBubbleViewTitle() { 368 return prompt_->GetDialogTitle(); 369} 370 371std::vector<base::string16> 372ExternalInstallGlobalError::GetBubbleViewMessages() { 373 std::vector<base::string16> messages; 374 messages.push_back(prompt_->GetHeading()); 375 if (prompt_->GetPermissionCount()) { 376 messages.push_back(prompt_->GetPermissionsHeading()); 377 for (size_t i = 0; i < prompt_->GetPermissionCount(); ++i) { 378 messages.push_back(l10n_util::GetStringFUTF16( 379 IDS_EXTENSION_PERMISSION_LINE, 380 prompt_->GetPermission(i))); 381 } 382 } 383 // TODO(yoz): OAuth issue advice? 384 return messages; 385} 386 387base::string16 ExternalInstallGlobalError::GetBubbleViewAcceptButtonLabel() { 388 return prompt_->GetAcceptButtonLabel(); 389} 390 391base::string16 ExternalInstallGlobalError::GetBubbleViewCancelButtonLabel() { 392 return prompt_->GetAbortButtonLabel(); 393} 394 395void ExternalInstallGlobalError::OnBubbleViewDidClose(Browser* browser) { 396} 397 398void ExternalInstallGlobalError::BubbleViewAcceptButtonPressed( 399 Browser* browser) { 400 ExternalInstallDialogDelegate* delegate = delegate_; 401 delegate_ = NULL; 402 delegate->InstallUIProceed(); 403} 404 405void ExternalInstallGlobalError::BubbleViewCancelButtonPressed( 406 Browser* browser) { 407 ExternalInstallDialogDelegate* delegate = delegate_; 408 delegate_ = NULL; 409 delegate->InstallUIAbort(true); 410} 411 412// Public interface --------------------------------------------------------- 413 414void AddExternalInstallError(ExtensionService* service, 415 const Extension* extension, 416 bool is_new_profile) { 417 GlobalErrorService* error_service = 418 GlobalErrorServiceFactory::GetForProfile(service->profile()); 419 if (error_service->GetGlobalErrorByMenuItemCommandID(kMenuCommandId)) 420 return; 421 422 if (UseBubbleInstall(extension, is_new_profile)) { 423 Browser* browser = NULL; 424#if !defined(OS_ANDROID) 425 browser = chrome::FindTabbedBrowser(service->profile(), 426 true, 427 chrome::GetActiveDesktop()); 428#endif 429 new ExternalInstallDialogDelegate(browser, service, extension, true); 430 } else { 431 error_service->AddGlobalError( 432 new ExternalInstallMenuAlert(service, extension)); 433 } 434} 435 436void RemoveExternalInstallError(ExtensionService* service) { 437 GlobalErrorService* error_service = 438 GlobalErrorServiceFactory::GetForProfile(service->profile()); 439 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( 440 kMenuCommandId); 441 if (error) { 442 error_service->RemoveGlobalError(error); 443 delete error; 444 } 445} 446 447bool HasExternalInstallError(ExtensionService* service) { 448 GlobalErrorService* error_service = 449 GlobalErrorServiceFactory::GetForProfile(service->profile()); 450 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( 451 kMenuCommandId); 452 return !!error; 453} 454 455bool HasExternalInstallBubble(ExtensionService* service) { 456 GlobalErrorService* error_service = 457 GlobalErrorServiceFactory::GetForProfile(service->profile()); 458 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( 459 kMenuCommandId); 460 return error && error->HasBubbleView(); 461} 462 463} // namespace extensions 464