Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: chrome/browser/process_singleton_linux.cc

Issue 9968053: Refactor ProcessSingleton so that it may be used distinctly from a full browser process. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix comment nits. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/process_singleton.cc ('k') | chrome/browser/process_singleton_linux_uitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // On Linux, when the user tries to launch a second copy of chrome, we check 5 // On Linux, when the user tries to launch a second copy of chrome, we check
6 // for a socket in the user's profile directory. If the socket file is open we 6 // for a socket in the user's profile directory. If the socket file is open we
7 // send a message to the first chrome browser process with the current 7 // send a message to the first chrome browser process with the current
8 // directory and second process command line flags. The second process then 8 // directory and second process command line flags. The second process then
9 // exits. 9 // exits.
10 // 10 //
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 #include "base/safe_strerror_posix.h" 73 #include "base/safe_strerror_posix.h"
74 #include "base/stl_util.h" 74 #include "base/stl_util.h"
75 #include "base/string_number_conversions.h" 75 #include "base/string_number_conversions.h"
76 #include "base/string_split.h" 76 #include "base/string_split.h"
77 #include "base/stringprintf.h" 77 #include "base/stringprintf.h"
78 #include "base/sys_string_conversions.h" 78 #include "base/sys_string_conversions.h"
79 #include "base/threading/platform_thread.h" 79 #include "base/threading/platform_thread.h"
80 #include "base/time.h" 80 #include "base/time.h"
81 #include "base/timer.h" 81 #include "base/timer.h"
82 #include "base/utf_string_conversions.h" 82 #include "base/utf_string_conversions.h"
83 #include "chrome/browser/browser_process.h"
84 #if defined(TOOLKIT_GTK) 83 #if defined(TOOLKIT_GTK)
85 #include "chrome/browser/ui/gtk/process_singleton_dialog.h" 84 #include "chrome/browser/ui/gtk/process_singleton_dialog.h"
86 #endif 85 #endif
87 #include "chrome/browser/io_thread.h"
88 #include "chrome/browser/profiles/profile.h"
89 #include "chrome/browser/profiles/profile_manager.h"
90 #include "chrome/browser/ui/browser_init.h"
91 #include "chrome/common/chrome_constants.h" 86 #include "chrome/common/chrome_constants.h"
92 #include "chrome/common/chrome_paths.h"
93 #include "chrome/common/chrome_switches.h" 87 #include "chrome/common/chrome_switches.h"
94 #include "content/public/browser/browser_thread.h" 88 #include "content/public/browser/browser_thread.h"
95 #include "grit/chromium_strings.h" 89 #include "grit/chromium_strings.h"
96 #include "grit/generated_resources.h" 90 #include "grit/generated_resources.h"
97 #include "net/base/net_util.h" 91 #include "net/base/net_util.h"
98 #include "ui/base/l10n/l10n_util.h" 92 #include "ui/base/l10n/l10n_util.h"
99 93
100 using content::BrowserThread; 94 using content::BrowserThread;
101 95
102 const int ProcessSingleton::kTimeoutInSeconds; 96 const int ProcessSingleton::kTimeoutInSeconds;
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 // we are probably in a first run critical phase. 617 // we are probably in a first run critical phase.
624 if (parent_->locked()) { 618 if (parent_->locked()) {
625 DLOG(WARNING) << "Browser is locked"; 619 DLOG(WARNING) << "Browser is locked";
626 parent_->saved_startup_messages_.push_back( 620 parent_->saved_startup_messages_.push_back(
627 std::make_pair(argv, FilePath(current_dir))); 621 std::make_pair(argv, FilePath(current_dir)));
628 // Send back "ACK" message to prevent the client process from starting up. 622 // Send back "ACK" message to prevent the client process from starting up.
629 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); 623 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1);
630 return; 624 return;
631 } 625 }
632 626
633 // Ignore the request if the browser process is already in shutdown path. 627 if (parent_->notification_callback_.Run(CommandLine(argv),
634 if (!g_browser_process || g_browser_process->IsShuttingDown()) { 628 FilePath(current_dir))) {
629 // Send back "ACK" message to prevent the client process from starting up.
630 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1);
631 } else {
635 LOG(WARNING) << "Not handling interprocess notification as browser" 632 LOG(WARNING) << "Not handling interprocess notification as browser"
636 " is shutting down"; 633 " is shutting down";
637 // Send back "SHUTDOWN" message, so that the client process can start up 634 // Send back "SHUTDOWN" message, so that the client process can start up
638 // without killing this process. 635 // without killing this process.
639 reader->FinishWithACK(kShutdownToken, arraysize(kShutdownToken) - 1); 636 reader->FinishWithACK(kShutdownToken, arraysize(kShutdownToken) - 1);
640 return; 637 return;
641 } 638 }
642
643 CommandLine parsed_command_line(argv);
644 parent_->ProcessCommandLine(parsed_command_line, FilePath(current_dir));
645
646 // Send back "ACK" message to prevent the client process from starting up.
647 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1);
648 } 639 }
649 640
650 void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { 641 void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) {
651 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 642 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
652 DCHECK(reader); 643 DCHECK(reader);
653 readers_.erase(reader); 644 readers_.erase(reader);
654 delete reader; 645 delete reader;
655 } 646 }
656 647
657 /////////////////////////////////////////////////////////////////////////////// 648 ///////////////////////////////////////////////////////////////////////////////
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 gdk_notify_startup_complete(); 870 gdk_notify_startup_complete();
880 #endif 871 #endif
881 // Assume the other process is handling the request. 872 // Assume the other process is handling the request.
882 return PROCESS_NOTIFIED; 873 return PROCESS_NOTIFIED;
883 } 874 }
884 875
885 NOTREACHED() << "The other process returned unknown message: " << buf; 876 NOTREACHED() << "The other process returned unknown message: " << buf;
886 return PROCESS_NOTIFIED; 877 return PROCESS_NOTIFIED;
887 } 878 }
888 879
889 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() { 880 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate(
881 const NotificationCallback& notification_callback) {
890 return NotifyOtherProcessWithTimeoutOrCreate( 882 return NotifyOtherProcessWithTimeoutOrCreate(
891 *CommandLine::ForCurrentProcess(), 883 *CommandLine::ForCurrentProcess(),
884 notification_callback,
892 kTimeoutInSeconds); 885 kTimeoutInSeconds);
893 } 886 }
894 887
895 ProcessSingleton::NotifyResult 888 ProcessSingleton::NotifyResult
896 ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate( 889 ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate(
897 const CommandLine& command_line, 890 const CommandLine& command_line,
891 const NotificationCallback& notification_callback,
898 int timeout_seconds) { 892 int timeout_seconds) {
899 NotifyResult result = NotifyOtherProcessWithTimeout(command_line, 893 NotifyResult result = NotifyOtherProcessWithTimeout(command_line,
900 timeout_seconds, true); 894 timeout_seconds, true);
901 if (result != PROCESS_NONE) 895 if (result != PROCESS_NONE)
902 return result; 896 return result;
903 if (Create()) 897 if (Create(notification_callback))
904 return PROCESS_NONE; 898 return PROCESS_NONE;
905 // If the Create() failed, try again to notify. (It could be that another 899 // If the Create() failed, try again to notify. (It could be that another
906 // instance was starting at the same time and managed to grab the lock before 900 // instance was starting at the same time and managed to grab the lock before
907 // we did.) 901 // we did.)
908 // This time, we don't want to kill anything if we aren't successful, since we 902 // This time, we don't want to kill anything if we aren't successful, since we
909 // aren't going to try to take over the lock ourselves. 903 // aren't going to try to take over the lock ourselves.
910 result = NotifyOtherProcessWithTimeout(command_line, timeout_seconds, false); 904 result = NotifyOtherProcessWithTimeout(command_line, timeout_seconds, false);
911 if (result != PROCESS_NONE) 905 if (result != PROCESS_NONE)
912 return result; 906 return result;
913 907
914 return LOCK_ERROR; 908 return LOCK_ERROR;
915 } 909 }
916 910
917 bool ProcessSingleton::Create() { 911 bool ProcessSingleton::Create(
912 const NotificationCallback& notification_callback) {
918 int sock; 913 int sock;
919 sockaddr_un addr; 914 sockaddr_un addr;
920 915
921 // The symlink lock is pointed to the hostname and process id, so other 916 // The symlink lock is pointed to the hostname and process id, so other
922 // processes can find it out. 917 // processes can find it out.
923 FilePath symlink_content(base::StringPrintf( 918 FilePath symlink_content(base::StringPrintf(
924 "%s%c%u", 919 "%s%c%u",
925 net::GetHostName().c_str(), 920 net::GetHostName().c_str(),
926 kLockDelimiter, 921 kLockDelimiter,
927 base::GetCurrentProcId())); 922 base::GetCurrentProcId()));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 959
965 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) { 960 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
966 PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); 961 PLOG(ERROR) << "Failed to bind() " << socket_target_path.value();
967 CloseSocket(sock); 962 CloseSocket(sock);
968 return false; 963 return false;
969 } 964 }
970 965
971 if (listen(sock, 5) < 0) 966 if (listen(sock, 5) < 0)
972 NOTREACHED() << "listen failed: " << safe_strerror(errno); 967 NOTREACHED() << "listen failed: " << safe_strerror(errno);
973 968
969 notification_callback_ = notification_callback;
970
974 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); 971 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO));
975 BrowserThread::PostTask( 972 BrowserThread::PostTask(
976 BrowserThread::IO, 973 BrowserThread::IO,
977 FROM_HERE, 974 FROM_HERE,
978 base::Bind(&ProcessSingleton::LinuxWatcher::StartListening, 975 base::Bind(&ProcessSingleton::LinuxWatcher::StartListening,
979 watcher_.get(), 976 watcher_.get(),
980 sock)); 977 sock));
981 978
982 return true; 979 return true;
983 } 980 }
984 981
985 void ProcessSingleton::Cleanup() { 982 void ProcessSingleton::Cleanup() {
986 UnlinkPath(socket_path_); 983 UnlinkPath(socket_path_);
987 UnlinkPath(cookie_path_); 984 UnlinkPath(cookie_path_);
988 UnlinkPath(lock_path_); 985 UnlinkPath(lock_path_);
989 } 986 }
990
991 void ProcessSingleton::ProcessCommandLine(const CommandLine& command_line,
992 const FilePath& current_directory) {
993 PrefService* prefs = g_browser_process->local_state();
994 DCHECK(prefs);
995
996 // Ignore the request if the process was passed the --product-version flag.
997 // Normally we wouldn't get here if that flag had been passed, but it can
998 // happen if it is passed to an older version of chrome. Since newer versions
999 // of chrome do this in the background, we want to avoid spawning extra
1000 // windows.
1001 if (command_line.HasSwitch(switches::kProductVersion)) {
1002 DLOG(WARNING) << "Remote process was passed product version flag, "
1003 << "but ignored it. Doing nothing.";
1004 } else {
1005 // Run the browser startup sequence again, with the command line of the
1006 // signalling process.
1007 BrowserInit::ProcessCommandLineAlreadyRunning(command_line,
1008 current_directory);
1009 }
1010 }
OLDNEW
« no previous file with comments | « chrome/browser/process_singleton.cc ('k') | chrome/browser/process_singleton_linux_uitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698