| 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/shell_integration_linux.h" | 5 #include "chrome/browser/shell_integration_linux.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 | 8 |
| 9 #if defined(USE_GLIB) | 9 #if defined(USE_GLIB) |
| 10 #include <glib.h> | 10 #include <glib.h> |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "base/command_line.h" | 22 #include "base/command_line.h" |
| 23 #include "base/environment.h" | 23 #include "base/environment.h" |
| 24 #include "base/files/file_enumerator.h" | 24 #include "base/files/file_enumerator.h" |
| 25 #include "base/files/file_path.h" | 25 #include "base/files/file_path.h" |
| 26 #include "base/files/file_util.h" | 26 #include "base/files/file_util.h" |
| 27 #include "base/files/scoped_temp_dir.h" | 27 #include "base/files/scoped_temp_dir.h" |
| 28 #include "base/i18n/file_util_icu.h" | 28 #include "base/i18n/file_util_icu.h" |
| 29 #include "base/memory/ref_counted_memory.h" | 29 #include "base/memory/ref_counted_memory.h" |
| 30 #include "base/memory/scoped_ptr.h" | 30 #include "base/memory/scoped_ptr.h" |
| 31 #include "base/message_loop/message_loop.h" | 31 #include "base/message_loop/message_loop.h" |
| 32 #include "base/nix/xdg_util.h" |
| 32 #include "base/path_service.h" | 33 #include "base/path_service.h" |
| 33 #include "base/posix/eintr_wrapper.h" | 34 #include "base/posix/eintr_wrapper.h" |
| 34 #include "base/process/kill.h" | 35 #include "base/process/kill.h" |
| 35 #include "base/process/launch.h" | 36 #include "base/process/launch.h" |
| 36 #include "base/strings/string_number_conversions.h" | 37 #include "base/strings/string_number_conversions.h" |
| 37 #include "base/strings/string_tokenizer.h" | 38 #include "base/strings/string_tokenizer.h" |
| 38 #include "base/strings/string_util.h" | 39 #include "base/strings/string_util.h" |
| 39 #include "base/strings/utf_string_conversions.h" | 40 #include "base/strings/utf_string_conversions.h" |
| 40 #include "base/threading/thread.h" | 41 #include "base/threading/thread.h" |
| 41 #include "base/threading/thread_restrictions.h" | 42 #include "base/threading/thread_restrictions.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 71 *exit_code = EXIT_FAILURE; | 72 *exit_code = EXIT_FAILURE; |
| 72 int devnull = open("/dev/null", O_RDONLY); | 73 int devnull = open("/dev/null", O_RDONLY); |
| 73 if (devnull < 0) | 74 if (devnull < 0) |
| 74 return false; | 75 return false; |
| 75 base::FileHandleMappingVector no_stdin; | 76 base::FileHandleMappingVector no_stdin; |
| 76 no_stdin.push_back(std::make_pair(devnull, STDIN_FILENO)); | 77 no_stdin.push_back(std::make_pair(devnull, STDIN_FILENO)); |
| 77 | 78 |
| 78 base::LaunchOptions options; | 79 base::LaunchOptions options; |
| 79 options.fds_to_remap = &no_stdin; | 80 options.fds_to_remap = &no_stdin; |
| 80 base::Process process = base::LaunchProcess(argv, options); | 81 base::Process process = base::LaunchProcess(argv, options); |
| 81 if (!process.IsValid()) { | 82 close(devnull); |
| 82 close(devnull); | 83 if (!process.IsValid()) |
| 83 return false; | 84 return false; |
| 84 } | |
| 85 close(devnull); | |
| 86 | |
| 87 return process.WaitForExit(exit_code); | 85 return process.WaitForExit(exit_code); |
| 88 } | 86 } |
| 89 | 87 |
| 90 std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images, | 88 std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images, |
| 91 const base::FilePath& shortcut_filename) { | 89 const base::FilePath& shortcut_filename) { |
| 92 if (icon_images.empty()) | 90 if (icon_images.empty()) |
| 93 return std::string(); | 91 return std::string(); |
| 94 | 92 |
| 95 // TODO(phajdan.jr): Report errors from this function, possibly as infobars. | 93 // TODO(phajdan.jr): Report errors from this function, possibly as infobars. |
| 96 base::ScopedTempDir temp_dir; | 94 base::ScopedTempDir temp_dir; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 | 471 |
| 474 g_key_file_free(key_file); | 472 g_key_file_free(key_file); |
| 475 return nodisplay; | 473 return nodisplay; |
| 476 #else | 474 #else |
| 477 NOTIMPLEMENTED(); | 475 NOTIMPLEMENTED(); |
| 478 return false; | 476 return false; |
| 479 #endif | 477 #endif |
| 480 } | 478 } |
| 481 | 479 |
| 482 // Gets the path to the Chrome executable or wrapper script. | 480 // Gets the path to the Chrome executable or wrapper script. |
| 483 // Returns an empty path if the executable path could not be found. | 481 // Returns an empty path if the executable path could not be found, which should |
| 482 // never happen. |
| 484 base::FilePath GetChromeExePath() { | 483 base::FilePath GetChromeExePath() { |
| 485 // Try to get the name of the wrapper script that launched Chrome. | 484 // Try to get the name of the wrapper script that launched Chrome. |
| 486 scoped_ptr<base::Environment> environment(base::Environment::Create()); | 485 scoped_ptr<base::Environment> environment(base::Environment::Create()); |
| 487 std::string wrapper_script; | 486 std::string wrapper_script; |
| 488 if (environment->GetVar("CHROME_WRAPPER", &wrapper_script)) { | 487 if (environment->GetVar("CHROME_WRAPPER", &wrapper_script)) |
| 489 return base::FilePath(wrapper_script); | 488 return base::FilePath(wrapper_script); |
| 490 } | |
| 491 | 489 |
| 492 // Just return the name of the executable path for Chrome. | 490 // Just return the name of the executable path for Chrome. |
| 493 base::FilePath chrome_exe_path; | 491 base::FilePath chrome_exe_path; |
| 494 PathService::Get(base::FILE_EXE, &chrome_exe_path); | 492 PathService::Get(base::FILE_EXE, &chrome_exe_path); |
| 495 return chrome_exe_path; | 493 return chrome_exe_path; |
| 496 } | 494 } |
| 497 | 495 |
| 498 } // namespace | 496 } // namespace |
| 499 | 497 |
| 500 // static | 498 // static |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 argv.push_back(kXdgSettingsDefaultBrowser); | 538 argv.push_back(kXdgSettingsDefaultBrowser); |
| 541 | 539 |
| 542 std::string browser; | 540 std::string browser; |
| 543 // We don't care about the return value here. | 541 // We don't care about the return value here. |
| 544 base::GetAppOutput(base::CommandLine(argv), &browser); | 542 base::GetAppOutput(base::CommandLine(argv), &browser); |
| 545 return browser.find("irefox") != std::string::npos; | 543 return browser.find("irefox") != std::string::npos; |
| 546 } | 544 } |
| 547 | 545 |
| 548 namespace shell_integration_linux { | 546 namespace shell_integration_linux { |
| 549 | 547 |
| 550 bool GetDataWriteLocation(base::Environment* env, base::FilePath* search_path) { | 548 base::FilePath GetDataWriteLocation(base::Environment* env) { |
| 551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 549 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 552 | 550 |
| 553 std::string xdg_data_home; | 551 return base::nix::GetXDGDirectory(env, "XDG_DATA_HOME", ".local/share"); |
| 554 std::string home; | |
| 555 if (env->GetVar("XDG_DATA_HOME", &xdg_data_home) && !xdg_data_home.empty()) { | |
| 556 *search_path = base::FilePath(xdg_data_home); | |
| 557 return true; | |
| 558 } else if (env->GetVar("HOME", &home) && !home.empty()) { | |
| 559 *search_path = base::FilePath(home).Append(".local").Append("share"); | |
| 560 return true; | |
| 561 } | |
| 562 return false; | |
| 563 } | 552 } |
| 564 | 553 |
| 565 std::vector<base::FilePath> GetDataSearchLocations(base::Environment* env) { | 554 std::vector<base::FilePath> GetDataSearchLocations(base::Environment* env) { |
| 566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 555 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 567 | 556 |
| 568 std::vector<base::FilePath> search_paths; | 557 std::vector<base::FilePath> search_paths; |
| 569 | 558 base::FilePath write_location = GetDataWriteLocation(env); |
| 570 base::FilePath write_location; | 559 search_paths.push_back(write_location); |
| 571 if (GetDataWriteLocation(env, &write_location)) | |
| 572 search_paths.push_back(write_location); | |
| 573 | 560 |
| 574 std::string xdg_data_dirs; | 561 std::string xdg_data_dirs; |
| 575 if (env->GetVar("XDG_DATA_DIRS", &xdg_data_dirs) && !xdg_data_dirs.empty()) { | 562 if (env->GetVar("XDG_DATA_DIRS", &xdg_data_dirs) && !xdg_data_dirs.empty()) { |
| 576 base::StringTokenizer tokenizer(xdg_data_dirs, ":"); | 563 base::StringTokenizer tokenizer(xdg_data_dirs, ":"); |
| 577 while (tokenizer.GetNext()) { | 564 while (tokenizer.GetNext()) { |
| 578 base::FilePath data_dir(tokenizer.token()); | 565 base::FilePath data_dir(tokenizer.token()); |
| 579 search_paths.push_back(data_dir); | 566 search_paths.push_back(data_dir); |
| 580 } | 567 } |
| 581 } else { | 568 } else { |
| 582 search_paths.push_back(base::FilePath("/usr/local/share")); | 569 search_paths.push_back(base::FilePath("/usr/local/share")); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 PathService::Get(base::DIR_USER_DESKTOP, &desktop_path); | 624 PathService::Get(base::DIR_USER_DESKTOP, &desktop_path); |
| 638 return GetExistingShortcutLocations(env, profile_path, extension_id, | 625 return GetExistingShortcutLocations(env, profile_path, extension_id, |
| 639 desktop_path); | 626 desktop_path); |
| 640 } | 627 } |
| 641 | 628 |
| 642 web_app::ShortcutLocations GetExistingShortcutLocations( | 629 web_app::ShortcutLocations GetExistingShortcutLocations( |
| 643 base::Environment* env, | 630 base::Environment* env, |
| 644 const base::FilePath& profile_path, | 631 const base::FilePath& profile_path, |
| 645 const std::string& extension_id, | 632 const std::string& extension_id, |
| 646 const base::FilePath& desktop_path) { | 633 const base::FilePath& desktop_path) { |
| 647 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 634 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 648 | 635 |
| 649 base::FilePath shortcut_filename = GetExtensionShortcutFilename( | 636 base::FilePath shortcut_filename = GetExtensionShortcutFilename( |
| 650 profile_path, extension_id); | 637 profile_path, extension_id); |
| 651 DCHECK(!shortcut_filename.empty()); | 638 DCHECK(!shortcut_filename.empty()); |
| 652 web_app::ShortcutLocations locations; | 639 web_app::ShortcutLocations locations; |
| 653 | 640 |
| 654 // Determine whether there is a shortcut on desktop. | 641 // Determine whether there is a shortcut on desktop. |
| 655 if (!desktop_path.empty()) { | 642 if (!desktop_path.empty()) { |
| 656 locations.on_desktop = | 643 locations.on_desktop = |
| 657 base::PathExists(desktop_path.Append(shortcut_filename)); | 644 base::PathExists(desktop_path.Append(shortcut_filename)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 668 ? web_app::APP_MENU_LOCATION_HIDDEN | 655 ? web_app::APP_MENU_LOCATION_HIDDEN |
| 669 : web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; | 656 : web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; |
| 670 } | 657 } |
| 671 | 658 |
| 672 return locations; | 659 return locations; |
| 673 } | 660 } |
| 674 | 661 |
| 675 bool GetExistingShortcutContents(base::Environment* env, | 662 bool GetExistingShortcutContents(base::Environment* env, |
| 676 const base::FilePath& desktop_filename, | 663 const base::FilePath& desktop_filename, |
| 677 std::string* output) { | 664 std::string* output) { |
| 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 665 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 679 | 666 |
| 680 std::vector<base::FilePath> search_paths = GetDataSearchLocations(env); | 667 std::vector<base::FilePath> search_paths = GetDataSearchLocations(env); |
| 681 | 668 |
| 682 for (std::vector<base::FilePath>::const_iterator i = search_paths.begin(); | 669 for (std::vector<base::FilePath>::const_iterator i = search_paths.begin(); |
| 683 i != search_paths.end(); ++i) { | 670 i != search_paths.end(); ++i) { |
| 684 base::FilePath path = i->Append("applications").Append(desktop_filename); | 671 base::FilePath path = i->Append("applications").Append(desktop_filename); |
| 685 VLOG(1) << "Looking for desktop file in " << path.value(); | 672 VLOG(1) << "Looking for desktop file in " << path.value(); |
| 686 if (base::PathExists(path)) { | 673 if (base::PathExists(path)) { |
| 687 VLOG(1) << "Found desktop file at " << path.value(); | 674 VLOG(1) << "Found desktop file at " << path.value(); |
| 688 return base::ReadFileToString(path, output); | 675 return base::ReadFileToString(path, output); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 base::i18n::ReplaceIllegalCharactersInPath(&filename, '_'); | 716 base::i18n::ReplaceIllegalCharactersInPath(&filename, '_'); |
| 730 // Spaces in filenames break xdg-desktop-menu | 717 // Spaces in filenames break xdg-desktop-menu |
| 731 // (see https://bugs.freedesktop.org/show_bug.cgi?id=66605). | 718 // (see https://bugs.freedesktop.org/show_bug.cgi?id=66605). |
| 732 base::ReplaceChars(filename, " ", "_", &filename); | 719 base::ReplaceChars(filename, " ", "_", &filename); |
| 733 return base::FilePath(filename.append(".desktop")); | 720 return base::FilePath(filename.append(".desktop")); |
| 734 } | 721 } |
| 735 | 722 |
| 736 std::vector<base::FilePath> GetExistingProfileShortcutFilenames( | 723 std::vector<base::FilePath> GetExistingProfileShortcutFilenames( |
| 737 const base::FilePath& profile_path, | 724 const base::FilePath& profile_path, |
| 738 const base::FilePath& directory) { | 725 const base::FilePath& directory) { |
| 739 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 726 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 727 |
| 740 // Use a prefix, because xdg-desktop-menu requires it. | 728 // Use a prefix, because xdg-desktop-menu requires it. |
| 741 std::string prefix(chrome::kBrowserProcessExecutableName); | 729 std::string prefix(chrome::kBrowserProcessExecutableName); |
| 742 prefix.append("-"); | 730 prefix.append("-"); |
| 743 std::string suffix("-"); | 731 std::string suffix("-"); |
| 744 suffix.append(profile_path.BaseName().value()); | 732 suffix.append(profile_path.BaseName().value()); |
| 745 base::i18n::ReplaceIllegalCharactersInPath(&suffix, '_'); | 733 base::i18n::ReplaceIllegalCharactersInPath(&suffix, '_'); |
| 746 // Spaces in filenames break xdg-desktop-menu | 734 // Spaces in filenames break xdg-desktop-menu |
| 747 // (see https://bugs.freedesktop.org/show_bug.cgi?id=66605). | 735 // (see https://bugs.freedesktop.org/show_bug.cgi?id=66605). |
| 748 base::ReplaceChars(suffix, " ", "_", &suffix); | 736 base::ReplaceChars(suffix, " ", "_", &suffix); |
| 749 std::string glob = prefix + "*" + suffix + ".desktop"; | 737 std::string glob = prefix + "*" + suffix + ".desktop"; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 return output_buffer; | 882 return output_buffer; |
| 895 #else | 883 #else |
| 896 NOTIMPLEMENTED(); | 884 NOTIMPLEMENTED(); |
| 897 return std::string(); | 885 return std::string(); |
| 898 #endif | 886 #endif |
| 899 } | 887 } |
| 900 | 888 |
| 901 bool CreateDesktopShortcut( | 889 bool CreateDesktopShortcut( |
| 902 const web_app::ShortcutInfo& shortcut_info, | 890 const web_app::ShortcutInfo& shortcut_info, |
| 903 const web_app::ShortcutLocations& creation_locations) { | 891 const web_app::ShortcutLocations& creation_locations) { |
| 904 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 892 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 905 | 893 |
| 906 base::FilePath shortcut_filename; | 894 base::FilePath shortcut_filename; |
| 907 if (!shortcut_info.extension_id.empty()) { | 895 if (!shortcut_info.extension_id.empty()) { |
| 908 shortcut_filename = GetExtensionShortcutFilename( | 896 shortcut_filename = GetExtensionShortcutFilename( |
| 909 shortcut_info.profile_path, shortcut_info.extension_id); | 897 shortcut_info.profile_path, shortcut_info.extension_id); |
| 910 // For extensions we do not want duplicate shortcuts. So, delete any that | 898 // For extensions we do not want duplicate shortcuts. So, delete any that |
| 911 // already exist and replace them. | 899 // already exist and replace them. |
| 912 if (creation_locations.on_desktop) | 900 if (creation_locations.on_desktop) |
| 913 DeleteShortcutOnDesktop(shortcut_filename); | 901 DeleteShortcutOnDesktop(shortcut_filename); |
| 914 | 902 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 925 std::string icon_name = | 913 std::string icon_name = |
| 926 CreateShortcutIcon(shortcut_info.favicon, shortcut_filename); | 914 CreateShortcutIcon(shortcut_info.favicon, shortcut_filename); |
| 927 | 915 |
| 928 std::string app_name = | 916 std::string app_name = |
| 929 web_app::GenerateApplicationNameFromInfo(shortcut_info); | 917 web_app::GenerateApplicationNameFromInfo(shortcut_info); |
| 930 | 918 |
| 931 bool success = true; | 919 bool success = true; |
| 932 | 920 |
| 933 base::FilePath chrome_exe_path = GetChromeExePath(); | 921 base::FilePath chrome_exe_path = GetChromeExePath(); |
| 934 if (chrome_exe_path.empty()) { | 922 if (chrome_exe_path.empty()) { |
| 935 LOG(WARNING) << "Could not get executable path."; | 923 NOTREACHED(); |
| 936 return false; | 924 return false; |
| 937 } | 925 } |
| 938 | 926 |
| 939 if (creation_locations.on_desktop) { | 927 if (creation_locations.on_desktop) { |
| 940 std::string contents = GetDesktopFileContents( | 928 std::string contents = GetDesktopFileContents( |
| 941 chrome_exe_path, | 929 chrome_exe_path, |
| 942 app_name, | 930 app_name, |
| 943 shortcut_info.url, | 931 shortcut_info.url, |
| 944 shortcut_info.extension_id, | 932 shortcut_info.extension_id, |
| 945 shortcut_info.title, | 933 shortcut_info.title, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 success = CreateShortcutInApplicationsMenu( | 975 success = CreateShortcutInApplicationsMenu( |
| 988 shortcut_filename, contents, directory_filename, directory_contents) && | 976 shortcut_filename, contents, directory_filename, directory_contents) && |
| 989 success; | 977 success; |
| 990 | 978 |
| 991 return success; | 979 return success; |
| 992 } | 980 } |
| 993 | 981 |
| 994 bool CreateAppListDesktopShortcut( | 982 bool CreateAppListDesktopShortcut( |
| 995 const std::string& wm_class, | 983 const std::string& wm_class, |
| 996 const std::string& title) { | 984 const std::string& title) { |
| 997 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 985 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 998 | 986 |
| 999 base::FilePath desktop_name(kAppListDesktopName); | 987 base::FilePath desktop_name(kAppListDesktopName); |
| 1000 base::FilePath shortcut_filename = desktop_name.AddExtension("desktop"); | 988 base::FilePath shortcut_filename = desktop_name.AddExtension("desktop"); |
| 1001 | 989 |
| 1002 // We do not want duplicate shortcuts. Delete any that already exist and | 990 // We do not want duplicate shortcuts. Delete any that already exist and |
| 1003 // replace them. | 991 // replace them. |
| 1004 DeleteShortcutInApplicationsMenu(shortcut_filename, base::FilePath()); | 992 DeleteShortcutInApplicationsMenu(shortcut_filename, base::FilePath()); |
| 1005 | 993 |
| 1006 base::FilePath chrome_exe_path = GetChromeExePath(); | 994 base::FilePath chrome_exe_path = GetChromeExePath(); |
| 1007 if (chrome_exe_path.empty()) { | 995 if (chrome_exe_path.empty()) { |
| 1008 LOG(WARNING) << "Could not get executable path."; | 996 NOTREACHED(); |
| 1009 return false; | 997 return false; |
| 1010 } | 998 } |
| 1011 | 999 |
| 1012 gfx::ImageFamily icon_images; | 1000 gfx::ImageFamily icon_images; |
| 1013 ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); | 1001 ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); |
| 1014 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_16)); | 1002 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_16)); |
| 1015 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_32)); | 1003 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_32)); |
| 1016 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_48)); | 1004 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_48)); |
| 1017 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_256)); | 1005 icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_256)); |
| 1018 std::string icon_name = CreateShortcutIcon(icon_images, desktop_name); | 1006 std::string icon_name = CreateShortcutIcon(icon_images, desktop_name); |
| 1019 | 1007 |
| 1020 base::CommandLine command_line(chrome_exe_path); | 1008 base::CommandLine command_line(chrome_exe_path); |
| 1021 command_line.AppendSwitch(switches::kShowAppList); | 1009 command_line.AppendSwitch(switches::kShowAppList); |
| 1022 std::string contents = | 1010 std::string contents = |
| 1023 GetDesktopFileContentsForCommand(command_line, | 1011 GetDesktopFileContentsForCommand(command_line, |
| 1024 wm_class, | 1012 wm_class, |
| 1025 GURL(), | 1013 GURL(), |
| 1026 base::UTF8ToUTF16(title), | 1014 base::UTF8ToUTF16(title), |
| 1027 icon_name, | 1015 icon_name, |
| 1028 kAppListCategories, | 1016 kAppListCategories, |
| 1029 false); | 1017 false); |
| 1030 return CreateShortcutInApplicationsMenu( | 1018 return CreateShortcutInApplicationsMenu( |
| 1031 shortcut_filename, contents, base::FilePath(), ""); | 1019 shortcut_filename, contents, base::FilePath(), ""); |
| 1032 } | 1020 } |
| 1033 | 1021 |
| 1034 void DeleteDesktopShortcuts(const base::FilePath& profile_path, | 1022 void DeleteDesktopShortcuts(const base::FilePath& profile_path, |
| 1035 const std::string& extension_id) { | 1023 const std::string& extension_id) { |
| 1036 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 1024 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 1037 | 1025 |
| 1038 base::FilePath shortcut_filename = GetExtensionShortcutFilename( | 1026 base::FilePath shortcut_filename = GetExtensionShortcutFilename( |
| 1039 profile_path, extension_id); | 1027 profile_path, extension_id); |
| 1040 DCHECK(!shortcut_filename.empty()); | 1028 DCHECK(!shortcut_filename.empty()); |
| 1041 | 1029 |
| 1042 DeleteShortcutOnDesktop(shortcut_filename); | 1030 DeleteShortcutOnDesktop(shortcut_filename); |
| 1043 // Delete shortcuts from |kDirectoryFilename|. | 1031 // Delete shortcuts from |kDirectoryFilename|. |
| 1044 // Note that it is possible that shortcuts were not created in the Chrome Apps | 1032 // Note that it is possible that shortcuts were not created in the Chrome Apps |
| 1045 // directory. It doesn't matter: this will still delete the shortcut even if | 1033 // directory. It doesn't matter: this will still delete the shortcut even if |
| 1046 // it isn't in the directory. | 1034 // it isn't in the directory. |
| 1047 DeleteShortcutInApplicationsMenu(shortcut_filename, | 1035 DeleteShortcutInApplicationsMenu(shortcut_filename, |
| 1048 base::FilePath(kDirectoryFilename)); | 1036 base::FilePath(kDirectoryFilename)); |
| 1049 } | 1037 } |
| 1050 | 1038 |
| 1051 void DeleteAllDesktopShortcuts(const base::FilePath& profile_path) { | 1039 void DeleteAllDesktopShortcuts(const base::FilePath& profile_path) { |
| 1052 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 1040 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 1053 | 1041 |
| 1054 scoped_ptr<base::Environment> env(base::Environment::Create()); | 1042 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 1055 | 1043 |
| 1056 // Delete shortcuts from Desktop. | 1044 // Delete shortcuts from Desktop. |
| 1057 base::FilePath desktop_path; | 1045 base::FilePath desktop_path; |
| 1058 if (PathService::Get(base::DIR_USER_DESKTOP, &desktop_path)) { | 1046 if (PathService::Get(base::DIR_USER_DESKTOP, &desktop_path)) { |
| 1059 std::vector<base::FilePath> shortcut_filenames_desktop = | 1047 std::vector<base::FilePath> shortcut_filenames_desktop = |
| 1060 GetExistingProfileShortcutFilenames(profile_path, desktop_path); | 1048 GetExistingProfileShortcutFilenames(profile_path, desktop_path); |
| 1061 for (std::vector<base::FilePath>::const_iterator it = | 1049 for (const auto& shortcut : shortcut_filenames_desktop) { |
| 1062 shortcut_filenames_desktop.begin(); | 1050 DeleteShortcutOnDesktop(shortcut); |
| 1063 it != shortcut_filenames_desktop.end(); ++it) { | |
| 1064 DeleteShortcutOnDesktop(*it); | |
| 1065 } | 1051 } |
| 1066 } | 1052 } |
| 1067 | 1053 |
| 1068 // Delete shortcuts from |kDirectoryFilename|. | 1054 // Delete shortcuts from |kDirectoryFilename|. |
| 1069 base::FilePath applications_menu; | 1055 base::FilePath applications_menu = GetDataWriteLocation(env.get()); |
| 1070 if (GetDataWriteLocation(env.get(), &applications_menu)) { | 1056 applications_menu = applications_menu.AppendASCII("applications"); |
| 1071 applications_menu = applications_menu.AppendASCII("applications"); | 1057 std::vector<base::FilePath> shortcut_filenames_app_menu = |
| 1072 std::vector<base::FilePath> shortcut_filenames_app_menu = | 1058 GetExistingProfileShortcutFilenames(profile_path, applications_menu); |
| 1073 GetExistingProfileShortcutFilenames(profile_path, applications_menu); | 1059 for (const auto& menu : shortcut_filenames_app_menu) { |
| 1074 for (std::vector<base::FilePath>::const_iterator it = | 1060 DeleteShortcutInApplicationsMenu(menu, base::FilePath(kDirectoryFilename)); |
| 1075 shortcut_filenames_app_menu.begin(); | |
| 1076 it != shortcut_filenames_app_menu.end(); ++it) { | |
| 1077 DeleteShortcutInApplicationsMenu(*it, | |
| 1078 base::FilePath(kDirectoryFilename)); | |
| 1079 } | |
| 1080 } | 1061 } |
| 1081 } | 1062 } |
| 1082 | 1063 |
| 1083 } // namespace shell_integration_linux | 1064 } // namespace shell_integration_linux |
| OLD | NEW |