From 1d0ee423b6a0bb307c7c19fe28c95d8761691e9a Mon Sep 17 00:00:00 2001 From: "sanjeevr@chromium.org" Date: Wed, 12 May 2010 19:25:07 +0000 Subject: Created a new process type called the service process to host background tasks such as the Cloud Print Proxy. BUG=None. TEST=None. Review URL: http://codereview.chromium.org/2001009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47055 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/service/cloud_print/cloud_print_proxy.cc | 32 +++++++++ chrome/service/cloud_print/cloud_print_proxy.h | 43 ++++++++++++ chrome/service/gaia/service_gaia_authenticator.cc | 86 +++++++++++++++++++++++ chrome/service/gaia/service_gaia_authenticator.h | 57 +++++++++++++++ chrome/service/net/service_url_request_context.cc | 55 +++++++++++++++ chrome/service/net/service_url_request_context.h | 78 ++++++++++++++++++++ chrome/service/service_main.cc | 34 +++++++++ chrome/service/service_process.cc | 48 +++++++++++++ chrome/service/service_process.h | 57 +++++++++++++++ 9 files changed, 490 insertions(+) create mode 100644 chrome/service/cloud_print/cloud_print_proxy.cc create mode 100644 chrome/service/cloud_print/cloud_print_proxy.h create mode 100644 chrome/service/gaia/service_gaia_authenticator.cc create mode 100644 chrome/service/gaia/service_gaia_authenticator.h create mode 100644 chrome/service/net/service_url_request_context.cc create mode 100644 chrome/service/net/service_url_request_context.h create mode 100644 chrome/service/service_main.cc create mode 100644 chrome/service/service_process.cc create mode 100644 chrome/service/service_process.h (limited to 'chrome/service') diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc new file mode 100644 index 0000000..ea6139b --- /dev/null +++ b/chrome/service/cloud_print/cloud_print_proxy.cc @@ -0,0 +1,32 @@ +// 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/service/cloud_print/cloud_print_proxy.h" + +CloudPrintProxy::CloudPrintProxy() { +} + +CloudPrintProxy::~CloudPrintProxy() { + Shutdown(); +} + +void CloudPrintProxy::Initialize() { +} + + +void CloudPrintProxy::EnableForUser(const std::string& lsid, + const std::string& proxy_id) { +} + +void CloudPrintProxy::DisableForUser() { + Shutdown(); +} + +void CloudPrintProxy::HandlePrinterNotification( + const std::string& printer_id) { +} + +void CloudPrintProxy::Shutdown() { +} + diff --git a/chrome/service/cloud_print/cloud_print_proxy.h b/chrome/service/cloud_print/cloud_print_proxy.h new file mode 100644 index 0000000..0f67d7f --- /dev/null +++ b/chrome/service/cloud_print/cloud_print_proxy.h @@ -0,0 +1,43 @@ +// 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. + +#ifndef CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_PROXY_H_ +#define CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_PROXY_H_ + +#include + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" + +// TODO(sanjeevr): Integrate this with the CloudPrintProxyBackend. This needs to +// happen after the cloud_print related files are moved to chrome/service. + +// CloudPrintProxy is the layer between the service process UI thread +// and the cloud print proxy backend. +class CloudPrintProxy { + public: + explicit CloudPrintProxy(); + virtual ~CloudPrintProxy(); + + // Initializes the object. This should be called every time an object of this + // class is constructed. + void Initialize(); + + // Enables/disables cloud printing for the user + virtual void EnableForUser(const std::string& lsid, + const std::string& proxy_id); + virtual void DisableForUser(); + + // Notification received from the server for a particular printer. + // We need to inform the backend to look for jobs for this printer. + void HandlePrinterNotification(const std::string& printer_id); + + protected: + void Shutdown(); + + DISALLOW_COPY_AND_ASSIGN(CloudPrintProxy); +}; + +#endif // CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_PROXY_H_ + diff --git a/chrome/service/gaia/service_gaia_authenticator.cc b/chrome/service/gaia/service_gaia_authenticator.cc new file mode 100644 index 0000000..55dfff2 --- /dev/null +++ b/chrome/service/gaia/service_gaia_authenticator.cc @@ -0,0 +1,86 @@ +// 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/service/gaia/service_gaia_authenticator.h" + +#include "base/message_loop_proxy.h" +#include "chrome/service/net/service_url_request_context.h" +#include "googleurl/src/gurl.h" + +ServiceGaiaAuthenticator::ServiceGaiaAuthenticator( + const std::string& user_agent, const std::string& service_id, + const std::string& gaia_url, + base::MessageLoopProxy* io_message_loop_proxy) + : gaia::GaiaAuthenticator(user_agent, service_id, gaia_url), + http_post_completed_(false, false), + io_message_loop_proxy_(io_message_loop_proxy), + http_response_code_(0) { +} + +ServiceGaiaAuthenticator::~ServiceGaiaAuthenticator() { +} + +bool ServiceGaiaAuthenticator::Post(const GURL& url, + const std::string& post_body, + unsigned long* response_code, + std::string* response_body) { + DCHECK(url.SchemeIsSecure()); + DCHECK(io_message_loop_proxy_); + io_message_loop_proxy_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &ServiceGaiaAuthenticator::DoPost, url, + post_body)); + if (!http_post_completed_.Wait()) // Block until network request completes. + NOTREACHED(); // See OnURLFetchComplete. + + *response_code = static_cast(http_response_code_); + *response_body = response_data_; + return true; +} + +// TODO(sanjeevr): This is a placeholder implementation. Need to move this logic +// to a common location within the service process so that it can be resued by +// other classes needing a backoff delay calculation. +int ServiceGaiaAuthenticator::GetBackoffDelaySeconds( + int current_backoff_delay) { + const int kMaxBackoffDelaySeconds = 60 * 60; // (1 hour) + int ret = 0; + if (0 == current_backoff_delay) { + ret = 1; + } else { + ret = current_backoff_delay * 2; + } + if (ret > kMaxBackoffDelaySeconds) { + ret = kMaxBackoffDelaySeconds; + } + return ret; +} + +void ServiceGaiaAuthenticator::DoPost(const GURL& post_url, + const std::string& post_body) { + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); + request_.reset(new URLFetcher(post_url, URLFetcher::POST, this)); + ServiceURLRequestContextGetter* context_getter = + new ServiceURLRequestContextGetter(); + request_->set_request_context(context_getter); + request_->set_upload_data("application/x-www-form-urlencoded", post_body); + request_->Start(); +} + +// URLFetcher::Delegate implementation +void ServiceGaiaAuthenticator::OnURLFetchComplete( + const URLFetcher *source, const GURL &url, const URLRequestStatus &status, + int response_code, const ResponseCookies &cookies, + const std::string &data) { + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); + http_response_code_ = response_code; + response_data_ = data; + // Add an extra reference because we want http_post_completed_ to remain + // valid until after Signal() returns. + scoped_refptr keep_alive(this); + // Wake the blocked thread in Post. + http_post_completed_.Signal(); + // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted! +} + diff --git a/chrome/service/gaia/service_gaia_authenticator.h b/chrome/service/gaia/service_gaia_authenticator.h new file mode 100644 index 0000000..aedc302 --- /dev/null +++ b/chrome/service/gaia/service_gaia_authenticator.h @@ -0,0 +1,57 @@ +// 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. + +#ifndef CHROME_SERVICE_GAIA_SERVICE_GAIA_AUTHENTICATOR_H_ +#define CHROME_SERVICE_GAIA_SERVICE_GAIA_AUTHENTICATOR_H_ + +#include + +#include "base/ref_counted.h" +#include "base/waitable_event.h" +#include "chrome/common/net/url_fetcher.h" +#include "chrome/common/net/gaia/gaia_authenticator.h" + +namespace base { +class MessageLoopProxy; +} + +// A GaiaAuthenticator implementation to be used in the service process (where +// we cannot rely on the existence of a Profile) +class ServiceGaiaAuthenticator + : public base::RefCountedThreadSafe, + public URLFetcher::Delegate, + public gaia::GaiaAuthenticator { + public: + ServiceGaiaAuthenticator(const std::string& user_agent, + const std::string& service_id, + const std::string& gaia_url, + base::MessageLoopProxy* io_message_loop_proxy); + ~ServiceGaiaAuthenticator(); + + // URLFetcher::Delegate implementation. + void OnURLFetchComplete(const URLFetcher *source, const GURL &url, + const URLRequestStatus &status, int response_code, + const ResponseCookies &cookies, + const std::string &data); + + protected: + // GaiaAuthenticator overrides. + virtual bool Post(const GURL& url, const std::string& post_body, + unsigned long* response_code, std::string* response_body); + virtual int GetBackoffDelaySeconds(int current_backoff_delay); + + private: + void DoPost(const GURL& post_url, const std::string& post_body); + + base::WaitableEvent http_post_completed_; + scoped_refptr io_message_loop_proxy_; + int http_response_code_; + std::string response_data_; + scoped_ptr request_; + + DISALLOW_COPY_AND_ASSIGN(ServiceGaiaAuthenticator); +}; + +#endif // CHROME_SERVICE_GAIA_SERVICE_GAIA_AUTHENTICATOR_H_ + diff --git a/chrome/service/net/service_url_request_context.cc b/chrome/service/net/service_url_request_context.cc new file mode 100644 index 0000000..ab5e61a --- /dev/null +++ b/chrome/service/net/service_url_request_context.cc @@ -0,0 +1,55 @@ +// 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/service/net/service_url_request_context.h" + +#include "chrome/service/service_process.h" +#include "net/base/cookie_monster.h" +#include "net/base/cookie_policy.h" +#include "net/base/host_resolver.h" +#include "net/base/ssl_config_service_defaults.h" +#include "net/ftp/ftp_network_layer.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_layer.h" +#include "net/proxy/proxy_service.h" + +ServiceURLRequestContextGetter::ServiceURLRequestContextGetter() + : io_message_loop_proxy_( + g_service_process->io_thread()->message_loop_proxy()) { +} + +ServiceURLRequestContext::ServiceURLRequestContext() { + host_resolver_ = net::CreateSystemHostResolver(NULL); + DCHECK(g_service_process); + // TODO(sanjeevr): Change CreateSystemProxyConfigService to accept a + // MessageLoopProxy* instead of MessageLoop*. + // Also this needs to be created on the UI thread on Linux. Fix this. + net::ProxyConfigService * proxy_config_service = + net::ProxyService::CreateSystemProxyConfigService( + g_service_process->io_thread()->message_loop(), + g_service_process->file_thread()->message_loop()); + proxy_service_ = net::ProxyService::Create(proxy_config_service, false, this, + NULL, NULL, NULL); + ftp_transaction_factory_ = new net::FtpNetworkLayer(host_resolver_); + ssl_config_service_ = new net::SSLConfigServiceDefaults; + http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(); + http_transaction_factory_ = new net::HttpCache( + net::HttpNetworkLayer::CreateFactory(NULL, host_resolver_, + proxy_service_, + ssl_config_service_, + http_auth_handler_factory_), + disk_cache::CreateInMemoryCacheBackend(0)); + // In-memory cookie store. + cookie_store_ = new net::CookieMonster(NULL, NULL); + accept_language_ = "en-us,fr"; + accept_charset_ = "iso-8859-1,*,utf-8"; +} + +ServiceURLRequestContext::~ServiceURLRequestContext() { + delete ftp_transaction_factory_; + delete http_transaction_factory_; + delete http_auth_handler_factory_; +} + diff --git a/chrome/service/net/service_url_request_context.h b/chrome/service/net/service_url_request_context.h new file mode 100644 index 0000000..90c9733 --- /dev/null +++ b/chrome/service/net/service_url_request_context.h @@ -0,0 +1,78 @@ +// 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. + +#ifndef CHROME_SERVICE_NET_SERVICE_URL_REQUEST_CONTEXT_H_ +#define CHROME_SERVICE_NET_SERVICE_URL_REQUEST_CONTEXT_H_ + +#include + +#include "base/message_loop_proxy.h" +#include "chrome/common/net/url_request_context_getter.h" +#include "net/base/cookie_monster.h" +#include "net/base/cookie_policy.h" +#include "net/base/host_resolver.h" +#include "net/base/ssl_config_service_defaults.h" +#include "net/disk_cache/disk_cache.h" +#include "net/ftp/ftp_network_layer.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_layer.h" +#include "net/proxy/proxy_service.h" +#include "net/url_request/url_request_context.h" + +// Subclass of URLRequestContext which can be used to store extra information +// for requests. This subclass is meant to be used in the service process where +// the profile is not available. +// +class ServiceURLRequestContext : public URLRequestContext { + public: + ServiceURLRequestContext(); + void set_cookie_policy(net::CookiePolicy* policy) { + cookie_policy_ = policy; + } + void set_user_agent(const std::string& ua) { + user_agent_ = ua; + } + + // URLRequestContext overrides + virtual const std::string& GetUserAgent(const GURL& url) const { + // If the user agent is set explicitly return that, otherwise call the + // base class method to return default value. + return user_agent_.empty() ? + URLRequestContext::GetUserAgent(url) : user_agent_; + } + + protected: + virtual ~ServiceURLRequestContext(); + + private: + std::string user_agent_; +}; + +class ServiceURLRequestContextGetter : public URLRequestContextGetter { + public: + ServiceURLRequestContextGetter(); + + virtual URLRequestContext* GetURLRequestContext() { + if (!url_request_context_) + url_request_context_ = new ServiceURLRequestContext(); + return url_request_context_; + } + virtual scoped_refptr GetIOMessageLoopProxy() { + return io_message_loop_proxy_; + } + + void set_user_agent(const std::string& ua) { + user_agent_ = ua; + } + private: + ~ServiceURLRequestContextGetter() {} + + std::string user_agent_; + scoped_refptr url_request_context_; + scoped_refptr io_message_loop_proxy_; +}; + +#endif // CHROME_SERVICE_NET_SERVICE_URL_REQUEST_CONTEXT_H_ + diff --git a/chrome/service/service_main.cc b/chrome/service/service_main.cc new file mode 100644 index 0000000..44ca8eb --- /dev/null +++ b/chrome/service/service_main.cc @@ -0,0 +1,34 @@ +// 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 "base/message_loop.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/main_function_params.h" +#include "chrome/service/cloud_print/cloud_print_proxy.h" +#include "chrome/service/service_process.h" + +// Mainline routine for running as the service process. +int ServiceProcessMain(const MainFunctionParams& parameters) { + MessageLoopForUI main_message_loop; + std::wstring app_name = chrome::kBrowserAppName; + PlatformThread::SetName(WideToASCII(app_name + L"_ServiceMain").c_str()); + + ServiceProcess service_process; + service_process.Initialize(); + if (parameters.command_line_.HasSwitch(switches::kEnableCloudPrintProxy)) { + std::string lsid = + parameters.command_line_.GetSwitchValueASCII( + switches::kServiceAccountLsid); + std::string proxy_id = + parameters.command_line_.GetSwitchValueASCII( + switches::kCloudPrintProxyId); + service_process.cloud_print_proxy()->EnableForUser(lsid, proxy_id); + } + MessageLoop::current()->Run(); + service_process.Teardown(); + + return 0; +} + diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc new file mode 100644 index 0000000..41bfe8d --- /dev/null +++ b/chrome/service/service_process.cc @@ -0,0 +1,48 @@ +// 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/service/service_process.h" + +#include "chrome/service/cloud_print/cloud_print_proxy.h" + +ServiceProcess* g_service_process = NULL; + +ServiceProcess::ServiceProcess() { + DCHECK(!g_service_process); + g_service_process = this; +} + +bool ServiceProcess::Initialize() { + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + io_thread_.reset(new base::Thread("ServiceProcess_IO")); + file_thread_.reset(new base::Thread("ServiceProcess_File")); + if (!io_thread_->StartWithOptions(options) || + !file_thread_->StartWithOptions(options)) { + NOTREACHED(); + Teardown(); + return false; + } + return true; +} + +bool ServiceProcess::Teardown() { + io_thread_.reset(); + file_thread_.reset(); + return true; +} + +CloudPrintProxy* ServiceProcess::cloud_print_proxy() { + if (!cloud_print_proxy_.get()) { + cloud_print_proxy_.reset(new CloudPrintProxy()); + cloud_print_proxy_->Initialize(); + } + return cloud_print_proxy_.get(); +} + +ServiceProcess::~ServiceProcess() { + Teardown(); + g_service_process = NULL; +} + diff --git a/chrome/service/service_process.h b/chrome/service/service_process.h new file mode 100644 index 0000000..9d980dd --- /dev/null +++ b/chrome/service/service_process.h @@ -0,0 +1,57 @@ +// 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. + +#ifndef CHROME_SERVICE_SERVICE_PROCESS_H_ +#define CHROME_SERVICE_SERVICE_PROCESS_H_ + + +#include "base/thread.h" + +class CloudPrintProxy; + +// The ServiceProcess does not inherit from ChildProcess because this +// process can live independently of the browser process. +class ServiceProcess { + public: + ServiceProcess(); + ~ServiceProcess(); + + bool Initialize(); + bool Teardown(); + // TODO(sanjeevr): Change various parts of the code such as + // net::ProxyService::CreateSystemProxyConfigService to take in + // MessageLoopProxy* instead of MessageLoop*. When we have done that, we can + // remove the io_thread() and file_thread() accessors and replace them with + // io_message_loop_proxy() and file_message_loop_proxy() respectively. + + // Returns the thread that we perform I/O coordination on (network requests, + // communication with renderers, etc. + // NOTE: You should ONLY use this to pass to IPC or other objects which must + // need a MessageLoop*. If you just want to post a task, use the thread's + // message_loop_proxy() as it takes care of checking that a thread is still + // alive, race conditions, lifetime differences etc. + // If you still must use this, need to check the return value for NULL. + base::Thread* io_thread() const { + return io_thread_.get(); + } + // Returns the thread that we perform random file operations on. For code + // that wants to do I/O operations (not network requests or even file: URL + // requests), this is the thread to use to avoid blocking the UI thread. + base::Thread* file_thread() const { + return file_thread_.get(); + } + CloudPrintProxy* cloud_print_proxy(); + + private: + scoped_ptr io_thread_; + scoped_ptr file_thread_; + scoped_ptr cloud_print_proxy_; + + DISALLOW_COPY_AND_ASSIGN(ServiceProcess); +}; + +extern ServiceProcess* g_service_process; + +#endif // CHROME_SERVICE_SERVICE_PROCESS_H_ + -- cgit v1.1