| 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 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 const char kDesktopEntry[] = "Desktop Entry"; | 225 const char kDesktopEntry[] = "Desktop Entry"; |
| 226 | 226 |
| 227 const char kXdgOpenShebang[] = "#!/usr/bin/env xdg-open"; | 227 const char kXdgOpenShebang[] = "#!/usr/bin/env xdg-open"; |
| 228 | 228 |
| 229 const char kXdgSettings[] = "xdg-settings"; | 229 const char kXdgSettings[] = "xdg-settings"; |
| 230 const char kXdgSettingsDefaultBrowser[] = "default-web-browser"; | 230 const char kXdgSettingsDefaultBrowser[] = "default-web-browser"; |
| 231 const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler"; | 231 const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler"; |
| 232 | 232 |
| 233 } // namespace | 233 } // namespace |
| 234 | 234 |
| 235 // static | |
| 236 std::string ShellIntegration::GetDesktopName(base::Environment* env) { | |
| 237 #if defined(GOOGLE_CHROME_BUILD) | |
| 238 return "google-chrome.desktop"; | |
| 239 #else // CHROMIUM_BUILD | |
| 240 // Allow $CHROME_DESKTOP to override the built-in value, so that development | |
| 241 // versions can set themselves as the default without interfering with | |
| 242 // non-official, packaged versions using the built-in value. | |
| 243 std::string name; | |
| 244 if (env->GetVar("CHROME_DESKTOP", &name) && !name.empty()) | |
| 245 return name; | |
| 246 return "chromium-browser.desktop"; | |
| 247 #endif | |
| 248 } | |
| 249 | |
| 250 namespace { | 235 namespace { |
| 251 | 236 |
| 252 // Utility function to get the path to the version of a script shipped with | 237 // Utility function to get the path to the version of a script shipped with |
| 253 // Chrome. |script| gives the name of the script. |chrome_version| returns the | 238 // Chrome. |script| gives the name of the script. |chrome_version| returns the |
| 254 // path to the Chrome version of the script, and the return value of the | 239 // path to the Chrome version of the script, and the return value of the |
| 255 // function is true if the function is successful and the Chrome version is | 240 // function is true if the function is successful and the Chrome version is |
| 256 // not the script found on the PATH. | 241 // not the script found on the PATH. |
| 257 bool GetChromeVersionOfScript(const std::string& script, | 242 bool GetChromeVersionOfScript(const std::string& script, |
| 258 std::string* chrome_version) { | 243 std::string* chrome_version) { |
| 259 // Get the path to the Chrome version. | 244 // Get the path to the Chrome version. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 | 285 |
| 301 std::vector<std::string> argv; | 286 std::vector<std::string> argv; |
| 302 argv.push_back(kXdgSettings); | 287 argv.push_back(kXdgSettings); |
| 303 argv.push_back("set"); | 288 argv.push_back("set"); |
| 304 if (protocol.empty()) { | 289 if (protocol.empty()) { |
| 305 argv.push_back(kXdgSettingsDefaultBrowser); | 290 argv.push_back(kXdgSettingsDefaultBrowser); |
| 306 } else { | 291 } else { |
| 307 argv.push_back(kXdgSettingsDefaultSchemeHandler); | 292 argv.push_back(kXdgSettingsDefaultSchemeHandler); |
| 308 argv.push_back(protocol); | 293 argv.push_back(protocol); |
| 309 } | 294 } |
| 310 argv.push_back(ShellIntegration::GetDesktopName(env.get())); | 295 argv.push_back(ShellIntegrationLinux::GetDesktopName(env.get())); |
| 311 | 296 |
| 312 int exit_code; | 297 int exit_code; |
| 313 bool ran_ok = LaunchXdgUtility(argv, &exit_code); | 298 bool ran_ok = LaunchXdgUtility(argv, &exit_code); |
| 314 if (ran_ok && exit_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { | 299 if (ran_ok && exit_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { |
| 315 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { | 300 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { |
| 316 ran_ok = LaunchXdgUtility(argv, &exit_code); | 301 ran_ok = LaunchXdgUtility(argv, &exit_code); |
| 317 } | 302 } |
| 318 } | 303 } |
| 319 | 304 |
| 320 return ran_ok && exit_code == EXIT_SUCCESS; | 305 return ran_ok && exit_code == EXIT_SUCCESS; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 331 | 316 |
| 332 std::vector<std::string> argv; | 317 std::vector<std::string> argv; |
| 333 argv.push_back(kXdgSettings); | 318 argv.push_back(kXdgSettings); |
| 334 argv.push_back("check"); | 319 argv.push_back("check"); |
| 335 if (protocol.empty()) { | 320 if (protocol.empty()) { |
| 336 argv.push_back(kXdgSettingsDefaultBrowser); | 321 argv.push_back(kXdgSettingsDefaultBrowser); |
| 337 } else { | 322 } else { |
| 338 argv.push_back(kXdgSettingsDefaultSchemeHandler); | 323 argv.push_back(kXdgSettingsDefaultSchemeHandler); |
| 339 argv.push_back(protocol); | 324 argv.push_back(protocol); |
| 340 } | 325 } |
| 341 argv.push_back(ShellIntegration::GetDesktopName(env.get())); | 326 argv.push_back(ShellIntegrationLinux::GetDesktopName(env.get())); |
| 342 | 327 |
| 343 std::string reply; | 328 std::string reply; |
| 344 int success_code; | 329 int success_code; |
| 345 bool ran_ok = base::GetAppOutputWithExitCode(CommandLine(argv), &reply, | 330 bool ran_ok = base::GetAppOutputWithExitCode(CommandLine(argv), &reply, |
| 346 &success_code); | 331 &success_code); |
| 347 if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { | 332 if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { |
| 348 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { | 333 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { |
| 349 ran_ok = base::GetAppOutputWithExitCode(CommandLine(argv), &reply, | 334 ran_ok = base::GetAppOutputWithExitCode(CommandLine(argv), &reply, |
| 350 &success_code); | 335 &success_code); |
| 351 } | 336 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 argv.push_back(kXdgSettings); | 380 argv.push_back(kXdgSettings); |
| 396 argv.push_back("get"); | 381 argv.push_back("get"); |
| 397 argv.push_back(kXdgSettingsDefaultBrowser); | 382 argv.push_back(kXdgSettingsDefaultBrowser); |
| 398 | 383 |
| 399 std::string browser; | 384 std::string browser; |
| 400 // We don't care about the return value here. | 385 // We don't care about the return value here. |
| 401 base::GetAppOutput(CommandLine(argv), &browser); | 386 base::GetAppOutput(CommandLine(argv), &browser); |
| 402 return browser.find("irefox") != std::string::npos; | 387 return browser.find("irefox") != std::string::npos; |
| 403 } | 388 } |
| 404 | 389 |
| 405 // static | 390 namespace ShellIntegrationLinux { |
| 406 bool ShellIntegration::GetDesktopShortcutTemplate( | 391 |
| 407 base::Environment* env, std::string* output) { | 392 std::string GetDesktopName(base::Environment* env) { |
| 393 #if defined(GOOGLE_CHROME_BUILD) |
| 394 return "google-chrome.desktop"; |
| 395 #else // CHROMIUM_BUILD |
| 396 // Allow $CHROME_DESKTOP to override the built-in value, so that development |
| 397 // versions can set themselves as the default without interfering with |
| 398 // non-official, packaged versions using the built-in value. |
| 399 std::string name; |
| 400 if (env->GetVar("CHROME_DESKTOP", &name) && !name.empty()) |
| 401 return name; |
| 402 return "chromium-browser.desktop"; |
| 403 #endif |
| 404 } |
| 405 |
| 406 bool GetDesktopShortcutTemplate(base::Environment* env, |
| 407 std::string* output) { |
| 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 409 | 409 |
| 410 std::vector<FilePath> search_paths; | 410 std::vector<FilePath> search_paths; |
| 411 | 411 |
| 412 std::string xdg_data_home; | 412 std::string xdg_data_home; |
| 413 if (env->GetVar("XDG_DATA_HOME", &xdg_data_home) && | 413 if (env->GetVar("XDG_DATA_HOME", &xdg_data_home) && |
| 414 !xdg_data_home.empty()) { | 414 !xdg_data_home.empty()) { |
| 415 search_paths.push_back(FilePath(xdg_data_home)); | 415 search_paths.push_back(FilePath(xdg_data_home)); |
| 416 } | 416 } |
| 417 | 417 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 439 if (file_util::PathExists(path)) { | 439 if (file_util::PathExists(path)) { |
| 440 VLOG(1) << "Found desktop file template at " << path.value(); | 440 VLOG(1) << "Found desktop file template at " << path.value(); |
| 441 return file_util::ReadFileToString(path, output); | 441 return file_util::ReadFileToString(path, output); |
| 442 } | 442 } |
| 443 } | 443 } |
| 444 | 444 |
| 445 LOG(ERROR) << "Could not find desktop file template."; | 445 LOG(ERROR) << "Could not find desktop file template."; |
| 446 return false; | 446 return false; |
| 447 } | 447 } |
| 448 | 448 |
| 449 // static | 449 FilePath GetDesktopShortcutFilename(const GURL& url) { |
| 450 FilePath ShellIntegration::GetDesktopShortcutFilename(const GURL& url) { | |
| 451 // Use a prefix, because xdg-desktop-menu requires it. | 450 // Use a prefix, because xdg-desktop-menu requires it. |
| 452 std::string filename = | 451 std::string filename = |
| 453 std::string(chrome::kBrowserProcessExecutableName) + "-" + url.spec(); | 452 std::string(chrome::kBrowserProcessExecutableName) + "-" + url.spec(); |
| 454 file_util::ReplaceIllegalCharactersInPath(&filename, '_'); | 453 file_util::ReplaceIllegalCharactersInPath(&filename, '_'); |
| 455 | 454 |
| 456 FilePath desktop_path; | 455 FilePath desktop_path; |
| 457 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_path)) | 456 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_path)) |
| 458 return FilePath(); | 457 return FilePath(); |
| 459 | 458 |
| 460 FilePath filepath = desktop_path.Append(filename); | 459 FilePath filepath = desktop_path.Append(filename); |
| 461 FilePath alternative_filepath(filepath.value() + ".desktop"); | 460 FilePath alternative_filepath(filepath.value() + ".desktop"); |
| 462 for (size_t i = 1; i < 100; ++i) { | 461 for (size_t i = 1; i < 100; ++i) { |
| 463 if (file_util::PathExists(FilePath(alternative_filepath))) { | 462 if (file_util::PathExists(FilePath(alternative_filepath))) { |
| 464 alternative_filepath = FilePath( | 463 alternative_filepath = FilePath( |
| 465 filepath.value() + "_" + base::IntToString(i) + ".desktop"); | 464 filepath.value() + "_" + base::IntToString(i) + ".desktop"); |
| 466 } else { | 465 } else { |
| 467 return FilePath(alternative_filepath).BaseName(); | 466 return FilePath(alternative_filepath).BaseName(); |
| 468 } | 467 } |
| 469 } | 468 } |
| 470 | 469 |
| 471 return FilePath(); | 470 return FilePath(); |
| 472 } | 471 } |
| 473 | 472 |
| 474 // static | 473 std::string GetDesktopFileContents( |
| 475 std::string ShellIntegration::GetDesktopFileContents( | |
| 476 const std::string& template_contents, | 474 const std::string& template_contents, |
| 477 const std::string& app_name, | 475 const std::string& app_name, |
| 478 const GURL& url, | 476 const GURL& url, |
| 479 const std::string& extension_id, | 477 const std::string& extension_id, |
| 480 const bool is_platform_app, | 478 const bool is_platform_app, |
| 481 const FilePath& web_app_path, | 479 const FilePath& web_app_path, |
| 482 const FilePath& extension_path, | 480 const FilePath& extension_path, |
| 483 const string16& title, | 481 const string16& title, |
| 484 const std::string& icon_name) { | 482 const std::string& icon_name) { |
| 485 if (template_contents.empty()) | 483 if (template_contents.empty()) |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 gchar* data_dump = g_key_file_to_data(key_file, &length, NULL); | 581 gchar* data_dump = g_key_file_to_data(key_file, &length, NULL); |
| 584 if (data_dump) { | 582 if (data_dump) { |
| 585 output_buffer += data_dump; | 583 output_buffer += data_dump; |
| 586 g_free(data_dump); | 584 g_free(data_dump); |
| 587 } | 585 } |
| 588 | 586 |
| 589 g_key_file_free(key_file); | 587 g_key_file_free(key_file); |
| 590 return output_buffer; | 588 return output_buffer; |
| 591 } | 589 } |
| 592 | 590 |
| 593 // static | 591 bool CreateDesktopShortcut( |
| 594 bool ShellIntegration::CreateDesktopShortcut( | 592 const ShellIntegration::ShortcutInfo& shortcut_info, |
| 595 const ShortcutInfo& shortcut_info, | |
| 596 const std::string& shortcut_template) { | 593 const std::string& shortcut_template) { |
| 597 DCHECK(!shortcut_info.is_platform_app); | 594 DCHECK(!shortcut_info.is_platform_app); |
| 598 DCHECK(shortcut_info.extension_id.empty()); | 595 DCHECK(shortcut_info.extension_id.empty()); |
| 599 | 596 |
| 600 return ShellIntegrationLinux::CreateDesktopShortcutForChromeApp( | 597 return ShellIntegrationLinux::CreateDesktopShortcutForChromeApp( |
| 601 shortcut_info, FilePath(), shortcut_template); | 598 shortcut_info, FilePath(), shortcut_template); |
| 602 } | 599 } |
| 603 | 600 |
| 604 namespace ShellIntegrationLinux { | |
| 605 | |
| 606 bool CreateDesktopShortcutForChromeApp( | 601 bool CreateDesktopShortcutForChromeApp( |
| 607 const ShellIntegration::ShortcutInfo& shortcut_info, | 602 const ShellIntegration::ShortcutInfo& shortcut_info, |
| 608 const FilePath& web_app_path, | 603 const FilePath& web_app_path, |
| 609 const std::string& shortcut_template) { | 604 const std::string& shortcut_template) { |
| 610 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 605 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 611 | 606 |
| 612 FilePath shortcut_filename = ShellIntegration::GetDesktopShortcutFilename( | 607 FilePath shortcut_filename = |
| 613 shortcut_info.url); | 608 ShellIntegrationLinux::GetDesktopShortcutFilename(shortcut_info.url); |
| 614 if (shortcut_filename.empty()) | 609 if (shortcut_filename.empty()) |
| 615 return false; | 610 return false; |
| 616 | 611 |
| 617 std::string icon_name = CreateShortcutIcon(shortcut_info, shortcut_filename); | 612 std::string icon_name =CreateShortcutIcon(shortcut_info, shortcut_filename); |
| 618 | 613 |
| 619 std::string app_name = | 614 std::string app_name = |
| 620 web_app::GenerateApplicationNameFromInfo(shortcut_info); | 615 web_app::GenerateApplicationNameFromInfo(shortcut_info); |
| 621 std::string contents = ShellIntegration::GetDesktopFileContents( | 616 std::string contents = ShellIntegrationLinux::GetDesktopFileContents( |
| 622 shortcut_template, | 617 shortcut_template, |
| 623 app_name, | 618 app_name, |
| 624 shortcut_info.url, | 619 shortcut_info.url, |
| 625 shortcut_info.extension_id, | 620 shortcut_info.extension_id, |
| 626 shortcut_info.is_platform_app, | 621 shortcut_info.is_platform_app, |
| 627 web_app_path, | 622 web_app_path, |
| 628 shortcut_info.extension_path, | 623 shortcut_info.extension_path, |
| 629 shortcut_info.title, | 624 shortcut_info.title, |
| 630 icon_name); | 625 icon_name); |
| 631 | 626 |
| 632 bool success = true; | 627 bool success = true; |
| 633 | 628 |
| 634 if (shortcut_info.create_on_desktop) | 629 if (shortcut_info.create_on_desktop) |
| 635 success = CreateShortcutOnDesktop(shortcut_filename, contents); | 630 success = CreateShortcutOnDesktop(shortcut_filename, contents); |
| 636 | 631 |
| 637 if (shortcut_info.create_in_applications_menu) | 632 if (shortcut_info.create_in_applications_menu) |
| 638 success = CreateShortcutInApplicationsMenu(shortcut_filename, contents) && | 633 success = CreateShortcutInApplicationsMenu(shortcut_filename, contents) && |
| 639 success; | 634 success; |
| 640 | 635 |
| 641 return success; | 636 return success; |
| 642 } | 637 } |
| 643 | 638 |
| 644 } // namespace ShellIntegrationLinux | 639 } // namespace ShellIntegrationLinux |
| OLD | NEW |