| 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 24 matching lines...) Expand all Loading... |
| 35 #include "ui/gfx/image/image_skia.h" | 35 #include "ui/gfx/image/image_skia.h" |
| 36 | 36 |
| 37 #if defined(OS_WIN) | 37 #if defined(OS_WIN) |
| 38 #include "ui/gfx/icon_util.h" | 38 #include "ui/gfx/icon_util.h" |
| 39 #endif | 39 #endif |
| 40 | 40 |
| 41 using content::BrowserThread; | 41 using content::BrowserThread; |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 | 44 |
| 45 typedef base::Callback<void(const web_app::ShortcutInfo&, | |
| 46 const extensions::FileHandlersInfo&)> InfoCallback; | |
| 47 | |
| 48 #if defined(OS_MACOSX) | 45 #if defined(OS_MACOSX) |
| 49 const int kDesiredSizes[] = {16, 32, 128, 256, 512}; | 46 const int kDesiredSizes[] = {16, 32, 128, 256, 512}; |
| 50 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | 47 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); |
| 51 #elif defined(OS_LINUX) | 48 #elif defined(OS_LINUX) |
| 52 // Linux supports icons of any size. FreeDesktop Icon Theme Specification states | 49 // Linux supports icons of any size. FreeDesktop Icon Theme Specification states |
| 53 // that "Minimally you should install a 48x48 icon in the hicolor theme." | 50 // that "Minimally you should install a 48x48 icon in the hicolor theme." |
| 54 const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; | 51 const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; |
| 55 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | 52 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); |
| 56 #elif defined(OS_WIN) | 53 #elif defined(OS_WIN) |
| 57 const int* kDesiredSizes = IconUtil::kIconDimensions; | 54 const int* kDesiredSizes = IconUtil::kIconDimensions; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 const extensions::FileHandlersInfo& file_handlers_info) { | 124 const extensions::FileHandlersInfo& file_handlers_info) { |
| 128 BrowserThread::PostTask( | 125 BrowserThread::PostTask( |
| 129 BrowserThread::FILE, | 126 BrowserThread::FILE, |
| 130 FROM_HERE, | 127 FROM_HERE, |
| 131 base::Bind(&UpdateShortcutsOnFileThread, | 128 base::Bind(&UpdateShortcutsOnFileThread, |
| 132 old_app_title, shortcut_info, file_handlers_info)); | 129 old_app_title, shortcut_info, file_handlers_info)); |
| 133 } | 130 } |
| 134 | 131 |
| 135 void OnImageLoaded(web_app::ShortcutInfo shortcut_info, | 132 void OnImageLoaded(web_app::ShortcutInfo shortcut_info, |
| 136 extensions::FileHandlersInfo file_handlers_info, | 133 extensions::FileHandlersInfo file_handlers_info, |
| 137 InfoCallback callback, | 134 web_app::InfoCallback callback, |
| 138 const gfx::ImageFamily& image_family) { | 135 const gfx::ImageFamily& image_family) { |
| 139 // If the image failed to load (e.g. if the resource being loaded was empty) | 136 // If the image failed to load (e.g. if the resource being loaded was empty) |
| 140 // use the standard application icon. | 137 // use the standard application icon. |
| 141 if (image_family.empty()) { | 138 if (image_family.empty()) { |
| 142 gfx::Image default_icon = | 139 gfx::Image default_icon = |
| 143 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); | 140 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); |
| 144 int size = kDesiredSizes[kNumDesiredSizes - 1]; | 141 int size = kDesiredSizes[kNumDesiredSizes - 1]; |
| 145 SkBitmap bmp = skia::ImageOperations::Resize( | 142 SkBitmap bmp = skia::ImageOperations::Resize( |
| 146 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, | 143 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, |
| 147 size, size); | 144 size, size); |
| 148 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); | 145 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); |
| 149 // We are on the UI thread, and this image is needed from the FILE thread, | 146 // We are on the UI thread, and this image is needed from the FILE thread, |
| 150 // for creating shortcut icon files. | 147 // for creating shortcut icon files. |
| 151 image_skia.MakeThreadSafe(); | 148 image_skia.MakeThreadSafe(); |
| 152 shortcut_info.favicon.Add(gfx::Image(image_skia)); | 149 shortcut_info.favicon.Add(gfx::Image(image_skia)); |
| 153 } else { | 150 } else { |
| 154 shortcut_info.favicon = image_family; | 151 shortcut_info.favicon = image_family; |
| 155 } | 152 } |
| 156 | 153 |
| 157 callback.Run(shortcut_info, file_handlers_info); | 154 callback.Run(shortcut_info, file_handlers_info); |
| 158 } | 155 } |
| 159 | 156 |
| 157 void IgnoreFileHandlersInfo( |
| 158 const web_app::ShortcutInfoCallback& shortcut_info_callback, |
| 159 const web_app::ShortcutInfo& shortcut_info, |
| 160 const extensions::FileHandlersInfo& file_handlers_info) { |
| 161 shortcut_info_callback.Run(shortcut_info); |
| 162 } |
| 163 |
| 164 } // namespace |
| 165 |
| 166 namespace web_app { |
| 167 |
| 168 // The following string is used to build the directory name for |
| 169 // shortcuts to chrome applications (the kind which are installed |
| 170 // from a CRX). Application shortcuts to URLs use the {host}_{path} |
| 171 // for the name of this directory. Hosts can't include an underscore. |
| 172 // By starting this string with an underscore, we ensure that there |
| 173 // are no naming conflicts. |
| 174 static const char* kCrxAppPrefix = "_crx_"; |
| 175 |
| 176 namespace internals { |
| 177 |
| 160 void GetInfoForApp(const extensions::Extension* extension, | 178 void GetInfoForApp(const extensions::Extension* extension, |
| 161 Profile* profile, | 179 Profile* profile, |
| 162 const InfoCallback& callback) { | 180 const InfoCallback& callback) { |
| 163 web_app::ShortcutInfo shortcut_info = | 181 web_app::ShortcutInfo shortcut_info = |
| 164 web_app::ShortcutInfoForExtensionAndProfile(extension, profile); | 182 web_app::ShortcutInfoForExtensionAndProfile(extension, profile); |
| 165 extensions::FileHandlersInfo file_handlers_info; | 183 extensions::FileHandlersInfo file_handlers_info; |
| 166 const std::vector<extensions::FileHandlerInfo>* file_handlers = | 184 const std::vector<extensions::FileHandlerInfo>* file_handlers = |
| 167 extensions::FileHandlers::GetFileHandlers(extension); | 185 extensions::FileHandlers::GetFileHandlers(extension); |
| 168 if (file_handlers) | 186 if (file_handlers) |
| 169 file_handlers_info.handlers = *file_handlers; | 187 file_handlers_info.handlers = *file_handlers; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 | 224 |
| 207 // |info_list| may still be empty at this point, in which case | 225 // |info_list| may still be empty at this point, in which case |
| 208 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty | 226 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty |
| 209 // image and exit immediately. | 227 // image and exit immediately. |
| 210 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( | 228 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( |
| 211 extension, | 229 extension, |
| 212 info_list, | 230 info_list, |
| 213 base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); | 231 base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); |
| 214 } | 232 } |
| 215 | 233 |
| 216 void IgnoreFileHandlersInfo( | |
| 217 const web_app::ShortcutInfoCallback& shortcut_info_callback, | |
| 218 const web_app::ShortcutInfo& shortcut_info, | |
| 219 const extensions::FileHandlersInfo& file_handlers_info) { | |
| 220 shortcut_info_callback.Run(shortcut_info); | |
| 221 } | |
| 222 | |
| 223 } // namespace | |
| 224 | |
| 225 namespace web_app { | |
| 226 | |
| 227 // The following string is used to build the directory name for | |
| 228 // shortcuts to chrome applications (the kind which are installed | |
| 229 // from a CRX). Application shortcuts to URLs use the {host}_{path} | |
| 230 // for the name of this directory. Hosts can't include an underscore. | |
| 231 // By starting this string with an underscore, we ensure that there | |
| 232 // are no naming conflicts. | |
| 233 static const char* kCrxAppPrefix = "_crx_"; | |
| 234 | |
| 235 namespace internals { | |
| 236 | |
| 237 base::FilePath GetSanitizedFileName(const base::string16& name) { | 234 base::FilePath GetSanitizedFileName(const base::string16& name) { |
| 238 #if defined(OS_WIN) | 235 #if defined(OS_WIN) |
| 239 base::string16 file_name = name; | 236 base::string16 file_name = name; |
| 240 #else | 237 #else |
| 241 std::string file_name = base::UTF16ToUTF8(name); | 238 std::string file_name = base::UTF16ToUTF8(name); |
| 242 #endif | 239 #endif |
| 243 file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); | 240 file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); |
| 244 return base::FilePath(file_name); | 241 return base::FilePath(file_name); |
| 245 } | 242 } |
| 246 | 243 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 shortcut_info.profile_path = profile->GetPath(); | 309 shortcut_info.profile_path = profile->GetPath(); |
| 313 shortcut_info.profile_name = | 310 shortcut_info.profile_name = |
| 314 profile->GetPrefs()->GetString(prefs::kProfileName); | 311 profile->GetPrefs()->GetString(prefs::kProfileName); |
| 315 return shortcut_info; | 312 return shortcut_info; |
| 316 } | 313 } |
| 317 | 314 |
| 318 void UpdateShortcutInfoAndIconForApp( | 315 void UpdateShortcutInfoAndIconForApp( |
| 319 const extensions::Extension* extension, | 316 const extensions::Extension* extension, |
| 320 Profile* profile, | 317 Profile* profile, |
| 321 const web_app::ShortcutInfoCallback& callback) { | 318 const web_app::ShortcutInfoCallback& callback) { |
| 322 GetInfoForApp(extension, | 319 internals::GetInfoForApp(extension, |
| 323 profile, | 320 profile, |
| 324 base::Bind(&IgnoreFileHandlersInfo, callback)); | 321 base::Bind(&IgnoreFileHandlersInfo, callback)); |
| 325 } | 322 } |
| 326 | 323 |
| 327 base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, | 324 base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, |
| 328 const std::string& extension_id, | 325 const std::string& extension_id, |
| 329 const GURL& url) { | 326 const GURL& url) { |
| 330 DCHECK(!profile_path.empty()); | 327 DCHECK(!profile_path.empty()); |
| 331 base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); | 328 base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); |
| 332 | 329 |
| 333 if (!extension_id.empty()) { | 330 if (!extension_id.empty()) { |
| 334 return app_data_dir.AppendASCII( | 331 return app_data_dir.AppendASCII( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 reason, locations, shortcut_info)); | 402 reason, locations, shortcut_info)); |
| 406 } | 403 } |
| 407 | 404 |
| 408 void CreateShortcuts( | 405 void CreateShortcuts( |
| 409 ShortcutCreationReason reason, | 406 ShortcutCreationReason reason, |
| 410 const web_app::ShortcutLocations& locations, | 407 const web_app::ShortcutLocations& locations, |
| 411 Profile* profile, | 408 Profile* profile, |
| 412 const extensions::Extension* app) { | 409 const extensions::Extension* app) { |
| 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 414 | 411 |
| 415 GetInfoForApp(app, | 412 internals::GetInfoForApp( |
| 416 profile, | 413 app, |
| 417 base::Bind(&CreateShortcutsWithInfo, reason, locations)); | 414 profile, |
| 415 base::Bind(&CreateShortcutsWithInfo, reason, locations)); |
| 418 } | 416 } |
| 419 | 417 |
| 420 void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { | 418 void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { |
| 421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 422 | 420 |
| 423 BrowserThread::PostTask( | 421 BrowserThread::PostTask( |
| 424 BrowserThread::FILE, | 422 BrowserThread::FILE, |
| 425 FROM_HERE, | 423 FROM_HERE, |
| 426 base::Bind(&DeleteShortcutsOnFileThread, | 424 base::Bind(&DeleteShortcutsOnFileThread, |
| 427 web_app::ShortcutInfoForExtensionAndProfile(app, profile))); | 425 web_app::ShortcutInfoForExtensionAndProfile(app, profile))); |
| 428 } | 426 } |
| 429 | 427 |
| 430 void UpdateAllShortcuts(const base::string16& old_app_title, | 428 void UpdateAllShortcuts(const base::string16& old_app_title, |
| 431 Profile* profile, | 429 Profile* profile, |
| 432 const extensions::Extension* app) { | 430 const extensions::Extension* app) { |
| 433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 434 | 432 |
| 435 GetInfoForApp(app, | 433 internals::GetInfoForApp( |
| 436 profile, | 434 app, |
| 437 base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); | 435 profile, |
| 436 base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); |
| 438 } | 437 } |
| 439 | 438 |
| 440 bool IsValidUrl(const GURL& url) { | 439 bool IsValidUrl(const GURL& url) { |
| 441 static const char* const kValidUrlSchemes[] = { | 440 static const char* const kValidUrlSchemes[] = { |
| 442 content::kFileScheme, | 441 content::kFileScheme, |
| 443 content::kFileSystemScheme, | 442 content::kFileSystemScheme, |
| 444 content::kFtpScheme, | 443 content::kFtpScheme, |
| 445 content::kHttpScheme, | 444 content::kHttpScheme, |
| 446 content::kHttpsScheme, | 445 content::kHttpsScheme, |
| 447 extensions::kExtensionScheme, | 446 extensions::kExtensionScheme, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 474 | 473 |
| 475 #if defined(OS_LINUX) | 474 #if defined(OS_LINUX) |
| 476 std::string GetWMClassFromAppName(std::string app_name) { | 475 std::string GetWMClassFromAppName(std::string app_name) { |
| 477 file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); | 476 file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); |
| 478 base::TrimString(app_name, "_", &app_name); | 477 base::TrimString(app_name, "_", &app_name); |
| 479 return app_name; | 478 return app_name; |
| 480 } | 479 } |
| 481 #endif | 480 #endif |
| 482 | 481 |
| 483 } // namespace web_app | 482 } // namespace web_app |
| OLD | NEW |