diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-24 17:14:36 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-24 17:14:36 +0000 |
commit | 56f0f264ff866052ebcb24e75147cb600e6547a1 (patch) | |
tree | 8b16bded93f914cacbf3cb130fae3539ad4bb268 /chrome/browser/service | |
parent | 04a8454da64b62bfad5091efd5cf1143443283f0 (diff) | |
download | chromium_src-56f0f264ff866052ebcb24e75147cb600e6547a1.zip chromium_src-56f0f264ff866052ebcb24e75147cb600e6547a1.tar.gz chromium_src-56f0f264ff866052ebcb24e75147cb600e6547a1.tar.bz2 |
Get service process running standalone on the mac by hooking it into launchd.
BUG=NONE
TEST=BUILD
Review URL: http://codereview.chromium.org/6482016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75893 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/service')
4 files changed, 128 insertions, 79 deletions
diff --git a/chrome/browser/service/service_process_control.cc b/chrome/browser/service/service_process_control.cc index 09bc1ad..eb7a983 100644 --- a/chrome/browser/service/service_process_control.cc +++ b/chrome/browser/service/service_process_control.cc @@ -21,79 +21,6 @@ #include "chrome/common/service_process_util.h" #include "ui/base/ui_base_switches.h" -// ServiceProcessControl::Launcher implementation. -// This class is responsible for launching the service process on the -// PROCESS_LAUNCHER thread. -class ServiceProcessControl::Launcher - : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> { - public: - Launcher(ServiceProcessControl* process, CommandLine* cmd_line) - : process_(process), - cmd_line_(cmd_line), - launched_(false), - retry_count_(0) { - } - - // Execute the command line to start the process asynchronously. - // After the comamnd is executed |task| is called with the process handle on - // the UI thread. - void Run(Task* task) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - notify_task_.reset(task); - BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, - NewRunnableMethod(this, &Launcher::DoRun)); - } - - bool launched() const { return launched_; } - - private: - void DoRun() { - DCHECK(notify_task_.get()); - base::LaunchApp(*cmd_line_.get(), false, true, NULL); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - NewRunnableMethod(this, &Launcher::DoDetectLaunched)); - } - - void DoDetectLaunched() { - DCHECK(notify_task_.get()); - const uint32 kMaxLaunchDetectRetries = 10; - - { - // We should not be doing blocking disk IO from this thread! - // Temporarily allowed until we fix - // http://code.google.com/p/chromium/issues/detail?id=60207 - base::ThreadRestrictions::ScopedAllowIO allow_io; - launched_ = CheckServiceProcessReady(); - } - - if (launched_ || (retry_count_ >= kMaxLaunchDetectRetries)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - NewRunnableMethod(this, &Launcher::Notify)); - return; - } - retry_count_++; - // If the service process is not launched yet then check again in 2 seconds. - const int kDetectLaunchRetry = 2000; - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - NewRunnableMethod(this, &Launcher::DoDetectLaunched), - kDetectLaunchRetry); - } - - void Notify() { - DCHECK(notify_task_.get()); - notify_task_->Run(); - notify_task_.reset(); - } - - ServiceProcessControl* process_; - scoped_ptr<CommandLine> cmd_line_; - scoped_ptr<Task> notify_task_; - bool launched_; - uint32 retry_count_; -}; // ServiceProcessControl implementation. ServiceProcessControl::ServiceProcessControl(Profile* profile) @@ -120,7 +47,7 @@ void ServiceProcessControl::ConnectInternal() { base::Thread* io_thread = g_browser_process->io_thread(); // TODO(hclam): Handle error connecting to channel. - const std::string channel_id = GetServiceProcessChannelName(); + const IPC::ChannelHandle channel_id = GetServiceProcessChannel(); channel_.reset( new IPC::SyncChannel(channel_id, IPC::Channel::MODE_NAMED_CLIENT, this, io_thread->message_loop(), true, @@ -201,10 +128,19 @@ void ServiceProcessControl::Launch(Task* success_task, Task* failure_task) { if (!logging_level.empty()) cmd_line->AppendSwitchASCII(switches::kLoggingLevel, logging_level); + std::string v_level = browser_command_line.GetSwitchValueASCII( + switches::kV); + if (!v_level.empty()) + cmd_line->AppendSwitchASCII(switches::kV, v_level); + if (browser_command_line.HasSwitch(switches::kWaitForDebuggerChildren)) { cmd_line->AppendSwitch(switches::kWaitForDebugger); } + if (browser_command_line.HasSwitch(switches::kEnableLogging)) { + cmd_line->AppendSwitch(switches::kEnableLogging); + } + std::string locale = g_browser_process->GetApplicationLocale(); cmd_line->AppendSwitchASCII(switches::kLang, locale); @@ -341,3 +277,56 @@ void ServiceProcessControl::RemoveMessageHandler( } DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControl); + +ServiceProcessControl::Launcher::Launcher(ServiceProcessControl* process, + CommandLine* cmd_line) + : process_(process), + cmd_line_(cmd_line), + launched_(false), + retry_count_(0) { +} + +// Execute the command line to start the process asynchronously. +// After the command is executed, |task| is called with the process handle on +// the UI thread. +void ServiceProcessControl::Launcher::Run(Task* task) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + notify_task_.reset(task); + BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE, + NewRunnableMethod(this, &Launcher::DoRun)); +} + +void ServiceProcessControl::Launcher::Notify() { + DCHECK(notify_task_.get()); + notify_task_->Run(); + notify_task_.reset(); +} + +#if !defined(OS_MACOSX) +void ServiceProcessControl::Launcher::DoDetectLaunched() { + DCHECK(notify_task_.get()); + const uint32 kMaxLaunchDetectRetries = 10; + launched_ = CheckServiceProcessReady(); + if (launched_ || (retry_count_ >= kMaxLaunchDetectRetries)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, &Launcher::Notify)); + return; + } + retry_count_++; + + // If the service process is not launched yet then check again in 2 seconds. + const int kDetectLaunchRetry = 2000; + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + NewRunnableMethod(this, &Launcher::DoDetectLaunched), + kDetectLaunchRetry); +} + +void ServiceProcessControl::Launcher::DoRun() { + DCHECK(notify_task_.get()); + base::LaunchApp(*cmd_line_.get(), false, true, NULL); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod(this, &Launcher::DoDetectLaunched)); +} +#endif // !OS_MACOSX diff --git a/chrome/browser/service/service_process_control.h b/chrome/browser/service/service_process_control.h index c2f18ba..d5e43e0 100644 --- a/chrome/browser/service/service_process_control.h +++ b/chrome/browser/service/service_process_control.h @@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/basictypes.h" #include "base/id_map.h" #include "base/callback.h" #include "base/process.h" @@ -20,6 +21,7 @@ #include "ipc/ipc_sync_channel.h" class Profile; +class CommandLine; namespace remoting { struct ChromotingHostInfo; @@ -126,7 +128,33 @@ class ServiceProcessControl : public IPC::Channel::Sender, void RemoveMessageHandler(MessageHandler* message_handler); private: - class Launcher; + // This class is responsible for launching the service process on the + // PROCESS_LAUNCHER thread. + class Launcher + : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> { + public: + Launcher(ServiceProcessControl* process, CommandLine* cmd_line); + // Execute the command line to start the process asynchronously. + // After the comamnd is executed |task| is called with the process handle on + // the UI thread. + void Run(Task* task); + + bool launched() const { return launched_; } + + private: +#if !defined(OS_MACOSX) + void DoDetectLaunched(); +#endif // !OS_MACOSX + + void DoRun(); + void Notify(); + ServiceProcessControl* process_; + scoped_ptr<CommandLine> cmd_line_; + scoped_ptr<Task> notify_task_; + bool launched_; + uint32 retry_count_; + }; + typedef std::vector<Task*> TaskList; // Helper method to invoke all the callbacks based on success on failure. diff --git a/chrome/browser/service/service_process_control_browsertest.cc b/chrome/browser/service/service_process_control_browsertest.cc index a0dee5d..ff6e514 100644 --- a/chrome/browser/service/service_process_control_browsertest.cc +++ b/chrome/browser/service/service_process_control_browsertest.cc @@ -25,6 +25,13 @@ class ServiceProcessControlBrowserTest ServiceProcessControlManager::GetInstance()->Shutdown(); } +#if defined(OS_MACOSX) + virtual void TearDown() { + // ForceServiceProcessShutdown removes the process from launchd on Mac. + ForceServiceProcessShutdown("", 0); + } +#endif // OS_MACOSX + protected: void LaunchServiceProcessControl() { ServiceProcessControl* process = @@ -72,7 +79,7 @@ class ServiceProcessControlBrowserTest void ProcessControlLaunched() { base::ProcessId service_pid; - EXPECT_TRUE(GetServiceProcessSharedData(NULL, &service_pid)); + EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid)); EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); EXPECT_TRUE(base::OpenProcessHandleWithAccess( service_pid, @@ -194,7 +201,7 @@ IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, // Make sure we are connected to the service process. EXPECT_TRUE(process()->is_connected()); base::ProcessId service_pid; - EXPECT_TRUE(GetServiceProcessSharedData(NULL, &service_pid)); + EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid)); EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); chrome::VersionInfo version_info; ForceServiceProcessShutdown(version_info.Version(), service_pid); @@ -203,10 +210,10 @@ IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, CheckPid) { base::ProcessId service_pid; - EXPECT_FALSE(GetServiceProcessSharedData(NULL, &service_pid)); + EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid)); // Launch the service process. LaunchServiceProcessControl(); - EXPECT_TRUE(GetServiceProcessSharedData(NULL, &service_pid)); + EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid)); EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); } diff --git a/chrome/browser/service/service_process_control_mac.mm b/chrome/browser/service/service_process_control_mac.mm new file mode 100644 index 0000000..ebb2f2d --- /dev/null +++ b/chrome/browser/service/service_process_control_mac.mm @@ -0,0 +1,25 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/service/service_process_control.h" + +#include "base/command_line.h" +#include "base/mac/scoped_cftyperef.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/common/service_process_util_posix.h" +#include "third_party/GTM/Foundation/GTMServiceManagement.h" + +void ServiceProcessControl::Launcher::DoRun() { + base::mac::ScopedCFTypeRef<CFDictionaryRef> launchd_plist( + CreateServiceProcessLaunchdPlist(cmd_line_.get())); + CFErrorRef error = NULL; + if (!GTMSMJobSubmit(launchd_plist, &error)) { + LOG(ERROR) << error; + CFRelease(error); + } else { + launched_ = true; + } + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, &Launcher::Notify)); +} |