Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / app_list / extension_app_model_builder.cc
blob818c03c28cdce91a967af4a9145e815acdd74b87
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"
7 #include <algorithm>
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/app_list_syncable_service.h"
18 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
19 #include "chrome/browser/ui/app_list/extension_app_item.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/pref_names.h"
22 #include "content/public/browser/notification_service.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/extension_set.h"
25 #include "ui/gfx/image/image_skia.h"
27 using extensions::Extension;
29 namespace {
31 bool ShouldDisplayInAppLauncher(Profile* profile,
32 scoped_refptr<const Extension> app) {
33 // If it's the web store, check the policy.
34 bool blocked_by_policy =
35 (app->id() == extension_misc::kWebStoreAppId ||
36 app->id() == extension_misc::kEnterpriseWebStoreAppId) &&
37 profile->GetPrefs()->GetBoolean(prefs::kHideWebStoreIcon);
38 return app->ShouldDisplayInAppLauncher() && !blocked_by_policy;
41 } // namespace
43 ExtensionAppModelBuilder::ExtensionAppModelBuilder(
44 AppListControllerDelegate* controller)
45 : service_(NULL),
46 profile_(NULL),
47 controller_(controller),
48 model_(NULL),
49 highlighted_app_pending_(false),
50 tracker_(NULL) {
53 ExtensionAppModelBuilder::~ExtensionAppModelBuilder() {
54 OnShutdown();
55 model_->item_list()->RemoveObserver(this);
58 void ExtensionAppModelBuilder::InitializeWithService(
59 app_list::AppListSyncableService* service) {
60 model_ = service->model();
61 model_->item_list()->AddObserver(this);
62 service_ = service;
63 profile_ = service->profile();
64 BuildModel();
67 void ExtensionAppModelBuilder::InitializeWithProfile(
68 Profile* profile,
69 app_list::AppListModel* model) {
70 model_ = model;
71 model_->item_list()->AddObserver(this);
72 profile_ = profile;
73 BuildModel();
76 void ExtensionAppModelBuilder::OnBeginExtensionInstall(
77 const ExtensionInstallParams& params) {
78 if (!params.is_app || params.is_ephemeral)
79 return;
81 DVLOG(2) << service_ << ": OnBeginExtensionInstall: "
82 << params.extension_id.substr(0, 8);
83 ExtensionAppItem* existing_item = GetExtensionAppItem(params.extension_id);
84 if (existing_item) {
85 existing_item->SetIsInstalling(true);
86 return;
88 InsertApp(CreateAppItem(params.extension_id,
89 params.extension_name,
90 params.installing_icon,
91 params.is_platform_app));
92 SetHighlightedApp(params.extension_id);
95 void ExtensionAppModelBuilder::OnDownloadProgress(
96 const std::string& extension_id,
97 int percent_downloaded) {
98 ExtensionAppItem* item = GetExtensionAppItem(extension_id);
99 if (!item)
100 return;
101 item->SetPercentDownloaded(percent_downloaded);
104 void ExtensionAppModelBuilder::OnInstallFailure(
105 const std::string& extension_id) {
106 model_->item_list()->DeleteItem(extension_id);
109 void ExtensionAppModelBuilder::OnExtensionLoaded(const Extension* extension) {
110 if (!extension->ShouldDisplayInAppLauncher())
111 return;
113 DVLOG(2) << service_ << ": OnExtensionLoaded: "
114 << extension->id().substr(0, 8);
115 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id());
116 if (existing_item) {
117 existing_item->Reload();
118 return;
121 InsertApp(CreateAppItem(extension->id(),
123 gfx::ImageSkia(),
124 extension->is_platform_app()));
125 UpdateHighlight();
128 void ExtensionAppModelBuilder::OnExtensionUnloaded(const Extension* extension) {
129 ExtensionAppItem* item = GetExtensionAppItem(extension->id());
130 if (!item)
131 return;
132 item->UpdateIcon();
135 void ExtensionAppModelBuilder::OnExtensionUninstalled(
136 const Extension* extension) {
137 if (service_) {
138 DVLOG(2) << service_ << ": OnExtensionUninstalled: "
139 << extension->id().substr(0, 8);
140 service_->RemoveItem(extension->id());
141 return;
143 model_->item_list()->DeleteItem(extension->id());
146 void ExtensionAppModelBuilder::OnAppsReordered() {
147 // Do nothing; App List order does not track extensions order.
150 void ExtensionAppModelBuilder::OnAppInstalledToAppList(
151 const std::string& extension_id) {
152 SetHighlightedApp(extension_id);
155 void ExtensionAppModelBuilder::OnShutdown() {
156 if (tracker_) {
157 tracker_->RemoveObserver(this);
158 tracker_ = NULL;
162 ExtensionAppItem* ExtensionAppModelBuilder::CreateAppItem(
163 const std::string& extension_id,
164 const std::string& extension_name,
165 const gfx::ImageSkia& installing_icon,
166 bool is_platform_app) {
167 const app_list::AppListSyncableService::SyncItem* sync_item =
168 service_ ? service_->GetSyncItem(extension_id) : NULL;
169 return new ExtensionAppItem(profile_,
170 sync_item,
171 extension_id,
172 extension_name,
173 installing_icon,
174 is_platform_app);
177 void ExtensionAppModelBuilder::AddApps(
178 const extensions::ExtensionSet* extensions,
179 ExtensionAppList* apps) {
180 for (extensions::ExtensionSet::const_iterator app = extensions->begin();
181 app != extensions->end(); ++app) {
182 if (ShouldDisplayInAppLauncher(profile_, *app)) {
183 apps->push_back(CreateAppItem((*app)->id(),
185 gfx::ImageSkia(),
186 (*app)->is_platform_app()));
191 void ExtensionAppModelBuilder::BuildModel() {
192 // Delete any extension apps.
193 model_->item_list()->DeleteItemsByType(ExtensionAppItem::kAppType);
195 if (tracker_)
196 tracker_->RemoveObserver(this);
198 tracker_ = controller_->GetInstallTrackerFor(profile_);
200 PopulateApps();
201 UpdateHighlight();
203 // Start observing after model is built.
204 if (tracker_)
205 tracker_->AddObserver(this);
208 void ExtensionAppModelBuilder::PopulateApps() {
209 extensions::ExtensionSet extensions;
210 controller_->GetApps(profile_, &extensions);
211 ExtensionAppList apps;
212 AddApps(&extensions, &apps);
214 if (apps.empty())
215 return;
217 for (size_t i = 0; i < apps.size(); ++i)
218 InsertApp(apps[i]);
221 void ExtensionAppModelBuilder::InsertApp(ExtensionAppItem* app) {
222 if (service_) {
223 service_->AddItem(app);
224 return;
226 model_->item_list()->AddItem(app);
229 void ExtensionAppModelBuilder::SetHighlightedApp(
230 const std::string& extension_id) {
231 if (extension_id == highlight_app_id_)
232 return;
233 ExtensionAppItem* old_app = GetExtensionAppItem(highlight_app_id_);
234 if (old_app)
235 old_app->SetHighlighted(false);
236 highlight_app_id_ = extension_id;
237 ExtensionAppItem* new_app = GetExtensionAppItem(highlight_app_id_);
238 highlighted_app_pending_ = !new_app;
239 if (new_app)
240 new_app->SetHighlighted(true);
243 ExtensionAppItem* ExtensionAppModelBuilder::GetExtensionAppItem(
244 const std::string& extension_id) {
245 app_list::AppListItem* item =
246 model_->item_list()->FindItem(extension_id);
247 LOG_IF(ERROR, item &&
248 item->GetAppType() != ExtensionAppItem::kAppType)
249 << "App Item matching id: " << extension_id
250 << " has incorrect type: '" << item->GetAppType() << "'";
251 return static_cast<ExtensionAppItem*>(item);
254 void ExtensionAppModelBuilder::UpdateHighlight() {
255 DCHECK(model_);
256 if (!highlighted_app_pending_ || highlight_app_id_.empty())
257 return;
258 ExtensionAppItem* item = GetExtensionAppItem(highlight_app_id_);
259 if (!item)
260 return;
261 item->SetHighlighted(true);
262 highlighted_app_pending_ = false;
265 void ExtensionAppModelBuilder::OnListItemMoved(size_t from_index,
266 size_t to_index,
267 app_list::AppListItem* item) {
268 // This will get called from AppListItemList::ListItemMoved after
269 // set_position is called for the item.
270 app_list::AppListItemList* item_list = model_->item_list();
271 if (item->GetAppType() != ExtensionAppItem::kAppType)
272 return;
274 if (service_) {
275 service_->UpdateItem(item);
276 return;
279 ExtensionAppItem* prev = NULL;
280 for (size_t idx = to_index; idx > 0; --idx) {
281 app_list::AppListItem* item = item_list->item_at(idx - 1);
282 if (item->GetAppType() == ExtensionAppItem::kAppType) {
283 prev = static_cast<ExtensionAppItem*>(item);
284 break;
287 ExtensionAppItem* next = NULL;
288 for (size_t idx = to_index; idx < item_list->item_count() - 1; ++idx) {
289 app_list::AppListItem* item = item_list->item_at(idx + 1);
290 if (item->GetAppType() == ExtensionAppItem::kAppType) {
291 next = static_cast<ExtensionAppItem*>(item);
292 break;
295 // item->Move will call set_position, overriding the item's position.
296 if (prev || next)
297 static_cast<ExtensionAppItem*>(item)->Move(prev, next);