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

Side by Side Diff: chrome/browser/web_applications/web_app_win.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_win.h" 5 #include "chrome/browser/web_applications/web_app_win.h"
6 6
7 #include <shlobj.h> 7 #include <shlobj.h>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/md5.h" 13 #include "base/md5.h"
14 #include "base/memory/scoped_ptr.h"
14 #include "base/path_service.h" 15 #include "base/path_service.h"
15 #include "base/strings/string16.h" 16 #include "base/strings/string16.h"
16 #include "base/strings/string_piece.h" 17 #include "base/strings/string_piece.h"
17 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
19 #include "base/win/shortcut.h" 20 #include "base/win/shortcut.h"
20 #include "base/win/windows_version.h" 21 #include "base/win/windows_version.h"
21 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/web_applications/update_shortcut_worker_win.h" 23 #include "chrome/browser/web_applications/update_shortcut_worker_win.h"
23 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/chrome_switches.h"
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 for (std::vector<base::FilePath>::const_iterator j = shortcut_files.begin(); 328 for (std::vector<base::FilePath>::const_iterator j = shortcut_files.begin();
328 j != shortcut_files.end(); ++j) { 329 j != shortcut_files.end(); ++j) {
329 // Any shortcut could have been pinned, either by chrome or the user, so 330 // Any shortcut could have been pinned, either by chrome or the user, so
330 // they are all unpinned. 331 // they are all unpinned.
331 base::win::TaskbarUnpinShortcutLink(j->value().c_str()); 332 base::win::TaskbarUnpinShortcutLink(j->value().c_str());
332 base::DeleteFile(*j, false); 333 base::DeleteFile(*j, false);
333 } 334 }
334 } 335 }
335 } 336 }
336 337
337 void CreateIconAndSetRelaunchDetails(const base::FilePath& web_app_path, 338 void CreateIconAndSetRelaunchDetails(
338 const base::FilePath& icon_file, 339 const base::FilePath& web_app_path,
339 const web_app::ShortcutInfo& shortcut_info, 340 const base::FilePath& icon_file,
340 HWND hwnd) { 341 scoped_ptr<web_app::ShortcutInfo> shortcut_info,
342 HWND hwnd) {
341 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 343 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
342 344
343 base::CommandLine command_line = 345 base::CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher(
344 ShellIntegration::CommandLineArgsForLauncher(shortcut_info.url, 346 shortcut_info->url, shortcut_info->extension_id,
345 shortcut_info.extension_id, 347 shortcut_info->profile_path);
346 shortcut_info.profile_path);
347 348
348 base::FilePath chrome_exe; 349 base::FilePath chrome_exe;
349 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 350 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
350 NOTREACHED(); 351 NOTREACHED();
351 return; 352 return;
352 } 353 }
353 command_line.SetProgram(chrome_exe); 354 command_line.SetProgram(chrome_exe);
354 ui::win::SetRelaunchDetailsForWindow( 355 ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(),
355 command_line.GetCommandLineString(), shortcut_info.title, hwnd); 356 shortcut_info->title, hwnd);
356 357
357 if (!base::PathExists(web_app_path) && !base::CreateDirectory(web_app_path)) 358 if (!base::PathExists(web_app_path) && !base::CreateDirectory(web_app_path))
358 return; 359 return;
359 360
360 ui::win::SetAppIconForWindow(icon_file.value(), hwnd); 361 ui::win::SetAppIconForWindow(icon_file.value(), hwnd);
361 web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon, true); 362 web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info->favicon, true);
362 } 363 }
363 364
364 void OnShortcutInfoLoadedForSetRelaunchDetails( 365 void OnShortcutInfoLoadedForSetRelaunchDetails(
365 HWND hwnd, 366 HWND hwnd,
366 const web_app::ShortcutInfo& shortcut_info) { 367 scoped_ptr<web_app::ShortcutInfo> shortcut_info) {
367 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 368 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
368 369
369 // Set window's icon to the one we're about to create/update in the web app 370 // Set window's icon to the one we're about to create/update in the web app
370 // path. The icon cache will refresh on icon creation. 371 // path. The icon cache will refresh on icon creation.
371 base::FilePath web_app_path = 372 base::FilePath web_app_path = web_app::GetWebAppDataDirectory(
372 web_app::GetWebAppDataDirectory(shortcut_info.profile_path, 373 shortcut_info->profile_path, shortcut_info->extension_id,
373 shortcut_info.extension_id, 374 shortcut_info->url);
374 shortcut_info.url);
375 base::FilePath icon_file = 375 base::FilePath icon_file =
376 web_app::internals::GetIconFilePath(web_app_path, shortcut_info.title); 376 web_app::internals::GetIconFilePath(web_app_path, shortcut_info->title);
377 content::BrowserThread::PostBlockingPoolTask( 377 content::BrowserThread::PostBlockingPoolTask(
378 FROM_HERE, 378 FROM_HERE, base::Bind(&CreateIconAndSetRelaunchDetails, web_app_path,
379 base::Bind(&CreateIconAndSetRelaunchDetails, 379 icon_file, base::Passed(&shortcut_info), hwnd));
380 web_app_path,
381 icon_file,
382 shortcut_info,
383 hwnd));
384 } 380 }
385 381
386 // Creates an "app shim exe" by linking or copying the generic app shim exe. 382 // Creates an "app shim exe" by linking or copying the generic app shim exe.
387 // This is the binary that will be run when the user opens a file with this 383 // This is the binary that will be run when the user opens a file with this
388 // application. The name and icon of the binary will be used on the Open With 384 // application. The name and icon of the binary will be used on the Open With
389 // menu. For this reason, we cannot simply launch chrome.exe. We give the app 385 // menu. For this reason, we cannot simply launch chrome.exe. We give the app
390 // shim exe the same name as the application (with no ".exe" extension), so that 386 // shim exe the same name as the application (with no ".exe" extension), so that
391 // the correct title will appear on the Open With menu. (Note: we also need a 387 // the correct title will appear on the Open With menu. (Note: we also need a
392 // separate binary per app because Windows only allows a single association with 388 // separate binary per app because Windows only allows a single association with
393 // each executable.) 389 // each executable.)
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 nullptr, nullptr); 514 nullptr, nullptr);
519 } 515 }
520 516
521 return num_successes == file_handlers_info.size(); 517 return num_successes == file_handlers_info.size();
522 } 518 }
523 519
524 } // namespace 520 } // namespace
525 521
526 namespace web_app { 522 namespace web_app {
527 523
528 base::FilePath CreateShortcutInWebAppDir(const base::FilePath& web_app_dir, 524 base::FilePath CreateShortcutInWebAppDir(
529 const ShortcutInfo& shortcut_info) { 525 const base::FilePath& web_app_dir,
526 scoped_ptr<ShortcutInfo> shortcut_info) {
530 std::vector<base::FilePath> paths; 527 std::vector<base::FilePath> paths;
531 paths.push_back(web_app_dir); 528 paths.push_back(web_app_dir);
532 std::vector<base::FilePath> out_filenames; 529 std::vector<base::FilePath> out_filenames;
533 base::FilePath web_app_dir_shortcut = 530 base::FilePath web_app_dir_shortcut =
534 web_app_dir.Append(internals::GetSanitizedFileName(shortcut_info.title)) 531 web_app_dir.Append(internals::GetSanitizedFileName(shortcut_info->title))
535 .AddExtension(installer::kLnkExt); 532 .AddExtension(installer::kLnkExt);
536 if (!PathExists(web_app_dir_shortcut)) { 533 if (!PathExists(web_app_dir_shortcut)) {
537 CreateShortcutsInPaths(web_app_dir, 534 CreateShortcutsInPaths(web_app_dir, *shortcut_info, paths,
538 shortcut_info, 535 SHORTCUT_CREATION_BY_USER, &out_filenames);
539 paths,
540 SHORTCUT_CREATION_BY_USER,
541 &out_filenames);
542 DCHECK_EQ(out_filenames.size(), 1u); 536 DCHECK_EQ(out_filenames.size(), 1u);
543 DCHECK_EQ(out_filenames[0].value(), web_app_dir_shortcut.value()); 537 DCHECK_EQ(out_filenames[0].value(), web_app_dir_shortcut.value());
544 } else { 538 } else {
545 internals::CheckAndSaveIcon( 539 internals::CheckAndSaveIcon(
546 internals::GetIconFilePath(web_app_dir, shortcut_info.title), 540 internals::GetIconFilePath(web_app_dir, shortcut_info->title),
547 shortcut_info.favicon, true); 541 shortcut_info->favicon, true);
548 } 542 }
549 return web_app_dir_shortcut; 543 return web_app_dir_shortcut;
550 } 544 }
551 545
552 void UpdateRelaunchDetailsForApp(Profile* profile, 546 void UpdateRelaunchDetailsForApp(Profile* profile,
553 const extensions::Extension* extension, 547 const extensions::Extension* extension,
554 HWND hwnd) { 548 HWND hwnd) {
555 web_app::GetShortcutInfoForApp( 549 web_app::GetShortcutInfoForApp(
556 extension, 550 extension,
557 profile, 551 profile,
(...skipping 21 matching lines...) Expand all
579 // see explorer rebuilding the icon cache. It would be great that we find 573 // see explorer rebuilding the icon cache. It would be great that we find
580 // a better way to achieve this. 574 // a better way to achieve this.
581 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, NULL, 575 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, NULL,
582 NULL); 576 NULL);
583 } 577 }
584 return true; 578 return true;
585 } 579 }
586 580
587 bool CreatePlatformShortcuts( 581 bool CreatePlatformShortcuts(
588 const base::FilePath& web_app_path, 582 const base::FilePath& web_app_path,
589 const ShortcutInfo& shortcut_info, 583 scoped_ptr<ShortcutInfo> shortcut_info,
590 const extensions::FileHandlersInfo& file_handlers_info, 584 const extensions::FileHandlersInfo& file_handlers_info,
591 const ShortcutLocations& creation_locations, 585 const ShortcutLocations& creation_locations,
592 ShortcutCreationReason creation_reason) { 586 ShortcutCreationReason creation_reason) {
593 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 587 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
594 588
595 // Nothing to do on Windows for hidden apps. 589 // Nothing to do on Windows for hidden apps.
596 if (creation_locations.applications_menu_location == APP_MENU_LOCATION_HIDDEN) 590 if (creation_locations.applications_menu_location == APP_MENU_LOCATION_HIDDEN)
597 return true; 591 return true;
598 592
599 // Shortcut paths under which to create shortcuts. 593 // Shortcut paths under which to create shortcuts.
600 std::vector<base::FilePath> shortcut_paths = 594 std::vector<base::FilePath> shortcut_paths =
601 GetShortcutPaths(creation_locations); 595 GetShortcutPaths(creation_locations);
602 596
603 bool pin_to_taskbar = creation_locations.in_quick_launch_bar && 597 bool pin_to_taskbar = creation_locations.in_quick_launch_bar &&
604 (base::win::GetVersion() >= base::win::VERSION_WIN7); 598 (base::win::GetVersion() >= base::win::VERSION_WIN7);
605 599
606 // Create/update the shortcut in the web app path for the "Pin To Taskbar" 600 // Create/update the shortcut in the web app path for the "Pin To Taskbar"
607 // option in Win7. We use the web app path shortcut because we will overwrite 601 // option in Win7. We use the web app path shortcut because we will overwrite
608 // it rather than appending unique numbers if the shortcut already exists. 602 // it rather than appending unique numbers if the shortcut already exists.
609 // This prevents pinned apps from having unique numbers in their names. 603 // This prevents pinned apps from having unique numbers in their names.
610 if (pin_to_taskbar) 604 if (pin_to_taskbar)
611 shortcut_paths.push_back(web_app_path); 605 shortcut_paths.push_back(web_app_path);
612 606
613 if (shortcut_paths.empty()) 607 if (shortcut_paths.empty())
614 return false; 608 return false;
615 609
616 if (!CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths, 610 if (!CreateShortcutsInPaths(web_app_path, *shortcut_info, shortcut_paths,
617 creation_reason, NULL)) 611 creation_reason, NULL))
618 return false; 612 return false;
619 613
620 if (pin_to_taskbar) { 614 if (pin_to_taskbar) {
621 base::FilePath file_name = GetSanitizedFileName(shortcut_info.title); 615 base::FilePath file_name = GetSanitizedFileName(shortcut_info->title);
622 // Use the web app path shortcut for pinning to avoid having unique numbers 616 // Use the web app path shortcut for pinning to avoid having unique numbers
623 // in the application name. 617 // in the application name.
624 base::FilePath shortcut_to_pin = web_app_path.Append(file_name). 618 base::FilePath shortcut_to_pin = web_app_path.Append(file_name).
625 AddExtension(installer::kLnkExt); 619 AddExtension(installer::kLnkExt);
626 if (!base::win::TaskbarPinShortcutLink(shortcut_to_pin.value().c_str())) 620 if (!base::win::TaskbarPinShortcutLink(shortcut_to_pin.value().c_str()))
627 return false; 621 return false;
628 } 622 }
629 623
630 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 624 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
631 switches::kEnableAppsFileAssociations)) { 625 switches::kEnableAppsFileAssociations)) {
632 CreateFileAssociationsForApp( 626 CreateFileAssociationsForApp(
633 shortcut_info.extension_id, shortcut_info.title, 627 shortcut_info->extension_id, shortcut_info->title,
634 shortcut_info.profile_path, file_handlers_info); 628 shortcut_info->profile_path, file_handlers_info);
635 } 629 }
636 630
637 return true; 631 return true;
638 } 632 }
639 633
640 void UpdatePlatformShortcuts( 634 void UpdatePlatformShortcuts(
641 const base::FilePath& web_app_path, 635 const base::FilePath& web_app_path,
642 const base::string16& old_app_title, 636 const base::string16& old_app_title,
643 const ShortcutInfo& shortcut_info, 637 scoped_ptr<ShortcutInfo> shortcut_info,
644 const extensions::FileHandlersInfo& file_handlers_info) { 638 const extensions::FileHandlersInfo& file_handlers_info) {
645 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 639 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
646 640
647 // Generates file name to use with persisted ico and shortcut file. 641 // Generates file name to use with persisted ico and shortcut file.
648 base::FilePath file_name = 642 base::FilePath file_name =
649 web_app::internals::GetSanitizedFileName(shortcut_info.title); 643 web_app::internals::GetSanitizedFileName(shortcut_info->title);
650 644
651 if (old_app_title != shortcut_info.title) { 645 if (old_app_title != shortcut_info->title) {
652 // The app's title has changed. Delete all existing app shortcuts and 646 // The app's title has changed. Delete all existing app shortcuts and
653 // recreate them in any locations they already existed (but do not add them 647 // recreate them in any locations they already existed (but do not add them
654 // to locations where they do not currently exist). 648 // to locations where they do not currently exist).
655 bool was_pinned_to_taskbar; 649 bool was_pinned_to_taskbar;
656 std::vector<base::FilePath> shortcut_paths; 650 std::vector<base::FilePath> shortcut_paths;
657 GetShortcutLocationsAndDeleteShortcuts( 651 GetShortcutLocationsAndDeleteShortcuts(
658 web_app_path, shortcut_info.profile_path, old_app_title, 652 web_app_path, shortcut_info->profile_path, old_app_title,
659 &was_pinned_to_taskbar, &shortcut_paths); 653 &was_pinned_to_taskbar, &shortcut_paths);
660 CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths, 654 CreateShortcutsInPaths(web_app_path, *shortcut_info, shortcut_paths,
661 SHORTCUT_CREATION_BY_USER, NULL); 655 SHORTCUT_CREATION_BY_USER, NULL);
662 // If the shortcut was pinned to the taskbar, 656 // If the shortcut was pinned to the taskbar,
663 // GetShortcutLocationsAndDeleteShortcuts will have deleted it. In that 657 // GetShortcutLocationsAndDeleteShortcuts will have deleted it. In that
664 // case, re-pin it. 658 // case, re-pin it.
665 if (was_pinned_to_taskbar) { 659 if (was_pinned_to_taskbar) {
666 base::FilePath file_name = GetSanitizedFileName(shortcut_info.title); 660 base::FilePath file_name = GetSanitizedFileName(shortcut_info->title);
667 // Use the web app path shortcut for pinning to avoid having unique 661 // Use the web app path shortcut for pinning to avoid having unique
668 // numbers in the application name. 662 // numbers in the application name.
669 base::FilePath shortcut_to_pin = web_app_path.Append(file_name). 663 base::FilePath shortcut_to_pin = web_app_path.Append(file_name).
670 AddExtension(installer::kLnkExt); 664 AddExtension(installer::kLnkExt);
671 base::win::TaskbarPinShortcutLink(shortcut_to_pin.value().c_str()); 665 base::win::TaskbarPinShortcutLink(shortcut_to_pin.value().c_str());
672 } 666 }
673 } 667 }
674 668
675 // Update the icon if necessary. 669 // Update the icon if necessary.
676 base::FilePath icon_file = GetIconFilePath(web_app_path, shortcut_info.title); 670 base::FilePath icon_file =
677 CheckAndSaveIcon(icon_file, shortcut_info.favicon, true); 671 GetIconFilePath(web_app_path, shortcut_info->title);
672 CheckAndSaveIcon(icon_file, shortcut_info->favicon, true);
678 } 673 }
679 674
680 void DeletePlatformShortcuts(const base::FilePath& web_app_path, 675 void DeletePlatformShortcuts(const base::FilePath& web_app_path,
681 const ShortcutInfo& shortcut_info) { 676 scoped_ptr<ShortcutInfo> shortcut_info) {
682 GetShortcutLocationsAndDeleteShortcuts( 677 GetShortcutLocationsAndDeleteShortcuts(web_app_path,
683 web_app_path, shortcut_info.profile_path, shortcut_info.title, NULL, 678 shortcut_info->profile_path,
684 NULL); 679 shortcut_info->title, NULL, NULL);
685 680
686 // If there are no more shortcuts in the Chrome Apps subdirectory, remove it. 681 // If there are no more shortcuts in the Chrome Apps subdirectory, remove it.
687 base::FilePath chrome_apps_dir; 682 base::FilePath chrome_apps_dir;
688 if (ShellUtil::GetShortcutPath( 683 if (ShellUtil::GetShortcutPath(
689 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, 684 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR,
690 BrowserDistribution::GetDistribution(), 685 BrowserDistribution::GetDistribution(),
691 ShellUtil::CURRENT_USER, 686 ShellUtil::CURRENT_USER,
692 &chrome_apps_dir)) { 687 &chrome_apps_dir)) {
693 if (base::IsDirectoryEmpty(chrome_apps_dir)) 688 if (base::IsDirectoryEmpty(chrome_apps_dir))
694 base::DeleteFile(chrome_apps_dir, false); 689 base::DeleteFile(chrome_apps_dir, false);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 765
771 } // namespace internals 766 } // namespace internals
772 767
773 void UpdateShortcutForTabContents(content::WebContents* web_contents) { 768 void UpdateShortcutForTabContents(content::WebContents* web_contents) {
774 // UpdateShortcutWorker will delete itself when it's done. 769 // UpdateShortcutWorker will delete itself when it's done.
775 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents); 770 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents);
776 worker->Run(); 771 worker->Run();
777 } 772 }
778 773
779 } // namespace web_app 774 } // namespace web_app
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698