| 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 |