diff options
-rw-r--r-- | chrome/browser/browser_main.cc | 6 | ||||
-rw-r--r-- | chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc | 82 | ||||
-rw-r--r-- | chrome/browser/printing/cloud_print/cloud_print_proxy_service.h | 23 | ||||
-rw-r--r-- | chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc | 199 | ||||
-rw-r--r-- | chrome/browser/printing/cloud_print/cloud_print_setup_flow.h | 14 | ||||
-rw-r--r-- | chrome/browser/profile_impl.cc | 2 | ||||
-rw-r--r-- | chrome/browser/profile_impl.h | 2 | ||||
-rw-r--r-- | chrome/browser/service/service_process_control.cc | 22 | ||||
-rw-r--r-- | chrome/browser/service/service_process_control.h | 12 | ||||
-rw-r--r-- | chrome/browser/service/service_process_control_browsertest.cc | 40 | ||||
-rw-r--r-- | chrome/browser/views/options/advanced_contents_view.cc | 15 | ||||
-rw-r--r-- | chrome/common/service_messages_internal.h | 3 | ||||
-rw-r--r-- | chrome/service/service_ipc_server.cc | 11 | ||||
-rw-r--r-- | chrome/service/service_ipc_server.h | 1 | ||||
-rw-r--r-- | chrome/service/service_process.cc | 16 | ||||
-rw-r--r-- | chrome/service/service_process.h | 15 |
16 files changed, 220 insertions, 243 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 85d2c76..1e556d3 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -58,6 +58,7 @@ #include "chrome/browser/plugin_service.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/pref_value_store.h" +#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" #include "chrome/browser/process_singleton.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" @@ -1440,6 +1441,11 @@ int BrowserMain(const MainFunctionParams& parameters) { } } + // Create the instance of the cloud print proxy service so that it can launch + // the service process if needed. This is needed because the service process + // might have shutdown because an update was available. + profile->GetCloudPrintProxyService(); + int result_code = ResultCodes::NORMAL_EXIT; if (parameters.ui_task) { // We are in test mode. Run one task and enter the main message loop. diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc index 1067923..20d0a73 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc +++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc @@ -16,7 +16,10 @@ #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/browser/service/service_process_control.h" +#include "chrome/browser/service/service_process_control_manager.h" #include "chrome/common/pref_names.h" +#include "chrome/common/service_messages.h" #include "grit/generated_resources.h" // TODO(sanjeevr): Localize the product name? @@ -51,25 +54,34 @@ CloudPrintProxyService::CloudPrintProxyService(Profile* profile) } CloudPrintProxyService::~CloudPrintProxyService() { - Shutdown(); } void CloudPrintProxyService::Initialize() { + if (profile_->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) && + !profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty()) { + // If the cloud print proxy is enabled, establish a channel with the + // service process and update the status. + RefreshStatusFromService(); + } } - -void CloudPrintProxyService::EnableForUser(const std::string& auth_token) { - // TODO(sanjeevr): Add code to communicate with the cloud print proxy code - // running in the service process here. +void CloudPrintProxyService::RefreshStatusFromService() { + InvokeServiceTask( + NewRunnableMethod( + this, &CloudPrintProxyService::RefreshCloudPrintProxyStatus)); } -void CloudPrintProxyService::DisableForUser() { - Shutdown(); +void CloudPrintProxyService::EnableForUser(const std::string& lsid, + const std::string& email) { + InvokeServiceTask( + NewRunnableMethod( + this, &CloudPrintProxyService::EnableCloudPrintProxy, lsid, email)); } -void CloudPrintProxyService::Shutdown() { - // TODO(sanjeevr): Add code to communicate with the cloud print proxy code - // running in the service process here. +void CloudPrintProxyService::DisableForUser() { + InvokeServiceTask( + NewRunnableMethod( + this, &CloudPrintProxyService::DisableCloudPrintProxy)); } bool CloudPrintProxyService::ShowTokenExpiredNotification() { @@ -126,3 +138,53 @@ void CloudPrintProxyService::OnDialogClosed() { FROM_HERE, NewRunnableFunction(&BrowserList::EndKeepAlive)); } +void CloudPrintProxyService::RefreshCloudPrintProxyStatus() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + ServiceProcessControl* process_control = + ServiceProcessControlManager::instance()->GetProcessControl(profile_); + DCHECK(process_control && process_control->is_connected()); + if (process_control && process_control->is_connected()) { + Callback2<bool, std::string>::Type* callback = + NewCallback(this, &CloudPrintProxyService::StatusCallback); + // GetCloudPrintProxyStatus takes ownership of callback. + process_control->GetCloudPrintProxyStatus(callback); + } +} + +void CloudPrintProxyService::EnableCloudPrintProxy(const std::string& lsid, + const std::string& email) { + ServiceProcessControl* process_control = + ServiceProcessControlManager::instance()->GetProcessControl(profile_); + DCHECK(process_control && process_control->is_connected()); + if (process_control->is_connected()) { + process_control->Send(new ServiceMsg_EnableCloudPrintProxy(lsid)); + // Assume the IPC worked. + profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, email); + } +} + +void CloudPrintProxyService::DisableCloudPrintProxy() { + ServiceProcessControl* process_control = + ServiceProcessControlManager::instance()->GetProcessControl(profile_); + DCHECK(process_control && process_control->is_connected()); + if (process_control->is_connected()) { + process_control->Send(new ServiceMsg_DisableCloudPrintProxy); + // Assume the IPC worked. + profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string()); + } +} + +void CloudPrintProxyService::StatusCallback(bool enabled, std::string email) { + profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, + enabled ? email : std::string()); +} + +bool CloudPrintProxyService::InvokeServiceTask(Task* task) { + ServiceProcessControl* process_control = + ServiceProcessControlManager::instance()->GetProcessControl(profile_); + DCHECK(process_control); + if (process_control) + process_control->Launch(task); + return !!process_control; +} + diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h index 538da2c..220cbd1 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h +++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h @@ -17,7 +17,9 @@ class Profile; // Layer between the browser user interface and the cloud print proxy code // running in the service process. -class CloudPrintProxyService : public CloudPrintSetupFlow::Delegate { +class CloudPrintProxyService + : public CloudPrintSetupFlow::Delegate, + public base::RefCountedThreadSafe<CloudPrintProxyService> { public: explicit CloudPrintProxyService(Profile* profile); virtual ~CloudPrintProxyService(); @@ -27,9 +29,13 @@ class CloudPrintProxyService : public CloudPrintSetupFlow::Delegate { void Initialize(); // Enables/disables cloud printing for the user - virtual void EnableForUser(const std::string& auth_token); + virtual void EnableForUser(const std::string& lsid, const std::string& email); virtual void DisableForUser(); + // Query the service process for the status of the cloud print proxy and + // update the browser prefs. + void RefreshStatusFromService(); + bool ShowTokenExpiredNotification(); // CloudPrintSetupFlow::Delegate implementation. @@ -43,7 +49,18 @@ class CloudPrintProxyService : public CloudPrintSetupFlow::Delegate { Profile* profile_; scoped_refptr<TokenExpiredNotificationDelegate> token_expired_delegate_; - void Shutdown(); + // Methods that send an IPC to the service. + void RefreshCloudPrintProxyStatus(); + void EnableCloudPrintProxy(const std::string& lsid, const std::string& email); + void DisableCloudPrintProxy(); + + // Callback that gets the cloud print proxy status. + void StatusCallback(bool enabled, std::string email); + // Invoke a task that gets run after the service process successfully + // launches. The task typically involves sending an IPC to the service + // process. + bool InvokeServiceTask(Task* task); + void OnTokenExpiredNotificationError(); void OnTokenExpiredNotificationClosed(bool by_user); void OnTokenExpiredNotificationClick(); diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc index f74f980..e361062 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc +++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc @@ -19,6 +19,7 @@ #endif // defined(TOOLKIT_GTK) #include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h" #include "chrome/browser/profile.h" #include "chrome/browser/remoting/remoting_resources_source.h" @@ -41,139 +42,6 @@ static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']"; static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']"; //////////////////////////////////////////////////////////////////////////////// -// CloudPrintServiceProcessHelper -// -// This is a helper class to perform actions when the service process -// is connected or launched. The events are sent back to CloudPrintSetupFlow -// when the dialog is still active. CloudPrintSetupFlow can detach from this -// helper class when the dialog is closed. - -class CloudPrintServiceProcessHelper - : public base::RefCountedThreadSafe<CloudPrintServiceProcessHelper> { - public: - explicit CloudPrintServiceProcessHelper(CloudPrintSetupFlow* flow) - : flow_(flow) { - } - - void Detach() { - flow_ = NULL; - } - - void OnProcessLaunched() { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - // If the flow is detached then show the done page. - if (!flow_) - return; - - flow_->OnProcessLaunched(); - } - - private: - CloudPrintSetupFlow* flow_; - - DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceProcessHelper); -}; - -//////////////////////////////////////////////////////////////////////////////// -// CloudPrintServiceDisableTask -// -// This is a helper class to get the proxy service launched if it -// isn't, in order to properly inform it that it should be disabled. - -class CloudPrintServiceDisableTask - : public base::RefCountedThreadSafe<CloudPrintServiceDisableTask> { - public: - explicit CloudPrintServiceDisableTask(Profile* profile) - : profile_(profile), - process_control_(NULL) { - } - - void StartDisable() { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - - process_control_ = - ServiceProcessControlManager::instance()->GetProcessControl(profile_); - - if (process_control_) { - // If the process isn't connected, launch it now. This will run - // the task whether the process is already launched or not, as - // long as it's able to connect back up. - process_control_->Launch( - NewRunnableMethod( - this, &CloudPrintServiceDisableTask::OnProcessLaunched)); - } - } - - void OnProcessLaunched() { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - DCHECK(process_control_); - if (process_control_->is_connected()) - process_control_->Send(new ServiceMsg_DisableCloudPrintProxy()); - profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string()); - } - - private: - Profile* profile_; - ServiceProcessControl* process_control_; - - DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceDisableTask); -}; - -//////////////////////////////////////////////////////////////////////////////// -// CloudPrintServiceRefreshTask -// -// This is a helper class to perform a preferences refresh of the -// enablement state and registered e-mail from the cloud print proxy -// service. - -class CloudPrintServiceRefreshTask - : public base::RefCountedThreadSafe<CloudPrintServiceRefreshTask> { - public: - explicit CloudPrintServiceRefreshTask( - Profile* profile, - Callback2<bool, std::string>::Type* callback) - : profile_(profile), - process_control_(NULL), - callback_(callback) { - DCHECK(callback); - } - - void StartRefresh() { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - - process_control_ = - ServiceProcessControlManager::instance()->GetProcessControl(profile_); - - if (process_control_) { - // If the process isn't connected, launch it now. This will run - // the task whether the process is already launched or not, as - // long as it's able to connect back up. - process_control_->Launch( - NewRunnableMethod( - this, &CloudPrintServiceRefreshTask::OnProcessLaunched)); - } - } - - void OnProcessLaunched() { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - DCHECK(process_control_); - - if (callback_ != NULL) - process_control_->GetCloudPrintProxyStatus(callback_.release()); - } - - private: - Profile* profile_; - ServiceProcessControl* process_control_; - - // Callback that gets invoked when a status message is received from - // the cloud print proxy. - scoped_ptr<Callback2<bool, std::string>::Type> callback_; - - DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceRefreshTask); -}; - -//////////////////////////////////////////////////////////////////////////////// // CloudPrintSetupFlow implementation. // static @@ -216,28 +84,6 @@ CloudPrintSetupFlow* CloudPrintSetupFlow::OpenDialog( return flow; } -// static -void CloudPrintSetupFlow::DisableCloudPrintProxy(Profile* profile) { - scoped_refptr<CloudPrintServiceDisableTask> refresh_task = - new CloudPrintServiceDisableTask(profile); - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(refresh_task.get(), - &CloudPrintServiceDisableTask::StartDisable)); -} - -// static -void CloudPrintSetupFlow::RefreshPreferencesFromService( - Profile* profile, - Callback2<bool, std::string>::Type* callback) { - scoped_refptr<CloudPrintServiceRefreshTask> refresh_task = - new CloudPrintServiceRefreshTask(profile, callback); - ChromeThread::PostTask( - ChromeThread::UI, FROM_HERE, - NewRunnableMethod(refresh_task.get(), - &CloudPrintServiceRefreshTask::StartRefresh)); -} - CloudPrintSetupFlow::CloudPrintSetupFlow(const std::string& args, Profile* profile, Delegate* delegate) @@ -296,12 +142,6 @@ void CloudPrintSetupFlow::OnDialogClosed(const std::string& json_retval) { if (authenticator_.get()) authenticator_->CancelRequest(); - // If the service process helper is still active then detach outself from it. - // This is because the dialog is closing and this object is going to be - // deleted but the service process launch is still in progress so we don't - // the service process helper to call us when the process is launched. - if (service_process_helper_.get()) - service_process_helper_->Detach(); if (delegate_) { delegate_->OnDialogClosed(); } @@ -342,26 +182,10 @@ void CloudPrintSetupFlow::OnClientLoginSuccess( ShowGaiaSuccessAndSettingUp(); authenticator_.reset(); - // And then launch the service process if it has not started yet. - // If we have already connected to the service process then submit the tokens - // to it to register the host. - process_control_ = - ServiceProcessControlManager::instance()->GetProcessControl(profile_); - -#if defined(OS_WIN) - // TODO(hclam): This call only works on Windows. I need to make it - // work on other platforms. - service_process_helper_ = new CloudPrintServiceProcessHelper(this); - - // If the process isn't connected, launch it now. This will run the - // task whether the process is already launched or not, as long as - // it's able to connect back up. - process_control_->Launch( - NewRunnableMethod(service_process_helper_.get(), - &CloudPrintServiceProcessHelper::OnProcessLaunched)); -#else + profile_->GetCloudPrintProxyService()->EnableForUser(credentials.lsid, + login_); + // TODO(sanjeevr): Should we wait and verify that the enable succeeded? ShowSetupDone(); -#endif } /////////////////////////////////////////////////////////////////////////////// @@ -387,21 +211,6 @@ void CloudPrintSetupFlow::OnUserSubmittedAuth(const std::string& user, } /////////////////////////////////////////////////////////////////////////////// -// Method called by CloudPrintServiceProcessHelper -void CloudPrintSetupFlow::OnProcessLaunched() { - DCHECK(process_control_->is_connected()); - // TODO(scottbyer): Need to wait for an ACK to be sure that it is - // actually active. - if (!lsid_.empty()) - process_control_->Send(new ServiceMsg_EnableCloudPrintProxy(lsid_)); - - // Save the preference that we have completed the setup of cloud - // print. - profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, login_); - ShowSetupDone(); -} - -/////////////////////////////////////////////////////////////////////////////// // Helper methods for showing contents of the DOM UI void CloudPrintSetupFlow::ShowGaiaLogin(const DictionaryValue& args) { if (dom_ui_) diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h index 453c1e3..d79e578 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h +++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h @@ -56,15 +56,6 @@ class CloudPrintSetupFlow : public HtmlDialogUIDelegate, static CloudPrintSetupFlow* OpenDialog(Profile* service, Delegate* delegate, gfx::NativeWindow parent_window); - // Disables the cloud print proxy if it's enabled and running. - static void DisableCloudPrintProxy(Profile* profile); - - // Ping the cloud print proxy service in order to get the true - // enablement state and user e-mail that the service is using, and - // reflect those back into the browser preferences. - static void RefreshPreferencesFromService( - Profile* profile, Callback2<bool, std::string>::Type* callback); - // Focuses the dialog. This is useful in cases where the dialog has been // obscured by a browser window. void Focus(); @@ -105,9 +96,6 @@ class CloudPrintSetupFlow : public HtmlDialogUIDelegate, const std::string& password, const std::string& captcha); - // Event triggered when the service process was launched. - void OnProcessLaunched(); - // The following methods control which iframe is visible. void ShowGaiaLogin(const DictionaryValue& args); void ShowGaiaSuccessAndSettingUp(); @@ -131,8 +119,6 @@ class CloudPrintSetupFlow : public HtmlDialogUIDelegate, // Handle to the ServiceProcessControl which talks to the service process. ServiceProcessControl* process_control_; - scoped_refptr<CloudPrintServiceProcessHelper> service_process_helper_; - Delegate* delegate_; DISALLOW_COPY_AND_ASSIGN(CloudPrintSetupFlow); diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc index b89057d..af95572 100644 --- a/chrome/browser/profile_impl.cc +++ b/chrome/browser/profile_impl.cc @@ -1242,7 +1242,7 @@ void ProfileImpl::InitSyncService(const std::string& cros_user) { } void ProfileImpl::InitCloudPrintProxyService() { - cloud_print_proxy_service_.reset(new CloudPrintProxyService(this)); + cloud_print_proxy_service_ = new CloudPrintProxyService(this); cloud_print_proxy_service_->Initialize(); } diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h index 25a38a9..efa00c1 100644 --- a/chrome/browser/profile_impl.h +++ b/chrome/browser/profile_impl.h @@ -179,7 +179,7 @@ class ProfileImpl : public Profile, scoped_ptr<TokenService> token_service_; scoped_ptr<ProfileSyncFactory> profile_sync_factory_; scoped_ptr<ProfileSyncService> sync_service_; - scoped_ptr<CloudPrintProxyService> cloud_print_proxy_service_; + scoped_refptr<CloudPrintProxyService> cloud_print_proxy_service_; scoped_refptr<ChromeURLRequestContextGetter> request_context_; diff --git a/chrome/browser/service/service_process_control.cc b/chrome/browser/service/service_process_control.cc index 6790b00..22ad863 100644 --- a/chrome/browser/service/service_process_control.cc +++ b/chrome/browser/service/service_process_control.cc @@ -11,8 +11,10 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/io_thread.h" +#include "chrome/browser/upgrade_detector.h" #include "chrome/common/child_process_host.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/notification_service.h" #include "chrome/common/service_messages.h" #include "chrome/common/service_process_util.h" @@ -108,6 +110,16 @@ void ServiceProcessControl::ConnectInternal(Task* task) { io_thread->message_loop(), true, g_browser_process->shutdown_event())); channel_->set_sync_messages_with_no_timeout_allowed(false); + + // We just established a channel with the service process. Notify it if an + // upgrade is available. + if (Singleton<UpgradeDetector>::get()->notify_upgrade()) { + Send(new ServiceMsg_UpdateAvailable); + } else { + if (registrar_.IsEmpty()) + registrar_.Add(this, NotificationType::UPGRADE_RECOMMENDED, + NotificationService::AllSources()); + } } void ServiceProcessControl::Launch(Task* task) { @@ -200,6 +212,16 @@ bool ServiceProcessControl::Send(IPC::Message* message) { return channel_->Send(message); } +// NotificationObserver implementation. +void ServiceProcessControl::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::UPGRADE_RECOMMENDED) { + Send(new ServiceMsg_UpdateAvailable); + } +} + + void ServiceProcessControl::OnGoodDay() { if (!message_handler_) return; diff --git a/chrome/browser/service/service_process_control.h b/chrome/browser/service/service_process_control.h index 021b669..e6df376 100644 --- a/chrome/browser/service/service_process_control.h +++ b/chrome/browser/service/service_process_control.h @@ -13,6 +13,8 @@ #include "base/process.h" #include "base/scoped_ptr.h" #include "base/task.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" #include "ipc/ipc_sync_channel.h" class Profile; @@ -28,7 +30,8 @@ class Profile; // This class is accessed on the UI thread through some UI actions. It then // talks to the IPC channel on the IO thread. class ServiceProcessControl : public IPC::Channel::Sender, - public IPC::Channel::Listener { + public IPC::Channel::Listener, + public NotificationObserver { public: typedef IDMap<ServiceProcessControl>::iterator iterator; typedef std::queue<IPC::Message> MessageQueue; @@ -67,6 +70,11 @@ class ServiceProcessControl : public IPC::Channel::Sender, // IPC::Channel::Sender implementation virtual bool Send(IPC::Message* message); + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + // Message handlers void OnGoodDay(); void OnCloudPrintProxyIsEnabled(bool enabled, std::string email); @@ -127,6 +135,8 @@ class ServiceProcessControl : public IPC::Channel::Sender, // Handler for messages from service process. MessageHandler* message_handler_; + + NotificationRegistrar registrar_; }; #endif // CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ diff --git a/chrome/browser/service/service_process_control_browsertest.cc b/chrome/browser/service/service_process_control_browsertest.cc index 391f99f..e48a60c 100644 --- a/chrome/browser/service/service_process_control_browsertest.cc +++ b/chrome/browser/service/service_process_control_browsertest.cc @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/test/in_process_browser_test.h" -#include "chrome/test/ui_test_utils.h" +#include "base/test/test_timeouts.h" #include "chrome/browser/browser.h" #include "chrome/browser/service/service_process_control.h" #include "chrome/browser/service/service_process_control_manager.h" +#include "chrome/common/service_process_util.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" class ServiceProcessControlBrowserTest : public InProcessBrowserTest, @@ -29,11 +31,32 @@ class ServiceProcessControlBrowserTest } void SayHelloAndWait() { - // Send a hello message to the service process and wait for a reply. + // Send a hello message to the service process and wait for a reply. process()->SendHello(); ui_test_utils::RunMessageLoop(); } + void DisconnectAndWaitForShutdown() { + // This will delete all instances of ServiceProcessControl and close the IPC + // connections. + ServiceProcessControlManager::instance()->Shutdown(); + process_ = NULL; + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + NewRunnableMethod(this, + &ServiceProcessControlBrowserTest::DoDetectShutdown), + TestTimeouts::wait_for_terminate_timeout_ms()); + ui_test_utils::RunMessageLoop(); + } + + + void DoDetectShutdown() { + EXPECT_FALSE(CheckServiceProcessRunning()); + // Quit the current message loop. + MessageLoop::current()->PostTask(FROM_HERE, + new MessageLoop::QuitTask()); + } + void ProcessControlLaunched() { process()->SetMessageHandler(this); // Quit the current message. @@ -85,6 +108,17 @@ IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, LaunchTwice) { // And then shutdown the service process. EXPECT_TRUE(process()->Shutdown()); } + +// Tests whether disconnecting from the service IPC causes the service process +// to die. +IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, DieOnDisconnect) { + // Launch the service process the first time. + LaunchServiceProcessControl(); + // Make sure we are connected to the service process. + EXPECT_TRUE(process()->is_connected()); + DisconnectAndWaitForShutdown(); +} + #endif DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest); diff --git a/chrome/browser/views/options/advanced_contents_view.cc b/chrome/browser/views/options/advanced_contents_view.cc index 2212d89..d066c0f 100644 --- a/chrome/browser/views/options/advanced_contents_view.cc +++ b/chrome/browser/views/options/advanced_contents_view.cc @@ -32,6 +32,7 @@ #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/pref_set_observer.h" +#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h" #include "chrome/browser/printing/cloud_print/cloud_print_url.h" #include "chrome/browser/profile.h" @@ -1377,9 +1378,6 @@ class CloudPrintProxySection : public AdvancedSection, // Overridden from views::ButtonListener: virtual void ButtonPressed(views::Button* sender, const views::Event& event); - // Callback that gets the cloud print proxy status. - void StatusCallback(bool enabled, std::string email); - // CloudPrintSetupFlow::Delegate implementation. virtual void OnDialogClosed(); @@ -1421,7 +1419,7 @@ void CloudPrintProxySection::ButtonPressed(views::Button* sender, // Enabled, we must be the disable button. UserMetricsRecordAction( UserMetricsAction("Options_DisableCloudPrintProxy"), NULL); - CloudPrintSetupFlow::DisableCloudPrintProxy(profile()); + profile()->GetCloudPrintProxyService()->DisableForUser(); } else { UserMetricsRecordAction( UserMetricsAction("Options_EnableCloudPrintProxy"), NULL); @@ -1444,11 +1442,6 @@ void CloudPrintProxySection::ButtonPressed(views::Button* sender, } } -void CloudPrintProxySection::StatusCallback(bool enabled, std::string email) { - profile()->GetPrefs()->SetString(prefs::kCloudPrintEmail, - enabled ? email : std::string()); -} - void CloudPrintProxySection::OnDialogClosed() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); enable_disable_button_->SetEnabled(true); @@ -1498,9 +1491,7 @@ void CloudPrintProxySection::InitControlLayout() { // Kick off a task to ask the background service what the real // answer is. - CloudPrintSetupFlow::RefreshPreferencesFromService( - profile(), - factory_.NewCallback(&CloudPrintProxySection::StatusCallback)); + profile()->GetCloudPrintProxyService()->RefreshStatusFromService(); } void CloudPrintProxySection::NotifyPrefChanged(const std::string* pref_name) { diff --git a/chrome/common/service_messages_internal.h b/chrome/common/service_messages_internal.h index bdacb34..bb6e34d 100644 --- a/chrome/common/service_messages_internal.h +++ b/chrome/common/service_messages_internal.h @@ -45,6 +45,9 @@ IPC_BEGIN_MESSAGES(Service) // Tell the service process to shutdown. IPC_MESSAGE_CONTROL0(ServiceMsg_Shutdown) + // Tell the service process that an update is available. + IPC_MESSAGE_CONTROL0(ServiceMsg_UpdateAvailable) + IPC_END_MESSAGES(Service) //------------------------------------------------------------------------------ diff --git a/chrome/service/service_ipc_server.cc b/chrome/service/service_ipc_server.cc index f912701..ae80d42 100644 --- a/chrome/service/service_ipc_server.cc +++ b/chrome/service/service_ipc_server.cc @@ -61,8 +61,11 @@ void ServiceIPCServer::OnChannelError() { // client requests, we will recreate the channel. bool client_was_connected = client_connected_; client_connected_ = false; - if (client_was_connected) + // TODO(sanjeevr): Instead of invoking the service process for such handlers, + // define a Client interface that the ServiceProcess can implement. + if (client_was_connected && g_service_process->HandleClientDisconnect()) { CreateChannel(); + } } bool ServiceIPCServer::Send(IPC::Message* msg) { @@ -88,6 +91,7 @@ void ServiceIPCServer::OnMessageReceived(const IPC::Message& msg) { OnIsCloudPrintProxyEnabled) IPC_MESSAGE_HANDLER(ServiceMsg_Hello, OnHello); IPC_MESSAGE_HANDLER(ServiceMsg_Shutdown, OnShutdown); + IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable); IPC_END_MESSAGE_MAP() } @@ -129,3 +133,8 @@ void ServiceIPCServer::OnHello() { void ServiceIPCServer::OnShutdown() { g_service_process->Shutdown(); } + +void ServiceIPCServer::OnUpdateAvailable() { + g_service_process->SetUpdateAvailable(); +} + diff --git a/chrome/service/service_ipc_server.h b/chrome/service/service_ipc_server.h index 1c8c19b..79416a5 100644 --- a/chrome/service/service_ipc_server.h +++ b/chrome/service/service_ipc_server.h @@ -51,6 +51,7 @@ class ServiceIPCServer : public IPC::Channel::Listener, void OnDisableCloudPrintProxy(); void OnHello(); void OnShutdown(); + void OnUpdateAvailable(); // Helper method to create the sync channel. void CreateChannel(); diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc index 86d787b..db562c3 100644 --- a/chrome/service/service_process.cc +++ b/chrome/service/service_process.cc @@ -52,7 +52,8 @@ static const int64 kShutdownDelay = 60000; ServiceProcess::ServiceProcess() : shutdown_event_(true, false), main_message_loop_(NULL), - enabled_services_(0) { + enabled_services_(0), + update_available_(false) { DCHECK(!g_service_process); g_service_process = this; } @@ -150,6 +151,17 @@ void ServiceProcess::Shutdown() { main_message_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); } +bool ServiceProcess::HandleClientDisconnect() { + // If there are no enabled services or if there is an update available + // we want to shutdown right away. Else we want to keep listening for + // new connections. + if (!enabled_services_ || update_available()) { + Shutdown(); + return false; + } + return true; +} + CloudPrintProxy* ServiceProcess::GetCloudPrintProxy() { if (!cloud_print_proxy_.get()) { cloud_print_proxy_.reset(new CloudPrintProxy()); @@ -180,7 +192,7 @@ void ServiceProcess::OnServiceEnabled() { } void ServiceProcess::OnServiceDisabled() { - DCHECK(0 != enabled_services_); + DCHECK_NE(enabled_services_, 0); enabled_services_--; if (0 == enabled_services_) { RemoveServiceProcessFromAutoStart(); diff --git a/chrome/service/service_process.h b/chrome/service/service_process.h index 3e99d21..a8a5e5a 100644 --- a/chrome/service/service_process.h +++ b/chrome/service/service_process.h @@ -6,6 +6,8 @@ #define CHROME_SERVICE_SERVICE_PROCESS_H_ #pragma once +#include <string> + #include "base/gtest_prod_util.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" @@ -74,6 +76,16 @@ class ServiceProcess : public RemotingDirectoryService::Client, // Shutdown the service process. This is likely triggered by a IPC message. void Shutdown(); + void SetUpdateAvailable() { + update_available_ = true; + } + bool update_available() const { return update_available_; } + + // Called by the IPC server when a client disconnects. A return value of + // true indicates that the IPC server should continue listening for new + // connections. + bool HandleClientDisconnect(); + CloudPrintProxy* GetCloudPrintProxy(); // CloudPrintProxy::Client implementation. @@ -168,6 +180,9 @@ class ServiceProcess : public RemotingDirectoryService::Client, // Count of currently enabled services in this process. int enabled_services_; + // Speficies whether a product update is available. + bool update_available_; + DISALLOW_COPY_AND_ASSIGN(ServiceProcess); }; |