diff options
17 files changed, 158 insertions, 5 deletions
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc index f76efd3..e218bbe 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc @@ -468,9 +468,11 @@ void CompleteInstallFunction::OnGetAppLauncherEnabled( bool app_launcher_enabled) { if (app_launcher_enabled) { std::string name; - DCHECK(approval_->parsed_manifest->GetString(extension_manifest_keys::kName, - &name)); #if defined(ENABLE_APP_LIST) + if (!approval_->parsed_manifest->GetString(extension_manifest_keys::kName, + &name)) { + NOTREACHED(); + } // Tell the app list about the install that we just started. chrome::NotifyAppListOfBeginExtensionInstall( profile(), id, name, approval_->installing_icon); @@ -513,6 +515,14 @@ void CompleteInstallFunction::OnExtensionInstallFailure( Release(); } +void CompleteInstallFunction::OnExtensionDownloadProgress( + const std::string& id, + content::DownloadItem* item) { +#if defined(ENABLE_APP_LIST) + chrome::NotifyAppListOfDownloadProgress(profile(), id, + item->PercentComplete()); +#endif +} bool GetBrowserLoginFunction::RunImpl() { SetResult(CreateLoginResult(profile_->GetOriginalProfile())); diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h index 2d5ed9c..3fbedc9 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h @@ -164,6 +164,9 @@ class CompleteInstallFunction const std::string& id, const std::string& error, WebstoreInstaller::FailureReason reason) OVERRIDE; + virtual void OnExtensionDownloadProgress( + const std::string& id, + content::DownloadItem* item) OVERRIDE; protected: virtual ~CompleteInstallFunction(); diff --git a/chrome/browser/ui/app_list/app_list_util.h b/chrome/browser/ui/app_list/app_list_util.h index 5cbada4..bdd17a6 100644 --- a/chrome/browser/ui/app_list/app_list_util.h +++ b/chrome/browser/ui/app_list/app_list_util.h @@ -50,6 +50,11 @@ void NotifyAppListOfBeginExtensionInstall( const std::string& extension_name, const gfx::ImageSkia& installing_icon); +void NotifyAppListOfDownloadProgress( + Profile* profile, + const std::string& extension_id, + int percent_downloaded); + } // namespace chrome #endif // CHROME_BROWSER_UI_APP_LIST_APP_LIST_UTIL_H_ diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index c0a7955..15d294e 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc @@ -63,6 +63,12 @@ void AppListViewDelegate::OnBeginExtensionInstall( installing_icon); } +void AppListViewDelegate::OnDownloadProgress( + const std::string& extension_id, + int percent_downloaded) { + apps_builder_->OnDownloadProgress(extension_id, percent_downloaded); +} + void AppListViewDelegate::ActivateAppListItem( app_list::AppListItemModel* item, int event_flags) { diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h index 457a7d9..4bd04b4 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.h +++ b/chrome/browser/ui/app_list/app_list_view_delegate.h @@ -36,6 +36,10 @@ class AppListViewDelegate : public app_list::AppListViewDelegate { const std::string& extension_name, const gfx::ImageSkia& installing_icon); + // Called when the download of an extension makes progress. + void OnDownloadProgress(const std::string& extension_id, + int percent_downloaded); + private: // Overridden from app_list::AppListViewDelegate: virtual void SetModel(app_list::AppListModel* model) OVERRIDE; diff --git a/chrome/browser/ui/app_list/apps_model_builder.cc b/chrome/browser/ui/app_list/apps_model_builder.cc index 399d4c5..8af3d3e 100644 --- a/chrome/browser/ui/app_list/apps_model_builder.cc +++ b/chrome/browser/ui/app_list/apps_model_builder.cc @@ -88,6 +88,14 @@ void AppsModelBuilder::OnBeginExtensionInstall( HighlightApp(); } +void AppsModelBuilder::OnDownloadProgress(const std::string& extension_id, + int percent_downloaded) { + int i = FindApp(extension_id); + if (i == -1) + return; + GetAppAt(i)->SetPercentDownloaded(percent_downloaded); +} + void AppsModelBuilder::AddApps(const ExtensionSet* extensions, Apps* apps) { for (ExtensionSet::const_iterator app = extensions->begin(); app != extensions->end(); ++app) { diff --git a/chrome/browser/ui/app_list/apps_model_builder.h b/chrome/browser/ui/app_list/apps_model_builder.h index f369d30..305bd941 100644 --- a/chrome/browser/ui/app_list/apps_model_builder.h +++ b/chrome/browser/ui/app_list/apps_model_builder.h @@ -40,6 +40,10 @@ class AppsModelBuilder : public content::NotificationObserver, const std::string& extension_name, const gfx::ImageSkia& installing_icon); + // Called when progress is made on an extension's download. + void OnDownloadProgress(const std::string& extension_id, + int percent_downloaded); + private: typedef std::vector<ExtensionAppItem*> Apps; diff --git a/chrome/browser/ui/app_list/extension_app_item.cc b/chrome/browser/ui/app_list/extension_app_item.cc index 56281dc..feae3f6 100644 --- a/chrome/browser/ui/app_list/extension_app_item.cc +++ b/chrome/browser/ui/app_list/extension_app_item.cc @@ -208,8 +208,9 @@ bool ExtensionAppItem::HasOverlay() const { void ExtensionAppItem::Reload() { const Extension* extension = GetExtension(); - // If the extension isn't there, show the 'extension is installing' UI. - if (!extension) { + bool is_installing = !extension; + SetIsInstalling(is_installing); + if (is_installing) { SetTitle(extension_name_); UpdateIcon(); return; diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc index ce6f119..55fb595 100644 --- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc +++ b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc @@ -91,4 +91,10 @@ void NotifyAppListOfBeginExtensionInstall( const gfx::ImageSkia& installing_icon) { } +void NotifyAppListOfDownloadProgress( + Profile* profile, + const std::string& extension_id, + int percent_downloaded) { +} + } // namespace chrome diff --git a/chrome/browser/ui/cocoa/app_list/app_list_controller_cocoa.mm b/chrome/browser/ui/cocoa/app_list/app_list_controller_cocoa.mm index 61dd01e..3580de6 100644 --- a/chrome/browser/ui/cocoa/app_list/app_list_controller_cocoa.mm +++ b/chrome/browser/ui/cocoa/app_list/app_list_controller_cocoa.mm @@ -87,4 +87,10 @@ void NotifyAppListOfBeginExtensionInstall( const gfx::ImageSkia& installing_icon) { } +void NotifyAppListOfDownloadProgress( + Profile* profile, + const std::string& extension_id, + int percent_downloaded) { +} + } // namespace chrome diff --git a/chrome/browser/ui/views/app_list/app_list_controller_win.cc b/chrome/browser/ui/views/app_list/app_list_controller_win.cc index 70df366..5fe7960 100644 --- a/chrome/browser/ui/views/app_list/app_list_controller_win.cc +++ b/chrome/browser/ui/views/app_list/app_list_controller_win.cc @@ -191,6 +191,9 @@ class AppListController : public ProfileInfoCacheObserver { const std::string& extension_id, const std::string& extension_name, const gfx::ImageSkia& installing_icon); + void OnDownloadProgress(Profile* profile, + const std::string& extension_id, + int percent_downloaded); private: // Loads a profile asynchronously and calls OnProfileLoaded() when done. @@ -547,6 +550,18 @@ void AppListController::OnBeginExtensionInstall( installing_icon); } +void AppListController::OnDownloadProgress(Profile* profile, + const std::string& extension_id, + int percent_downloaded) { + // We only have a model for the current profile, so ignore events about + // others. + // TODO(koz): We should keep a model for each profile so we can record + // information like this. + if (profile != profile_) + return; + view_delegate_->OnDownloadProgress(extension_id, percent_downloaded); +} + // Attempts to find the bounds of the Windows taskbar. Returns true on success. // |rect| is in screen coordinates. If the taskbar is in autohide mode and is // not visible, |rect| will be outside the current monitor's bounds, except for @@ -860,6 +875,15 @@ void NotifyAppListOfBeginExtensionInstall( extension_name, installing_icon); } + +void NotifyAppListOfDownloadProgress( + Profile* profile, + const std::string& extension_id, + int percent_downloaded) { + g_app_list_controller.Get().OnDownloadProgress(profile, extension_id, + percent_downloaded); +} + #endif // !defined(USE_ASH) } // namespace chrome diff --git a/ui/app_list/app_list_item_model.cc b/ui/app_list/app_list_item_model.cc index c3a74bf..c9a2831 100644 --- a/ui/app_list/app_list_item_model.cc +++ b/ui/app_list/app_list_item_model.cc @@ -9,7 +9,10 @@ namespace app_list { -AppListItemModel::AppListItemModel() : highlighted_(false) { +AppListItemModel::AppListItemModel() + : highlighted_(false), + is_installing_(false), + percent_downloaded_(-1) { } AppListItemModel::~AppListItemModel() { @@ -38,6 +41,26 @@ void AppListItemModel::SetHighlighted(bool highlighted) { ItemHighlightedChanged()); } +void AppListItemModel::SetIsInstalling(bool is_installing) { + if (is_installing_ == is_installing) + return; + + is_installing_ = is_installing; + FOR_EACH_OBSERVER(AppListItemModelObserver, + observers_, + ItemIsInstallingChanged()); +} + +void AppListItemModel::SetPercentDownloaded(int percent_downloaded) { + if (percent_downloaded_ == percent_downloaded) + return; + + percent_downloaded_ = percent_downloaded; + FOR_EACH_OBSERVER(AppListItemModelObserver, + observers_, + ItemPercentDownloadedChanged()); +} + void AppListItemModel::AddObserver(AppListItemModelObserver* observer) { observers_.AddObserver(observer); } diff --git a/ui/app_list/app_list_item_model.h b/ui/app_list/app_list_item_model.h index ca382de..2960931 100644 --- a/ui/app_list/app_list_item_model.h +++ b/ui/app_list/app_list_item_model.h @@ -36,6 +36,12 @@ class APP_LIST_EXPORT AppListItemModel { void SetHighlighted(bool highlighted); bool highlighted() const { return highlighted_; } + void SetIsInstalling(bool is_installing); + bool is_installing() const { return is_installing_; } + + void SetPercentDownloaded(int percent_downloaded); + int percent_downloaded() const { return percent_downloaded_; } + void AddObserver(AppListItemModelObserver* observer); void RemoveObserver(AppListItemModelObserver* observer); @@ -47,6 +53,8 @@ class APP_LIST_EXPORT AppListItemModel { gfx::ImageSkia icon_; std::string title_; bool highlighted_; + bool is_installing_; + int percent_downloaded_; ObserverList<AppListItemModelObserver> observers_; diff --git a/ui/app_list/app_list_item_model_observer.h b/ui/app_list/app_list_item_model_observer.h index 0e5f99d..80abb39 100644 --- a/ui/app_list/app_list_item_model_observer.h +++ b/ui/app_list/app_list_item_model_observer.h @@ -20,6 +20,12 @@ class APP_LIST_EXPORT AppListItemModelObserver { // Invoked after item's highlighted state is changed. virtual void ItemHighlightedChanged() = 0; + // Invoked after item begins or finishes installing. + virtual void ItemIsInstallingChanged() = 0; + + // Invoked after item's download percentage changes. + virtual void ItemPercentDownloadedChanged() = 0; + protected: virtual ~AppListItemModelObserver() {} }; diff --git a/ui/app_list/views/app_list_item_view.cc b/ui/app_list/views/app_list_item_view.cc index e481cb4..4793a99 100644 --- a/ui/app_list/views/app_list_item_view.cc +++ b/ui/app_list/views/app_list_item_view.cc @@ -31,6 +31,9 @@ namespace { const int kTopBottomPadding = 10; const int kTopPadding = 20; const int kIconTitleSpacing = 7; +const int kProgressBarHorizontalPadding = 8; +const int kProgressBarVerticalPadding = 4; +const int kProgressBarHeight = 4; const SkColor kTitleColor = SkColorSetRGB(0x5A, 0x5A, 0x5A); const SkColor kTitleHoverColor = SkColorSetRGB(0x3C, 0x3C, 0x3C); @@ -38,6 +41,9 @@ const SkColor kTitleHoverColor = SkColorSetRGB(0x3C, 0x3C, 0x3C); const SkColor kHoverAndPushedColor = SkColorSetARGB(0x19, 0, 0, 0); const SkColor kSelectedColor = SkColorSetARGB(0x0D, 0, 0, 0); const SkColor kHighlightedColor = kHoverAndPushedColor; +const SkColor kDownloadProgressBackgroundColor = + SkColorSetRGB(0x90, 0x90, 0x90); +const SkColor kDownloadProgressColor = SkColorSetRGB(0x20, 0xAA, 0x20); const int kLeftRightPaddingChars = 1; @@ -168,6 +174,16 @@ void AppListItemView::ItemHighlightedChanged() { SchedulePaint(); } +void AppListItemView::ItemIsInstallingChanged() { + if (model_->is_installing()) + apps_grid_view_->EnsureViewVisible(this); + SchedulePaint(); +} + +void AppListItemView::ItemPercentDownloadedChanged() { + SchedulePaint(); +} + std::string AppListItemView::GetClassName() const { return kViewClassName; } @@ -210,6 +226,25 @@ void AppListItemView::OnPaint(gfx::Canvas* canvas) { } else if (apps_grid_view_->IsSelectedView(this)) { canvas->FillRect(rect, kSelectedColor); } + + if (model_->is_installing()) { + gfx::Rect progress_bar_background( + rect.x() + kProgressBarHorizontalPadding, + rect.bottom() - kProgressBarVerticalPadding - kProgressBarHeight, + rect.width() - 2 * kProgressBarHorizontalPadding, + kProgressBarHeight); + canvas->FillRect(progress_bar_background, kDownloadProgressBackgroundColor); + + if (model_->percent_downloaded() != -1) { + float percent = model_->percent_downloaded() / 100.0; + gfx::Rect progress_bar( + progress_bar_background.x(), + progress_bar_background.y(), + progress_bar_background.width() * percent, + progress_bar_background.height()); + canvas->FillRect(progress_bar, kDownloadProgressColor); + } + } } void AppListItemView::GetAccessibleState(ui::AccessibleViewState* state) { diff --git a/ui/app_list/views/app_list_item_view.h b/ui/app_list/views/app_list_item_view.h index 7cabc5f..a037de2 100644 --- a/ui/app_list/views/app_list_item_view.h +++ b/ui/app_list/views/app_list_item_view.h @@ -64,6 +64,8 @@ class APP_LIST_EXPORT AppListItemView : public views::CustomButton, virtual void ItemIconChanged() OVERRIDE; virtual void ItemTitleChanged() OVERRIDE; virtual void ItemHighlightedChanged() OVERRIDE; + virtual void ItemIsInstallingChanged() OVERRIDE; + virtual void ItemPercentDownloadedChanged() OVERRIDE; // views::View overrides: virtual std::string GetClassName() const OVERRIDE; diff --git a/ui/app_list/views/app_list_main_view.cc b/ui/app_list/views/app_list_main_view.cc index f73f428..bfadf21 100644 --- a/ui/app_list/views/app_list_main_view.cc +++ b/ui/app_list/views/app_list_main_view.cc @@ -60,6 +60,8 @@ class AppListMainView::IconLoader : public AppListItemModelObserver { } virtual void ItemTitleChanged() OVERRIDE {} virtual void ItemHighlightedChanged() OVERRIDE {} + virtual void ItemIsInstallingChanged() OVERRIDE {}; + virtual void ItemPercentDownloadedChanged() OVERRIDE {}; AppListMainView* owner_; AppListItemModel* item_; |