Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc

Issue 3450021: Cloud print proxy management UI. (Closed)
Patch Set: Fix nits. Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2010 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_setup_flow.h"
6
7 #include "app/gfx/font_util.h"
8 #include "base/json/json_writer.h"
9 #include "base/singleton.h"
10 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/browser.h"
14 #include "chrome/browser/browser_list.h"
15 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
16 #include "chrome/browser/dom_ui/dom_ui_util.h"
17 #include "chrome/browser/platform_util.h"
18 #include "chrome/browser/prefs/pref_service.h"
19 #include "chrome/browser/printing/cloud_print/cloud_print_setup_message_handler. h"
20 #include "chrome/browser/profile.h"
21 #include "chrome/browser/remoting/remoting_resources_source.h"
22 #include "chrome/browser/renderer_host/render_view_host.h"
23 #include "chrome/browser/service/service_process_control.h"
24 #include "chrome/browser/service/service_process_control_manager.h"
25 #include "chrome/browser/tab_contents/tab_contents.h"
26 #include "chrome/common/net/gaia/gaia_authenticator2.h"
27 #include "chrome/common/net/gaia/gaia_constants.h"
28 #include "chrome/common/net/gaia/google_service_auth_error.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/common/service_messages.h"
31 #include "chrome/common/service_process_type.h"
32 #include "gfx/font.h"
33 #include "grit/locale_settings.h"
34
35 static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']";
36 static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']";
37
38 ////////////////////////////////////////////////////////////////////////////////
39 // CloudPrintServiceProcessHelper
40 //
41 // This is a helper class to perform actions when the service process
42 // is connected or launched. The events are sent back to CloudPrintSetupFlow
43 // when the dialog is still active. CloudPrintSetupFlow can detach from this
44 // helper class when the dialog is closed.
45
46 class CloudPrintServiceProcessHelper
47 : public base::RefCountedThreadSafe<CloudPrintServiceProcessHelper> {
48 public:
49 explicit CloudPrintServiceProcessHelper(CloudPrintSetupFlow* flow)
50 : flow_(flow) {
51 }
52
53 void Detach() {
54 flow_ = NULL;
55 }
56
57 void OnProcessLaunched() {
58 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
59 // If the flow is detached then show the done page.
60 if (!flow_)
61 return;
62
63 flow_->OnProcessLaunched();
64 }
65
66 private:
67 CloudPrintSetupFlow* flow_;
68
69 DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceProcessHelper);
70 };
71
72 ////////////////////////////////////////////////////////////////////////////////
73 // CloudPrintServiceDisableTask
74 //
75 // This is a helper class to get the proxy service launched if it
76 // isn't, in order to properly inform it that it should be disabled.
77
78 class CloudPrintServiceDisableTask
79 : public base::RefCountedThreadSafe<CloudPrintServiceDisableTask> {
80 public:
81 explicit CloudPrintServiceDisableTask(Profile* profile)
82 : profile_(profile),
83 process_control_(NULL) {
84 }
85
86 void StartDisable() {
87 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
88
89 process_control_ =
90 ServiceProcessControlManager::instance()->GetProcessControl(
91 profile_,
92 kServiceProcessCloudPrint);
93
94 if (process_control_) {
95 // If the process isn't connected, launch it now. This will run
96 // the task whether the process is already launched or not, as
97 // long as it's able to connect back up.
98 process_control_->Launch(
99 NewRunnableMethod(
100 this, &CloudPrintServiceDisableTask::OnProcessLaunched));
101 }
102 }
103
104 void OnProcessLaunched() {
105 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
106 DCHECK(process_control_);
107 if (process_control_->is_connected())
108 process_control_->Send(new ServiceMsg_DisableCloudPrintProxy());
109 profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
110 }
111
112 private:
113 Profile* profile_;
114 ServiceProcessControl* process_control_;
115
116 DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceDisableTask);
117 };
118
119 ////////////////////////////////////////////////////////////////////////////////
120 // CloudPrintServiceRefreshTask
121 //
122 // This is a helper class to perform a preferences refresh of the
123 // enablement state and registered e-mail from the cloud print proxy
124 // service.
125
126 class CloudPrintServiceRefreshTask
127 : public base::RefCountedThreadSafe<CloudPrintServiceRefreshTask> {
128 public:
129 explicit CloudPrintServiceRefreshTask(
130 Profile* profile,
131 Callback2<bool, std::string>::Type* callback)
132 : profile_(profile),
133 process_control_(NULL),
134 callback_(callback) {
135 DCHECK(callback);
136 }
137
138 void StartRefresh() {
139 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
140
141 process_control_ =
142 ServiceProcessControlManager::instance()->GetProcessControl(
143 profile_,
144 kServiceProcessCloudPrint);
145
146 if (process_control_) {
147 // If the process isn't connected, launch it now. This will run
148 // the task whether the process is already launched or not, as
149 // long as it's able to connect back up.
150 process_control_->Launch(
151 NewRunnableMethod(
152 this, &CloudPrintServiceRefreshTask::OnProcessLaunched));
153 }
154 }
155
156 void OnProcessLaunched() {
157 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
158 DCHECK(process_control_);
159
160 if (callback_ != NULL)
161 process_control_->GetCloudPrintProxyStatus(callback_.release());
162 }
163
164 private:
165 Profile* profile_;
166 ServiceProcessControl* process_control_;
167
168 // Callback that gets invoked when a status message is received from
169 // the cloud print proxy.
170 scoped_ptr<Callback2<bool, std::string>::Type> callback_;
171
172 DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceRefreshTask);
173 };
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // CloudPrintSetupFlow implementation.
177
178 // static
179 CloudPrintSetupFlow* CloudPrintSetupFlow::OpenDialog(Profile* profile) {
180 // Set the arguments for showing the gaia login page.
181 DictionaryValue args;
182 args.SetString("iframeToShow", "login");
183 args.SetString("user", "");
184 args.SetInteger("error", 0);
185 args.SetBoolean("editable_user", true);
186
187 if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
188 !profile->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty()) {
189 args.SetString("iframeToShow", "done");
190 }
191
192 std::string json_args;
193 base::JSONWriter::Write(&args, false, &json_args);
194
195 // Create a browser to run the dialog. The new CloudPrintSetupFlow
196 // class takes ownership.
197 Browser* browser = Browser::CreateForPopup(profile);
198 DCHECK(browser);
199
200 CloudPrintSetupFlow* flow = new CloudPrintSetupFlow(json_args, browser);
201 browser->BrowserShowHtmlDialog(flow, NULL);
202 return flow;
203 }
204
205 // static
206 void CloudPrintSetupFlow::DisableCloudPrintProxy(Profile* profile) {
207 scoped_refptr<CloudPrintServiceDisableTask> refresh_task =
208 new CloudPrintServiceDisableTask(profile);
209 ChromeThread::PostTask(
210 ChromeThread::UI, FROM_HERE,
211 NewRunnableMethod(refresh_task.get(),
212 &CloudPrintServiceDisableTask::StartDisable));
213 }
214
215 // static
216 void CloudPrintSetupFlow::RefreshPreferencesFromService(
217 Profile* profile,
218 Callback2<bool, std::string>::Type* callback) {
219 scoped_refptr<CloudPrintServiceRefreshTask> refresh_task =
220 new CloudPrintServiceRefreshTask(profile, callback);
221 ChromeThread::PostTask(
222 ChromeThread::UI, FROM_HERE,
223 NewRunnableMethod(refresh_task.get(),
224 &CloudPrintServiceRefreshTask::StartRefresh));
225 }
226
227 CloudPrintSetupFlow::CloudPrintSetupFlow(const std::string& args,
228 Browser* browser)
229 : dom_ui_(NULL),
230 dialog_start_args_(args),
231 process_control_(NULL) {
232 // TODO(hclam): The data source should be added once.
233 browser_.reset(browser);
234 ChromeThread::PostTask(
235 ChromeThread::IO, FROM_HERE,
236 NewRunnableMethod(Singleton<ChromeURLDataManager>::get(),
237 &ChromeURLDataManager::AddDataSource,
238 make_scoped_refptr(new RemotingResourcesSource())));
239 }
240
241 CloudPrintSetupFlow::~CloudPrintSetupFlow() {
242 }
243
244 void CloudPrintSetupFlow::Focus() {
245 // TODO(pranavk): implement this method.
246 NOTIMPLEMENTED();
247 }
248
249 ///////////////////////////////////////////////////////////////////////////////
250 // HtmlDialogUIDelegate implementation.
251 GURL CloudPrintSetupFlow::GetDialogContentURL() const {
252 return GURL("chrome://remotingresources/setup");
253 }
254
255 void CloudPrintSetupFlow::GetDOMMessageHandlers(
256 std::vector<DOMMessageHandler*>* handlers) const {
257 // Create the message handler only after we are asked, the caller is
258 // responsible for deleting the objects.
259 handlers->push_back(
260 new CloudPrintSetupMessageHandler(
261 const_cast<CloudPrintSetupFlow*>(this)));
262 }
263
264 void CloudPrintSetupFlow::GetDialogSize(gfx::Size* size) const {
265 PrefService* prefs = browser_->profile()->GetPrefs();
266 gfx::Font approximate_web_font(
267 UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
268 prefs->GetInteger(prefs::kWebKitDefaultFontSize));
269
270 // TODO(pranavk) Replace the following SYNC resources with REMOTING Resources.
271 *size = gfx::GetLocalizedContentsSizeForFont(
272 IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
273 IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
274 approximate_web_font);
275 }
276
277 // A callback to notify the delegate that the dialog closed.
278 void CloudPrintSetupFlow::OnDialogClosed(const std::string& json_retval) {
279 // If we are fetching the token then cancel the request.
280 if (authenticator_.get())
281 authenticator_->CancelRequest();
282
283 // If the service process helper is still active then detach outself from it.
284 // This is because the dialog is closing and this object is going to be
285 // deleted but the service process launch is still in progress so we don't
286 // the service process helper to call us when the process is launched.
287 if (service_process_helper_.get())
288 service_process_helper_->Detach();
289 delete this;
290 }
291
292 std::string CloudPrintSetupFlow::GetDialogArgs() const {
293 return dialog_start_args_;
294 }
295
296 void CloudPrintSetupFlow::OnCloseContents(TabContents* source,
297 bool* out_close_dialog) {
298 }
299
300 std::wstring CloudPrintSetupFlow::GetDialogTitle() const {
301 return l10n_util::GetString(IDS_CLOUD_PRINT_SETUP_DIALOG_TITLE);
302 }
303
304 bool CloudPrintSetupFlow::IsDialogModal() const {
305 return true;
306 }
307
308 ///////////////////////////////////////////////////////////////////////////////
309 // GaiaAuthConsumer implementation.
310 void CloudPrintSetupFlow::OnClientLoginFailure(
311 const GoogleServiceAuthError& error) {
312 ShowGaiaFailed(error);
313 authenticator_.reset();
314 }
315
316 void CloudPrintSetupFlow::OnClientLoginSuccess(
317 const GaiaAuthConsumer::ClientLoginResult& credentials) {
318 // Save the token for the cloud print proxy.
319 lsid_ = credentials.lsid;
320
321 // Show that Gaia login has succeeded.
322 ShowGaiaSuccessAndSettingUp();
323 authenticator_.reset();
324
325 // And then launch the service process if it has not started yet.
326 // If we have already connected to the service process then submit the tokens
327 // to it to register the host.
328 process_control_ =
329 ServiceProcessControlManager::instance()->GetProcessControl(
330 browser_->profile(),
331 kServiceProcessCloudPrint);
332
333 #if defined(OS_WIN)
334 // TODO(hclam): This call only works on Windows. I need to make it
335 // work on other platforms.
336 service_process_helper_ = new CloudPrintServiceProcessHelper(this);
337
338 // If the process isn't connected, launch it now. This will run the
339 // task whether the process is already launched or not, as long as
340 // it's able to connect back up.
341 process_control_->Launch(
342 NewRunnableMethod(service_process_helper_.get(),
343 &CloudPrintServiceProcessHelper::OnProcessLaunched));
344 #else
345 ShowSetupDone();
346 #endif
347 }
348
349 ///////////////////////////////////////////////////////////////////////////////
350 // Methods called by CloudPrintSetupMessageHandler
351 void CloudPrintSetupFlow::Attach(DOMUI* dom_ui) {
352 dom_ui_ = dom_ui;
353 }
354
355 void CloudPrintSetupFlow::OnUserSubmittedAuth(const std::string& user,
356 const std::string& password,
357 const std::string& captcha) {
358 // Save the login name only.
359 login_ = user;
360
361 // Start the authenticator.
362 authenticator_.reset(
363 new GaiaAuthenticator2(this, GaiaConstants::kChromeSource,
364 browser_->profile()->GetRequestContext()));
365 authenticator_->StartClientLogin(user, password,
366 GaiaConstants::kCloudPrintService,
367 "", captcha);
368 }
369
370 ///////////////////////////////////////////////////////////////////////////////
371 // Method called by CloudPrintServiceProcessHelper
372 void CloudPrintSetupFlow::OnProcessLaunched() {
373 DCHECK(process_control_->is_connected());
374 // TODO(scottbyer): Need to wait for an ACK to be sure that it is
375 // actually active.
376 if (!lsid_.empty())
377 process_control_->Send(new ServiceMsg_EnableCloudPrintProxy(lsid_));
378
379 // Save the preference that we have completed the setup of cloud
380 // print.
381 browser_->profile()->GetPrefs()->SetString(prefs::kCloudPrintEmail, login_);
382 ShowSetupDone();
383 }
384
385 ///////////////////////////////////////////////////////////////////////////////
386 // Helper methods for showing contents of the DOM UI
387 void CloudPrintSetupFlow::ShowGaiaLogin(const DictionaryValue& args) {
388 if (dom_ui_)
389 dom_ui_->CallJavascriptFunction(L"showGaiaLoginIframe");
390
391 std::string json;
392 base::JSONWriter::Write(&args, false, &json);
393 std::wstring javascript = std::wstring(L"showGaiaLogin") +
394 L"(" + UTF8ToWide(json) + L");";
395 ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
396 }
397
398 void CloudPrintSetupFlow::ShowGaiaSuccessAndSettingUp() {
399 ExecuteJavascriptInIFrame(kLoginIFrameXPath,
400 L"showGaiaSuccessAndSettingUp();");
401 }
402
403 void CloudPrintSetupFlow::ShowGaiaFailed(const GoogleServiceAuthError& error) {
404 DictionaryValue args;
405 args.SetString("iframeToShow", "login");
406 args.SetString("user", "");
407 args.SetInteger("error", error.state());
408 args.SetBoolean("editable_user", true);
409 args.SetString("captchaUrl", error.captcha().image_url.spec());
410 ShowGaiaLogin(args);
411 }
412
413 void CloudPrintSetupFlow::ShowSetupDone() {
414 std::wstring javascript = L"setMessage('You are all set!');";
415 ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
416
417 if (dom_ui_)
418 dom_ui_->CallJavascriptFunction(L"showSetupDone");
419
420 ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();");
421 }
422
423 void CloudPrintSetupFlow::ExecuteJavascriptInIFrame(
424 const std::wstring& iframe_xpath,
425 const std::wstring& js) {
426 if (dom_ui_) {
427 RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
428 rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
429 }
430 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698