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

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

Issue 482003: Get web app icon via FavIconHelper and auto repair/update (Closed)
Patch Set: miranda's review 1 Created 11 years 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
« no previous file with comments | « chrome/browser/web_applications/web_app.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 #if defined(OS_WIN)
8 #include <ShellAPI.h>
9 #endif // defined(OS_WIN)
10
7 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/md5.h"
8 #include "base/message_loop.h" 13 #include "base/message_loop.h"
9 #include "base/path_service.h" 14 #include "base/path_service.h"
10 #include "base/thread.h" 15 #include "base/thread.h"
16 #include "base/scoped_ptr.h"
11 #include "base/string_util.h" 17 #include "base/string_util.h"
12 #include "chrome/browser/browser_process.h" 18 #include "chrome/browser/chrome_thread.h"
19 #include "chrome/browser/profile.h"
20 #include "chrome/browser/tab_contents/tab_contents.h"
21 #include "chrome/common/chrome_constants.h"
13 #include "chrome/common/chrome_paths.h" 22 #include "chrome/common/chrome_paths.h"
14 #include "chrome/common/chrome_plugin_util.h" 23 #include "chrome/common/chrome_plugin_util.h"
24 #include "chrome/common/notification_registrar.h"
25 #include "chrome/common/notification_service.h"
15 #include "chrome/common/url_constants.h" 26 #include "chrome/common/url_constants.h"
27 #include "webkit/glue/dom_operations.h"
16 28
17 #if defined(OS_WIN) 29 #if defined(OS_WIN)
18 #include "app/gfx/icon_util.h" 30 #include "app/gfx/icon_util.h"
19 #include "base/win_util.h" 31 #include "base/win_util.h"
20 #endif // defined(OS_WIN) 32 #endif // defined(OS_WIN)
21 33
22 namespace { 34 namespace {
23 35
36 const FilePath::CharType kIconChecksumFileExt[] = FILE_PATH_LITERAL(".ico.md5");
37
24 // Returns true if |ch| is in visible ASCII range and not one of 38 // Returns true if |ch| is in visible ASCII range and not one of
25 // "/ \ : * ? " < > | ; ,". 39 // "/ \ : * ? " < > | ; ,".
26 bool IsValidFilePathChar(char16 c) { 40 bool IsValidFilePathChar(char16 c) {
27 if (c < 32) 41 if (c < 32)
28 return false; 42 return false;
29 43
30 switch (c) { 44 switch (c) {
31 case '/': 45 case '/':
32 case '\\': 46 case '\\':
33 case ':': 47 case ':':
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 95
82 return FilePath(host).Append(scheme_port); 96 return FilePath(host).Append(scheme_port);
83 } 97 }
84 98
85 // Returns data directory for given web app url 99 // Returns data directory for given web app url
86 FilePath GetWebAppDataDirectory(const FilePath& root_dir, 100 FilePath GetWebAppDataDirectory(const FilePath& root_dir,
87 const GURL& url) { 101 const GURL& url) {
88 return root_dir.Append(GetWebAppDir(url)); 102 return root_dir.Append(GetWebAppDir(url));
89 } 103 }
90 104
105 // Predicator for sorting images from largest to smallest.
106 bool IconPrecedes(
107 const webkit_glue::WebApplicationInfo::IconInfo& left,
108 const webkit_glue::WebApplicationInfo::IconInfo& right) {
109 return left.width < right.width;
110 }
111
112 // Calculates image checksum using MD5.
113 void GetImageCheckSum(const SkBitmap& image, MD5Digest* digest) {
114 DCHECK(digest);
115
116 SkAutoLockPixels image_lock(image);
117 MD5Sum(image.getPixels(), image.getSize(), digest);
118 }
119
120 #if defined(OS_WIN)
121 // Saves |image| as an |icon_file| with the checksum.
122 bool SaveIconWithCheckSum(const FilePath& icon_file, const SkBitmap& image) {
123 if (!IconUtil::CreateIconFileFromSkBitmap(image, icon_file.value()))
124 return false;
125
126 MD5Digest digest;
127 GetImageCheckSum(image, &digest);
128
129 FilePath cheksum_file(icon_file.ReplaceExtension(kIconChecksumFileExt));
130 return file_util::WriteFile(cheksum_file,
131 reinterpret_cast<const char*>(&digest),
132 sizeof(digest)) == sizeof(digest);
133 }
134
135 // Returns true if |icon_file| is missing or different from |image|.
136 bool ShouldUpdateIcon(const FilePath& icon_file, const SkBitmap& image) {
137 FilePath checksum_file(icon_file.ReplaceExtension(kIconChecksumFileExt));
138
139 // Returns true if icon_file or checksum file is missing.
140 if (!file_util::PathExists(icon_file) ||
141 !file_util::PathExists(checksum_file))
142 return true;
143
144 MD5Digest persisted_image_checksum;
145 if (sizeof(persisted_image_checksum) != file_util::ReadFile(checksum_file,
146 reinterpret_cast<char*>(&persisted_image_checksum),
147 sizeof(persisted_image_checksum)))
148 return true;
149
150 MD5Digest downloaded_image_checksum;
151 GetImageCheckSum(image, &downloaded_image_checksum);
152
153 // Update icon if checksums are not equal.
154 return memcmp(&persisted_image_checksum, &downloaded_image_checksum,
155 sizeof(MD5Digest)) != 0;
156 }
157
158 // Saves |image| to |icon_file| if the file is outdated and refresh shell's
159 // icon cache to ensure correct icon is displayed. Returns true if icon_file
160 // is up to date or successfully updated.
161 bool CheckAndSaveIcon(const FilePath& icon_file, const SkBitmap& image) {
162 if (ShouldUpdateIcon(icon_file, image)) {
163 if (SaveIconWithCheckSum(icon_file, image)) {
164 // Refresh shell's icon cache. This call is quite disruptive as user would
165 // see explorer rebuilding the icon cache. It would be great that we find
166 // a better way to achieve this.
167 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT,
168 NULL, NULL);
169 } else {
170 return false;
171 }
172 }
173
174 return true;
175 }
176
177 #endif // defined(OS_WIN)
178
91 // Represents a task that creates web application shortcut. This runs on 179 // Represents a task that creates web application shortcut. This runs on
92 // file thread and schedules the callback (if any) on the calling thread 180 // file thread and schedules the callback (if any) on the calling thread
93 // when finished (either success or failure). 181 // when finished (either success or failure).
94 class CreateShortcutTask : public Task { 182 class CreateShortcutTask : public Task {
95 public: 183 public:
96 CreateShortcutTask(const FilePath& root_dir, 184 CreateShortcutTask(const FilePath& root_dir,
97 const ShellIntegration::ShortcutInfo& shortcut_info, 185 const ShellIntegration::ShortcutInfo& shortcut_info,
98 web_app::CreateShortcutCallback* callback); 186 web_app::CreateShortcutCallback* callback);
99 187
100 private: 188 private:
(...skipping 14 matching lines...) Expand all
115 web_app::CreateShortcutCallback* callback_; 203 web_app::CreateShortcutCallback* callback_;
116 bool success_; 204 bool success_;
117 }; 205 };
118 206
119 // Overridden from Task: 207 // Overridden from Task:
120 virtual void Run(); 208 virtual void Run();
121 209
122 // Returns true if shortcut is created successfully. 210 // Returns true if shortcut is created successfully.
123 bool CreateShortcut(); 211 bool CreateShortcut();
124 212
125 // Path to store persisted data for web_app. 213 // Path to store persisted data for web app.
126 FilePath web_app_path_; 214 FilePath web_app_path_;
127 215
128 // Our copy of short cut data. 216 // Our copy of short cut data.
129 ShellIntegration::ShortcutInfo shortcut_info_; 217 ShellIntegration::ShortcutInfo shortcut_info_;
130 218
131 // Callback when task is finished. 219 // Callback when task is finished.
132 web_app::CreateShortcutCallback* callback_; 220 web_app::CreateShortcutCallback* callback_;
133 MessageLoop* message_loop_; 221 MessageLoop* message_loop_;
222
223 DISALLOW_COPY_AND_ASSIGN(CreateShortcutTask);
134 }; 224 };
135 225
136 CreateShortcutTask::CreateShortcutTask( 226 CreateShortcutTask::CreateShortcutTask(
137 const FilePath& root_dir, 227 const FilePath& root_dir,
138 const ShellIntegration::ShortcutInfo& shortcut_info, 228 const ShellIntegration::ShortcutInfo& shortcut_info,
139 web_app::CreateShortcutCallback* callback) 229 web_app::CreateShortcutCallback* callback)
140 : web_app_path_(GetWebAppDataDirectory(root_dir, shortcut_info.url)), 230 : web_app_path_(GetWebAppDataDirectory(root_dir, shortcut_info.url)),
141 shortcut_info_(shortcut_info), 231 shortcut_info_(shortcut_info),
142 callback_(callback), 232 callback_(callback),
143 message_loop_(MessageLoop::current()) { 233 message_loop_(MessageLoop::current()) {
(...skipping 25 matching lines...) Expand all
169 { 259 {
170 shortcut_info_.create_on_desktop, 260 shortcut_info_.create_on_desktop,
171 chrome::DIR_USER_DESKTOP, 261 chrome::DIR_USER_DESKTOP,
172 NULL 262 NULL
173 }, { 263 }, {
174 shortcut_info_.create_in_applications_menu, 264 shortcut_info_.create_in_applications_menu,
175 base::DIR_START_MENU, 265 base::DIR_START_MENU,
176 NULL 266 NULL
177 }, { 267 }, {
178 shortcut_info_.create_in_quick_launch_bar, 268 shortcut_info_.create_in_quick_launch_bar,
179 // For Win7, create_in_quick_launch_bar means pining to taskbar. Use 269 // For Win7, create_in_quick_launch_bar means pinning to taskbar. Use
180 // base::PATH_START as a flag for this case. 270 // base::PATH_START as a flag for this case.
181 (win_util::GetWinVersion() >= win_util::WINVERSION_WIN7) ? 271 (win_util::GetWinVersion() >= win_util::WINVERSION_WIN7) ?
182 base::PATH_START : base::DIR_APP_DATA, 272 base::PATH_START : base::DIR_APP_DATA,
183 (win_util::GetWinVersion() >= win_util::WINVERSION_WIN7) ? 273 (win_util::GetWinVersion() >= win_util::WINVERSION_WIN7) ?
184 NULL : L"Microsoft\\Internet Explorer\\Quick Launch" 274 NULL : L"Microsoft\\Internet Explorer\\Quick Launch"
185 } 275 }
186 }; 276 };
187 277
188 // Populate shortcut_paths. 278 // Populate shortcut_paths.
189 for (int i = 0; i < arraysize(locations); ++i) { 279 for (int i = 0; i < arraysize(locations); ++i) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 NOTREACHED(); 319 NOTREACHED();
230 return false; 320 return false;
231 } 321 }
232 322
233 // Generates file name to use with persisted ico and shortcut file. 323 // Generates file name to use with persisted ico and shortcut file.
234 FilePath file_name = GetSanitizedFileName(shortcut_info_.title); 324 FilePath file_name = GetSanitizedFileName(shortcut_info_.title);
235 325
236 // Creates an ico file to use with shortcut. 326 // Creates an ico file to use with shortcut.
237 FilePath icon_file = web_app_path_.Append(file_name).ReplaceExtension( 327 FilePath icon_file = web_app_path_.Append(file_name).ReplaceExtension(
238 FILE_PATH_LITERAL(".ico")); 328 FILE_PATH_LITERAL(".ico"));
239 if (!IconUtil::CreateIconFileFromSkBitmap(shortcut_info_.favicon, 329 if (!CheckAndSaveIcon(icon_file, shortcut_info_.favicon)) {
240 icon_file.value())) {
241 NOTREACHED(); 330 NOTREACHED();
242 return false; 331 return false;
243 } 332 }
244 333
245 std::wstring chrome_exe; 334 std::wstring chrome_exe;
246 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 335 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
247 NOTREACHED(); 336 NOTREACHED();
248 return false; 337 return false;
249 } 338 }
250 339
(...skipping 30 matching lines...) Expand all
281 success &= file_util::TaskbarPinShortcutLink(shortcut_file.value().c_str()); 370 success &= file_util::TaskbarPinShortcutLink(shortcut_file.value().c_str());
282 } 371 }
283 372
284 return success; 373 return success;
285 #else 374 #else
286 NOTIMPLEMENTED(); 375 NOTIMPLEMENTED();
287 return false; 376 return false;
288 #endif 377 #endif
289 } 378 }
290 379
380 #if defined(OS_WIN)
381 // UpdateShortcutWorker holds all context data needed for update shortcut.
382 // It schedules a pre-update check to find all shortcuts that needs to be
383 // updated. If there are such shortcuts, it schedules icon download and
384 // update them when icons are downloaded. It observes TAB_CLOSING notification
385 // and cancels all the work when the underlying tab is closing.
386 class UpdateShortcutWorker : public NotificationObserver {
387 public:
388 explicit UpdateShortcutWorker(TabContents* tab_contents);
389
390 void Run();
391
392 private:
393 // Overridden from NotificationObserver:
394 virtual void Observe(NotificationType type,
395 const NotificationSource& source,
396 const NotificationDetails& details);
397
398 // Downloads icon via TabContents.
399 void DownloadIcon();
400
401 // Callback when icon downloaded.
402 void OnIconDownloaded(int download_id, bool errored, const SkBitmap& image);
403
404 // Checks if shortcuts exists on desktop, start menu and quick launch.
405 void CheckExistingShortcuts();
406
407 // Update shortcut files and icons.
408 void UpdateShortcuts();
409 void UpdateShortcutsOnFileThread();
410
411 // Callback after shortcuts are updated.
412 void OnShortcutsUpdated(bool);
413
414 // Deletes the worker on UI thread where it gets created.
415 void DeleteMe();
416 void DeleteMeOnUIThread();
417
418 NotificationRegistrar registrar_;
419
420 // Underlying TabContents whose shortcuts will be updated.
421 TabContents* tab_contents_;
422
423 // Icons info from tab_contents_'s web app data.
424 web_app::IconInfoList unprocessed_icons_;
425
426 // Cached shortcut data from the tab_contents_.
427 ShellIntegration::ShortcutInfo shortcut_info_;
428
429 // Root dir of web app data.
430 FilePath root_dir_;
431
432 // File name of shortcut/ico file based on app title.
433 FilePath file_name_;
434
435 // Existing shortcuts.
436 std::vector<FilePath> shortcut_files_;
437
438 DISALLOW_COPY_AND_ASSIGN(UpdateShortcutWorker);
439 };
440
441 UpdateShortcutWorker::UpdateShortcutWorker(TabContents* tab_contents)
442 : tab_contents_(tab_contents),
443 root_dir_(web_app::GetDataDir(tab_contents->profile())) {
444 web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_);
445 web_app::GetIconsInfo(tab_contents_->web_app_info(), &unprocessed_icons_);
446 file_name_ = GetSanitizedFileName(shortcut_info_.title);
447
448 registrar_.Add(this, NotificationType::TAB_CLOSING,
449 Source<NavigationController>(&tab_contents_->controller()));
450 }
451
452 void UpdateShortcutWorker::Run() {
453 // Starting by downloading app icon.
454 DownloadIcon();
455 }
456
457 void UpdateShortcutWorker::Observe(NotificationType type,
458 const NotificationSource& source,
459 const NotificationDetails& details) {
460 if (type == NotificationType::TAB_CLOSING &&
461 Source<NavigationController>(source).ptr() ==
462 &tab_contents_->controller()) {
463 // Underlying tab is closing.
464 tab_contents_ = NULL;
465 }
466 }
467
468 void UpdateShortcutWorker::DownloadIcon() {
469 // FetchIcon must run on UI thread because it relies on TabContents
470 // to download the icon.
471 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
472
473 if (tab_contents_ == NULL) {
474 DeleteMe(); // We are done if underlying TabContents is gone.
475 return;
476 }
477
478 if (unprocessed_icons_.empty()) {
479 // No app icon. Just use the favicon from TabContents.
480 UpdateShortcuts();
481 return;
482 }
483
484 tab_contents_->fav_icon_helper().DownloadImage(
485 unprocessed_icons_.back().url,
486 std::max(unprocessed_icons_.back().width,
487 unprocessed_icons_.back().height),
488 NewCallback(this, &UpdateShortcutWorker::OnIconDownloaded));
489 unprocessed_icons_.pop_back();
490 }
491
492 void UpdateShortcutWorker::OnIconDownloaded(int download_id,
493 bool errored,
494 const SkBitmap& image) {
495 if (tab_contents_ == NULL) {
496 DeleteMe(); // We are done if underlying TabContents is gone.
497 return;
498 }
499
500 if (!errored && !image.isNull()) {
501 // Update icon with download image and update shortcut.
502 shortcut_info_.favicon = image;
503 UpdateShortcuts();
504 } else {
505 // Try the next icon otherwise.
506 DownloadIcon();
507 }
508 }
509
510 void UpdateShortcutWorker::CheckExistingShortcuts() {
511 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
512
513 // Locations to check to shortcut_paths.
514 struct {
515 bool& use_this_location;
516 int location_id;
517 const wchar_t* sub_dir;
518 } locations[] = {
519 {
520 shortcut_info_.create_on_desktop,
521 chrome::DIR_USER_DESKTOP,
522 NULL
523 }, {
524 shortcut_info_.create_in_applications_menu,
525 base::DIR_START_MENU,
526 NULL
527 }, {
528 shortcut_info_.create_in_quick_launch_bar,
529 // For Win7, create_in_quick_launch_bar means pinning to taskbar.
530 base::DIR_APP_DATA,
531 (win_util::GetWinVersion() >= win_util::WINVERSION_WIN7) ?
532 L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar" :
533 L"Microsoft\\Internet Explorer\\Quick Launch"
534 }
535 };
536
537 for (int i = 0; i < arraysize(locations); ++i) {
538 locations[i].use_this_location = false;
539
540 FilePath path;
541 if (!PathService::Get(locations[i].location_id, &path)) {
542 NOTREACHED();
543 continue;
544 }
545
546 if (locations[i].sub_dir != NULL)
547 path = path.Append(locations[i].sub_dir);
548
549 FilePath shortcut_file = path.Append(file_name_).
550 ReplaceExtension(FILE_PATH_LITERAL(".lnk"));
551 if (file_util::PathExists(shortcut_file)) {
552 locations[i].use_this_location = true;
553 shortcut_files_.push_back(shortcut_file);
554 }
555 }
556 }
557
558 void UpdateShortcutWorker::UpdateShortcuts() {
559 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
560 NewRunnableMethod(this,
561 &UpdateShortcutWorker::UpdateShortcutsOnFileThread));
562 }
563
564 void UpdateShortcutWorker::UpdateShortcutsOnFileThread() {
565 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
566
567 FilePath web_app_path = GetWebAppDataDirectory(root_dir_, shortcut_info_.url);
568 FilePath icon_file = web_app_path.Append(file_name_).ReplaceExtension(
569 FILE_PATH_LITERAL(".ico"));
570 CheckAndSaveIcon(icon_file, shortcut_info_.favicon);
571
572 CheckExistingShortcuts();
573 if (shortcut_files_.empty()) {
574 // No shortcuts to update.
575 OnShortcutsUpdated(true);
576 } else {
577 // Re-create shortcuts to make sure application url, name and description
578 // are up to date
579 web_app::CreateShortcut(root_dir_, shortcut_info_,
580 NewCallback(this, &UpdateShortcutWorker::OnShortcutsUpdated));
581 }
582 }
583
584 void UpdateShortcutWorker::OnShortcutsUpdated(bool) {
585 DeleteMe(); // We are done.
586 }
587
588 void UpdateShortcutWorker::DeleteMe() {
589 if (ChromeThread::CurrentlyOn(ChromeThread::UI)) {
590 DeleteMeOnUIThread();
591 } else {
592 ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
593 NewRunnableMethod(this, &UpdateShortcutWorker::DeleteMeOnUIThread));
594 }
595 }
596
597 void UpdateShortcutWorker::DeleteMeOnUIThread() {
598 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
599 delete this;
600 }
601 #endif // defined(OS_WIN)
602
291 }; // namespace 603 }; // namespace
292 604
605 // Allows UpdateShortcutWorker without adding refcounting. UpdateShortcutWorker
606 // manages its own life time and will delete itself when it's done.
607 template <>
608 struct RunnableMethodTraits<UpdateShortcutWorker> {
609 void RetainCallee(UpdateShortcutWorker* worker) {}
610 void ReleaseCallee(UpdateShortcutWorker* worker) {}
611 };
612
293 namespace web_app { 613 namespace web_app {
294 614
295 std::wstring GenerateApplicationNameFromURL(const GURL& url) { 615 std::wstring GenerateApplicationNameFromURL(const GURL& url) {
296 std::string t; 616 std::string t;
297 t.append(url.host()); 617 t.append(url.host());
298 t.append("_"); 618 t.append("_");
299 t.append(url.path()); 619 t.append(url.path());
300 return UTF8ToWide(t); 620 return UTF8ToWide(t);
301 } 621 }
302 622
303 void CreateShortcut( 623 void CreateShortcut(
304 const FilePath& data_dir, 624 const FilePath& data_dir,
305 const ShellIntegration::ShortcutInfo& shortcut_info, 625 const ShellIntegration::ShortcutInfo& shortcut_info,
306 CreateShortcutCallback* callback) { 626 CreateShortcutCallback* callback) {
307 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, 627 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
308 new CreateShortcutTask(data_dir, shortcut_info, callback)); 628 new CreateShortcutTask(data_dir, shortcut_info, callback));
309 } 629 }
310 630
311 bool IsValidUrl(const GURL& url) { 631 bool IsValidUrl(const GURL& url) {
312 static const char* const kValidUrlSchemes[] = { 632 static const char* const kValidUrlSchemes[] = {
313 chrome::kFileScheme, 633 chrome::kFileScheme,
314 chrome::kFtpScheme, 634 chrome::kFtpScheme,
315 chrome::kHttpScheme, 635 chrome::kHttpScheme,
316 chrome::kHttpsScheme, 636 chrome::kHttpsScheme,
317 }; 637 };
318 638
319 for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) { 639 for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) {
320 if (url.SchemeIs(kValidUrlSchemes[i])) 640 if (url.SchemeIs(kValidUrlSchemes[i]))
321 return true; 641 return true;
322 } 642 }
323 643
324 return false; 644 return false;
325 } 645 }
326 646
647 FilePath GetDataDir(Profile* profile) {
648 DCHECK(profile);
649 return profile->GetPath().Append(chrome::kWebAppDirname);
650 }
651
652 void GetIconsInfo(const webkit_glue::WebApplicationInfo& app_info,
653 IconInfoList* icons) {
654 DCHECK(icons);
655
656 icons->clear();
657 for (size_t i = 0; i < app_info.icons.size(); ++i) {
658 // We only take square shaped icons (i.e. width == height).
659 if (app_info.icons[i].width == app_info.icons[i].height) {
660 icons->push_back(app_info.icons[i]);
661 }
662 }
663
664 std::sort(icons->begin(), icons->end(), &IconPrecedes);
665 }
666
667 void GetShortcutInfoForTab(TabContents* tab_contents,
668 ShellIntegration::ShortcutInfo* info) {
669 DCHECK(info); // Must provide a valid info.
670
671 const webkit_glue::WebApplicationInfo& app_info =
672 tab_contents->web_app_info();
673
674 info->url = app_info.app_url.is_empty() ? tab_contents->GetURL() :
675 app_info.app_url;
676 info->title = app_info.title.empty() ?
677 (tab_contents->GetTitle().empty() ? UTF8ToUTF16(info->url.spec()) :
678 tab_contents->GetTitle()) :
679 app_info.title;
680 info->description = app_info.description;
681 info->favicon = tab_contents->GetFavIcon();
682 }
683
684 void UpdateShortcutForTabContents(TabContents* tab_contents) {
685 #if defined(OS_WIN)
686 // UpdateShortcutWorker will delete itself when it's done.
687 UpdateShortcutWorker* worker = new UpdateShortcutWorker(tab_contents);
688 worker->Run();
689 #endif // defined(OS_WIN)
690 }
691
327 }; // namespace web_app 692 }; // namespace web_app
OLDNEW
« no previous file with comments | « chrome/browser/web_applications/web_app.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698