extension_app_model_builder.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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/ui/app_list/extension_app_model_builder.h" 6 7#include <algorithm> 8 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/extension_service.h" 14#include "chrome/browser/extensions/extension_sorting.h" 15#include "chrome/browser/extensions/extension_system.h" 16#include "chrome/browser/extensions/install_tracker.h" 17#include "chrome/browser/extensions/install_tracker_factory.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/ui/app_list/extension_app_item.h" 20#include "chrome/common/extensions/extension.h" 21#include "chrome/common/extensions/extension_constants.h" 22#include "chrome/common/pref_names.h" 23#include "content/public/browser/notification_service.h" 24#include "ui/gfx/image/image_skia.h" 25 26using extensions::Extension; 27 28namespace { 29 30bool ShouldDisplayInAppLauncher(Profile* profile, 31 scoped_refptr<const Extension> app) { 32 // If it's the web store, check the policy. 33 bool blocked_by_policy = 34 (app->id() == extension_misc::kWebStoreAppId || 35 app->id() == extension_misc::kEnterpriseWebStoreAppId) && 36 profile->GetPrefs()->GetBoolean(prefs::kHideWebStoreIcon); 37 return app->ShouldDisplayInAppLauncher() && !blocked_by_policy; 38} 39 40} // namespace 41 42ExtensionAppModelBuilder::ExtensionAppModelBuilder( 43 Profile* profile, 44 app_list::AppListModel* model, 45 AppListControllerDelegate* controller) 46 : profile_(NULL), 47 controller_(controller), 48 model_(model), 49 highlighted_app_pending_(false), 50 tracker_(NULL) { 51 model_->apps()->AddObserver(this); 52 SwitchProfile(profile); // Builds the model. 53} 54 55ExtensionAppModelBuilder::~ExtensionAppModelBuilder() { 56 OnShutdown(); 57 model_->apps()->RemoveObserver(this); 58} 59 60void ExtensionAppModelBuilder::OnBeginExtensionInstall( 61 const std::string& extension_id, 62 const std::string& extension_name, 63 const gfx::ImageSkia& installing_icon, 64 bool is_app, 65 bool is_platform_app) { 66 if (!is_app) 67 return; 68 69 ExtensionAppItem* existing_item = GetExtensionAppItem(extension_id); 70 if (existing_item) { 71 existing_item->SetIsInstalling(true); 72 return; 73 } 74 75 InsertApp(new ExtensionAppItem(profile_, 76 extension_id, 77 controller_, 78 extension_name, 79 installing_icon, 80 is_platform_app)); 81 SetHighlightedApp(extension_id); 82} 83 84void ExtensionAppModelBuilder::OnDownloadProgress( 85 const std::string& extension_id, 86 int percent_downloaded) { 87 ExtensionAppItem* item = GetExtensionAppItem(extension_id); 88 if (!item) 89 return; 90 item->SetPercentDownloaded(percent_downloaded); 91} 92 93void ExtensionAppModelBuilder::OnInstallFailure( 94 const std::string& extension_id) { 95 // Do nothing, item will be disabled 96} 97 98void ExtensionAppModelBuilder::OnExtensionLoaded(const Extension* extension) { 99 if (!extension->ShouldDisplayInAppLauncher()) 100 return; 101 102 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id()); 103 if (existing_item) { 104 existing_item->Reload(); 105 return; 106 } 107 108 InsertApp(new ExtensionAppItem(profile_, 109 extension->id(), 110 controller_, 111 "", 112 gfx::ImageSkia(), 113 extension->is_platform_app())); 114 UpdateHighlight(); 115} 116 117void ExtensionAppModelBuilder::OnExtensionUnloaded(const Extension* extension) { 118 ExtensionAppItem* item = GetExtensionAppItem(extension->id()); 119 if (!item) 120 return; 121 item->UpdateIcon(); 122} 123 124void ExtensionAppModelBuilder::OnExtensionUninstalled( 125 const Extension* extension) { 126 model_->DeleteItem(extension->id()); 127} 128 129void ExtensionAppModelBuilder::OnAppsReordered() { 130 // Do nothing; App List order does not track extensions order. 131} 132 133void ExtensionAppModelBuilder::OnAppInstalledToAppList( 134 const std::string& extension_id) { 135 SetHighlightedApp(extension_id); 136} 137 138void ExtensionAppModelBuilder::OnShutdown() { 139 if (tracker_) { 140 tracker_->RemoveObserver(this); 141 tracker_ = NULL; 142 } 143} 144 145void ExtensionAppModelBuilder::AddApps(const ExtensionSet* extensions, 146 ExtensionAppList* apps) { 147 for (ExtensionSet::const_iterator app = extensions->begin(); 148 app != extensions->end(); ++app) { 149 if (ShouldDisplayInAppLauncher(profile_, *app)) 150 apps->push_back(new ExtensionAppItem(profile_, 151 (*app)->id(), 152 controller_, 153 "", 154 gfx::ImageSkia(), 155 (*app)->is_platform_app())); 156 } 157} 158 159void ExtensionAppModelBuilder::SwitchProfile(Profile* profile) { 160 if (profile_ == profile) 161 return; 162 profile_ = profile; 163 164 // Delete any extension apps. 165 app_list::AppListModel::Apps* app_list = model_->apps(); 166 for (int i = static_cast<int>(app_list->item_count()) - 1; i >= 0; --i) { 167 app_list::AppListItemModel* item = app_list->GetItemAt(i); 168 if (item->GetAppType() == ExtensionAppItem::kAppType) 169 app_list->DeleteAt(i); 170 } 171 172 if (tracker_) 173 tracker_->RemoveObserver(this); 174 175 if (extensions::ExtensionSystem::Get(profile_)->extension_service()) 176 tracker_ = extensions::InstallTrackerFactory::GetForProfile(profile_); 177 else 178 tracker_ = NULL; 179 180 PopulateApps(); 181 UpdateHighlight(); 182 183 // Start observing after model is built. 184 if (tracker_) 185 tracker_->AddObserver(this); 186} 187 188void ExtensionAppModelBuilder::PopulateApps() { 189 ExtensionService* service = 190 extensions::ExtensionSystem::Get(profile_)->extension_service(); 191 if (!service) 192 return; 193 194 ExtensionAppList apps; 195 AddApps(service->extensions(), &apps); 196 AddApps(service->disabled_extensions(), &apps); 197 AddApps(service->terminated_extensions(), &apps); 198 199 if (apps.empty()) 200 return; 201 202 for (size_t i = 0; i < apps.size(); ++i) 203 InsertApp(apps[i]); 204} 205 206void ExtensionAppModelBuilder::InsertApp(ExtensionAppItem* app) { 207 model_->AddItem(app); 208} 209 210void ExtensionAppModelBuilder::SetHighlightedApp( 211 const std::string& extension_id) { 212 if (extension_id == highlight_app_id_) 213 return; 214 ExtensionAppItem* old_app = GetExtensionAppItem(highlight_app_id_); 215 if (old_app) 216 old_app->SetHighlighted(false); 217 highlight_app_id_ = extension_id; 218 ExtensionAppItem* new_app = GetExtensionAppItem(highlight_app_id_); 219 highlighted_app_pending_ = !new_app; 220 if (new_app) 221 new_app->SetHighlighted(true); 222} 223 224ExtensionAppItem* ExtensionAppModelBuilder::GetExtensionAppItem( 225 const std::string& extension_id) { 226 app_list::AppListItemModel* item = model_->FindItem(extension_id); 227 LOG_IF(ERROR, item && 228 item->GetAppType() != ExtensionAppItem::kAppType) 229 << "App Item matching id: " << extension_id 230 << " has incorrect type: '" << item->GetAppType() << "'"; 231 return static_cast<ExtensionAppItem*>(item); 232} 233 234void ExtensionAppModelBuilder::UpdateHighlight() { 235 DCHECK(model_); 236 if (!highlighted_app_pending_ || highlight_app_id_.empty()) 237 return; 238 ExtensionAppItem* item = GetExtensionAppItem(highlight_app_id_); 239 if (!item) 240 return; 241 item->SetHighlighted(true); 242 highlighted_app_pending_ = false; 243} 244 245void ExtensionAppModelBuilder::ListItemsAdded(size_t start, size_t count) { 246} 247 248void ExtensionAppModelBuilder::ListItemsRemoved(size_t start, size_t count) { 249} 250 251void ExtensionAppModelBuilder::ListItemMoved(size_t index, 252 size_t target_index) { 253 app_list::AppListModel::Apps* app_list = model_->apps(); 254 app_list::AppListItemModel* item = app_list->GetItemAt(target_index); 255 if (item->GetAppType() != ExtensionAppItem::kAppType) 256 return; 257 258 ExtensionAppItem* prev = NULL; 259 for (size_t idx = target_index; idx > 1; --idx) { 260 app_list::AppListItemModel* item = app_list->GetItemAt(idx - 1); 261 if (item->GetAppType() == ExtensionAppItem::kAppType) { 262 prev = static_cast<ExtensionAppItem*>(item); 263 break; 264 } 265 } 266 ExtensionAppItem* next = NULL; 267 for (size_t idx = target_index; idx < app_list->item_count() - 1; ++idx) { 268 app_list::AppListItemModel* item = app_list->GetItemAt(idx + 1); 269 if (item->GetAppType() == ExtensionAppItem::kAppType) { 270 next = static_cast<ExtensionAppItem*>(item); 271 break; 272 } 273 } 274 if (prev || next) 275 static_cast<ExtensionAppItem*>(item)->Move(prev, next); 276} 277 278void ExtensionAppModelBuilder::ListItemsChanged(size_t start, size_t count) { 279 NOTREACHED(); 280} 281