Chromium Code Reviews| 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 #include <glib.h> | 8 #include <glib.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 #include "base/strings/string_tokenizer.h" | 33 #include "base/strings/string_tokenizer.h" |
| 34 #include "base/strings/string_util.h" | 34 #include "base/strings/string_util.h" |
| 35 #include "base/strings/utf_string_conversions.h" | 35 #include "base/strings/utf_string_conversions.h" |
| 36 #include "base/threading/thread.h" | 36 #include "base/threading/thread.h" |
| 37 #include "base/threading/thread_restrictions.h" | 37 #include "base/threading/thread_restrictions.h" |
| 38 #include "build/build_config.h" | 38 #include "build/build_config.h" |
| 39 #include "chrome/browser/web_applications/web_app.h" | 39 #include "chrome/browser/web_applications/web_app.h" |
| 40 #include "chrome/common/chrome_constants.h" | 40 #include "chrome/common/chrome_constants.h" |
| 41 #include "chrome/common/chrome_version_info.h" | 41 #include "chrome/common/chrome_version_info.h" |
| 42 #include "content/public/browser/browser_thread.h" | 42 #include "content/public/browser/browser_thread.h" |
| 43 #include "grit/chromium_strings.h" | |
| 44 #include "ui/base/l10n/l10n_util.h" | |
|
gab
2013/10/17 15:13:31
Includes no longer required.
calamity
2013/11/20 05:43:30
Done.
| |
| 43 #include "ui/gfx/image/image_family.h" | 45 #include "ui/gfx/image/image_family.h" |
| 44 #include "url/gurl.h" | 46 #include "url/gurl.h" |
| 45 | 47 |
| 46 using content::BrowserThread; | 48 using content::BrowserThread; |
| 47 | 49 |
| 48 namespace { | 50 namespace { |
| 49 | 51 |
| 50 // Helper to launch xdg scripts. We don't want them to ask any questions on the | 52 // Helper to launch xdg scripts. We don't want them to ask any questions on the |
| 51 // terminal etc. The function returns true if the utility launches and exits | 53 // terminal etc. The function returns true if the utility launches and exits |
| 52 // cleanly, in which case |exit_code| returns the utility's exit code. | 54 // cleanly, in which case |exit_code| returns the utility's exit code. |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 } | 581 } |
| 580 | 582 |
| 581 ShellIntegration::ShortcutLocations GetExistingShortcutLocations( | 583 ShellIntegration::ShortcutLocations GetExistingShortcutLocations( |
| 582 base::Environment* env, | 584 base::Environment* env, |
| 583 const base::FilePath& profile_path, | 585 const base::FilePath& profile_path, |
| 584 const std::string& extension_id) { | 586 const std::string& extension_id) { |
| 585 base::FilePath desktop_path; | 587 base::FilePath desktop_path; |
| 586 // If Get returns false, just leave desktop_path empty. | 588 // If Get returns false, just leave desktop_path empty. |
| 587 PathService::Get(base::DIR_USER_DESKTOP, &desktop_path); | 589 PathService::Get(base::DIR_USER_DESKTOP, &desktop_path); |
| 588 return GetExistingShortcutLocations(env, profile_path, extension_id, | 590 return GetExistingShortcutLocations(env, profile_path, extension_id, |
| 589 desktop_path); | 591 desktop_path); |
| 590 } | 592 } |
| 591 | 593 |
| 592 ShellIntegration::ShortcutLocations GetExistingShortcutLocations( | 594 ShellIntegration::ShortcutLocations GetExistingShortcutLocations( |
| 593 base::Environment* env, | 595 base::Environment* env, |
| 594 const base::FilePath& profile_path, | 596 const base::FilePath& profile_path, |
| 595 const std::string& extension_id, | 597 const std::string& extension_id, |
| 596 const base::FilePath& desktop_path) { | 598 const base::FilePath& desktop_path) { |
| 597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 599 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 598 | 600 |
| 599 base::FilePath shortcut_filename = GetExtensionShortcutFilename( | 601 base::FilePath shortcut_filename = GetExtensionShortcutFilename( |
| 600 profile_path, extension_id); | 602 profile_path, extension_id); |
| 601 DCHECK(!shortcut_filename.empty()); | 603 DCHECK(!shortcut_filename.empty()); |
| 602 ShellIntegration::ShortcutLocations locations; | 604 ShellIntegration::ShortcutLocations locations; |
| 603 | 605 |
| 604 // Determine whether there is a shortcut on desktop. | 606 // Determine whether there is a shortcut on desktop. |
| 605 if (!desktop_path.empty()) { | 607 if (!desktop_path.empty()) { |
| 606 locations.on_desktop = | 608 locations.on_desktop = |
| 607 base::PathExists(desktop_path.Append(shortcut_filename)); | 609 base::PathExists(desktop_path.Append(shortcut_filename)); |
| 608 } | 610 } |
| 609 | 611 |
| 610 // Determine whether there is a shortcut in the applications directory. | 612 // Determine whether there is a shortcut in the applications directory. |
| 611 std::string shortcut_contents; | 613 std::string shortcut_contents; |
| 612 if (GetExistingShortcutContents(env, shortcut_filename, &shortcut_contents)) { | 614 if (GetExistingShortcutContents(env, shortcut_filename, &shortcut_contents)) { |
| 613 // Whether this counts as "hidden" or "in_applications_menu" depends on | 615 // Whether this counts as "hidden" or |
| 614 // whether it contains NoDisplay=true. | 616 // "APP_MENU_LOCATION_SUBDIR_CHROMEAPPS" depends on whether it contains |
|
huangs
2013/10/17 19:13:35
NIT: I think you can unwrap "APP_MENU_LOCATION_SUB
calamity
2013/11/20 05:43:30
Done.
| |
| 615 if (GetNoDisplayFromDesktopFile(shortcut_contents)) | 617 // NoDisplay=true. Since these shortcuts are for apps, they are always in |
| 618 // the "Chrome Apps" directory. | |
| 619 if (GetNoDisplayFromDesktopFile(shortcut_contents)) { | |
| 616 locations.hidden = true; | 620 locations.hidden = true; |
| 617 else | 621 } else { |
| 618 locations.in_applications_menu = true; | 622 locations.applications_menu_location = |
| 623 ShellIntegration::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; | |
| 624 } | |
| 619 } | 625 } |
| 620 | 626 |
| 621 return locations; | 627 return locations; |
| 622 } | 628 } |
| 623 | 629 |
| 624 bool GetExistingShortcutContents(base::Environment* env, | 630 bool GetExistingShortcutContents(base::Environment* env, |
| 625 const base::FilePath& desktop_filename, | 631 const base::FilePath& desktop_filename, |
| 626 std::string* output) { | 632 std::string* output) { |
| 627 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 633 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 628 | 634 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 841 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 836 | 842 |
| 837 base::FilePath shortcut_filename; | 843 base::FilePath shortcut_filename; |
| 838 if (!shortcut_info.extension_id.empty()) { | 844 if (!shortcut_info.extension_id.empty()) { |
| 839 shortcut_filename = GetExtensionShortcutFilename( | 845 shortcut_filename = GetExtensionShortcutFilename( |
| 840 shortcut_info.profile_path, shortcut_info.extension_id); | 846 shortcut_info.profile_path, shortcut_info.extension_id); |
| 841 // For extensions we do not want duplicate shortcuts. So, delete any that | 847 // For extensions we do not want duplicate shortcuts. So, delete any that |
| 842 // already exist and replace them. | 848 // already exist and replace them. |
| 843 if (creation_locations.on_desktop) | 849 if (creation_locations.on_desktop) |
| 844 DeleteShortcutOnDesktop(shortcut_filename); | 850 DeleteShortcutOnDesktop(shortcut_filename); |
| 845 if (creation_locations.in_applications_menu || creation_locations.hidden) | 851 // The 'applications_menu_location' and 'hidden' locations are actually the |
| 852 // same place ('applications'). | |
| 853 if (creation_locations.applications_menu_location != | |
| 854 ShellIntegration::APP_MENU_LOCATION_NONE || | |
|
gab
2013/10/17 15:13:31
nit: indent this line 4 spaces as it's a continuat
calamity
2013/11/20 05:43:30
Done.
| |
| 855 creation_locations.hidden) | |
| 846 DeleteShortcutInApplicationsMenu(shortcut_filename, base::FilePath()); | 856 DeleteShortcutInApplicationsMenu(shortcut_filename, base::FilePath()); |
| 847 } else { | 857 } else { |
| 848 shortcut_filename = GetWebShortcutFilename(shortcut_info.url); | 858 shortcut_filename = GetWebShortcutFilename(shortcut_info.url); |
| 849 } | 859 } |
| 850 if (shortcut_filename.empty()) | 860 if (shortcut_filename.empty()) |
| 851 return false; | 861 return false; |
| 852 | 862 |
| 853 std::string icon_name = CreateShortcutIcon(shortcut_info, shortcut_filename); | 863 std::string icon_name = CreateShortcutIcon(shortcut_info, shortcut_filename); |
| 854 | 864 |
| 855 std::string app_name = | 865 std::string app_name = |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 870 shortcut_info.url, | 880 shortcut_info.url, |
| 871 shortcut_info.extension_id, | 881 shortcut_info.extension_id, |
| 872 shortcut_info.extension_path, | 882 shortcut_info.extension_path, |
| 873 shortcut_info.title, | 883 shortcut_info.title, |
| 874 icon_name, | 884 icon_name, |
| 875 shortcut_info.profile_path, | 885 shortcut_info.profile_path, |
| 876 false); | 886 false); |
| 877 success = CreateShortcutOnDesktop(shortcut_filename, contents); | 887 success = CreateShortcutOnDesktop(shortcut_filename, contents); |
| 878 } | 888 } |
| 879 | 889 |
| 880 // The 'in_applications_menu' and 'hidden' locations are actually the same | 890 if (creation_locations.applications_menu_location != |
| 881 // place ('applications'). | 891 ShellIntegration::APP_MENU_LOCATION_NONE || |
|
gab
2013/10/17 15:13:31
nit: indent 4 spaces in here too
calamity
2013/11/20 05:43:30
Done.
| |
| 882 if (creation_locations.in_applications_menu || creation_locations.hidden) { | 892 creation_locations.hidden) { |
| 883 base::FilePath directory_filename; | 893 base::FilePath directory_filename; |
| 884 std::string directory_contents; | 894 std::string directory_contents; |
| 885 if (!creation_locations.applications_menu_subdir.empty()) { | 895 if (creation_locations.applications_menu_location == |
| 896 ShellIntegration::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS) { | |
|
gab
2013/10/17 15:13:31
nit: indent 4 spaces
calamity
2013/11/20 05:43:30
Done.
| |
| 886 directory_filename = base::FilePath(kDirectoryFilename); | 897 directory_filename = base::FilePath(kDirectoryFilename); |
| 887 directory_contents = ShellIntegrationLinux::GetDirectoryFileContents( | 898 directory_contents = ShellIntegrationLinux::GetDirectoryFileContents( |
| 888 creation_locations.applications_menu_subdir, ""); | 899 ShellIntegration::GetAppShortcutsSubdirName(), ""); |
| 889 } | 900 } |
| 890 // Set NoDisplay=true if hidden but not in_applications_menu. This will hide | 901 // Set NoDisplay=true if hidden but not in the applications menu. This will |
| 891 // the application from user-facing menus. | 902 // hide the application from user-facing menus. |
| 892 std::string contents = ShellIntegrationLinux::GetDesktopFileContents( | 903 std::string contents = ShellIntegrationLinux::GetDesktopFileContents( |
| 893 chrome_exe_path, | 904 chrome_exe_path, |
| 894 app_name, | 905 app_name, |
| 895 shortcut_info.url, | 906 shortcut_info.url, |
| 896 shortcut_info.extension_id, | 907 shortcut_info.extension_id, |
| 897 shortcut_info.extension_path, | 908 shortcut_info.extension_path, |
| 898 shortcut_info.title, | 909 shortcut_info.title, |
| 899 icon_name, | 910 icon_name, |
| 900 shortcut_info.profile_path, | 911 shortcut_info.profile_path, |
| 901 !creation_locations.in_applications_menu); | 912 creation_locations.applications_menu_location == |
| 913 ShellIntegration::APP_MENU_LOCATION_NONE); | |
| 902 success = CreateShortcutInApplicationsMenu( | 914 success = CreateShortcutInApplicationsMenu( |
| 903 shortcut_filename, contents, directory_filename, directory_contents) && | 915 shortcut_filename, contents, directory_filename, directory_contents) && |
| 904 success; | 916 success; |
| 905 } | 917 } |
| 906 | 918 |
| 907 return success; | 919 return success; |
| 908 } | 920 } |
| 909 | 921 |
| 910 void DeleteDesktopShortcuts(const base::FilePath& profile_path, | 922 void DeleteDesktopShortcuts(const base::FilePath& profile_path, |
| 911 const std::string& extension_id) { | 923 const std::string& extension_id) { |
| 912 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 924 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 913 | 925 |
| 914 base::FilePath shortcut_filename = GetExtensionShortcutFilename( | 926 base::FilePath shortcut_filename = GetExtensionShortcutFilename( |
| 915 profile_path, extension_id); | 927 profile_path, extension_id); |
| 916 DCHECK(!shortcut_filename.empty()); | 928 DCHECK(!shortcut_filename.empty()); |
| 917 | 929 |
| 918 DeleteShortcutOnDesktop(shortcut_filename); | 930 DeleteShortcutOnDesktop(shortcut_filename); |
| 919 // Delete shortcuts from |kDirectoryFilename|. | 931 // Delete shortcuts from |kDirectoryFilename|. |
| 920 // Note that it is possible that shortcuts were not created in the Chrome Apps | 932 // Note that it is possible that shortcuts were not created in the Chrome Apps |
| 921 // directory (depending on the value of |applications_menu_subdir| when they | 933 // directory. It doesn't matter: this will still delete the shortcut even if |
| 922 // were created). It doesn't matter: this will still delete the shortcut even | 934 // it isn't in the directory. |
| 923 // if it isn't in the directory. | |
| 924 DeleteShortcutInApplicationsMenu(shortcut_filename, | 935 DeleteShortcutInApplicationsMenu(shortcut_filename, |
| 925 base::FilePath(kDirectoryFilename)); | 936 base::FilePath(kDirectoryFilename)); |
| 926 } | 937 } |
| 927 | 938 |
| 928 void DeleteAllDesktopShortcuts(const base::FilePath& profile_path) { | 939 void DeleteAllDesktopShortcuts(const base::FilePath& profile_path) { |
| 929 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 940 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 930 | 941 |
| 931 scoped_ptr<base::Environment> env(base::Environment::Create()); | 942 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 932 | 943 |
| 933 // Delete shortcuts from Desktop. | 944 // Delete shortcuts from Desktop. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 951 for (std::vector<base::FilePath>::const_iterator it = | 962 for (std::vector<base::FilePath>::const_iterator it = |
| 952 shortcut_filenames_app_menu.begin(); | 963 shortcut_filenames_app_menu.begin(); |
| 953 it != shortcut_filenames_app_menu.end(); ++it) { | 964 it != shortcut_filenames_app_menu.end(); ++it) { |
| 954 DeleteShortcutInApplicationsMenu(*it, | 965 DeleteShortcutInApplicationsMenu(*it, |
| 955 base::FilePath(kDirectoryFilename)); | 966 base::FilePath(kDirectoryFilename)); |
| 956 } | 967 } |
| 957 } | 968 } |
| 958 } | 969 } |
| 959 | 970 |
| 960 } // namespace ShellIntegrationLinux | 971 } // namespace ShellIntegrationLinux |
| OLD | NEW |