| 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/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/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/i18n/file_util_icu.h" | 10 #include "base/i18n/file_util_icu.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "url/url_constants.h" | 37 #include "url/url_constants.h" |
| 38 | 38 |
| 39 #if defined(OS_WIN) | 39 #if defined(OS_WIN) |
| 40 #include "ui/gfx/icon_util.h" | 40 #include "ui/gfx/icon_util.h" |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 using content::BrowserThread; | 43 using content::BrowserThread; |
| 44 | 44 |
| 45 namespace { | 45 namespace { |
| 46 | 46 |
| 47 typedef base::Callback<void(const web_app::ShortcutInfo&, | |
| 48 const extensions::FileHandlersInfo&)> InfoCallback; | |
| 49 | |
| 50 #if defined(OS_MACOSX) | 47 #if defined(OS_MACOSX) |
| 51 const int kDesiredSizes[] = {16, 32, 128, 256, 512}; | 48 const int kDesiredSizes[] = {16, 32, 128, 256, 512}; |
| 52 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | 49 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); |
| 53 #elif defined(OS_LINUX) | 50 #elif defined(OS_LINUX) |
| 54 // Linux supports icons of any size. FreeDesktop Icon Theme Specification states | 51 // Linux supports icons of any size. FreeDesktop Icon Theme Specification states |
| 55 // that "Minimally you should install a 48x48 icon in the hicolor theme." | 52 // that "Minimally you should install a 48x48 icon in the hicolor theme." |
| 56 const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; | 53 const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; |
| 57 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | 54 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); |
| 58 #elif defined(OS_WIN) | 55 #elif defined(OS_WIN) |
| 59 const int* kDesiredSizes = IconUtil::kIconDimensions; | 56 const int* kDesiredSizes = IconUtil::kIconDimensions; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 BrowserThread::PostTask( | 97 BrowserThread::PostTask( |
| 101 BrowserThread::FILE, | 98 BrowserThread::FILE, |
| 102 FROM_HERE, | 99 FROM_HERE, |
| 103 base::Bind(&web_app::internals::UpdatePlatformShortcuts, | 100 base::Bind(&web_app::internals::UpdatePlatformShortcuts, |
| 104 GetShortcutDataDir(shortcut_info), | 101 GetShortcutDataDir(shortcut_info), |
| 105 old_app_title, shortcut_info, file_handlers_info)); | 102 old_app_title, shortcut_info, file_handlers_info)); |
| 106 } | 103 } |
| 107 | 104 |
| 108 void OnImageLoaded(web_app::ShortcutInfo shortcut_info, | 105 void OnImageLoaded(web_app::ShortcutInfo shortcut_info, |
| 109 extensions::FileHandlersInfo file_handlers_info, | 106 extensions::FileHandlersInfo file_handlers_info, |
| 110 InfoCallback callback, | 107 web_app::InfoCallback callback, |
| 111 const gfx::ImageFamily& image_family) { | 108 const gfx::ImageFamily& image_family) { |
| 112 // If the image failed to load (e.g. if the resource being loaded was empty) | 109 // If the image failed to load (e.g. if the resource being loaded was empty) |
| 113 // use the standard application icon. | 110 // use the standard application icon. |
| 114 if (image_family.empty()) { | 111 if (image_family.empty()) { |
| 115 gfx::Image default_icon = | 112 gfx::Image default_icon = |
| 116 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); | 113 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); |
| 117 int size = kDesiredSizes[kNumDesiredSizes - 1]; | 114 int size = kDesiredSizes[kNumDesiredSizes - 1]; |
| 118 SkBitmap bmp = skia::ImageOperations::Resize( | 115 SkBitmap bmp = skia::ImageOperations::Resize( |
| 119 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, | 116 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, |
| 120 size, size); | 117 size, size); |
| 121 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); | 118 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); |
| 122 // We are on the UI thread, and this image is needed from the FILE thread, | 119 // We are on the UI thread, and this image is needed from the FILE thread, |
| 123 // for creating shortcut icon files. | 120 // for creating shortcut icon files. |
| 124 image_skia.MakeThreadSafe(); | 121 image_skia.MakeThreadSafe(); |
| 125 shortcut_info.favicon.Add(gfx::Image(image_skia)); | 122 shortcut_info.favicon.Add(gfx::Image(image_skia)); |
| 126 } else { | 123 } else { |
| 127 shortcut_info.favicon = image_family; | 124 shortcut_info.favicon = image_family; |
| 128 } | 125 } |
| 129 | 126 |
| 130 callback.Run(shortcut_info, file_handlers_info); | 127 callback.Run(shortcut_info, file_handlers_info); |
| 131 } | 128 } |
| 132 | 129 |
| 130 void IgnoreFileHandlersInfo( |
| 131 const web_app::ShortcutInfoCallback& shortcut_info_callback, |
| 132 const web_app::ShortcutInfo& shortcut_info, |
| 133 const extensions::FileHandlersInfo& file_handlers_info) { |
| 134 shortcut_info_callback.Run(shortcut_info); |
| 135 } |
| 136 |
| 137 } // namespace |
| 138 |
| 139 namespace web_app { |
| 140 |
| 141 // The following string is used to build the directory name for |
| 142 // shortcuts to chrome applications (the kind which are installed |
| 143 // from a CRX). Application shortcuts to URLs use the {host}_{path} |
| 144 // for the name of this directory. Hosts can't include an underscore. |
| 145 // By starting this string with an underscore, we ensure that there |
| 146 // are no naming conflicts. |
| 147 static const char kCrxAppPrefix[] = "_crx_"; |
| 148 |
| 149 namespace internals { |
| 150 |
| 133 void GetInfoForApp(const extensions::Extension* extension, | 151 void GetInfoForApp(const extensions::Extension* extension, |
| 134 Profile* profile, | 152 Profile* profile, |
| 135 const InfoCallback& callback) { | 153 const InfoCallback& callback) { |
| 136 web_app::ShortcutInfo shortcut_info = | 154 web_app::ShortcutInfo shortcut_info = |
| 137 web_app::ShortcutInfoForExtensionAndProfile(extension, profile); | 155 web_app::ShortcutInfoForExtensionAndProfile(extension, profile); |
| 138 const std::vector<extensions::FileHandlerInfo>* file_handlers = | 156 const std::vector<extensions::FileHandlerInfo>* file_handlers = |
| 139 extensions::FileHandlers::GetFileHandlers(extension); | 157 extensions::FileHandlers::GetFileHandlers(extension); |
| 140 extensions::FileHandlersInfo file_handlers_info = | 158 extensions::FileHandlersInfo file_handlers_info = |
| 141 file_handlers ? *file_handlers : extensions::FileHandlersInfo(); | 159 file_handlers ? *file_handlers : extensions::FileHandlersInfo(); |
| 142 | 160 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 | 196 |
| 179 // |info_list| may still be empty at this point, in which case | 197 // |info_list| may still be empty at this point, in which case |
| 180 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty | 198 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty |
| 181 // image and exit immediately. | 199 // image and exit immediately. |
| 182 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( | 200 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( |
| 183 extension, | 201 extension, |
| 184 info_list, | 202 info_list, |
| 185 base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); | 203 base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); |
| 186 } | 204 } |
| 187 | 205 |
| 188 void IgnoreFileHandlersInfo( | |
| 189 const web_app::ShortcutInfoCallback& shortcut_info_callback, | |
| 190 const web_app::ShortcutInfo& shortcut_info, | |
| 191 const extensions::FileHandlersInfo& file_handlers_info) { | |
| 192 shortcut_info_callback.Run(shortcut_info); | |
| 193 } | |
| 194 | |
| 195 } // namespace | |
| 196 | |
| 197 namespace web_app { | |
| 198 | |
| 199 // The following string is used to build the directory name for | |
| 200 // shortcuts to chrome applications (the kind which are installed | |
| 201 // from a CRX). Application shortcuts to URLs use the {host}_{path} | |
| 202 // for the name of this directory. Hosts can't include an underscore. | |
| 203 // By starting this string with an underscore, we ensure that there | |
| 204 // are no naming conflicts. | |
| 205 static const char* kCrxAppPrefix = "_crx_"; | |
| 206 | |
| 207 namespace internals { | |
| 208 | |
| 209 base::FilePath GetSanitizedFileName(const base::string16& name) { | 206 base::FilePath GetSanitizedFileName(const base::string16& name) { |
| 210 #if defined(OS_WIN) | 207 #if defined(OS_WIN) |
| 211 base::string16 file_name = name; | 208 base::string16 file_name = name; |
| 212 #else | 209 #else |
| 213 std::string file_name = base::UTF16ToUTF8(name); | 210 std::string file_name = base::UTF16ToUTF8(name); |
| 214 #endif | 211 #endif |
| 215 file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); | 212 file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); |
| 216 return base::FilePath(file_name); | 213 return base::FilePath(file_name); |
| 217 } | 214 } |
| 218 | 215 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 shortcut_info.extension_path = app->path(); | 280 shortcut_info.extension_path = app->path(); |
| 284 shortcut_info.profile_path = profile->GetPath(); | 281 shortcut_info.profile_path = profile->GetPath(); |
| 285 shortcut_info.profile_name = | 282 shortcut_info.profile_name = |
| 286 profile->GetPrefs()->GetString(prefs::kProfileName); | 283 profile->GetPrefs()->GetString(prefs::kProfileName); |
| 287 return shortcut_info; | 284 return shortcut_info; |
| 288 } | 285 } |
| 289 | 286 |
| 290 void UpdateShortcutInfoAndIconForApp(const extensions::Extension* extension, | 287 void UpdateShortcutInfoAndIconForApp(const extensions::Extension* extension, |
| 291 Profile* profile, | 288 Profile* profile, |
| 292 const ShortcutInfoCallback& callback) { | 289 const ShortcutInfoCallback& callback) { |
| 293 GetInfoForApp(extension, | 290 web_app::internals::GetInfoForApp( |
| 294 profile, | 291 extension, profile, base::Bind(&IgnoreFileHandlersInfo, callback)); |
| 295 base::Bind(&IgnoreFileHandlersInfo, callback)); | |
| 296 } | 292 } |
| 297 | 293 |
| 298 bool ShouldCreateShortcutFor(Profile* profile, | 294 bool ShouldCreateShortcutFor(Profile* profile, |
| 299 const extensions::Extension* extension) { | 295 const extensions::Extension* extension) { |
| 300 return extension->is_platform_app() && | 296 return extension->is_platform_app() && |
| 301 extension->location() != extensions::Manifest::COMPONENT && | 297 extension->location() != extensions::Manifest::COMPONENT && |
| 302 extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile); | 298 extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile); |
| 303 } | 299 } |
| 304 | 300 |
| 305 base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, | 301 base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 | 376 |
| 381 void CreateShortcuts(ShortcutCreationReason reason, | 377 void CreateShortcuts(ShortcutCreationReason reason, |
| 382 const ShortcutLocations& locations, | 378 const ShortcutLocations& locations, |
| 383 Profile* profile, | 379 Profile* profile, |
| 384 const extensions::Extension* app) { | 380 const extensions::Extension* app) { |
| 385 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 386 | 382 |
| 387 if (!ShouldCreateShortcutFor(profile, app)) | 383 if (!ShouldCreateShortcutFor(profile, app)) |
| 388 return; | 384 return; |
| 389 | 385 |
| 390 GetInfoForApp(app, | 386 internals::GetInfoForApp( |
| 391 profile, | 387 app, profile, base::Bind(&CreateShortcutsWithInfo, reason, locations)); |
| 392 base::Bind(&CreateShortcutsWithInfo, reason, locations)); | |
| 393 } | 388 } |
| 394 | 389 |
| 395 void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { | 390 void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { |
| 396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 397 | 392 |
| 398 ShortcutInfo shortcut_info = | 393 ShortcutInfo shortcut_info = |
| 399 ShortcutInfoForExtensionAndProfile(app, profile); | 394 ShortcutInfoForExtensionAndProfile(app, profile); |
| 400 BrowserThread::PostTask( | 395 BrowserThread::PostTask( |
| 401 BrowserThread::FILE, | 396 BrowserThread::FILE, |
| 402 FROM_HERE, | 397 FROM_HERE, |
| 403 base::Bind(&web_app::internals::DeletePlatformShortcuts, | 398 base::Bind(&web_app::internals::DeletePlatformShortcuts, |
| 404 GetShortcutDataDir(shortcut_info), shortcut_info)); | 399 GetShortcutDataDir(shortcut_info), shortcut_info)); |
| 405 } | 400 } |
| 406 | 401 |
| 407 void UpdateAllShortcuts(const base::string16& old_app_title, | 402 void UpdateAllShortcuts(const base::string16& old_app_title, |
| 408 Profile* profile, | 403 Profile* profile, |
| 409 const extensions::Extension* app) { | 404 const extensions::Extension* app) { |
| 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 411 | 406 |
| 412 GetInfoForApp(app, | 407 internals::GetInfoForApp( |
| 413 profile, | 408 app, |
| 414 base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); | 409 profile, |
| 410 base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); |
| 415 } | 411 } |
| 416 | 412 |
| 417 bool IsValidUrl(const GURL& url) { | 413 bool IsValidUrl(const GURL& url) { |
| 418 static const char* const kValidUrlSchemes[] = { | 414 static const char* const kValidUrlSchemes[] = { |
| 419 url::kFileScheme, | 415 url::kFileScheme, |
| 420 url::kFileSystemScheme, | 416 url::kFileSystemScheme, |
| 421 url::kFtpScheme, | 417 url::kFtpScheme, |
| 422 url::kHttpScheme, | 418 url::kHttpScheme, |
| 423 url::kHttpsScheme, | 419 url::kHttpsScheme, |
| 424 extensions::kExtensionScheme, | 420 extensions::kExtensionScheme, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 451 | 447 |
| 452 #if defined(OS_LINUX) | 448 #if defined(OS_LINUX) |
| 453 std::string GetWMClassFromAppName(std::string app_name) { | 449 std::string GetWMClassFromAppName(std::string app_name) { |
| 454 file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); | 450 file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); |
| 455 base::TrimString(app_name, "_", &app_name); | 451 base::TrimString(app_name, "_", &app_name); |
| 456 return app_name; | 452 return app_name; |
| 457 } | 453 } |
| 458 #endif | 454 #endif |
| 459 | 455 |
| 460 } // namespace web_app | 456 } // namespace web_app |
| OLD | NEW |