OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-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/shell_integration.h" | 5 #include "chrome/browser/shell_integration.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
23 #include "base/process_util.h" | 23 #include "base/process_util.h" |
24 #include "base/scoped_temp_dir.h" | 24 #include "base/scoped_temp_dir.h" |
25 #include "base/string_tokenizer.h" | 25 #include "base/string_tokenizer.h" |
26 #include "base/string_util.h" | 26 #include "base/string_util.h" |
27 #include "base/task.h" | 27 #include "base/task.h" |
28 #include "base/thread.h" | 28 #include "base/thread.h" |
29 #include "chrome/browser/browser_process.h" | 29 #include "chrome/browser/browser_process.h" |
30 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
31 #include "chrome/common/chrome_paths.h" | 31 #include "chrome/common/chrome_paths.h" |
| 32 #include "chrome/common/chrome_plugin_util.h" |
32 #include "chrome/common/chrome_switches.h" | 33 #include "chrome/common/chrome_switches.h" |
33 #include "googleurl/src/gurl.h" | 34 #include "googleurl/src/gurl.h" |
34 | 35 |
35 namespace { | 36 namespace { |
36 | 37 |
37 const char* GetDesktopName() { | 38 const char* GetDesktopName() { |
38 #if defined(GOOGLE_CHROME_BUILD) | 39 #if defined(GOOGLE_CHROME_BUILD) |
39 return "google-chrome.desktop"; | 40 return "google-chrome.desktop"; |
40 #else // CHROMIUM_BUILD | 41 #else // CHROMIUM_BUILD |
41 static const char* name = NULL; | 42 static const char* name = NULL; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 } | 115 } |
115 | 116 |
116 virtual void Run() { | 117 virtual void Run() { |
117 // TODO(phajdan.jr): Report errors from this function, possibly as infobars. | 118 // TODO(phajdan.jr): Report errors from this function, possibly as infobars. |
118 std::string template_contents; | 119 std::string template_contents; |
119 if (!GetDesktopShortcutTemplate(&template_contents)) | 120 if (!GetDesktopShortcutTemplate(&template_contents)) |
120 return; | 121 return; |
121 | 122 |
122 FilePath shortcut_filename = | 123 FilePath shortcut_filename = |
123 ShellIntegration::GetDesktopShortcutFilename(shortcut_info_.url); | 124 ShellIntegration::GetDesktopShortcutFilename(shortcut_info_.url); |
| 125 if (shortcut_filename.empty()) |
| 126 return; |
124 | 127 |
125 std::string icon_name = CreateIcon(shortcut_filename); | 128 std::string icon_name = CreateIcon(shortcut_filename); |
126 | 129 |
127 std::string contents = ShellIntegration::GetDesktopFileContents( | 130 std::string contents = ShellIntegration::GetDesktopFileContents( |
128 template_contents, shortcut_info_.url, shortcut_info_.title, | 131 template_contents, shortcut_info_.url, shortcut_info_.title, |
129 icon_name); | 132 icon_name); |
130 | 133 |
131 if (shortcut_info_.create_on_desktop) | 134 if (shortcut_info_.create_on_desktop) |
132 CreateOnDesktop(shortcut_filename, contents); | 135 CreateOnDesktop(shortcut_filename, contents); |
133 | 136 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 argv.push_back("default-web-browser"); | 289 argv.push_back("default-web-browser"); |
287 | 290 |
288 std::string browser; | 291 std::string browser; |
289 // We don't care about the return value here. | 292 // We don't care about the return value here. |
290 base::GetAppOutput(CommandLine(argv), &browser); | 293 base::GetAppOutput(CommandLine(argv), &browser); |
291 return browser.find("irefox") != std::string::npos; | 294 return browser.find("irefox") != std::string::npos; |
292 } | 295 } |
293 | 296 |
294 FilePath ShellIntegration::GetDesktopShortcutFilename(const GURL& url) { | 297 FilePath ShellIntegration::GetDesktopShortcutFilename(const GURL& url) { |
295 // Use a prefix, because xdg-desktop-menu requires it. | 298 // Use a prefix, because xdg-desktop-menu requires it. |
296 std::wstring filename = std::wstring(chrome::kBrowserProcessExecutableName) + | 299 std::wstring filename_wide = |
297 L"-" + UTF8ToWide(url.spec()) + L".desktop"; | 300 std::wstring(chrome::kBrowserProcessExecutableName) + L"-" + |
298 file_util::ReplaceIllegalCharacters(&filename, '_'); | 301 UTF8ToWide(url.spec()); |
| 302 file_util::ReplaceIllegalCharacters(&filename_wide, '_'); |
299 | 303 |
300 // Return BaseName to be absolutely sure we're not vulnerable to a directory | 304 FilePath desktop_path; |
301 // traversal attack. | 305 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_path)) |
302 return FilePath::FromWStringHack(filename).BaseName(); | 306 return FilePath(); |
| 307 |
| 308 FilePath filepath = desktop_path.Append( |
| 309 FilePath::FromWStringHack(filename_wide)); |
| 310 FilePath alternative_filepath(filepath.value() + ".desktop"); |
| 311 for (size_t i = 1; i < 100; ++i) { |
| 312 if (file_util::PathExists(FilePath(alternative_filepath))) { |
| 313 alternative_filepath = FilePath(filepath.value() + "_" + IntToString(i) + |
| 314 ".desktop"); |
| 315 } else { |
| 316 return FilePath(alternative_filepath).BaseName(); |
| 317 } |
| 318 } |
| 319 |
| 320 return FilePath(); |
303 } | 321 } |
304 | 322 |
305 std::string ShellIntegration::GetDesktopFileContents( | 323 std::string ShellIntegration::GetDesktopFileContents( |
306 const std::string& template_contents, const GURL& url, | 324 const std::string& template_contents, const GURL& url, |
307 const string16& title, const std::string& icon_name) { | 325 const string16& title, const std::string& icon_name) { |
308 // See http://standards.freedesktop.org/desktop-entry-spec/latest/ | 326 // See http://standards.freedesktop.org/desktop-entry-spec/latest/ |
309 // Although not required by the spec, Nautilus on Ubuntu Karmic creates its | 327 // Although not required by the spec, Nautilus on Ubuntu Karmic creates its |
310 // launchers with an xdg-open shebang. Follow that convention. | 328 // launchers with an xdg-open shebang. Follow that convention. |
311 std::string output_buffer("#!/usr/bin/env xdg-open\n"); | 329 std::string output_buffer("#!/usr/bin/env xdg-open\n"); |
312 StringTokenizer tokenizer(template_contents, "\n"); | 330 StringTokenizer tokenizer(template_contents, "\n"); |
313 while (tokenizer.GetNext()) { | 331 while (tokenizer.GetNext()) { |
314 if (tokenizer.token().substr(0, 5) == "Exec=") { | 332 if (tokenizer.token().substr(0, 5) == "Exec=") { |
315 std::string exec_path = tokenizer.token().substr(5); | 333 std::string exec_path = tokenizer.token().substr(5); |
316 StringTokenizer exec_tokenizer(exec_path, " "); | 334 StringTokenizer exec_tokenizer(exec_path, " "); |
317 std::string final_path; | 335 std::string final_path; |
318 while (exec_tokenizer.GetNext()) { | 336 while (exec_tokenizer.GetNext()) { |
319 if (exec_tokenizer.token() != "%U") | 337 if (exec_tokenizer.token() != "%U") |
320 final_path += exec_tokenizer.token() + " "; | 338 final_path += exec_tokenizer.token() + " "; |
321 } | 339 } |
322 std::wstring app_switch_wide(switches::kApp); | 340 std::string switches; |
323 std::string app_switch(StringPrintf("\"--%s=%s\"", | 341 CPB_GetCommandLineArgumentsCommon(url.spec().c_str(), &switches); |
324 WideToUTF8(app_switch_wide).c_str(), | 342 output_buffer += std::string("Exec=") + final_path + switches + "\n"; |
325 url.spec().c_str())); | |
326 // Sanitize the command line string. | |
327 ReplaceSubstringsAfterOffset(&app_switch, 0, "%", "%%"); | |
328 ReplaceSubstringsAfterOffset(&app_switch, 0, ";", ""); | |
329 ReplaceSubstringsAfterOffset(&app_switch, 0, "$", ""); | |
330 output_buffer += std::string("Exec=") + final_path + app_switch + "\n"; | |
331 } else if (tokenizer.token().substr(0, 5) == "Name=") { | 343 } else if (tokenizer.token().substr(0, 5) == "Name=") { |
332 std::string final_title = UTF16ToUTF8(title); | 344 std::string final_title = UTF16ToUTF8(title); |
333 // Make sure no endline characters can slip in and possibly introduce | 345 // Make sure no endline characters can slip in and possibly introduce |
334 // additional lines (like Exec, which makes it a security risk). Also | 346 // additional lines (like Exec, which makes it a security risk). Also |
335 // use the URL as a default when the title is empty. | 347 // use the URL as a default when the title is empty. |
336 if (final_title.empty() || | 348 if (final_title.empty() || |
337 final_title.find("\n") != std::string::npos || | 349 final_title.find("\n") != std::string::npos || |
338 final_title.find("\r") != std::string::npos) { | 350 final_title.find("\r") != std::string::npos) { |
339 final_title = url.spec(); | 351 final_title = url.spec(); |
340 } | 352 } |
(...skipping 10 matching lines...) Expand all Loading... |
351 } | 363 } |
352 } | 364 } |
353 return output_buffer; | 365 return output_buffer; |
354 } | 366 } |
355 | 367 |
356 void ShellIntegration::CreateDesktopShortcut( | 368 void ShellIntegration::CreateDesktopShortcut( |
357 const ShortcutInfo& shortcut_info) { | 369 const ShortcutInfo& shortcut_info) { |
358 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, | 370 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, |
359 new CreateDesktopShortcutTask(shortcut_info)); | 371 new CreateDesktopShortcutTask(shortcut_info)); |
360 } | 372 } |
OLD | NEW |