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_item.h" | 5 #include "chrome/browser/ui/app_list/extension_app_item.h" |
6 | 6 |
7 #include "base/prefs/pref_service.h" | 7 #include "base/prefs/pref_service.h" |
8 #include "chrome/browser/extensions/extension_util.h" | 8 #include "chrome/browser/extensions/extension_util.h" |
9 #include "chrome/browser/extensions/launch_util.h" | 9 #include "chrome/browser/extensions/launch_util.h" |
10 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
11 #include "chrome/browser/ui/app_list/app_context_menu.h" | 11 #include "chrome/browser/ui/app_list/app_context_menu.h" |
12 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" | 12 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" |
13 #include "chrome/browser/ui/app_list/app_list_service.h" | |
14 #include "chrome/browser/ui/extensions/extension_enable_flow.h" | 13 #include "chrome/browser/ui/extensions/extension_enable_flow.h" |
15 #include "chrome/browser/ui/host_desktop.h" | |
16 #include "chrome/common/extensions/extension_constants.h" | 14 #include "chrome/common/extensions/extension_constants.h" |
17 #include "chrome/common/extensions/extension_metrics.h" | 15 #include "chrome/common/extensions/extension_metrics.h" |
18 #include "content/public/browser/user_metrics.h" | 16 #include "content/public/browser/user_metrics.h" |
19 #include "extensions/browser/app_sorting.h" | 17 #include "extensions/browser/app_sorting.h" |
20 #include "extensions/browser/extension_prefs.h" | 18 #include "extensions/browser/extension_prefs.h" |
21 #include "extensions/browser/extension_registry.h" | 19 #include "extensions/browser/extension_registry.h" |
22 #include "extensions/browser/extension_system.h" | |
23 #include "extensions/common/extension.h" | 20 #include "extensions/common/extension.h" |
24 #include "extensions/common/extension_icon_set.h" | 21 #include "extensions/common/extension_icon_set.h" |
25 #include "extensions/common/manifest_handlers/icons_handler.h" | 22 #include "extensions/common/manifest_handlers/icons_handler.h" |
26 #include "extensions/common/manifest_url_handlers.h" | 23 #include "extensions/common/manifest_url_handlers.h" |
27 #include "grit/theme_resources.h" | 24 #include "grit/theme_resources.h" |
28 #include "sync/api/string_ordinal.h" | 25 #include "sync/api/string_ordinal.h" |
29 #include "ui/base/resource/resource_bundle.h" | 26 #include "ui/base/resource/resource_bundle.h" |
30 #include "ui/gfx/canvas.h" | 27 #include "ui/gfx/canvas.h" |
31 #include "ui/gfx/color_utils.h" | |
32 #include "ui/gfx/geometry/rect.h" | 28 #include "ui/gfx/geometry/rect.h" |
33 #include "ui/gfx/image/canvas_image_source.h" | 29 #include "ui/gfx/image/canvas_image_source.h" |
34 #include "ui/gfx/image/image_skia_operations.h" | |
35 | 30 |
36 using extensions::Extension; | 31 using extensions::Extension; |
37 | 32 |
38 namespace { | 33 namespace { |
39 | 34 |
40 // Overlays a shortcut icon over the bottom left corner of a given image. | 35 // Overlays a shortcut icon over the bottom left corner of a given image. |
41 class ShortcutOverlayImageSource : public gfx::CanvasImageSource { | 36 class ShortcutOverlayImageSource : public gfx::CanvasImageSource { |
42 public: | 37 public: |
43 explicit ShortcutOverlayImageSource(const gfx::ImageSkia& icon) | 38 explicit ShortcutOverlayImageSource(const gfx::ImageSkia& icon) |
44 : gfx::CanvasImageSource(icon.size(), false), | 39 : gfx::CanvasImageSource(icon.size(), false), |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 masking_paint.setXfermodeMode(SkXfermode::kDstIn_Mode); | 89 masking_paint.setXfermodeMode(SkXfermode::kDstIn_Mode); |
95 canvas->DrawImageInt( | 90 canvas->DrawImageInt( |
96 gfx::ImageSkia(masking_canvas->ExtractImageRep()), 0, 0, masking_paint); | 91 gfx::ImageSkia(masking_canvas->ExtractImageRep()), 0, 0, masking_paint); |
97 } | 92 } |
98 | 93 |
99 gfx::ImageSkia icon_; | 94 gfx::ImageSkia icon_; |
100 | 95 |
101 DISALLOW_COPY_AND_ASSIGN(RoundedCornersImageSource); | 96 DISALLOW_COPY_AND_ASSIGN(RoundedCornersImageSource); |
102 }; | 97 }; |
103 | 98 |
104 extensions::AppSorting* GetAppSorting(Profile* profile) { | |
105 return extensions::ExtensionSystem::Get(profile)->app_sorting(); | |
106 } | |
107 | |
108 gfx::ImageSkia CreateDisabledIcon(const gfx::ImageSkia& icon) { | |
109 const color_utils::HSL shift = {-1, 0, 0.6}; | |
110 return gfx::ImageSkiaOperations::CreateHSLShiftedImage(icon, shift); | |
111 } | |
112 | |
113 } // namespace | 99 } // namespace |
114 | 100 |
115 ExtensionAppItem::ExtensionAppItem( | 101 ExtensionAppItem::ExtensionAppItem( |
116 Profile* profile, | 102 Profile* profile, |
117 const app_list::AppListSyncableService::SyncItem* sync_item, | 103 const app_list::AppListSyncableService::SyncItem* sync_item, |
118 const std::string& extension_id, | 104 const std::string& extension_id, |
119 const std::string& extension_name, | 105 const std::string& extension_name, |
120 const gfx::ImageSkia& installing_icon, | 106 const gfx::ImageSkia& installing_icon, |
121 bool is_platform_app) | 107 bool is_platform_app) |
122 : app_list::AppListItem(extension_id), | 108 : ChromeAppListItem(profile, extension_id), |
123 profile_(profile), | |
124 extension_id_(extension_id), | |
125 extension_enable_flow_controller_(NULL), | 109 extension_enable_flow_controller_(NULL), |
126 extension_name_(extension_name), | 110 extension_name_(extension_name), |
127 installing_icon_(CreateDisabledIcon(installing_icon)), | 111 installing_icon_(CreateDisabledIcon(installing_icon)), |
128 is_platform_app_(is_platform_app), | 112 is_platform_app_(is_platform_app), |
129 has_overlay_(false) { | 113 has_overlay_(false) { |
130 Reload(); | 114 Reload(); |
131 if (sync_item && sync_item->item_ordinal.IsValid()) { | 115 UpdateFromSync(sync_item); |
132 // An existing synced position exists, use that. | |
133 set_position(sync_item->item_ordinal); | |
134 // Only set the name from the sync item if it is empty. | |
135 if (name().empty()) | |
136 SetName(sync_item->item_name); | |
137 return; | |
138 } | |
139 GetAppSorting(profile_)->EnsureValidOrdinals(extension_id_, | |
140 syncer::StringOrdinal()); | |
141 UpdatePositionFromExtensionOrdering(); | |
142 } | 116 } |
143 | 117 |
144 ExtensionAppItem::~ExtensionAppItem() { | 118 ExtensionAppItem::~ExtensionAppItem() { |
145 } | 119 } |
146 | 120 |
147 bool ExtensionAppItem::NeedsOverlay() const { | 121 bool ExtensionAppItem::NeedsOverlay() const { |
148 #if defined(OS_CHROMEOS) | 122 #if defined(OS_CHROMEOS) |
149 // The overlay is disabled completely in ChromeOS. | 123 // The overlay is disabled completely in ChromeOS. |
150 return false; | 124 return false; |
151 #endif | 125 #endif |
152 | 126 |
153 extensions::LaunchType launch_type = | 127 extensions::LaunchType launch_type = GetExtension() |
154 GetExtension() | 128 ? extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile()), |
155 ? extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile_), | 129 GetExtension()) |
156 GetExtension()) | 130 : extensions::LAUNCH_TYPE_WINDOW; |
157 : extensions::LAUNCH_TYPE_WINDOW; | |
158 | 131 |
159 // The overlay icon is disabled for hosted apps in windowed mode with | 132 // The overlay icon is disabled for hosted apps in windowed mode with |
160 // bookmark apps enabled. | 133 // bookmark apps enabled. |
161 return !is_platform_app_ && extension_id_ != extension_misc::kChromeAppId && | 134 return !is_platform_app_ && extension_id() != extension_misc::kChromeAppId && |
162 (!extensions::util::IsNewBookmarkAppsEnabled() || | 135 (!extensions::util::IsNewBookmarkAppsEnabled() || |
163 launch_type != extensions::LAUNCH_TYPE_WINDOW); | 136 launch_type != extensions::LAUNCH_TYPE_WINDOW); |
164 } | 137 } |
165 | 138 |
166 void ExtensionAppItem::Reload() { | 139 void ExtensionAppItem::Reload() { |
167 const Extension* extension = GetExtension(); | 140 const Extension* extension = GetExtension(); |
168 bool is_installing = !extension; | 141 bool is_installing = !extension; |
169 SetIsInstalling(is_installing); | 142 SetIsInstalling(is_installing); |
170 if (is_installing) { | 143 if (is_installing) { |
171 SetName(extension_name_); | 144 SetName(extension_name_); |
172 UpdateIcon(); | 145 UpdateIcon(); |
173 return; | 146 return; |
174 } | 147 } |
175 SetNameAndShortName(extension->name(), extension->short_name()); | 148 SetNameAndShortName(extension->name(), extension->short_name()); |
176 LoadImage(extension); | 149 LoadImage(extension); |
177 } | 150 } |
178 | 151 |
179 void ExtensionAppItem::UpdateIcon() { | 152 void ExtensionAppItem::UpdateIcon() { |
180 gfx::ImageSkia icon = installing_icon_; | 153 gfx::ImageSkia icon = installing_icon_; |
181 | 154 |
182 // Use the app icon if the app exists. Turn the image greyscale if the app is | 155 // Use the app icon if the app exists. Turn the image greyscale if the app is |
183 // not launchable. | 156 // not launchable. |
184 if (GetExtension() && icon_) { | 157 if (GetExtension() && icon_) { |
185 icon = icon_->image_skia(); | 158 icon = icon_->image_skia(); |
186 const bool enabled = extensions::util::IsAppLaunchable(extension_id_, | 159 const bool enabled = extensions::util::IsAppLaunchable(extension_id(), |
187 profile_); | 160 profile()); |
188 if (!enabled) | 161 if (!enabled) |
189 icon = CreateDisabledIcon(icon); | 162 icon = CreateDisabledIcon(icon); |
190 | 163 |
191 if (GetExtension()->from_bookmark()) | 164 if (GetExtension()->from_bookmark()) |
192 icon = gfx::ImageSkia(new RoundedCornersImageSource(icon), icon.size()); | 165 icon = gfx::ImageSkia(new RoundedCornersImageSource(icon), icon.size()); |
193 } | 166 } |
194 // Paint the shortcut overlay if necessary. | 167 // Paint the shortcut overlay if necessary. |
195 has_overlay_ = NeedsOverlay(); | 168 has_overlay_ = NeedsOverlay(); |
196 if (has_overlay_) | 169 if (has_overlay_) |
197 icon = gfx::ImageSkia(new ShortcutOverlayImageSource(icon), icon.size()); | 170 icon = gfx::ImageSkia(new ShortcutOverlayImageSource(icon), icon.size()); |
198 | 171 |
199 SetIcon(icon); | 172 SetIcon(icon); |
200 } | 173 } |
201 | 174 |
202 void ExtensionAppItem::Move(const ExtensionAppItem* prev, | 175 void ExtensionAppItem::Move(const ExtensionAppItem* prev, |
203 const ExtensionAppItem* next) { | 176 const ExtensionAppItem* next) { |
204 if (!prev && !next) | 177 if (!prev && !next) |
205 return; // No reordering necessary | 178 return; // No reordering necessary |
206 | 179 |
207 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); | 180 extensions::ExtensionPrefs* prefs = |
208 extensions::AppSorting* sorting = GetAppSorting(profile_); | 181 extensions::ExtensionPrefs::Get(profile()); |
| 182 extensions::AppSorting* sorting = GetAppSorting(); |
209 | 183 |
210 syncer::StringOrdinal page; | 184 syncer::StringOrdinal page; |
211 std::string prev_id, next_id; | 185 std::string prev_id, next_id; |
212 if (!prev) { | 186 if (!prev) { |
213 next_id = next->extension_id(); | 187 next_id = next->extension_id(); |
214 page = sorting->GetPageOrdinal(next_id); | 188 page = sorting->GetPageOrdinal(next_id); |
215 } else if (!next) { | 189 } else if (!next) { |
216 prev_id = prev->extension_id(); | 190 prev_id = prev->extension_id(); |
217 page = sorting->GetPageOrdinal(prev_id); | 191 page = sorting->GetPageOrdinal(prev_id); |
218 } else { | 192 } else { |
219 prev_id = prev->extension_id(); | 193 prev_id = prev->extension_id(); |
220 page = sorting->GetPageOrdinal(prev_id); | 194 page = sorting->GetPageOrdinal(prev_id); |
221 // Only set |next_id| if on the same page, otherwise just insert after prev. | 195 // Only set |next_id| if on the same page, otherwise just insert after prev. |
222 if (page.Equals(sorting->GetPageOrdinal(next->extension_id()))) | 196 if (page.Equals(sorting->GetPageOrdinal(next->extension_id()))) |
223 next_id = next->extension_id(); | 197 next_id = next->extension_id(); |
224 } | 198 } |
225 prefs->SetAppDraggedByUser(extension_id_); | 199 prefs->SetAppDraggedByUser(extension_id()); |
226 sorting->SetPageOrdinal(extension_id_, page); | 200 sorting->SetPageOrdinal(extension_id(), page); |
227 sorting->OnExtensionMoved(extension_id_, prev_id, next_id); | 201 sorting->OnExtensionMoved(extension_id(), prev_id, next_id); |
228 UpdatePositionFromExtensionOrdering(); | 202 UpdatePositionFromOrdering(); |
229 } | 203 } |
230 | 204 |
231 const Extension* ExtensionAppItem::GetExtension() const { | 205 const Extension* ExtensionAppItem::GetExtension() const { |
232 const extensions::ExtensionRegistry* registry = | 206 const extensions::ExtensionRegistry* registry = |
233 extensions::ExtensionRegistry::Get(profile_); | 207 extensions::ExtensionRegistry::Get(profile()); |
234 const Extension* extension = registry->GetInstalledExtension( | 208 const Extension* extension = registry->GetInstalledExtension( |
235 extension_id_); | 209 extension_id()); |
236 return extension; | 210 return extension; |
237 } | 211 } |
238 | 212 |
239 void ExtensionAppItem::LoadImage(const Extension* extension) { | 213 void ExtensionAppItem::LoadImage(const Extension* extension) { |
240 icon_.reset(new extensions::IconImage( | 214 icon_.reset(new extensions::IconImage( |
241 profile_, | 215 profile(), |
242 extension, | 216 extension, |
243 extensions::IconsInfo::GetIcons(extension), | 217 extensions::IconsInfo::GetIcons(extension), |
244 extension_misc::EXTENSION_ICON_MEDIUM, | 218 extension_misc::EXTENSION_ICON_MEDIUM, |
245 extensions::util::GetDefaultAppIcon(), | 219 extensions::util::GetDefaultAppIcon(), |
246 this)); | 220 this)); |
247 UpdateIcon(); | 221 UpdateIcon(); |
248 } | 222 } |
249 | 223 |
250 bool ExtensionAppItem::RunExtensionEnableFlow() { | 224 bool ExtensionAppItem::RunExtensionEnableFlow() { |
251 if (extensions::util::IsAppLaunchableWithoutEnabling(extension_id_, profile_)) | 225 if (extensions::util::IsAppLaunchableWithoutEnabling(extension_id(), |
| 226 profile())) |
252 return false; | 227 return false; |
253 | 228 |
254 if (!extension_enable_flow_) { | 229 if (!extension_enable_flow_) { |
255 extension_enable_flow_controller_ = GetController(); | 230 extension_enable_flow_controller_ = GetController(); |
256 extension_enable_flow_controller_->OnShowChildDialog(); | 231 extension_enable_flow_controller_->OnShowChildDialog(); |
257 | 232 |
258 extension_enable_flow_.reset(new ExtensionEnableFlow( | 233 extension_enable_flow_.reset(new ExtensionEnableFlow( |
259 profile_, extension_id_, this)); | 234 profile(), extension_id(), this)); |
260 extension_enable_flow_->StartForNativeWindow( | 235 extension_enable_flow_->StartForNativeWindow( |
261 extension_enable_flow_controller_->GetAppListWindow()); | 236 extension_enable_flow_controller_->GetAppListWindow()); |
262 } | 237 } |
263 return true; | 238 return true; |
264 } | 239 } |
265 | 240 |
266 void ExtensionAppItem::Launch(int event_flags) { | 241 void ExtensionAppItem::Launch(int event_flags) { |
267 // |extension| could be NULL when it is being unloaded for updating. | 242 // |extension| could be NULL when it is being unloaded for updating. |
268 const Extension* extension = GetExtension(); | 243 const Extension* extension = GetExtension(); |
269 if (!extension) | 244 if (!extension) |
270 return; | 245 return; |
271 | 246 |
272 // Don't auto-enable apps that cannot be launched. | 247 // Don't auto-enable apps that cannot be launched. |
273 if (!extensions::util::IsAppLaunchable(extension_id_, profile_)) | 248 if (!extensions::util::IsAppLaunchable(extension_id(), profile())) |
274 return; | 249 return; |
275 | 250 |
276 if (RunExtensionEnableFlow()) | 251 if (RunExtensionEnableFlow()) |
277 return; | 252 return; |
278 | 253 |
279 GetController()->LaunchApp(profile_, | 254 GetController()->LaunchApp(profile(), |
280 extension, | 255 extension, |
281 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, | 256 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, |
282 event_flags); | 257 event_flags); |
283 } | 258 } |
284 | 259 |
285 void ExtensionAppItem::OnExtensionIconImageChanged( | 260 void ExtensionAppItem::OnExtensionIconImageChanged( |
286 extensions::IconImage* image) { | 261 extensions::IconImage* image) { |
287 DCHECK(icon_.get() == image); | 262 DCHECK(icon_.get() == image); |
288 UpdateIcon(); | 263 UpdateIcon(); |
289 } | 264 } |
(...skipping 13 matching lines...) Expand all Loading... |
303 extension_enable_flow_controller_ = NULL; | 278 extension_enable_flow_controller_ = NULL; |
304 } | 279 } |
305 | 280 |
306 void ExtensionAppItem::Activate(int event_flags) { | 281 void ExtensionAppItem::Activate(int event_flags) { |
307 // |extension| could be NULL when it is being unloaded for updating. | 282 // |extension| could be NULL when it is being unloaded for updating. |
308 const Extension* extension = GetExtension(); | 283 const Extension* extension = GetExtension(); |
309 if (!extension) | 284 if (!extension) |
310 return; | 285 return; |
311 | 286 |
312 // Don't auto-enable apps that cannot be launched. | 287 // Don't auto-enable apps that cannot be launched. |
313 if (!extensions::util::IsAppLaunchable(extension_id_, profile_)) | 288 if (!extensions::util::IsAppLaunchable(extension_id(), profile())) |
314 return; | 289 return; |
315 | 290 |
316 if (RunExtensionEnableFlow()) | 291 if (RunExtensionEnableFlow()) |
317 return; | 292 return; |
318 | 293 |
319 content::RecordAction(base::UserMetricsAction("AppList_ClickOnApp")); | 294 content::RecordAction(base::UserMetricsAction("AppList_ClickOnApp")); |
320 extensions::RecordAppListMainLaunch(extension); | 295 extensions::RecordAppListMainLaunch(extension); |
321 GetController()->ActivateApp(profile_, | 296 GetController()->ActivateApp(profile(), |
322 extension, | 297 extension, |
323 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, | 298 AppListControllerDelegate::LAUNCH_FROM_APP_LIST, |
324 event_flags); | 299 event_flags); |
325 } | 300 } |
326 | 301 |
327 ui::MenuModel* ExtensionAppItem::GetContextMenuModel() { | 302 ui::MenuModel* ExtensionAppItem::GetContextMenuModel() { |
328 context_menu_.reset(new app_list::AppContextMenu( | 303 context_menu_.reset(new app_list::AppContextMenu( |
329 this, profile_, extension_id_, GetController())); | 304 this, profile(), extension_id(), GetController())); |
330 context_menu_->set_is_platform_app(is_platform_app_); | 305 context_menu_->set_is_platform_app(is_platform_app_); |
331 if (IsInFolder()) | 306 if (IsInFolder()) |
332 context_menu_->set_is_in_folder(true); | 307 context_menu_->set_is_in_folder(true); |
333 return context_menu_->GetMenuModel(); | 308 return context_menu_->GetMenuModel(); |
334 } | 309 } |
335 | 310 |
336 void ExtensionAppItem::OnExtensionPreferenceChanged() { | 311 void ExtensionAppItem::OnExtensionPreferenceChanged() { |
337 if (has_overlay_ != NeedsOverlay()) | 312 if (has_overlay_ != NeedsOverlay()) |
338 UpdateIcon(); | 313 UpdateIcon(); |
339 } | 314 } |
340 | 315 |
341 // static | 316 // static |
342 const char ExtensionAppItem::kItemType[] = "ExtensionAppItem"; | 317 const char ExtensionAppItem::kItemType[] = "ExtensionAppItem"; |
343 | 318 |
344 const char* ExtensionAppItem::GetItemType() const { | 319 const char* ExtensionAppItem::GetItemType() const { |
345 return ExtensionAppItem::kItemType; | 320 return ExtensionAppItem::kItemType; |
346 } | 321 } |
347 | 322 |
348 void ExtensionAppItem::ExecuteLaunchCommand(int event_flags) { | 323 void ExtensionAppItem::ExecuteLaunchCommand(int event_flags) { |
349 Launch(event_flags); | 324 Launch(event_flags); |
350 } | 325 } |
351 | |
352 void ExtensionAppItem::UpdatePositionFromExtensionOrdering() { | |
353 const syncer::StringOrdinal& page = | |
354 GetAppSorting(profile_)->GetPageOrdinal(extension_id_); | |
355 const syncer::StringOrdinal& launch = | |
356 GetAppSorting(profile_)->GetAppLaunchOrdinal(extension_id_); | |
357 set_position(syncer::StringOrdinal( | |
358 page.ToInternalValue() + launch.ToInternalValue())); | |
359 } | |
360 | |
361 AppListControllerDelegate* ExtensionAppItem::GetController() { | |
362 return AppListService::Get(chrome::GetActiveDesktop())-> | |
363 GetControllerDelegate(); | |
364 } | |
OLD | NEW |