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: 33 explicit TokenExpiredNotificationDelegate( 34 CloudPrintProxyService* cloud_print_service) 35 : cloud_print_service_(cloud_print_service) { 36 } 37 void Display() {} 38 void Error() { 39 cloud_print_service_->OnTokenExpiredNotificationError(); 40 } 41 void Close(bool by_user) { 42 cloud_print_service_->OnTokenExpiredNotificationClosed(by_user); 43 } 44 void Click() { 45 cloud_print_service_->OnTokenExpiredNotificationClick(); 46 } 47 std::string id() const { return "cloudprint.tokenexpired"; } 48 49 private: 50 CloudPrintProxyService* cloud_print_service_; 51 DISALLOW_COPY_AND_ASSIGN(TokenExpiredNotificationDelegate); 52 }; 53 54 CloudPrintProxyService::CloudPrintProxyService(Profile* profile) 55 : profile_(profile), token_expired_delegate_(NULL) { 56 } 57 58 CloudPrintProxyService::~CloudPrintProxyService() { 59 } 60 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 70 void CloudPrintProxyService::RefreshStatusFromService() { 71 InvokeServiceTask( 72 NewRunnableMethod( 73 this, &CloudPrintProxyService::RefreshCloudPrintProxyStatus)); 74 } 75 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 83 void CloudPrintProxyService::DisableForUser() { 84 InvokeServiceTask( 85 NewRunnableMethod( 86 this, &CloudPrintProxyService::DisableCloudPrintProxy)); 87 } 88 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 111 void CloudPrintProxyService::OnTokenExpiredNotificationError() { 112 TokenExpiredNotificationDone(false); 113 } 114 115 void CloudPrintProxyService::OnTokenExpiredNotificationClosed(bool by_user) { 116 TokenExpiredNotificationDone(false); 117 } 118 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 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 139 void CloudPrintProxyService::OnCloudPrintSetupClosed() { 140 MessageLoop::current()->PostTask( 141 FROM_HERE, NewRunnableFunction(&BrowserList::EndKeepAlive)); 142 } 143 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 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 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 174 void CloudPrintProxyService::StatusCallback(bool enabled, std::string email) { 175 profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, 176 enabled ? email : std::string()); 177 } 178 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