1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
6
7 #include <stack>
8 #include <vector>
9
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/notifications/desktop_notification_service.h"
13 #include "chrome/browser/notifications/notification.h"
14 #include "chrome/browser/notifications/notification_ui_manager.h"
15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/service/service_process_control.h"
19 #include "chrome/browser/service/service_process_control_manager.h"
20 #include "chrome/browser/ui/browser_list.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/service_messages.h"
23 #include "content/browser/browser_thread.h"
24 #include "grit/generated_resources.h"
25 #include "ui/base/l10n/l10n_util.h"
26
27 // TODO(sanjeevr): Localize the product name?
28 const char kCloudPrintProductName[] = "Google Cloud Print";
29
30 class CloudPrintProxyService::TokenExpiredNotificationDelegate
31 : public NotificationDelegate {
32 public:
TokenExpiredNotificationDelegate(CloudPrintProxyService * cloud_print_service)33 explicit TokenExpiredNotificationDelegate(
34 CloudPrintProxyService* cloud_print_service)
35 : cloud_print_service_(cloud_print_service) {
36 }
Display()37 void Display() {}
Error()38 void Error() {
39 cloud_print_service_->OnTokenExpiredNotificationError();
40 }
Close(bool by_user)41 void Close(bool by_user) {
42 cloud_print_service_->OnTokenExpiredNotificationClosed(by_user);
43 }
Click()44 void Click() {
45 cloud_print_service_->OnTokenExpiredNotificationClick();
46 }
id() const47 std::string id() const { return "cloudprint.tokenexpired"; }
48
49 private:
50 CloudPrintProxyService* cloud_print_service_;
51 DISALLOW_COPY_AND_ASSIGN(TokenExpiredNotificationDelegate);
52 };
53
CloudPrintProxyService(Profile * profile)54 CloudPrintProxyService::CloudPrintProxyService(Profile* profile)
55 : profile_(profile), token_expired_delegate_(NULL) {
56 }
57
~CloudPrintProxyService()58 CloudPrintProxyService::~CloudPrintProxyService() {
59 }
60
Initialize()61 void CloudPrintProxyService::Initialize() {
62 if (profile_->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
63 !profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty()) {
64 // If the cloud print proxy is enabled, establish a channel with the
65 // service process and update the status.
66 RefreshStatusFromService();
67 }
68 }
69
RefreshStatusFromService()70 void CloudPrintProxyService::RefreshStatusFromService() {
71 InvokeServiceTask(
72 NewRunnableMethod(
73 this, &CloudPrintProxyService::RefreshCloudPrintProxyStatus));
74 }
75
EnableForUser(const std::string & lsid,const std::string & email)76 void CloudPrintProxyService::EnableForUser(const std::string& lsid,
77 const std::string& email) {
78 InvokeServiceTask(
79 NewRunnableMethod(
80 this, &CloudPrintProxyService::EnableCloudPrintProxy, lsid, email));
81 }
82
DisableForUser()83 void CloudPrintProxyService::DisableForUser() {
84 InvokeServiceTask(
85 NewRunnableMethod(
86 this, &CloudPrintProxyService::DisableCloudPrintProxy));
87 }
88
ShowTokenExpiredNotification()89 bool CloudPrintProxyService::ShowTokenExpiredNotification() {
90 // If we already have a pending notification, don't show another one.
91 if (token_expired_delegate_.get())
92 return false;
93
94 // TODO(sanjeevr): Get icon for this notification.
95 GURL icon_url;
96
97 string16 title = UTF8ToUTF16(kCloudPrintProductName);
98 string16 message =
99 l10n_util::GetStringUTF16(IDS_CLOUD_PRINT_TOKEN_EXPIRED_MESSAGE);
100 string16 content_url = DesktopNotificationService::CreateDataUrl(
101 icon_url, title, message, WebKit::WebTextDirectionDefault);
102 token_expired_delegate_ = new TokenExpiredNotificationDelegate(this);
103 Notification notification(GURL(), GURL(content_url), string16(), string16(),
104 token_expired_delegate_.get());
105 g_browser_process->notification_ui_manager()->Add(notification, profile_);
106 // Keep the browser alive while we are showing the notification.
107 BrowserList::StartKeepAlive();
108 return true;
109 }
110
OnTokenExpiredNotificationError()111 void CloudPrintProxyService::OnTokenExpiredNotificationError() {
112 TokenExpiredNotificationDone(false);
113 }
114
OnTokenExpiredNotificationClosed(bool by_user)115 void CloudPrintProxyService::OnTokenExpiredNotificationClosed(bool by_user) {
116 TokenExpiredNotificationDone(false);
117 }
118
OnTokenExpiredNotificationClick()119 void CloudPrintProxyService::OnTokenExpiredNotificationClick() {
120 TokenExpiredNotificationDone(true);
121 // Clear the cached cloud print email pref so that the cloud print setup
122 // flow happens.
123 profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
124 cloud_print_setup_handler_.reset(new CloudPrintSetupHandler(this));
125 CloudPrintSetupFlow::OpenDialog(
126 profile_, cloud_print_setup_handler_->AsWeakPtr(), NULL);
127 }
128
TokenExpiredNotificationDone(bool keep_alive)129 void CloudPrintProxyService::TokenExpiredNotificationDone(bool keep_alive) {
130 if (token_expired_delegate_.get()) {
131 g_browser_process->notification_ui_manager()->CancelById(
132 token_expired_delegate_->id());
133 token_expired_delegate_ = NULL;
134 if (!keep_alive)
135 BrowserList::EndKeepAlive();
136 }
137 }
138
OnCloudPrintSetupClosed()139 void CloudPrintProxyService::OnCloudPrintSetupClosed() {
140 MessageLoop::current()->PostTask(
141 FROM_HERE, NewRunnableFunction(&BrowserList::EndKeepAlive));
142 }
143
RefreshCloudPrintProxyStatus()144 void CloudPrintProxyService::RefreshCloudPrintProxyStatus() {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146 ServiceProcessControl* process_control =
147 ServiceProcessControlManager::GetInstance()->GetProcessControl(profile_);
148 DCHECK(process_control->is_connected());
149 Callback2<bool, std::string>::Type* callback =
150 NewCallback(this, &CloudPrintProxyService::StatusCallback);
151 // GetCloudPrintProxyStatus takes ownership of callback.
152 process_control->GetCloudPrintProxyStatus(callback);
153 }
154
EnableCloudPrintProxy(const std::string & lsid,const std::string & email)155 void CloudPrintProxyService::EnableCloudPrintProxy(const std::string& lsid,
156 const std::string& email) {
157 ServiceProcessControl* process_control =
158 ServiceProcessControlManager::GetInstance()->GetProcessControl(profile_);
159 DCHECK(process_control->is_connected());
160 process_control->Send(new ServiceMsg_EnableCloudPrintProxy(lsid));
161 // Assume the IPC worked.
162 profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, email);
163 }
164
DisableCloudPrintProxy()165 void CloudPrintProxyService::DisableCloudPrintProxy() {
166 ServiceProcessControl* process_control =
167 ServiceProcessControlManager::GetInstance()->GetProcessControl(profile_);
168 DCHECK(process_control->is_connected());
169 process_control->Send(new ServiceMsg_DisableCloudPrintProxy);
170 // Assume the IPC worked.
171 profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
172 }
173
StatusCallback(bool enabled,std::string email)174 void CloudPrintProxyService::StatusCallback(bool enabled, std::string email) {
175 profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail,
176 enabled ? email : std::string());
177 }
178
InvokeServiceTask(Task * task)179 bool CloudPrintProxyService::InvokeServiceTask(Task* task) {
180 ServiceProcessControl* process_control =
181 ServiceProcessControlManager::GetInstance()->GetProcessControl(profile_);
182 DCHECK(process_control);
183 if (process_control)
184 process_control->Launch(task, NULL);
185 return !!process_control;
186 }
187