OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" | 5 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "chrome/browser/extensions/extension_ui_util.h" | 12 #include "chrome/browser/extensions/extension_ui_util.h" |
13 #include "chrome/browser/extensions/extension_util.h" | 13 #include "chrome/browser/extensions/extension_util.h" |
14 #include "chrome/browser/extensions/install_tracker.h" | 14 #include "chrome/browser/extensions/install_tracker.h" |
15 #include "chrome/browser/extensions/install_tracker_factory.h" | |
16 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" | 16 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" |
18 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" | 17 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" |
19 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" | |
20 #include "chrome/browser/ui/app_list/extension_app_item.h" | 18 #include "chrome/browser/ui/app_list/extension_app_item.h" |
21 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
22 #include "extensions/browser/extension_prefs.h" | 20 #include "extensions/browser/extension_prefs.h" |
23 #include "extensions/browser/extension_registry.h" | 21 #include "extensions/browser/extension_registry.h" |
24 #include "extensions/browser/extension_system.h" | 22 #include "extensions/browser/extension_system.h" |
25 #include "extensions/browser/extensions_browser_client.h" | 23 #include "extensions/browser/extensions_browser_client.h" |
26 #include "extensions/browser/pref_names.h" | 24 #include "extensions/browser/pref_names.h" |
27 #include "extensions/common/constants.h" | 25 #include "extensions/common/constants.h" |
28 #include "extensions/common/extension.h" | 26 #include "extensions/common/extension.h" |
29 #include "extensions/common/extension_set.h" | 27 #include "extensions/common/extension_set.h" |
30 #include "ui/gfx/image/image_skia.h" | 28 #include "ui/gfx/image/image_skia.h" |
31 #include "ui/gfx/image/image_skia_operations.h" | 29 #include "ui/gfx/image/image_skia_operations.h" |
32 | 30 |
33 using extensions::Extension; | 31 using extensions::Extension; |
34 | 32 |
35 ExtensionAppModelBuilder::ExtensionAppModelBuilder( | 33 ExtensionAppModelBuilder::ExtensionAppModelBuilder( |
36 AppListControllerDelegate* controller) | 34 AppListControllerDelegate* controller) |
37 : service_(NULL), | 35 : AppListModelBuilder(controller, ExtensionAppItem::kItemType) { |
38 profile_(NULL), | |
39 controller_(controller), | |
40 model_(NULL), | |
41 tracker_(NULL), | |
42 extension_registry_(NULL) { | |
43 } | 36 } |
44 | 37 |
45 ExtensionAppModelBuilder::~ExtensionAppModelBuilder() { | 38 ExtensionAppModelBuilder::~ExtensionAppModelBuilder() { |
46 OnShutdown(); | 39 OnShutdown(); |
47 OnShutdown(extension_registry_); | 40 OnShutdown(extension_registry_); |
48 if (!service_) | |
49 model_->top_level_item_list()->RemoveObserver(this); | |
50 } | |
51 | |
52 void ExtensionAppModelBuilder::InitializeWithService( | |
53 app_list::AppListSyncableService* service, | |
54 app_list::AppListModel* model) { | |
55 DCHECK(!service_ && !profile_); | |
56 model_ = model; | |
57 service_ = service; | |
58 profile_ = service->profile(); | |
59 InitializePrefChangeRegistrars(); | |
60 | |
61 BuildModel(); | |
62 } | |
63 | |
64 void ExtensionAppModelBuilder::InitializeWithProfile( | |
65 Profile* profile, | |
66 app_list::AppListModel* model) { | |
67 DCHECK(!service_ && !profile_); | |
68 model_ = model; | |
69 model_->top_level_item_list()->AddObserver(this); | |
70 profile_ = profile; | |
71 InitializePrefChangeRegistrars(); | |
72 | |
73 BuildModel(); | |
74 } | 41 } |
75 | 42 |
76 void ExtensionAppModelBuilder::InitializePrefChangeRegistrars() { | 43 void ExtensionAppModelBuilder::InitializePrefChangeRegistrars() { |
77 profile_pref_change_registrar_.Init(profile_->GetPrefs()); | 44 profile_pref_change_registrar_.Init(profile()->GetPrefs()); |
78 profile_pref_change_registrar_.Add( | 45 profile_pref_change_registrar_.Add( |
79 prefs::kHideWebStoreIcon, | 46 prefs::kHideWebStoreIcon, |
80 base::Bind(&ExtensionAppModelBuilder::OnProfilePreferenceChanged, | 47 base::Bind(&ExtensionAppModelBuilder::OnProfilePreferenceChanged, |
81 base::Unretained(this))); | 48 base::Unretained(this))); |
82 | 49 |
83 if (!extensions::util::IsNewBookmarkAppsEnabled()) | 50 if (!extensions::util::IsNewBookmarkAppsEnabled()) |
84 return; | 51 return; |
85 | 52 |
86 // TODO(calamity): analyze the performance impact of doing this every | 53 // TODO(calamity): analyze the performance impact of doing this every |
87 // extension pref change. | 54 // extension pref change. |
88 extensions::ExtensionsBrowserClient* client = | 55 extensions::ExtensionsBrowserClient* client = |
89 extensions::ExtensionsBrowserClient::Get(); | 56 extensions::ExtensionsBrowserClient::Get(); |
90 extension_pref_change_registrar_.Init( | 57 extension_pref_change_registrar_.Init( |
91 client->GetPrefServiceForContext(profile_)); | 58 client->GetPrefServiceForContext(profile())); |
92 extension_pref_change_registrar_.Add( | 59 extension_pref_change_registrar_.Add( |
93 extensions::pref_names::kExtensions, | 60 extensions::pref_names::kExtensions, |
94 base::Bind(&ExtensionAppModelBuilder::OnExtensionPreferenceChanged, | 61 base::Bind(&ExtensionAppModelBuilder::OnExtensionPreferenceChanged, |
95 base::Unretained(this))); | 62 base::Unretained(this))); |
96 } | 63 } |
97 | 64 |
98 void ExtensionAppModelBuilder::OnProfilePreferenceChanged() { | 65 void ExtensionAppModelBuilder::OnProfilePreferenceChanged() { |
99 extensions::ExtensionSet extensions; | 66 extensions::ExtensionSet extensions; |
100 controller_->GetApps(profile_, &extensions); | 67 controller()->GetApps(profile(), &extensions); |
101 | 68 |
102 for (extensions::ExtensionSet::const_iterator app = extensions.begin(); | 69 for (extensions::ExtensionSet::const_iterator app = extensions.begin(); |
103 app != extensions.end(); ++app) { | 70 app != extensions.end(); ++app) { |
104 bool should_display = | 71 bool should_display = |
105 extensions::ui_util::ShouldDisplayInAppLauncher(app->get(), profile_); | 72 extensions::ui_util::ShouldDisplayInAppLauncher(app->get(), profile()); |
106 bool does_display = GetExtensionAppItem((*app)->id()) != NULL; | 73 bool does_display = GetExtensionAppItem((*app)->id()) != nullptr; |
107 | 74 |
108 if (should_display == does_display) | 75 if (should_display == does_display) |
109 continue; | 76 continue; |
110 | 77 |
111 if (should_display) { | 78 if (should_display) { |
112 InsertApp(CreateAppItem((*app)->id(), | 79 InsertApp(CreateAppItem((*app)->id(), |
113 "", | 80 "", |
114 gfx::ImageSkia(), | 81 gfx::ImageSkia(), |
115 (*app)->is_platform_app())); | 82 (*app)->is_platform_app())); |
116 } else { | 83 } else { |
117 if (service_) | 84 if (service()) |
118 service_->RemoveItem((*app)->id()); | 85 service()->RemoveItem((*app)->id()); |
119 else | 86 else |
120 model_->DeleteItem((*app)->id()); | 87 model()->DeleteItem((*app)->id()); |
121 } | 88 } |
122 } | 89 } |
123 } | 90 } |
124 | 91 |
125 void ExtensionAppModelBuilder::OnExtensionPreferenceChanged() { | 92 void ExtensionAppModelBuilder::OnExtensionPreferenceChanged() { |
126 model_->NotifyExtensionPreferenceChanged(); | 93 model()->NotifyExtensionPreferenceChanged(); |
127 } | 94 } |
128 | 95 |
129 void ExtensionAppModelBuilder::OnBeginExtensionInstall( | 96 void ExtensionAppModelBuilder::OnBeginExtensionInstall( |
130 const ExtensionInstallParams& params) { | 97 const ExtensionInstallParams& params) { |
131 if (!params.is_app) | 98 if (!params.is_app) |
132 return; | 99 return; |
133 | 100 |
134 DVLOG(2) << service_ << ": OnBeginExtensionInstall: " | 101 DVLOG(2) << service() << ": OnBeginExtensionInstall: " |
135 << params.extension_id.substr(0, 8); | 102 << params.extension_id.substr(0, 8); |
136 ExtensionAppItem* existing_item = GetExtensionAppItem(params.extension_id); | 103 ExtensionAppItem* existing_item = GetExtensionAppItem(params.extension_id); |
137 if (existing_item) { | 104 if (existing_item) { |
138 existing_item->SetIsInstalling(true); | 105 existing_item->SetIsInstalling(true); |
139 return; | 106 return; |
140 } | 107 } |
141 | 108 |
142 // Icons from the webstore can be unusual sizes. Once installed, | 109 // Icons from the webstore can be unusual sizes. Once installed, |
143 // ExtensionAppItem uses extension_misc::EXTENSION_ICON_MEDIUM (48) to load | 110 // ExtensionAppItem uses extension_misc::EXTENSION_ICON_MEDIUM (48) to load |
144 // it, so be consistent with that. | 111 // it, so be consistent with that. |
(...skipping 12 matching lines...) Expand all Loading... |
157 const std::string& extension_id, | 124 const std::string& extension_id, |
158 int percent_downloaded) { | 125 int percent_downloaded) { |
159 ExtensionAppItem* item = GetExtensionAppItem(extension_id); | 126 ExtensionAppItem* item = GetExtensionAppItem(extension_id); |
160 if (!item) | 127 if (!item) |
161 return; | 128 return; |
162 item->SetPercentDownloaded(percent_downloaded); | 129 item->SetPercentDownloaded(percent_downloaded); |
163 } | 130 } |
164 | 131 |
165 void ExtensionAppModelBuilder::OnInstallFailure( | 132 void ExtensionAppModelBuilder::OnInstallFailure( |
166 const std::string& extension_id) { | 133 const std::string& extension_id) { |
167 model_->DeleteItem(extension_id); | 134 model()->DeleteItem(extension_id); |
168 } | 135 } |
169 | 136 |
170 void ExtensionAppModelBuilder::OnExtensionLoaded( | 137 void ExtensionAppModelBuilder::OnExtensionLoaded( |
171 content::BrowserContext* browser_context, | 138 content::BrowserContext* browser_context, |
172 const extensions::Extension* extension) { | 139 const extensions::Extension* extension) { |
173 if (!extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile_)) | 140 if (!extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile())) |
174 return; | 141 return; |
175 | 142 |
176 DVLOG(2) << service_ << ": OnExtensionLoaded: " | 143 DVLOG(2) << service() << ": OnExtensionLoaded: " |
177 << extension->id().substr(0, 8); | 144 << extension->id().substr(0, 8); |
178 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id()); | 145 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id()); |
179 if (existing_item) { | 146 if (existing_item) { |
180 existing_item->Reload(); | 147 existing_item->Reload(); |
181 if (service_) | 148 if (service()) |
182 service_->UpdateItem(existing_item); | 149 service()->UpdateItem(existing_item); |
183 return; | 150 return; |
184 } | 151 } |
185 | 152 |
186 InsertApp(CreateAppItem(extension->id(), | 153 InsertApp(CreateAppItem(extension->id(), |
187 "", | 154 "", |
188 gfx::ImageSkia(), | 155 gfx::ImageSkia(), |
189 extension->is_platform_app())); | 156 extension->is_platform_app())); |
190 } | 157 } |
191 | 158 |
192 void ExtensionAppModelBuilder::OnExtensionUnloaded( | 159 void ExtensionAppModelBuilder::OnExtensionUnloaded( |
193 content::BrowserContext* browser_context, | 160 content::BrowserContext* browser_context, |
194 const extensions::Extension* extension, | 161 const extensions::Extension* extension, |
195 extensions::UnloadedExtensionInfo::Reason reason) { | 162 extensions::UnloadedExtensionInfo::Reason reason) { |
196 ExtensionAppItem* item = GetExtensionAppItem(extension->id()); | 163 ExtensionAppItem* item = GetExtensionAppItem(extension->id()); |
197 if (!item) | 164 if (!item) |
198 return; | 165 return; |
199 item->UpdateIcon(); | 166 item->UpdateIcon(); |
200 } | 167 } |
201 | 168 |
202 void ExtensionAppModelBuilder::OnExtensionUninstalled( | 169 void ExtensionAppModelBuilder::OnExtensionUninstalled( |
203 content::BrowserContext* browser_context, | 170 content::BrowserContext* browser_context, |
204 const extensions::Extension* extension, | 171 const extensions::Extension* extension, |
205 extensions::UninstallReason reason) { | 172 extensions::UninstallReason reason) { |
206 if (service_) { | 173 if (service()) { |
207 DVLOG(2) << service_ << ": OnExtensionUninstalled: " | 174 DVLOG(2) << service() << ": OnExtensionUninstalled: " |
208 << extension->id().substr(0, 8); | 175 << extension->id().substr(0, 8); |
209 service_->RemoveUninstalledItem(extension->id()); | 176 service()->RemoveUninstalledItem(extension->id()); |
210 return; | 177 return; |
211 } | 178 } |
212 model_->DeleteUninstalledItem(extension->id()); | 179 model()->DeleteUninstalledItem(extension->id()); |
213 } | 180 } |
214 | 181 |
215 void ExtensionAppModelBuilder::OnDisabledExtensionUpdated( | 182 void ExtensionAppModelBuilder::OnDisabledExtensionUpdated( |
216 const Extension* extension) { | 183 const Extension* extension) { |
217 if (!extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile_)) | 184 if (!extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile())) |
218 return; | 185 return; |
219 | 186 |
220 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id()); | 187 ExtensionAppItem* existing_item = GetExtensionAppItem(extension->id()); |
221 if (existing_item) | 188 if (existing_item) |
222 existing_item->Reload(); | 189 existing_item->Reload(); |
223 } | 190 } |
224 | 191 |
225 void ExtensionAppModelBuilder::OnShutdown() { | 192 void ExtensionAppModelBuilder::OnShutdown() { |
226 if (tracker_) { | 193 if (tracker_) { |
227 tracker_->RemoveObserver(this); | 194 tracker_->RemoveObserver(this); |
228 tracker_ = NULL; | 195 tracker_ = nullptr; |
229 } | 196 } |
230 } | 197 } |
231 | 198 |
232 void ExtensionAppModelBuilder::OnShutdown( | 199 void ExtensionAppModelBuilder::OnShutdown( |
233 extensions::ExtensionRegistry* registry) { | 200 extensions::ExtensionRegistry* registry) { |
234 if (!extension_registry_) | 201 if (!extension_registry_) |
235 return; | 202 return; |
236 | 203 |
237 DCHECK_EQ(extension_registry_, registry); | 204 DCHECK_EQ(extension_registry_, registry); |
238 extension_registry_->RemoveObserver(this); | 205 extension_registry_->RemoveObserver(this); |
239 extension_registry_ = NULL; | 206 extension_registry_ = nullptr; |
240 } | 207 } |
241 | 208 |
242 scoped_ptr<ExtensionAppItem> ExtensionAppModelBuilder::CreateAppItem( | 209 scoped_ptr<ExtensionAppItem> ExtensionAppModelBuilder::CreateAppItem( |
243 const std::string& extension_id, | 210 const std::string& extension_id, |
244 const std::string& extension_name, | 211 const std::string& extension_name, |
245 const gfx::ImageSkia& installing_icon, | 212 const gfx::ImageSkia& installing_icon, |
246 bool is_platform_app) { | 213 bool is_platform_app) { |
247 const app_list::AppListSyncableService::SyncItem* sync_item = | 214 return make_scoped_ptr(new ExtensionAppItem(profile(), |
248 service_ ? service_->GetSyncItem(extension_id) : NULL; | 215 GetSyncItem(extension_id), |
249 return make_scoped_ptr(new ExtensionAppItem(profile_, | |
250 sync_item, | |
251 extension_id, | 216 extension_id, |
252 extension_name, | 217 extension_name, |
253 installing_icon, | 218 installing_icon, |
254 is_platform_app)); | 219 is_platform_app)); |
255 } | 220 } |
256 | 221 |
257 void ExtensionAppModelBuilder::BuildModel() { | 222 void ExtensionAppModelBuilder::BuildModel() { |
258 DCHECK(!tracker_); | 223 DCHECK(!tracker_); |
259 tracker_ = controller_->GetInstallTrackerFor(profile_); | 224 |
260 extension_registry_ = extensions::ExtensionRegistry::Get(profile_); | 225 InitializePrefChangeRegistrars(); |
| 226 |
| 227 tracker_ = controller()->GetInstallTrackerFor(profile()); |
| 228 extension_registry_ = extensions::ExtensionRegistry::Get(profile()); |
261 | 229 |
262 PopulateApps(); | 230 PopulateApps(); |
263 | 231 |
264 // Start observing after model is built. | 232 // Start observing after model is built. |
265 if (tracker_) | 233 if (tracker_) |
266 tracker_->AddObserver(this); | 234 tracker_->AddObserver(this); |
267 | 235 |
268 if (extension_registry_) | 236 if (extension_registry_) |
269 extension_registry_->AddObserver(this); | 237 extension_registry_->AddObserver(this); |
270 } | 238 } |
271 | 239 |
272 void ExtensionAppModelBuilder::PopulateApps() { | 240 void ExtensionAppModelBuilder::PopulateApps() { |
273 extensions::ExtensionSet extensions; | 241 extensions::ExtensionSet extensions; |
274 controller_->GetApps(profile_, &extensions); | 242 controller()->GetApps(profile(), &extensions); |
275 | 243 |
276 for (extensions::ExtensionSet::const_iterator app = extensions.begin(); | 244 for (extensions::ExtensionSet::const_iterator app = extensions.begin(); |
277 app != extensions.end(); ++app) { | 245 app != extensions.end(); ++app) { |
278 if (!extensions::ui_util::ShouldDisplayInAppLauncher(app->get(), profile_)) | 246 if (!extensions::ui_util::ShouldDisplayInAppLauncher(app->get(), profile())) |
279 continue; | 247 continue; |
280 InsertApp(CreateAppItem((*app)->id(), | 248 InsertApp(CreateAppItem((*app)->id(), |
281 "", | 249 "", |
282 gfx::ImageSkia(), | 250 gfx::ImageSkia(), |
283 (*app)->is_platform_app())); | 251 (*app)->is_platform_app())); |
284 } | 252 } |
285 } | 253 } |
286 | 254 |
287 void ExtensionAppModelBuilder::InsertApp(scoped_ptr<ExtensionAppItem> app) { | |
288 if (service_) { | |
289 service_->AddItem(app.Pass()); | |
290 return; | |
291 } | |
292 model_->AddItem(app.Pass()); | |
293 } | |
294 | |
295 ExtensionAppItem* ExtensionAppModelBuilder::GetExtensionAppItem( | 255 ExtensionAppItem* ExtensionAppModelBuilder::GetExtensionAppItem( |
296 const std::string& extension_id) { | 256 const std::string& extension_id) { |
297 app_list::AppListItem* item = model_->FindItem(extension_id); | 257 return static_cast<ExtensionAppItem*>(GetAppItem(extension_id)); |
298 LOG_IF(ERROR, item && | |
299 item->GetItemType() != ExtensionAppItem::kItemType) | |
300 << "App Item matching id: " << extension_id | |
301 << " has incorrect type: '" << item->GetItemType() << "'"; | |
302 return static_cast<ExtensionAppItem*>(item); | |
303 } | 258 } |
304 | 259 |
305 void ExtensionAppModelBuilder::OnListItemMoved(size_t from_index, | 260 void ExtensionAppModelBuilder::OnListItemMoved(size_t from_index, |
306 size_t to_index, | 261 size_t to_index, |
307 app_list::AppListItem* item) { | 262 app_list::AppListItem* item) { |
308 DCHECK(!service_); | 263 DCHECK(!service()); |
309 | 264 |
310 // This will get called from AppListItemList::ListItemMoved after | 265 // This will get called from AppListItemList::ListItemMoved after |
311 // set_position is called for the item. | 266 // set_position is called for the item. |
312 if (item->GetItemType() != ExtensionAppItem::kItemType) | 267 if (item->GetItemType() != ExtensionAppItem::kItemType) |
313 return; | 268 return; |
314 | 269 |
315 app_list::AppListItemList* item_list = model_->top_level_item_list(); | 270 app_list::AppListItemList* item_list = model()->top_level_item_list(); |
316 ExtensionAppItem* prev = NULL; | 271 ExtensionAppItem* prev = nullptr; |
317 for (size_t idx = to_index; idx > 0; --idx) { | 272 for (size_t idx = to_index; idx > 0; --idx) { |
318 app_list::AppListItem* item = item_list->item_at(idx - 1); | 273 app_list::AppListItem* item = item_list->item_at(idx - 1); |
319 if (item->GetItemType() == ExtensionAppItem::kItemType) { | 274 if (item->GetItemType() == ExtensionAppItem::kItemType) { |
320 prev = static_cast<ExtensionAppItem*>(item); | 275 prev = static_cast<ExtensionAppItem*>(item); |
321 break; | 276 break; |
322 } | 277 } |
323 } | 278 } |
324 ExtensionAppItem* next = NULL; | 279 ExtensionAppItem* next = nullptr; |
325 for (size_t idx = to_index; idx < item_list->item_count() - 1; ++idx) { | 280 for (size_t idx = to_index; idx < item_list->item_count() - 1; ++idx) { |
326 app_list::AppListItem* item = item_list->item_at(idx + 1); | 281 app_list::AppListItem* item = item_list->item_at(idx + 1); |
327 if (item->GetItemType() == ExtensionAppItem::kItemType) { | 282 if (item->GetItemType() == ExtensionAppItem::kItemType) { |
328 next = static_cast<ExtensionAppItem*>(item); | 283 next = static_cast<ExtensionAppItem*>(item); |
329 break; | 284 break; |
330 } | 285 } |
331 } | 286 } |
332 // item->Move will call set_position, overriding the item's position. | 287 // item->Move will call set_position, overriding the item's position. |
333 if (prev || next) | 288 if (prev || next) |
334 static_cast<ExtensionAppItem*>(item)->Move(prev, next); | 289 static_cast<ExtensionAppItem*>(item)->Move(prev, next); |
335 } | 290 } |
OLD | NEW |