| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_install_ui.h" | 5 #include "chrome/browser/extensions/extension_install_ui.h" |
| 6 | 6 |
| 7 #include <map> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/file_util.h" | |
| 11 #include "base/message_loop.h" | |
| 12 #include "base/string_number_conversions.h" | |
| 13 #include "base/string_util.h" | |
| 14 #include "base/stringprintf.h" | |
| 15 #include "base/utf_string_conversions.h" | |
| 16 #include "chrome/browser/extensions/bundle_installer.h" | |
| 17 #include "chrome/browser/extensions/extension_install_dialog.h" | |
| 18 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h" | |
| 19 #include "chrome/browser/infobars/infobar_tab_helper.h" | |
| 20 #include "chrome/browser/profiles/profile.h" | |
| 21 #include "chrome/browser/themes/theme_service.h" | |
| 22 #include "chrome/browser/themes/theme_service_factory.h" | |
| 23 #include "chrome/browser/ui/browser.h" | |
| 24 #include "chrome/browser/ui/browser_dialogs.h" | |
| 25 #include "chrome/browser/ui/browser_finder.h" | |
| 26 #include "chrome/browser/ui/browser_navigator.h" | |
| 27 #include "chrome/browser/ui/browser_window.h" | |
| 28 #include "chrome/browser/ui/simple_message_box.h" | |
| 29 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | |
| 30 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 31 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" | |
| 32 #include "chrome/common/chrome_notification_types.h" | |
| 33 #include "chrome/common/chrome_switches.h" | |
| 34 #include "chrome/common/extensions/extension.h" | |
| 35 #include "chrome/common/extensions/extension_icon_set.h" | |
| 36 #include "chrome/common/extensions/extension_manifest_constants.h" | |
| 37 #include "chrome/common/extensions/extension_resource.h" | |
| 38 #include "chrome/common/extensions/url_pattern.h" | |
| 39 #include "chrome/common/url_constants.h" | |
| 40 #include "content/public/browser/notification_service.h" | |
| 41 #include "grit/chromium_strings.h" | |
| 42 #include "grit/generated_resources.h" | |
| 43 #include "grit/theme_resources.h" | |
| 44 #include "ui/base/l10n/l10n_util.h" | |
| 45 #include "ui/base/resource/resource_bundle.h" | |
| 46 #include "ui/gfx/image/image.h" | |
| 47 | |
| 48 #if defined(USE_ASH) | |
| 49 #include "ash/shell.h" | |
| 50 #endif | |
| 51 | |
| 52 using content::WebContents; | |
| 53 using extensions::BundleInstaller; | |
| 54 using extensions::Extension; | |
| 55 | |
| 56 static const int kTitleIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { | |
| 57 0, // The regular install prompt depends on what's being installed. | |
| 58 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE, | |
| 59 IDS_EXTENSION_INSTALL_PROMPT_TITLE, | |
| 60 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE, | |
| 61 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE | |
| 62 }; | |
| 63 static const int kHeadingIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { | |
| 64 IDS_EXTENSION_INSTALL_PROMPT_HEADING, | |
| 65 0, // Inline installs use the extension name. | |
| 66 0, // Heading for bundle installs depends on the bundle contents. | |
| 67 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING, | |
| 68 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING | |
| 69 }; | |
| 70 static const int kAcceptButtonIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { | |
| 71 IDS_EXTENSION_PROMPT_INSTALL_BUTTON, | |
| 72 IDS_EXTENSION_PROMPT_INSTALL_BUTTON, | |
| 73 IDS_EXTENSION_PROMPT_INSTALL_BUTTON, | |
| 74 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON, | |
| 75 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON | |
| 76 }; | |
| 77 static const int kAbortButtonIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { | |
| 78 0, // These all use the platform's default cancel label. | |
| 79 0, | |
| 80 0, | |
| 81 0, | |
| 82 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON | |
| 83 }; | |
| 84 static const int kPermissionsHeaderIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { | |
| 85 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO, | |
| 86 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO, | |
| 87 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO, | |
| 88 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO, | |
| 89 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO, | |
| 90 }; | |
| 91 | |
| 92 namespace { | |
| 93 | |
| 94 // Size of extension icon in top left of dialog. | |
| 95 const int kIconSize = 69; | |
| 96 | |
| 97 } // namespace | |
| 98 | |
| 99 ExtensionInstallUI::Prompt::Prompt(PromptType type) | |
| 100 : type_(type), | |
| 101 extension_(NULL), | |
| 102 bundle_(NULL), | |
| 103 average_rating_(0.0), | |
| 104 rating_count_(0) { | |
| 105 } | |
| 106 | |
| 107 ExtensionInstallUI::Prompt::~Prompt() { | |
| 108 } | |
| 109 | |
| 110 void ExtensionInstallUI::Prompt::SetPermissions( | |
| 111 const std::vector<string16>& permissions) { | |
| 112 permissions_ = permissions; | |
| 113 } | |
| 114 | |
| 115 void ExtensionInstallUI::Prompt::SetInlineInstallWebstoreData( | |
| 116 const std::string& localized_user_count, | |
| 117 double average_rating, | |
| 118 int rating_count) { | |
| 119 CHECK_EQ(INLINE_INSTALL_PROMPT, type_); | |
| 120 localized_user_count_ = localized_user_count; | |
| 121 average_rating_ = average_rating; | |
| 122 rating_count_ = rating_count; | |
| 123 } | |
| 124 | |
| 125 string16 ExtensionInstallUI::Prompt::GetDialogTitle() const { | |
| 126 if (type_ == INSTALL_PROMPT) { | |
| 127 return l10n_util::GetStringUTF16(extension_->is_app() ? | |
| 128 IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE : | |
| 129 IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE); | |
| 130 } else { | |
| 131 return l10n_util::GetStringUTF16(kTitleIds[type_]); | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 string16 ExtensionInstallUI::Prompt::GetHeading() const { | |
| 136 if (type_ == INLINE_INSTALL_PROMPT) { | |
| 137 return UTF8ToUTF16(extension_->name()); | |
| 138 } else if (type_ == BUNDLE_INSTALL_PROMPT) { | |
| 139 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING); | |
| 140 } else { | |
| 141 return l10n_util::GetStringFUTF16( | |
| 142 kHeadingIds[type_], UTF8ToUTF16(extension_->name())); | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 string16 ExtensionInstallUI::Prompt::GetAcceptButtonLabel() const { | |
| 147 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]); | |
| 148 } | |
| 149 | |
| 150 bool ExtensionInstallUI::Prompt::HasAbortButtonLabel() const { | |
| 151 return kAbortButtonIds[type_] > 0; | |
| 152 } | |
| 153 | |
| 154 string16 ExtensionInstallUI::Prompt::GetAbortButtonLabel() const { | |
| 155 CHECK(HasAbortButtonLabel()); | |
| 156 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]); | |
| 157 } | |
| 158 | |
| 159 string16 ExtensionInstallUI::Prompt::GetPermissionsHeading() const { | |
| 160 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]); | |
| 161 } | |
| 162 | |
| 163 void ExtensionInstallUI::Prompt::AppendRatingStars( | |
| 164 StarAppender appender, void* data) const { | |
| 165 CHECK(appender); | |
| 166 CHECK_EQ(INLINE_INSTALL_PROMPT, type_); | |
| 167 int rating_integer = floor(average_rating_); | |
| 168 double rating_fractional = average_rating_ - rating_integer; | |
| 169 | |
| 170 if (rating_fractional > 0.66) { | |
| 171 rating_integer++; | |
| 172 } | |
| 173 | |
| 174 if (rating_fractional < 0.33 || rating_fractional > 0.66) { | |
| 175 rating_fractional = 0; | |
| 176 } | |
| 177 | |
| 178 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 179 int i; | |
| 180 for (i = 0; i < rating_integer; i++) { | |
| 181 appender(rb.GetBitmapNamed(IDR_EXTENSIONS_RATING_STAR_ON), data); | |
| 182 } | |
| 183 if (rating_fractional) { | |
| 184 appender(rb.GetBitmapNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data); | |
| 185 i++; | |
| 186 } | |
| 187 for (; i < kMaxExtensionRating; i++) { | |
| 188 appender(rb.GetBitmapNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 string16 ExtensionInstallUI::Prompt::GetRatingCount() const { | |
| 193 CHECK_EQ(INLINE_INSTALL_PROMPT, type_); | |
| 194 return l10n_util::GetStringFUTF16( | |
| 195 IDS_EXTENSION_RATING_COUNT, | |
| 196 UTF8ToUTF16(base::IntToString(rating_count_))); | |
| 197 } | |
| 198 | |
| 199 string16 ExtensionInstallUI::Prompt::GetUserCount() const { | |
| 200 CHECK_EQ(INLINE_INSTALL_PROMPT, type_); | |
| 201 return l10n_util::GetStringFUTF16( | |
| 202 IDS_EXTENSION_USER_COUNT, | |
| 203 UTF8ToUTF16(localized_user_count_)); | |
| 204 } | |
| 205 | |
| 206 size_t ExtensionInstallUI::Prompt::GetPermissionCount() const { | |
| 207 return permissions_.size(); | |
| 208 } | |
| 209 | |
| 210 string16 ExtensionInstallUI::Prompt::GetPermission(size_t index) const { | |
| 211 CHECK_LT(index, permissions_.size()); | |
| 212 return l10n_util::GetStringFUTF16( | |
| 213 IDS_EXTENSION_PERMISSION_LINE, permissions_[index]); | |
| 214 } | |
| 215 | |
| 216 // static | |
| 217 scoped_refptr<Extension> ExtensionInstallUI::GetLocalizedExtensionForDisplay( | |
| 218 const DictionaryValue* manifest, | |
| 219 const std::string& id, | |
| 220 const std::string& localized_name, | |
| 221 const std::string& localized_description, | |
| 222 std::string* error) { | |
| 223 scoped_ptr<DictionaryValue> localized_manifest; | |
| 224 if (!localized_name.empty() || !localized_description.empty()) { | |
| 225 localized_manifest.reset(manifest->DeepCopy()); | |
| 226 if (!localized_name.empty()) { | |
| 227 localized_manifest->SetString(extension_manifest_keys::kName, | |
| 228 localized_name); | |
| 229 } | |
| 230 if (!localized_description.empty()) { | |
| 231 localized_manifest->SetString(extension_manifest_keys::kDescription, | |
| 232 localized_description); | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 return Extension::Create( | |
| 237 FilePath(), | |
| 238 Extension::INTERNAL, | |
| 239 localized_manifest.get() ? *localized_manifest.get() : *manifest, | |
| 240 Extension::NO_FLAGS, | |
| 241 id, | |
| 242 error); | |
| 243 } | |
| 244 | |
| 245 ExtensionInstallUI::ExtensionInstallUI(Profile* profile) | 7 ExtensionInstallUI::ExtensionInstallUI(Profile* profile) |
| 246 : profile_(profile), | 8 : profile_(profile) { |
| 247 ui_loop_(MessageLoop::current()), | |
| 248 previous_using_native_theme_(false), | |
| 249 extension_(NULL), | |
| 250 delegate_(NULL), | |
| 251 prompt_(UNSET_PROMPT_TYPE), | |
| 252 prompt_type_(UNSET_PROMPT_TYPE), | |
| 253 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)), | |
| 254 use_app_installed_bubble_(false), | |
| 255 skip_post_install_ui_(false) { | |
| 256 // Remember the current theme in case the user presses undo. | |
| 257 if (profile_) { | |
| 258 const Extension* previous_theme = | |
| 259 ThemeServiceFactory::GetThemeForProfile(profile_); | |
| 260 if (previous_theme) | |
| 261 previous_theme_id_ = previous_theme->id(); | |
| 262 previous_using_native_theme_ = | |
| 263 ThemeServiceFactory::GetForProfile(profile_)->UsingNativeTheme(); | |
| 264 } | |
| 265 } | 9 } |
| 266 | 10 |
| 267 ExtensionInstallUI::~ExtensionInstallUI() { | 11 ExtensionInstallUI::~ExtensionInstallUI() { |
| 268 } | 12 } |
| 269 | |
| 270 void ExtensionInstallUI::ConfirmBundleInstall( | |
| 271 extensions::BundleInstaller* bundle, | |
| 272 const ExtensionPermissionSet* permissions) { | |
| 273 DCHECK(ui_loop_ == MessageLoop::current()); | |
| 274 bundle_ = bundle; | |
| 275 permissions_ = permissions; | |
| 276 delegate_ = bundle; | |
| 277 prompt_type_ = BUNDLE_INSTALL_PROMPT; | |
| 278 | |
| 279 ShowConfirmation(); | |
| 280 } | |
| 281 | |
| 282 void ExtensionInstallUI::ConfirmInlineInstall( | |
| 283 Delegate* delegate, | |
| 284 const Extension* extension, | |
| 285 SkBitmap* icon, | |
| 286 const ExtensionInstallUI::Prompt& prompt) { | |
| 287 DCHECK(ui_loop_ == MessageLoop::current()); | |
| 288 extension_ = extension; | |
| 289 permissions_ = extension->GetActivePermissions(); | |
| 290 delegate_ = delegate; | |
| 291 prompt_ = prompt; | |
| 292 prompt_type_ = INLINE_INSTALL_PROMPT; | |
| 293 | |
| 294 SetIcon(icon); | |
| 295 ShowConfirmation(); | |
| 296 } | |
| 297 | |
| 298 void ExtensionInstallUI::ConfirmWebstoreInstall(Delegate* delegate, | |
| 299 const Extension* extension, | |
| 300 const SkBitmap* icon) { | |
| 301 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the | |
| 302 // remaining fields. | |
| 303 extension_ = extension; | |
| 304 SetIcon(icon); | |
| 305 ConfirmInstall(delegate, extension); | |
| 306 } | |
| 307 | |
| 308 void ExtensionInstallUI::ConfirmInstall(Delegate* delegate, | |
| 309 const Extension* extension) { | |
| 310 DCHECK(ui_loop_ == MessageLoop::current()); | |
| 311 extension_ = extension; | |
| 312 permissions_ = extension->GetActivePermissions(); | |
| 313 delegate_ = delegate; | |
| 314 prompt_type_ = INSTALL_PROMPT; | |
| 315 | |
| 316 // We special-case themes to not show any confirm UI. Instead they are | |
| 317 // immediately installed, and then we show an infobar (see OnInstallSuccess) | |
| 318 // to allow the user to revert if they don't like it. | |
| 319 if (extension->is_theme()) { | |
| 320 delegate->InstallUIProceed(); | |
| 321 return; | |
| 322 } | |
| 323 | |
| 324 LoadImageIfNeeded(); | |
| 325 } | |
| 326 | |
| 327 void ExtensionInstallUI::ConfirmReEnable(Delegate* delegate, | |
| 328 const Extension* extension) { | |
| 329 DCHECK(ui_loop_ == MessageLoop::current()); | |
| 330 extension_ = extension; | |
| 331 permissions_ = extension->GetActivePermissions(); | |
| 332 delegate_ = delegate; | |
| 333 prompt_type_ = RE_ENABLE_PROMPT; | |
| 334 | |
| 335 LoadImageIfNeeded(); | |
| 336 } | |
| 337 | |
| 338 void ExtensionInstallUI::ConfirmPermissions( | |
| 339 Delegate* delegate, | |
| 340 const Extension* extension, | |
| 341 const ExtensionPermissionSet* permissions) { | |
| 342 DCHECK(ui_loop_ == MessageLoop::current()); | |
| 343 extension_ = extension; | |
| 344 permissions_ = permissions; | |
| 345 delegate_ = delegate; | |
| 346 prompt_type_ = PERMISSIONS_PROMPT; | |
| 347 | |
| 348 LoadImageIfNeeded(); | |
| 349 } | |
| 350 | |
| 351 void ExtensionInstallUI::OnInstallSuccess(const Extension* extension, | |
| 352 SkBitmap* icon) { | |
| 353 if (skip_post_install_ui_) | |
| 354 return; | |
| 355 | |
| 356 extension_ = extension; | |
| 357 SetIcon(icon); | |
| 358 | |
| 359 if (extension->is_theme()) { | |
| 360 ShowThemeInfoBar(previous_theme_id_, previous_using_native_theme_, | |
| 361 extension, profile_); | |
| 362 return; | |
| 363 } | |
| 364 | |
| 365 // Extensions aren't enabled by default in incognito so we confirm | |
| 366 // the install in a normal window. | |
| 367 Profile* profile = profile_->GetOriginalProfile(); | |
| 368 Browser* browser = browser::FindOrCreateTabbedBrowser(profile); | |
| 369 if (browser->tab_count() == 0) | |
| 370 browser->AddBlankTab(true); | |
| 371 browser->window()->Show(); | |
| 372 | |
| 373 bool use_bubble_for_apps = false; | |
| 374 | |
| 375 #if defined(TOOLKIT_VIEWS) | |
| 376 CommandLine* cmdline = CommandLine::ForCurrentProcess(); | |
| 377 use_bubble_for_apps = (use_app_installed_bubble_ || | |
| 378 cmdline->HasSwitch(switches::kAppsNewInstallBubble)); | |
| 379 #endif | |
| 380 | |
| 381 if (extension->is_app() && !use_bubble_for_apps) { | |
| 382 ExtensionInstallUI::OpenAppInstalledUI(browser, extension->id()); | |
| 383 return; | |
| 384 } | |
| 385 | |
| 386 browser::ShowExtensionInstalledBubble(extension, browser, icon_, profile); | |
| 387 } | |
| 388 | |
| 389 namespace { | |
| 390 | |
| 391 bool disable_failure_ui_for_tests = false; | |
| 392 | |
| 393 } // namespace | |
| 394 | |
| 395 void ExtensionInstallUI::OnInstallFailure(const string16& error) { | |
| 396 DCHECK(ui_loop_ == MessageLoop::current()); | |
| 397 if (disable_failure_ui_for_tests || skip_post_install_ui_) | |
| 398 return; | |
| 399 | |
| 400 Browser* browser = browser::FindLastActiveWithProfile(profile_); | |
| 401 browser::ShowMessageBox(browser ? browser->window()->GetNativeHandle() : NULL, | |
| 402 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE), error, | |
| 403 browser::MESSAGE_BOX_TYPE_WARNING); | |
| 404 } | |
| 405 | |
| 406 void ExtensionInstallUI::SetIcon(const SkBitmap* image) { | |
| 407 if (image) | |
| 408 icon_ = *image; | |
| 409 else | |
| 410 icon_ = SkBitmap(); | |
| 411 if (icon_.empty()) | |
| 412 icon_ = Extension::GetDefaultIcon(extension_->is_app()); | |
| 413 } | |
| 414 | |
| 415 void ExtensionInstallUI::OnImageLoaded(const gfx::Image& image, | |
| 416 const std::string& extension_id, | |
| 417 int index) { | |
| 418 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap()); | |
| 419 ShowConfirmation(); | |
| 420 } | |
| 421 | |
| 422 // static | |
| 423 void ExtensionInstallUI::OpenAppInstalledUI(Browser* browser, | |
| 424 const std::string& app_id) { | |
| 425 if (NewTabUI::ShouldShowApps()) { | |
| 426 browser::NavigateParams params = browser->GetSingletonTabNavigateParams( | |
| 427 GURL(chrome::kChromeUINewTabURL)); | |
| 428 browser::Navigate(¶ms); | |
| 429 | |
| 430 content::NotificationService::current()->Notify( | |
| 431 chrome::NOTIFICATION_APP_INSTALLED_TO_NTP, | |
| 432 content::Source<WebContents>(params.target_contents->web_contents()), | |
| 433 content::Details<const std::string>(&app_id)); | |
| 434 } else { | |
| 435 #if defined(USE_ASH) | |
| 436 ash::Shell::GetInstance()->ToggleAppList(); | |
| 437 | |
| 438 content::NotificationService::current()->Notify( | |
| 439 chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST, | |
| 440 content::Source<Profile>(browser->profile()), | |
| 441 content::Details<const std::string>(&app_id)); | |
| 442 #else | |
| 443 NOTREACHED(); | |
| 444 #endif | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 // static | |
| 449 void ExtensionInstallUI::DisableFailureUIForTests() { | |
| 450 disable_failure_ui_for_tests = true; | |
| 451 } | |
| 452 | |
| 453 void ExtensionInstallUI::ShowThemeInfoBar(const std::string& previous_theme_id, | |
| 454 bool previous_using_native_theme, | |
| 455 const Extension* new_theme, | |
| 456 Profile* profile) { | |
| 457 if (!new_theme->is_theme()) | |
| 458 return; | |
| 459 | |
| 460 // Get last active tabbed browser of profile. | |
| 461 Browser* browser = browser::FindTabbedBrowser(profile, true); | |
| 462 if (!browser) | |
| 463 return; | |
| 464 | |
| 465 TabContentsWrapper* tab_contents = browser->GetSelectedTabContentsWrapper(); | |
| 466 if (!tab_contents) | |
| 467 return; | |
| 468 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); | |
| 469 | |
| 470 // First find any previous theme preview infobars. | |
| 471 InfoBarDelegate* old_delegate = NULL; | |
| 472 for (size_t i = 0; i < infobar_helper->infobar_count(); ++i) { | |
| 473 InfoBarDelegate* delegate = infobar_helper->GetInfoBarDelegateAt(i); | |
| 474 ThemeInstalledInfoBarDelegate* theme_infobar = | |
| 475 delegate->AsThemePreviewInfobarDelegate(); | |
| 476 if (theme_infobar) { | |
| 477 // If the user installed the same theme twice, ignore the second install | |
| 478 // and keep the first install info bar, so that they can easily undo to | |
| 479 // get back the previous theme. | |
| 480 if (theme_infobar->MatchesTheme(new_theme)) | |
| 481 return; | |
| 482 old_delegate = delegate; | |
| 483 break; | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 // Then either replace that old one or add a new one. | |
| 488 InfoBarDelegate* new_delegate = GetNewThemeInstalledInfoBarDelegate( | |
| 489 tab_contents, new_theme, previous_theme_id, previous_using_native_theme); | |
| 490 | |
| 491 if (old_delegate) | |
| 492 infobar_helper->ReplaceInfoBar(old_delegate, new_delegate); | |
| 493 else | |
| 494 infobar_helper->AddInfoBar(new_delegate); | |
| 495 } | |
| 496 | |
| 497 void ExtensionInstallUI::LoadImageIfNeeded() { | |
| 498 // Bundle install prompts do not have an icon. | |
| 499 if (!icon_.empty()) { | |
| 500 ShowConfirmation(); | |
| 501 return; | |
| 502 } | |
| 503 | |
| 504 // Load the image asynchronously. For the response, check OnImageLoaded. | |
| 505 ExtensionResource image = | |
| 506 extension_->GetIconResource(ExtensionIconSet::EXTENSION_ICON_LARGE, | |
| 507 ExtensionIconSet::MATCH_BIGGER); | |
| 508 tracker_.LoadImage(extension_, image, | |
| 509 gfx::Size(kIconSize, kIconSize), | |
| 510 ImageLoadingTracker::DONT_CACHE); | |
| 511 } | |
| 512 | |
| 513 void ExtensionInstallUI::ShowConfirmation() { | |
| 514 prompt_.set_type(prompt_type_); | |
| 515 prompt_.SetPermissions(permissions_->GetWarningMessages()); | |
| 516 | |
| 517 switch (prompt_type_) { | |
| 518 case PERMISSIONS_PROMPT: | |
| 519 case RE_ENABLE_PROMPT: | |
| 520 case INLINE_INSTALL_PROMPT: | |
| 521 case INSTALL_PROMPT: { | |
| 522 prompt_.set_extension(extension_); | |
| 523 prompt_.set_icon(gfx::Image(icon_)); | |
| 524 ShowExtensionInstallDialog(profile_, delegate_, prompt_); | |
| 525 break; | |
| 526 } | |
| 527 case BUNDLE_INSTALL_PROMPT: { | |
| 528 prompt_.set_bundle(bundle_); | |
| 529 ShowExtensionInstallDialog(profile_, delegate_, prompt_); | |
| 530 break; | |
| 531 } | |
| 532 default: | |
| 533 NOTREACHED() << "Unknown message"; | |
| 534 break; | |
| 535 } | |
| 536 } | |
| 537 | |
| 538 InfoBarDelegate* ExtensionInstallUI::GetNewThemeInstalledInfoBarDelegate( | |
| 539 TabContentsWrapper* tab_contents, | |
| 540 const Extension* new_theme, | |
| 541 const std::string& previous_theme_id, | |
| 542 bool previous_using_native_theme) { | |
| 543 Profile* profile = tab_contents->profile(); | |
| 544 return new ThemeInstalledInfoBarDelegate( | |
| 545 tab_contents->infobar_tab_helper(), | |
| 546 profile->GetExtensionService(), | |
| 547 ThemeServiceFactory::GetForProfile(profile), | |
| 548 new_theme, | |
| 549 previous_theme_id, | |
| 550 previous_using_native_theme); | |
| 551 } | |
| OLD | NEW |