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/platform_util.h" | 5 #include "chrome/browser/platform_util.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | |
| 8 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 9 #include "base/process/kill.h" | 10 #include "base/process/kill.h" |
| 10 #include "base/process/launch.h" | 11 #include "base/process/launch.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/version.h" | |
| 12 #include "chrome/browser/platform_util_internal.h" | 14 #include "chrome/browser/platform_util_internal.h" |
| 13 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 14 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 15 | 17 |
| 16 using content::BrowserThread; | 18 using content::BrowserThread; |
| 17 | 19 |
| 18 namespace platform_util { | 20 namespace platform_util { |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 24 const char kNautilusKey[] = "nautilus"; | |
| 25 const char kSupportedNautilusVersion[] = "3.0.2"; | |
| 26 | |
| 22 void XDGUtil(const std::string& util, | 27 void XDGUtil(const std::string& util, |
| 23 const base::FilePath& working_directory, | 28 const base::FilePath& working_directory, |
| 24 const std::string& arg) { | 29 const std::string& arg) { |
| 25 std::vector<std::string> argv; | 30 std::vector<std::string> argv; |
| 26 argv.push_back(util); | 31 argv.push_back(util); |
| 27 argv.push_back(arg); | 32 argv.push_back(arg); |
| 28 | 33 |
| 29 base::LaunchOptions options; | 34 base::LaunchOptions options; |
| 30 options.current_directory = working_directory; | 35 options.current_directory = working_directory; |
| 31 options.allow_new_privs = true; | 36 options.allow_new_privs = true; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 49 } | 54 } |
| 50 | 55 |
| 51 void XDGOpen(const base::FilePath& working_directory, const std::string& path) { | 56 void XDGOpen(const base::FilePath& working_directory, const std::string& path) { |
| 52 XDGUtil("xdg-open", working_directory, path); | 57 XDGUtil("xdg-open", working_directory, path); |
| 53 } | 58 } |
| 54 | 59 |
| 55 void XDGEmail(const std::string& email) { | 60 void XDGEmail(const std::string& email) { |
| 56 XDGUtil("xdg-email", base::FilePath(), email); | 61 XDGUtil("xdg-email", base::FilePath(), email); |
| 57 } | 62 } |
| 58 | 63 |
| 64 void ShowFileInNautilus(const base::FilePath& working_directory, | |
| 65 const std::string& path){ | |
|
Lei Zhang
2016/04/19 21:51:25
nit: space after )
maksims (do not use this acc)
2016/04/20 12:02:45
Done.
| |
| 66 XDGUtil("nautilus", working_directory, path); | |
| 67 } | |
| 68 | |
| 69 std::string GetNautilusVersion() { | |
| 70 std::string output; | |
| 71 std::string found_version; | |
| 72 | |
| 73 base::CommandLine nautilus_cl(base::FilePath("/usr/bin/nautilus")); | |
|
Lei Zhang
2016/04/19 21:51:25
Don't hard code /usr/bin/nautilus. It's also weird
maksims (do not use this acc)
2016/04/20 12:02:45
Done.
| |
| 74 nautilus_cl.AppendArg("--version"); | |
| 75 | |
| 76 if (base::GetAppOutputAndError(nautilus_cl, &output)) { | |
| 77 const std::size_t version_position = output.find(kNautilusKey) + | |
| 78 std::char_traits<char>::length(kNautilusKey) + 1; | |
|
Lei Zhang
2016/04/19 21:51:25
Why not just strlen()?
maksims (do not use this acc)
2016/04/20 12:02:45
Done. Different people like different ways of doin
Lei Zhang
2016/04/20 20:45:57
IMO the simpler version, unless there's some advan
| |
| 79 found_version = output.substr(version_position); | |
| 80 | |
| 81 if (!found_version.empty() && | |
| 82 found_version[found_version.length()-1] == '\n') { | |
|
Lei Zhang
2016/04/19 21:51:25
foo - 1
maksims (do not use this acc)
2016/04/20 12:02:45
Spaces?
Lei Zhang
2016/04/20 20:45:57
Yes, you forgot the next line as well. Alternative
| |
| 83 found_version.erase(found_version.length()-1); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 return found_version; | |
| 88 } | |
| 89 | |
| 90 void CheckNautilusIsDefault(std::string* str) { | |
| 91 const base::Version supported_version(kSupportedNautilusVersion); | |
|
Lei Zhang
2016/04/19 21:51:25
You can declare variables closer to where they are
maksims (do not use this acc)
2016/04/20 12:02:45
Done.
Lei Zhang
2016/04/20 20:45:57
I didn't mean move |kSupportedNautilusVersion|. I
| |
| 92 std::string file_browser; | |
| 93 | |
| 94 base::CommandLine xdg_mime(base::FilePath("/usr/bin/xdg-mime")); | |
|
Lei Zhang
2016/04/19 21:51:25
Don't hard code /usr/bin/xdg-mime. Use whatever th
maksims (do not use this acc)
2016/04/20 12:02:45
Done.
| |
| 95 xdg_mime.AppendArg("query"); | |
| 96 xdg_mime.AppendArg("default"); | |
| 97 xdg_mime.AppendArg("inode/directory"); | |
| 98 | |
| 99 if (base::GetAppOutputAndError(xdg_mime, &file_browser)) { | |
| 100 if (file_browser.find(kNautilusKey) != std::string::npos) { | |
|
Lei Zhang
2016/04/19 21:51:25
xdg-mime query default inode/directory is expected
maksims (do not use this acc)
2016/04/20 12:02:45
Done. Right my fault.
Lei Zhang
2016/04/20 20:45:57
Simplify to: file_browser == kNautilusKey ? If you
| |
| 101 base::Version current_version(GetNautilusVersion()); | |
| 102 if ((current_version.IsValid() && supported_version.IsValid()) && | |
| 103 (current_version >= supported_version)) { | |
| 104 *str = file_browser; | |
| 105 } | |
| 106 } | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 void ShowItem(Profile* profile, const base::FilePath& full_path, | |
| 111 const std::string* file_browser) { | |
| 112 if ((*file_browser).find(kNautilusKey) != std::string::npos) | |
|
Lei Zhang
2016/04/19 21:51:25
In general (*foo).bar() can be written as foo->bar
maksims (do not use this acc)
2016/04/20 12:02:45
Done. Depends how you like it.
| |
| 113 OpenItem(profile, full_path, SHOW_ITEM_IN_FOLDER, OpenOperationCallback()); | |
| 114 else | |
|
Lei Zhang
2016/04/19 21:51:25
Once again, when there are multi-line statements,
maksims (do not use this acc)
2016/04/20 12:02:45
Done.
| |
| 115 OpenItem(profile, full_path.DirName(), OPEN_FOLDER, | |
| 116 OpenOperationCallback()); | |
| 117 } | |
| 118 | |
| 59 } // namespace | 119 } // namespace |
| 60 | 120 |
| 61 namespace internal { | 121 namespace internal { |
| 62 | 122 |
| 63 void PlatformOpenVerifiedItem(const base::FilePath& path, OpenItemType type) { | 123 void PlatformOpenVerifiedItem(const base::FilePath& path, OpenItemType type) { |
| 64 switch (type) { | 124 switch (type) { |
| 65 case OPEN_FILE: | 125 case OPEN_FILE: |
| 66 XDGOpen(path.DirName(), path.value()); | 126 XDGOpen(path.DirName(), path.value()); |
| 67 break; | 127 break; |
| 68 case OPEN_FOLDER: | 128 case OPEN_FOLDER: |
| 69 // The utility process checks the working directory prior to the | 129 // The utility process checks the working directory prior to the |
| 70 // invocation of xdg-open by changing the current directory into it. This | 130 // invocation of xdg-open by changing the current directory into it. This |
| 71 // operation only succeeds if |path| is a directory. Opening "." from | 131 // operation only succeeds if |path| is a directory. Opening "." from |
| 72 // there ensures that the target of the operation is a directory. Note | 132 // there ensures that the target of the operation is a directory. Note |
| 73 // that there remains a TOCTOU race where the directory could be unlinked | 133 // that there remains a TOCTOU race where the directory could be unlinked |
| 74 // between the time the utility process changes into the directory and the | 134 // between the time the utility process changes into the directory and the |
| 75 // time the application invoked by xdg-open inspects the path by name. | 135 // time the application invoked by xdg-open inspects the path by name. |
| 76 XDGOpen(path, "."); | 136 XDGOpen(path, "."); |
| 77 break; | 137 break; |
| 138 case SHOW_ITEM_IN_FOLDER: | |
| 139 ShowFileInNautilus(path.DirName(), path.value()); | |
| 140 break; | |
| 78 } | 141 } |
| 79 } | 142 } |
| 143 | |
| 80 } // namespace internal | 144 } // namespace internal |
| 81 | 145 |
| 82 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) { | 146 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) { |
| 83 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 147 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 84 // TODO(estade): It would be nice to be able to select the file in the file | 148 std::string* output = new std::string; |
|
Lei Zhang
2016/04/19 21:51:25
No need, just:
base::PostTaskAndReplyWithResult(
maksims (do not use this acc)
2016/04/20 12:02:45
Done.
| |
| 85 // manager, but that probably requires extending xdg-open. For now just show | 149 BrowserThread::PostBlockingPoolTaskAndReply(FROM_HERE, |
| 86 // the folder. | 150 base::Bind(&CheckNautilusIsDefault, output), |
| 87 OpenItem(profile, full_path.DirName(), OPEN_FOLDER, OpenOperationCallback()); | 151 base::Bind(&ShowItem, profile, full_path, base::Owned(output))); |
| 88 } | 152 } |
| 89 | 153 |
| 90 void OpenExternal(Profile* profile, const GURL& url) { | 154 void OpenExternal(Profile* profile, const GURL& url) { |
| 91 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 155 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 92 if (url.SchemeIs("mailto")) | 156 if (url.SchemeIs("mailto")) |
| 93 XDGEmail(url.spec()); | 157 XDGEmail(url.spec()); |
| 94 else | 158 else |
| 95 XDGOpen(base::FilePath(), url.spec()); | 159 XDGOpen(base::FilePath(), url.spec()); |
| 96 } | 160 } |
| 97 | 161 |
| 98 } // namespace platform_util | 162 } // namespace platform_util |
| OLD | NEW |