Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: chrome/browser/web_applications/web_app.cc

Issue 1038573002: Fixed thread-unsafe use of gfx::Image in app shortcut creation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/web_applications/web_app.h" 5 #include "chrome/browser/web_applications/web_app.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 #endif 76 #endif
77 77
78 base::FilePath GetShortcutDataDir(const web_app::ShortcutInfo& shortcut_info) { 78 base::FilePath GetShortcutDataDir(const web_app::ShortcutInfo& shortcut_info) {
79 return web_app::GetWebAppDataDirectory(shortcut_info.profile_path, 79 return web_app::GetWebAppDataDirectory(shortcut_info.profile_path,
80 shortcut_info.extension_id, 80 shortcut_info.extension_id,
81 shortcut_info.url); 81 shortcut_info.url);
82 } 82 }
83 83
84 void UpdateAllShortcutsForShortcutInfo( 84 void UpdateAllShortcutsForShortcutInfo(
85 const base::string16& old_app_title, 85 const base::string16& old_app_title,
86 const web_app::ShortcutInfo& shortcut_info, 86 scoped_ptr<web_app::ShortcutInfo> shortcut_info,
87 const extensions::FileHandlersInfo& file_handlers_info) { 87 const extensions::FileHandlersInfo& file_handlers_info) {
88 base::FilePath shortcut_data_dir = GetShortcutDataDir(*shortcut_info);
88 BrowserThread::PostTask( 89 BrowserThread::PostTask(
89 BrowserThread::FILE, 90 BrowserThread::FILE, FROM_HERE,
90 FROM_HERE,
91 base::Bind(&web_app::internals::UpdatePlatformShortcuts, 91 base::Bind(&web_app::internals::UpdatePlatformShortcuts,
92 GetShortcutDataDir(shortcut_info), 92 shortcut_data_dir, old_app_title, base::Passed(&shortcut_info),
93 old_app_title, shortcut_info, file_handlers_info)); 93 file_handlers_info));
94 } 94 }
95 95
96 void OnImageLoaded(web_app::ShortcutInfo shortcut_info, 96 void OnImageLoaded(scoped_ptr<web_app::ShortcutInfo> shortcut_info,
97 extensions::FileHandlersInfo file_handlers_info, 97 extensions::FileHandlersInfo file_handlers_info,
98 web_app::InfoCallback callback, 98 web_app::InfoCallback callback,
99 const gfx::ImageFamily& image_family) { 99 const gfx::ImageFamily& image_family) {
100 // If the image failed to load (e.g. if the resource being loaded was empty) 100 // If the image failed to load (e.g. if the resource being loaded was empty)
101 // use the standard application icon. 101 // use the standard application icon.
102 if (image_family.empty()) { 102 if (image_family.empty()) {
103 gfx::Image default_icon = 103 gfx::Image default_icon =
104 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); 104 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON);
105 int size = kDesiredSizes[kNumDesiredSizes - 1]; 105 int size = kDesiredSizes[kNumDesiredSizes - 1];
106 SkBitmap bmp = skia::ImageOperations::Resize( 106 SkBitmap bmp = skia::ImageOperations::Resize(
107 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, 107 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
108 size, size); 108 size, size);
109 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); 109 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp);
110 // We are on the UI thread, and this image is needed from the FILE thread, 110 // We are on the UI thread, and this image is needed from the FILE thread,
111 // for creating shortcut icon files. 111 // for creating shortcut icon files.
112 image_skia.MakeThreadSafe(); 112 image_skia.MakeThreadSafe();
113 shortcut_info.favicon.Add(gfx::Image(image_skia)); 113 shortcut_info->favicon.Add(gfx::Image(image_skia));
114 } else { 114 } else {
115 shortcut_info.favicon = image_family; 115 shortcut_info->favicon = image_family;
116 } 116 }
117 117
118 callback.Run(shortcut_info, file_handlers_info); 118 callback.Run(shortcut_info.Pass(), file_handlers_info);
119 } 119 }
120 120
121 void IgnoreFileHandlersInfo( 121 void IgnoreFileHandlersInfo(
122 const web_app::ShortcutInfoCallback& shortcut_info_callback, 122 const web_app::ShortcutInfoCallback& shortcut_info_callback,
123 const web_app::ShortcutInfo& shortcut_info, 123 scoped_ptr<web_app::ShortcutInfo> shortcut_info,
124 const extensions::FileHandlersInfo& file_handlers_info) { 124 const extensions::FileHandlersInfo& file_handlers_info) {
125 shortcut_info_callback.Run(shortcut_info); 125 shortcut_info_callback.Run(shortcut_info.Pass());
126 } 126 }
127 127
128 void ScheduleCreatePlatformShortcut( 128 void ScheduleCreatePlatformShortcut(
129 web_app::ShortcutCreationReason reason, 129 web_app::ShortcutCreationReason reason,
130 const web_app::ShortcutLocations& locations, 130 const web_app::ShortcutLocations& locations,
131 const web_app::ShortcutInfo& shortcut_info, 131 scoped_ptr<web_app::ShortcutInfo> shortcut_info,
132 const extensions::FileHandlersInfo& file_handlers_info) { 132 const extensions::FileHandlersInfo& file_handlers_info) {
133 base::FilePath shortcut_data_dir = GetShortcutDataDir(*shortcut_info);
133 BrowserThread::PostTask( 134 BrowserThread::PostTask(
134 BrowserThread::FILE, FROM_HERE, 135 BrowserThread::FILE, FROM_HERE,
135 base::Bind( 136 base::Bind(
136 base::IgnoreResult(&web_app::internals::CreatePlatformShortcuts), 137 base::IgnoreResult(&web_app::internals::CreatePlatformShortcuts),
137 GetShortcutDataDir(shortcut_info), shortcut_info, file_handlers_info, 138 shortcut_data_dir, base::Passed(&shortcut_info), file_handlers_info,
138 locations, reason)); 139 locations, reason));
139 } 140 }
140 141
141 } // namespace 142 } // namespace
142 143
143 namespace web_app { 144 namespace web_app {
144 145
145 // The following string is used to build the directory name for 146 // The following string is used to build the directory name for
146 // shortcuts to chrome applications (the kind which are installed 147 // shortcuts to chrome applications (the kind which are installed
147 // from a CRX). Application shortcuts to URLs use the {host}_{path} 148 // from a CRX). Application shortcuts to URLs use the {host}_{path}
(...skipping 22 matching lines...) Expand all
170 171
171 ShortcutInfo::~ShortcutInfo() {} 172 ShortcutInfo::~ShortcutInfo() {}
172 173
173 ShortcutLocations::ShortcutLocations() 174 ShortcutLocations::ShortcutLocations()
174 : on_desktop(false), 175 : on_desktop(false),
175 applications_menu_location(APP_MENU_LOCATION_NONE), 176 applications_menu_location(APP_MENU_LOCATION_NONE),
176 in_quick_launch_bar(false) { 177 in_quick_launch_bar(false) {
177 } 178 }
178 179
179 #if defined(TOOLKIT_VIEWS) 180 #if defined(TOOLKIT_VIEWS)
180 void GetShortcutInfoForTab(content::WebContents* web_contents, 181 scoped_ptr<ShortcutInfo> GetShortcutInfoForTab(
181 ShortcutInfo* info) { 182 content::WebContents* web_contents) {
182 DCHECK(info); // Must provide a valid info.
183
184 const FaviconTabHelper* favicon_tab_helper = 183 const FaviconTabHelper* favicon_tab_helper =
185 FaviconTabHelper::FromWebContents(web_contents); 184 FaviconTabHelper::FromWebContents(web_contents);
186 const extensions::TabHelper* extensions_tab_helper = 185 const extensions::TabHelper* extensions_tab_helper =
187 extensions::TabHelper::FromWebContents(web_contents); 186 extensions::TabHelper::FromWebContents(web_contents);
188 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); 187 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info();
189 188
189 scoped_ptr<ShortcutInfo> info(new ShortcutInfo);
190 info->url = app_info.app_url.is_empty() ? web_contents->GetURL() : 190 info->url = app_info.app_url.is_empty() ? web_contents->GetURL() :
191 app_info.app_url; 191 app_info.app_url;
192 info->title = app_info.title.empty() ? 192 info->title = app_info.title.empty() ?
193 (web_contents->GetTitle().empty() ? base::UTF8ToUTF16(info->url.spec()) : 193 (web_contents->GetTitle().empty() ? base::UTF8ToUTF16(info->url.spec()) :
194 web_contents->GetTitle()) : 194 web_contents->GetTitle()) :
195 app_info.title; 195 app_info.title;
196 info->description = app_info.description; 196 info->description = app_info.description;
197 info->favicon.Add(favicon_tab_helper->GetFavicon()); 197 info->favicon.Add(favicon_tab_helper->GetFavicon());
198 198
199 Profile* profile = 199 Profile* profile =
200 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 200 Profile::FromBrowserContext(web_contents->GetBrowserContext());
201 info->profile_path = profile->GetPath(); 201 info->profile_path = profile->GetPath();
202
203 return info;
202 } 204 }
203 #endif 205 #endif
204 206
205 #if !defined(OS_WIN) 207 #if !defined(OS_WIN)
206 void UpdateShortcutForTabContents(content::WebContents* web_contents) {} 208 void UpdateShortcutForTabContents(content::WebContents* web_contents) {}
207 #endif 209 #endif
208 210
209 ShortcutInfo ShortcutInfoForExtensionAndProfile( 211 scoped_ptr<ShortcutInfo> ShortcutInfoForExtensionAndProfile(
210 const extensions::Extension* app, Profile* profile) { 212 const extensions::Extension* app,
211 ShortcutInfo shortcut_info; 213 Profile* profile) {
212 shortcut_info.extension_id = app->id(); 214 scoped_ptr<ShortcutInfo> shortcut_info(new ShortcutInfo);
213 shortcut_info.is_platform_app = app->is_platform_app(); 215 shortcut_info->extension_id = app->id();
214 shortcut_info.url = extensions::AppLaunchInfo::GetLaunchWebURL(app); 216 shortcut_info->is_platform_app = app->is_platform_app();
215 shortcut_info.title = base::UTF8ToUTF16(app->name()); 217 shortcut_info->url = extensions::AppLaunchInfo::GetLaunchWebURL(app);
216 shortcut_info.description = base::UTF8ToUTF16(app->description()); 218 shortcut_info->title = base::UTF8ToUTF16(app->name());
217 shortcut_info.extension_path = app->path(); 219 shortcut_info->description = base::UTF8ToUTF16(app->description());
218 shortcut_info.profile_path = profile->GetPath(); 220 shortcut_info->extension_path = app->path();
219 shortcut_info.profile_name = 221 shortcut_info->profile_path = profile->GetPath();
222 shortcut_info->profile_name =
220 profile->GetPrefs()->GetString(prefs::kProfileName); 223 profile->GetPrefs()->GetString(prefs::kProfileName);
221 shortcut_info.version_for_display = app->GetVersionForDisplay(); 224 shortcut_info->version_for_display = app->GetVersionForDisplay();
222 return shortcut_info; 225 return shortcut_info;
223 } 226 }
224 227
225 void GetInfoForApp(const extensions::Extension* extension, 228 void GetInfoForApp(const extensions::Extension* extension,
226 Profile* profile, 229 Profile* profile,
227 const InfoCallback& callback) { 230 const InfoCallback& callback) {
228 web_app::ShortcutInfo shortcut_info = 231 scoped_ptr<web_app::ShortcutInfo> shortcut_info(
229 web_app::ShortcutInfoForExtensionAndProfile(extension, profile); 232 web_app::ShortcutInfoForExtensionAndProfile(extension, profile));
230 const std::vector<extensions::FileHandlerInfo>* file_handlers = 233 const std::vector<extensions::FileHandlerInfo>* file_handlers =
231 extensions::FileHandlers::GetFileHandlers(extension); 234 extensions::FileHandlers::GetFileHandlers(extension);
232 extensions::FileHandlersInfo file_handlers_info = 235 extensions::FileHandlersInfo file_handlers_info =
233 file_handlers ? *file_handlers : extensions::FileHandlersInfo(); 236 file_handlers ? *file_handlers : extensions::FileHandlersInfo();
234 237
235 std::vector<extensions::ImageLoader::ImageRepresentation> info_list; 238 std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
236 for (size_t i = 0; i < kNumDesiredSizes; ++i) { 239 for (size_t i = 0; i < kNumDesiredSizes; ++i) {
237 int size = kDesiredSizes[i]; 240 int size = kDesiredSizes[i];
238 extensions::ExtensionResource resource = 241 extensions::ExtensionResource resource =
239 extensions::IconsInfo::GetIconResource( 242 extensions::IconsInfo::GetIconResource(
(...skipping 25 matching lines...) Expand all
265 resource, 268 resource,
266 extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, 269 extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
267 gfx::Size(size, size), 270 gfx::Size(size, size),
268 ui::SCALE_FACTOR_100P)); 271 ui::SCALE_FACTOR_100P));
269 } 272 }
270 273
271 // |info_list| may still be empty at this point, in which case 274 // |info_list| may still be empty at this point, in which case
272 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty 275 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty
273 // image and exit immediately. 276 // image and exit immediately.
274 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( 277 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync(
275 extension, 278 extension, info_list,
276 info_list, 279 base::Bind(&OnImageLoaded, base::Passed(&shortcut_info),
277 base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); 280 file_handlers_info, callback));
278 } 281 }
279 282
280 void GetShortcutInfoForApp(const extensions::Extension* extension, 283 void GetShortcutInfoForApp(const extensions::Extension* extension,
281 Profile* profile, 284 Profile* profile,
282 const ShortcutInfoCallback& callback) { 285 const ShortcutInfoCallback& callback) {
283 GetInfoForApp( 286 GetInfoForApp(
284 extension, profile, base::Bind(&IgnoreFileHandlersInfo, callback)); 287 extension, profile, base::Bind(&IgnoreFileHandlersInfo, callback));
285 } 288 }
286 289
287 bool ShouldCreateShortcutFor(web_app::ShortcutCreationReason reason, 290 bool ShouldCreateShortcutFor(web_app::ShortcutCreationReason reason,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 std::string GetExtensionIdFromApplicationName(const std::string& app_name) { 374 std::string GetExtensionIdFromApplicationName(const std::string& app_name) {
372 std::string prefix(kCrxAppPrefix); 375 std::string prefix(kCrxAppPrefix);
373 if (app_name.substr(0, prefix.length()) != prefix) 376 if (app_name.substr(0, prefix.length()) != prefix)
374 return std::string(); 377 return std::string();
375 return app_name.substr(prefix.length()); 378 return app_name.substr(prefix.length());
376 } 379 }
377 380
378 void CreateShortcutsWithInfo( 381 void CreateShortcutsWithInfo(
379 ShortcutCreationReason reason, 382 ShortcutCreationReason reason,
380 const ShortcutLocations& locations, 383 const ShortcutLocations& locations,
381 const ShortcutInfo& shortcut_info, 384 scoped_ptr<ShortcutInfo> shortcut_info,
382 const extensions::FileHandlersInfo& file_handlers_info) { 385 const extensions::FileHandlersInfo& file_handlers_info) {
383 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
384 387
385 // If the shortcut is for an application shortcut with the new bookmark app 388 // If the shortcut is for an application shortcut with the new bookmark app
386 // flow disabled, there will be no corresponding extension. 389 // flow disabled, there will be no corresponding extension.
387 if (!shortcut_info.extension_id.empty()) { 390 if (!shortcut_info->extension_id.empty()) {
388 // It's possible for the extension to be deleted before we get here. 391 // It's possible for the extension to be deleted before we get here.
389 // For example, creating a hosted app from a website. Double check that 392 // For example, creating a hosted app from a website. Double check that
390 // it still exists. 393 // it still exists.
391 Profile* profile = g_browser_process->profile_manager()->GetProfileByPath( 394 Profile* profile = g_browser_process->profile_manager()->GetProfileByPath(
392 shortcut_info.profile_path); 395 shortcut_info->profile_path);
393 if (!profile) 396 if (!profile)
394 return; 397 return;
395 398
396 extensions::ExtensionRegistry* registry = 399 extensions::ExtensionRegistry* registry =
397 extensions::ExtensionRegistry::Get(profile); 400 extensions::ExtensionRegistry::Get(profile);
398 const extensions::Extension* extension = registry->GetExtensionById( 401 const extensions::Extension* extension = registry->GetExtensionById(
399 shortcut_info.extension_id, extensions::ExtensionRegistry::EVERYTHING); 402 shortcut_info->extension_id, extensions::ExtensionRegistry::EVERYTHING);
400 if (!extension) 403 if (!extension)
401 return; 404 return;
402 } 405 }
403 406
404 ScheduleCreatePlatformShortcut(reason, locations, shortcut_info, 407 ScheduleCreatePlatformShortcut(reason, locations, shortcut_info.Pass(),
405 file_handlers_info); 408 file_handlers_info);
406 } 409 }
407 410
408 void CreateNonAppShortcut(const ShortcutLocations& locations, 411 void CreateNonAppShortcut(const ShortcutLocations& locations,
409 const ShortcutInfo& shortcut_info) { 412 scoped_ptr<ShortcutInfo> shortcut_info) {
410 ScheduleCreatePlatformShortcut(SHORTCUT_CREATION_AUTOMATED, locations, 413 ScheduleCreatePlatformShortcut(SHORTCUT_CREATION_AUTOMATED, locations,
411 shortcut_info, extensions::FileHandlersInfo()); 414 shortcut_info.Pass(),
415 extensions::FileHandlersInfo());
412 } 416 }
413 417
414 void CreateShortcuts(ShortcutCreationReason reason, 418 void CreateShortcuts(ShortcutCreationReason reason,
415 const ShortcutLocations& locations, 419 const ShortcutLocations& locations,
416 Profile* profile, 420 Profile* profile,
417 const extensions::Extension* app) { 421 const extensions::Extension* app) {
418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
419 423
420 if (!ShouldCreateShortcutFor(reason, profile, app)) 424 if (!ShouldCreateShortcutFor(reason, profile, app))
421 return; 425 return;
422 426
423 GetInfoForApp( 427 GetInfoForApp(
424 app, profile, base::Bind(&CreateShortcutsWithInfo, reason, locations)); 428 app, profile, base::Bind(&CreateShortcutsWithInfo, reason, locations));
425 } 429 }
426 430
427 void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { 431 void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) {
428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
429 433
430 ShortcutInfo shortcut_info = 434 scoped_ptr<ShortcutInfo> shortcut_info(
431 ShortcutInfoForExtensionAndProfile(app, profile); 435 ShortcutInfoForExtensionAndProfile(app, profile));
436 base::FilePath shortcut_data_dir = GetShortcutDataDir(*shortcut_info);
432 BrowserThread::PostTask( 437 BrowserThread::PostTask(
433 BrowserThread::FILE, 438 BrowserThread::FILE, FROM_HERE,
434 FROM_HERE,
435 base::Bind(&web_app::internals::DeletePlatformShortcuts, 439 base::Bind(&web_app::internals::DeletePlatformShortcuts,
436 GetShortcutDataDir(shortcut_info), shortcut_info)); 440 shortcut_data_dir, base::Passed(&shortcut_info)));
437 } 441 }
438 442
439 void UpdateAllShortcuts(const base::string16& old_app_title, 443 void UpdateAllShortcuts(const base::string16& old_app_title,
440 Profile* profile, 444 Profile* profile,
441 const extensions::Extension* app) { 445 const extensions::Extension* app) {
442 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
443 447
444 GetInfoForApp(app, 448 GetInfoForApp(app,
445 profile, 449 profile,
446 base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); 450 base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 487
484 #if defined(OS_LINUX) 488 #if defined(OS_LINUX)
485 std::string GetWMClassFromAppName(std::string app_name) { 489 std::string GetWMClassFromAppName(std::string app_name) {
486 base::i18n::ReplaceIllegalCharactersInPath(&app_name, '_'); 490 base::i18n::ReplaceIllegalCharactersInPath(&app_name, '_');
487 base::TrimString(app_name, "_", &app_name); 491 base::TrimString(app_name, "_", &app_name);
488 return app_name; 492 return app_name;
489 } 493 }
490 #endif 494 #endif
491 495
492 } // namespace web_app 496 } // namespace web_app
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698