Home | History | Annotate | Download | only in extensions
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "chrome/browser/chrome_notification_types.h"
     11 #include "chrome/browser/extensions/image_loader.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/ui/browser.h"
     14 #include "chrome/common/extensions/extension_constants.h"
     15 #include "chrome/common/extensions/extension_icon_set.h"
     16 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
     17 #include "content/public/browser/notification_service.h"
     18 #include "content/public/browser/notification_source.h"
     19 #include "extensions/common/extension.h"
     20 #include "extensions/common/extension_resource.h"
     21 #include "grit/generated_resources.h"
     22 #include "grit/theme_resources.h"
     23 #include "ui/base/resource/resource_bundle.h"
     24 #include "ui/gfx/image/image.h"
     25 #include "ui/gfx/image/image_skia.h"
     26 
     27 namespace {
     28 
     29 // Returns pixel size under maximal scale factor for the icon whose device
     30 // independent size is |size_in_dip|
     31 int GetSizeForMaxScaleFactor(int size_in_dip) {
     32   float max_scale_factor_scale = gfx::ImageSkia::GetMaxSupportedScale();
     33 
     34   return static_cast<int>(size_in_dip * max_scale_factor_scale);
     35 }
     36 
     37 // Returns bitmap for the default icon with size equal to the default icon's
     38 // pixel size under maximal supported scale factor.
     39 SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
     40   const gfx::ImageSkia& image = is_app ?
     41       extensions::IconsInfo::GetDefaultAppIcon() :
     42       extensions::IconsInfo::GetDefaultExtensionIcon();
     43   return image.GetRepresentation(
     44       gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
     45 }
     46 
     47 }  // namespace
     48 
     49 // Size of extension icon in top left of dialog.
     50 static const int kIconSize = 69;
     51 
     52 ExtensionUninstallDialog::ExtensionUninstallDialog(
     53     Profile* profile,
     54     Browser* browser,
     55     ExtensionUninstallDialog::Delegate* delegate)
     56     : profile_(profile),
     57       browser_(browser),
     58       delegate_(delegate),
     59       extension_(NULL),
     60       state_(kImageIsLoading),
     61       ui_loop_(base::MessageLoop::current()) {
     62   if (browser) {
     63     registrar_.Add(this,
     64                    chrome::NOTIFICATION_BROWSER_CLOSED,
     65                    content::Source<Browser>(browser));
     66   }
     67 }
     68 
     69 ExtensionUninstallDialog::~ExtensionUninstallDialog() {
     70 }
     71 
     72 void ExtensionUninstallDialog::ConfirmUninstall(
     73     const extensions::Extension* extension) {
     74   DCHECK(ui_loop_ == base::MessageLoop::current());
     75   extension_ = extension;
     76   extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
     77       extension_,
     78       extension_misc::EXTENSION_ICON_LARGE,
     79       ExtensionIconSet::MATCH_BIGGER);
     80   // Load the icon whose pixel size is large enough to be displayed under
     81   // maximal supported scale factor. UI code will scale the icon down if needed.
     82   int pixel_size = GetSizeForMaxScaleFactor(kIconSize);
     83 
     84   // Load the image asynchronously. The response will be sent to OnImageLoaded.
     85   state_ = kImageIsLoading;
     86   extensions::ImageLoader* loader =
     87       extensions::ImageLoader::Get(profile_);
     88   loader->LoadImageAsync(extension_, image,
     89                          gfx::Size(pixel_size, pixel_size),
     90                          base::Bind(&ExtensionUninstallDialog::OnImageLoaded,
     91                                     AsWeakPtr()));
     92 }
     93 
     94 void ExtensionUninstallDialog::SetIcon(const gfx::Image& image) {
     95   if (image.IsEmpty()) {
     96     // Let's set default icon bitmap whose size is equal to the default icon's
     97     // pixel size under maximal supported scale factor. If the bitmap is larger
     98     // than the one we need, it will be scaled down by the ui code.
     99     // TODO(tbarzic): We should use IconImage here and load the required bitmap
    100     //     lazily.
    101     icon_ = gfx::ImageSkia::CreateFrom1xBitmap(
    102         GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app()));
    103   } else {
    104     icon_ = *image.ToImageSkia();
    105   }
    106 }
    107 
    108 void ExtensionUninstallDialog::OnImageLoaded(const gfx::Image& image) {
    109   SetIcon(image);
    110 
    111   // Show the dialog unless the browser has been closed while we were waiting
    112   // for the image.
    113   DCHECK(state_ == kImageIsLoading || state_ == kBrowserIsClosing);
    114   if (state_ == kImageIsLoading) {
    115     state_ = kDialogIsShowing;
    116     Show();
    117   }
    118 }
    119 
    120 void ExtensionUninstallDialog::Observe(
    121     int type,
    122     const content::NotificationSource& source,
    123     const content::NotificationDetails& details) {
    124   DCHECK(type == chrome::NOTIFICATION_BROWSER_CLOSED);
    125 
    126   browser_ = NULL;
    127   // If the browser is closed while waiting for the image, we need to send a
    128   // "cancel" event here, because there will not be another opportunity to
    129   // notify the delegate of the cancellation as we won't open the dialog.
    130   if (state_ == kImageIsLoading) {
    131     state_ = kBrowserIsClosing;
    132     delegate_->ExtensionUninstallCanceled();
    133   }
    134 }
    135