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.
5 #include "chrome/browser/ui/app_list/extension_app_model_builder.h"
9 #include "base/auto_reset.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/extension_prefs.h"
13 #include "chrome/browser/extensions/install_tracker.h"
14 #include "chrome/browser/extensions/install_tracker_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
17 #include "chrome/browser/ui/app_list/extension_app_item.h"
18 #include "chrome/common/extensions/extension.h"
19 #include "chrome/common/extensions/extension_constants.h"
20 #include "chrome/common/extensions/extension_set.h"
21 #include "chrome/common/pref_names.h"
22 #include "content/public/browser/notification_service.h"
23 #include "ui/gfx/image/image_skia.h"
25 using extensions::Extension;
29 bool ShouldDisplayInAppLauncher(Profile* profile,
30 scoped_refptr<const Extension> app) {
31 // If it's the web store, check the policy.
32 bool blocked_by_policy =
33 (app->id() == extension_misc::kWebStoreAppId ||
34 app->id() == extension_misc::kEnterpriseWebStoreAppId) &&
35 profile->GetPrefs()->GetBoolean(prefs::kHideWebStoreIcon);
36 return app->ShouldDisplayInAppLauncher() && !blocked_by_policy;
41 ExtensionAppModelBuilder::ExtensionAppModelBuilder(
43 app_list::AppListModel* model,
44 AppListControllerDelegate* controller)
46 controller_(controller),
48 highlighted_app_pending_(false),
50 model_->item_list()->AddObserver(this);
51 SwitchProfile(profile); // Builds the model.
54 ExtensionAppModelBuilder::~ExtensionAppModelBuilder() {
56 model_->item_list()->RemoveObserver(this);
59 void ExtensionAppModelBuilder::OnBeginExtensionInstall(
60 const std::string& extension_id,
61 const std::string& extension_name,
62 const gfx::ImageSkia& installing_icon,
64 bool is_platform_app) {
68 ExtensionAppItem* existing_item = GetExtensionAppItem(extension_id);
70 existing_item->SetIsInstalling(true);
74 InsertApp(new ExtensionAppItem(profile_,
80 SetHighlightedApp(extension_id);
83 void ExtensionAppModelBuilder::OnDownloadProgress(
84 const std::string& extension_id,
85 int percent_downloaded) {
86 ExtensionAppItem* item = GetExtensionAppItem(extension_id);
89 item->SetPercentDownloaded(percent_downloaded);
92 void ExtensionAppModelBuilder::OnInstallFailure(
93 const std::string& extension_id) {
94 // Do nothing, item will be disabled
97 void ExtensionAppModelBuilder::OnExtensionLoaded(const Extension* extension) {
98 if (!extension->ShouldDisplayInAppLauncher())
101 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id());
103 existing_item->Reload();
107 InsertApp(new ExtensionAppItem(profile_,
112 extension->is_platform_app()));
116 void ExtensionAppModelBuilder::OnExtensionUnloaded(const Extension* extension) {
117 ExtensionAppItem* item = GetExtensionAppItem(extension->id());
123 void ExtensionAppModelBuilder::OnExtensionUninstalled(
124 const Extension* extension) {
125 model_->item_list()->DeleteItem(extension->id());
128 void ExtensionAppModelBuilder::OnAppsReordered() {
129 // Do nothing; App List order does not track extensions order.
132 void ExtensionAppModelBuilder::OnAppInstalledToAppList(
133 const std::string& extension_id) {
134 SetHighlightedApp(extension_id);
137 void ExtensionAppModelBuilder::OnShutdown() {
139 tracker_->RemoveObserver(this);
144 void ExtensionAppModelBuilder::AddApps(const ExtensionSet* extensions,
145 ExtensionAppList* apps) {
146 for (ExtensionSet::const_iterator app = extensions->begin();
147 app != extensions->end(); ++app) {
148 if (ShouldDisplayInAppLauncher(profile_, *app))
149 apps->push_back(new ExtensionAppItem(profile_,
154 (*app)->is_platform_app()));
158 void ExtensionAppModelBuilder::SwitchProfile(Profile* profile) {
159 if (profile_ == profile)
163 // Delete any extension apps.
164 model_->item_list()->DeleteItemsByType(ExtensionAppItem::kAppType);
167 tracker_->RemoveObserver(this);
169 tracker_ = controller_->GetInstallTrackerFor(profile_);
174 // Start observing after model is built.
176 tracker_->AddObserver(this);
179 void ExtensionAppModelBuilder::PopulateApps() {
180 ExtensionSet extensions;
181 controller_->GetApps(profile_, &extensions);
182 ExtensionAppList apps;
183 AddApps(&extensions, &apps);
188 for (size_t i = 0; i < apps.size(); ++i)
192 void ExtensionAppModelBuilder::InsertApp(ExtensionAppItem* app) {
193 model_->item_list()->AddItem(app);
196 void ExtensionAppModelBuilder::SetHighlightedApp(
197 const std::string& extension_id) {
198 if (extension_id == highlight_app_id_)
200 ExtensionAppItem* old_app = GetExtensionAppItem(highlight_app_id_);
202 old_app->SetHighlighted(false);
203 highlight_app_id_ = extension_id;
204 ExtensionAppItem* new_app = GetExtensionAppItem(highlight_app_id_);
205 highlighted_app_pending_ = !new_app;
207 new_app->SetHighlighted(true);
210 ExtensionAppItem* ExtensionAppModelBuilder::GetExtensionAppItem(
211 const std::string& extension_id) {
212 app_list::AppListItemModel* item =
213 model_->item_list()->FindItem(extension_id);
214 LOG_IF(ERROR, item &&
215 item->GetAppType() != ExtensionAppItem::kAppType)
216 << "App Item matching id: " << extension_id
217 << " has incorrect type: '" << item->GetAppType() << "'";
218 return static_cast<ExtensionAppItem*>(item);
221 void ExtensionAppModelBuilder::UpdateHighlight() {
223 if (!highlighted_app_pending_ || highlight_app_id_.empty())
225 ExtensionAppItem* item = GetExtensionAppItem(highlight_app_id_);
228 item->SetHighlighted(true);
229 highlighted_app_pending_ = false;
232 void ExtensionAppModelBuilder::OnListItemMoved(
235 app_list::AppListItemModel* item) {
236 // This will get called from AppListItemList::ListItemMoved after
237 // set_position is called for the item.
238 app_list::AppListItemList* item_list = model_->item_list();
239 if (item->GetAppType() != ExtensionAppItem::kAppType)
242 ExtensionAppItem* prev = NULL;
243 for (size_t idx = to_index; idx > 0; --idx) {
244 app_list::AppListItemModel* item = item_list->item_at(idx - 1);
245 if (item->GetAppType() == ExtensionAppItem::kAppType) {
246 prev = static_cast<ExtensionAppItem*>(item);
250 ExtensionAppItem* next = NULL;
251 for (size_t idx = to_index; idx < item_list->item_count() - 1; ++idx) {
252 app_list::AppListItemModel* item = item_list->item_at(idx + 1);
253 if (item->GetAppType() == ExtensionAppItem::kAppType) {
254 next = static_cast<ExtensionAppItem*>(item);
258 // item->Move will call set_position, overriding the item's position.
260 static_cast<ExtensionAppItem*>(item)->Move(prev, next);