local_discovery_ui_handler.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
1// Copyright 2013 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/ui/webui/local_discovery/local_discovery_ui_handler.h"
6
7#include <set>
8
9#include "base/bind.h"
10#include "base/command_line.h"
11#include "base/message_loop/message_loop.h"
12#include "base/prefs/pref_service.h"
13#include "base/strings/stringprintf.h"
14#include "base/strings/utf_string_conversions.h"
15#include "base/values.h"
16#include "chrome/browser/chrome_notification_types.h"
17#include "chrome/browser/local_discovery/cloud_print_account_manager.h"
18#include "chrome/browser/local_discovery/privet_confirm_api_flow.h"
19#include "chrome/browser/local_discovery/privet_constants.h"
20#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
21#include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h"
22#include "chrome/browser/local_discovery/privet_http_impl.h"
23#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
24#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
25#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
26#include "chrome/browser/printing/cloud_print/cloud_print_url.h"
27#include "chrome/browser/profiles/profile.h"
28#include "chrome/browser/signin/profile_oauth2_token_service.h"
29#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
30#include "chrome/browser/signin/signin_manager.h"
31#include "chrome/browser/signin/signin_manager_base.h"
32#include "chrome/browser/signin/signin_manager_factory.h"
33#include "chrome/browser/signin/signin_promo.h"
34#include "chrome/browser/ui/browser_finder.h"
35#include "chrome/browser/ui/browser_tabstrip.h"
36#include "chrome/common/chrome_switches.h"
37#include "chrome/common/pref_names.h"
38#include "content/public/browser/notification_source.h"
39#include "content/public/browser/user_metrics.h"
40#include "content/public/browser/user_metrics.h"
41#include "content/public/browser/web_ui.h"
42#include "content/public/common/page_transition_types.h"
43#include "grit/generated_resources.h"
44#include "net/base/host_port_pair.h"
45#include "net/base/net_util.h"
46#include "net/http/http_status_code.h"
47#include "ui/base/l10n/l10n_util.h"
48
49#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS) && \
50  !defined(OS_MACOSX)
51#define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
52#endif
53
54namespace local_discovery {
55
56namespace {
57const char kPrivetAutomatedClaimURLFormat[] = "%s/confirm?token=%s";
58const int kRegistrationAnnouncementTimeoutSeconds = 5;
59
60const int kInitialRequeryTimeSeconds = 1;
61const int kMaxRequeryTimeSeconds = 2; // Time for last requery
62
63int g_num_visible = 0;
64
65}  // namespace
66
67LocalDiscoveryUIHandler::LocalDiscoveryUIHandler() : is_visible_(false) {
68#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
69#if !defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN)
70  // On Windows, we need the PDF plugin which is only guaranteed to exist on
71  // Google Chrome builds. Use a command-line switch for Windows non-Google
72  //  Chrome builds.
73  cloud_print_connector_ui_enabled_ =
74      CommandLine::ForCurrentProcess()->HasSwitch(
75      switches::kEnableCloudPrintProxy);
76#elif !defined(OS_CHROMEOS)
77  // Always enabled for Linux and Google Chrome Windows builds.
78  // Never enabled for Chrome OS, we don't even need to indicate it.
79  cloud_print_connector_ui_enabled_ = true;
80#endif
81#endif  // !defined(OS_MACOSX)
82}
83
84LocalDiscoveryUIHandler::~LocalDiscoveryUIHandler() {
85  ResetCurrentRegistration();
86  SetIsVisible(false);
87}
88
89// static
90bool LocalDiscoveryUIHandler::GetHasVisible() {
91  return g_num_visible != 0;
92}
93
94void LocalDiscoveryUIHandler::RegisterMessages() {
95  web_ui()->RegisterMessageCallback("start", base::Bind(
96      &LocalDiscoveryUIHandler::HandleStart,
97      base::Unretained(this)));
98  web_ui()->RegisterMessageCallback("isVisible", base::Bind(
99      &LocalDiscoveryUIHandler::HandleIsVisible,
100      base::Unretained(this)));
101  web_ui()->RegisterMessageCallback("registerDevice", base::Bind(
102      &LocalDiscoveryUIHandler::HandleRegisterDevice,
103      base::Unretained(this)));
104  web_ui()->RegisterMessageCallback("cancelRegistration", base::Bind(
105      &LocalDiscoveryUIHandler::HandleCancelRegistration,
106      base::Unretained(this)));
107  web_ui()->RegisterMessageCallback("requestPrinterList", base::Bind(
108      &LocalDiscoveryUIHandler::HandleRequestPrinterList,
109      base::Unretained(this)));
110  web_ui()->RegisterMessageCallback("openCloudPrintURL", base::Bind(
111      &LocalDiscoveryUIHandler::HandleOpenCloudPrintURL,
112      base::Unretained(this)));
113  web_ui()->RegisterMessageCallback("showSyncUI", base::Bind(
114      &LocalDiscoveryUIHandler::HandleShowSyncUI,
115      base::Unretained(this)));
116
117  // Cloud print connector related messages
118#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
119  if (cloud_print_connector_ui_enabled_) {
120    web_ui()->RegisterMessageCallback(
121        "showCloudPrintSetupDialog",
122        base::Bind(&LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog,
123                   base::Unretained(this)));
124    web_ui()->RegisterMessageCallback(
125        "disableCloudPrintConnector",
126        base::Bind(&LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector,
127                   base::Unretained(this)));
128  }
129#endif  // defined(ENABLE_FULL_PRINTING)
130}
131
132void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) {
133  Profile* profile = Profile::FromWebUI(web_ui());
134
135  // If privet_lister_ is already set, it is a mock used for tests or the result
136  // of a reload.
137  if (!privet_lister_) {
138    service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
139    privet_lister_.reset(new PrivetDeviceListerImpl(
140        service_discovery_client_.get(), this));
141    privet_http_factory_ =
142        PrivetHTTPAsynchronousFactory::CreateInstance(
143            service_discovery_client_.get(), profile->GetRequestContext());
144  }
145
146  privet_lister_->Start();
147  SendQuery(kInitialRequeryTimeSeconds);
148
149#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
150  StartCloudPrintConnector();
151#endif
152
153  CheckUserLoggedIn();
154
155  notification_registrar_.RemoveAll();
156  notification_registrar_.Add(this,
157                              chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
158                              content::Source<Profile>(profile));
159  notification_registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
160                              content::Source<Profile>(profile));
161}
162
163void LocalDiscoveryUIHandler::HandleIsVisible(const base::ListValue* args) {
164  bool is_visible = false;
165  bool rv = args->GetBoolean(0, &is_visible);
166  DCHECK(rv);
167  SetIsVisible(is_visible);
168}
169
170void LocalDiscoveryUIHandler::HandleRegisterDevice(
171    const base::ListValue* args) {
172  std::string device;
173
174  bool rv = args->GetString(0, &device);
175  DCHECK(rv);
176
177  privet_resolution_ = privet_http_factory_->CreatePrivetHTTP(
178      device,
179      device_descriptions_[device].address,
180      base::Bind(&LocalDiscoveryUIHandler::StartRegisterHTTP,
181                 base::Unretained(this)));
182  privet_resolution_->Start();
183}
184
185void LocalDiscoveryUIHandler::HandleCancelRegistration(
186    const base::ListValue* args) {
187  ResetCurrentRegistration();
188}
189
190void LocalDiscoveryUIHandler::HandleRequestPrinterList(
191    const base::ListValue* args) {
192  Profile* profile = Profile::FromWebUI(web_ui());
193  ProfileOAuth2TokenService* token_service =
194      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
195
196  cloud_print_printer_list_.reset(new CloudPrintPrinterList(
197      profile->GetRequestContext(),
198      GetCloudPrintBaseUrl(),
199      token_service,
200      token_service->GetPrimaryAccountId(),
201      this));
202  cloud_print_printer_list_->Start();
203}
204
205void LocalDiscoveryUIHandler::HandleOpenCloudPrintURL(
206    const base::ListValue* args) {
207  std::string url;
208  bool rv = args->GetString(0, &url);
209  DCHECK(rv);
210
211  GURL url_full(GetCloudPrintBaseUrl() + url);
212
213  Browser* browser = chrome::FindBrowserWithWebContents(
214      web_ui()->GetWebContents());
215  DCHECK(browser);
216
217  chrome::AddSelectedTabWithURL(browser,
218                                url_full,
219                                content::PAGE_TRANSITION_FROM_API);
220}
221
222void LocalDiscoveryUIHandler::HandleShowSyncUI(
223    const base::ListValue* args) {
224  Browser* browser = chrome::FindBrowserWithWebContents(
225      web_ui()->GetWebContents());
226  DCHECK(browser);
227
228  // We use SOURCE_SETTINGS because the URL for SOURCE_SETTINGS is detected on
229  // redirect.
230  GURL url(signin::GetPromoURL(signin::SOURCE_SETTINGS,
231                               true));  // auto close after success.
232
233  browser->OpenURL(
234      content::OpenURLParams(url, content::Referrer(), SINGLETON_TAB,
235                             content::PAGE_TRANSITION_AUTO_BOOKMARK, false));
236}
237
238void LocalDiscoveryUIHandler::StartRegisterHTTP(
239    scoped_ptr<PrivetHTTPClient> http_client) {
240  current_http_client_.swap(http_client);
241
242  std::string user = GetSyncAccount();
243
244  if (!current_http_client_) {
245    SendRegisterError();
246    return;
247  }
248
249  current_register_operation_ =
250      current_http_client_->CreateRegisterOperation(user, this);
251  current_register_operation_->Start();
252}
253
254void LocalDiscoveryUIHandler::OnPrivetRegisterClaimToken(
255    PrivetRegisterOperation* operation,
256    const std::string& token,
257    const GURL& url) {
258  web_ui()->CallJavascriptFunction(
259      "local_discovery.onRegistrationConfirmedOnPrinter");
260  if (device_descriptions_.count(current_http_client_->GetName()) == 0) {
261    SendRegisterError();
262    return;
263  }
264
265  std::string base_url = GetCloudPrintBaseUrl();
266
267  GURL automated_claim_url(base::StringPrintf(
268      kPrivetAutomatedClaimURLFormat,
269      base_url.c_str(),
270      token.c_str()));
271
272  Profile* profile = Profile::FromWebUI(web_ui());
273
274  ProfileOAuth2TokenService* token_service =
275      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
276
277  if (!token_service) {
278    SendRegisterError();
279    return;
280  }
281
282  confirm_api_call_flow_.reset(new PrivetConfirmApiCallFlow(
283      profile->GetRequestContext(),
284      token_service,
285      token_service->GetPrimaryAccountId(),
286      automated_claim_url,
287      base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone,
288                 base::Unretained(this))));
289  confirm_api_call_flow_->Start();
290}
291
292void LocalDiscoveryUIHandler::OnPrivetRegisterError(
293    PrivetRegisterOperation* operation,
294    const std::string& action,
295    PrivetRegisterOperation::FailureReason reason,
296    int printer_http_code,
297    const DictionaryValue* json) {
298  std::string error;
299
300  if (reason == PrivetRegisterOperation::FAILURE_JSON_ERROR &&
301      json->GetString(kPrivetKeyError, &error)) {
302    if (error == kPrivetErrorTimeout) {
303        web_ui()->CallJavascriptFunction(
304            "local_discovery.onRegistrationTimeout");
305      return;
306    } else if (error == kPrivetErrorCancel) {
307      web_ui()->CallJavascriptFunction(
308            "local_discovery.onRegistrationCanceledPrinter");
309      return;
310    }
311  }
312
313  SendRegisterError();
314}
315
316void LocalDiscoveryUIHandler::OnPrivetRegisterDone(
317    PrivetRegisterOperation* operation,
318    const std::string& device_id) {
319  std::string name = operation->GetHTTPClient()->GetName();
320
321  current_register_operation_.reset();
322  current_http_client_.reset();
323
324  DeviceDescriptionMap::iterator found = device_descriptions_.find(name);
325
326  if (found == device_descriptions_.end() || found->second.id.empty()) {
327    // HACK(noamsml): Generate network traffic so the Windows firewall doesn't
328    // block the printer's announcement.
329    privet_lister_->DiscoverNewDevices(false);
330
331    new_register_device_ = name;
332    registration_announce_timeout_.Reset(base::Bind(
333        &LocalDiscoveryUIHandler::OnAnnouncementTimeoutReached,
334        base::Unretained(this)));
335
336    base::MessageLoop::current()->PostDelayedTask(
337        FROM_HERE,
338        registration_announce_timeout_.callback(),
339        base::TimeDelta::FromSeconds(kRegistrationAnnouncementTimeoutSeconds));
340  }
341}
342
343void LocalDiscoveryUIHandler::OnAnnouncementTimeoutReached() {
344  new_register_device_.clear();
345  registration_announce_timeout_.Cancel();
346
347  SendRegisterError();
348}
349
350void LocalDiscoveryUIHandler::OnConfirmDone(
351    CloudPrintBaseApiFlow::Status status) {
352  if (status == CloudPrintBaseApiFlow::SUCCESS) {
353    confirm_api_call_flow_.reset();
354    current_register_operation_->CompleteRegistration();
355  } else {
356    SendRegisterError();
357  }
358}
359
360void LocalDiscoveryUIHandler::DeviceChanged(
361    bool added,
362    const std::string& name,
363    const DeviceDescription& description) {
364  device_descriptions_[name] = description;
365
366  base::DictionaryValue info;
367
368  base::StringValue service_name(name);
369  scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
370
371  if (description.id.empty()) {
372    info.SetString("service_name", name);
373    info.SetString("human_readable_name", description.name);
374    info.SetString("description", description.description);
375
376    web_ui()->CallJavascriptFunction(
377        "local_discovery.onUnregisteredDeviceUpdate",
378        service_name, info);
379  } else {
380    web_ui()->CallJavascriptFunction(
381        "local_discovery.onUnregisteredDeviceUpdate",
382        service_name, *null_value);
383
384    if (name == new_register_device_) {
385      new_register_device_.clear();
386      SendRegisterDone(description);
387    }
388  }
389}
390
391void LocalDiscoveryUIHandler::DeviceRemoved(const std::string& name) {
392  device_descriptions_.erase(name);
393  scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
394  base::StringValue name_value(name);
395
396  web_ui()->CallJavascriptFunction("local_discovery.onUnregisteredDeviceUpdate",
397                                   name_value, *null_value);
398}
399
400void LocalDiscoveryUIHandler::DeviceCacheFlushed() {
401  web_ui()->CallJavascriptFunction("local_discovery.onDeviceCacheFlushed");
402  SendQuery(kInitialRequeryTimeSeconds);
403}
404
405void LocalDiscoveryUIHandler::OnCloudPrintPrinterListReady() {
406  base::ListValue printer_object_list;
407  std::set<std::string> local_ids;
408
409  for (DeviceDescriptionMap::iterator i = device_descriptions_.begin();
410       i != device_descriptions_.end();
411       i++) {
412    std::string device_id = i->second.id;
413    if (!device_id.empty()) {
414      const CloudPrintPrinterList::PrinterDetails* details =
415          cloud_print_printer_list_->GetDetailsFor(device_id);
416
417      if (details) {
418        local_ids.insert(device_id);
419        printer_object_list.Append(CreatePrinterInfo(*details).release());
420      }
421    }
422  }
423
424  for (CloudPrintPrinterList::iterator i = cloud_print_printer_list_->begin();
425       i != cloud_print_printer_list_->end(); i++) {
426    if (local_ids.count(i->id) == 0) {
427      printer_object_list.Append(CreatePrinterInfo(*i).release());
428    }
429  }
430
431  web_ui()->CallJavascriptFunction(
432      "local_discovery.onCloudDeviceListAvailable", printer_object_list);
433}
434
435void LocalDiscoveryUIHandler::OnCloudPrintPrinterListUnavailable() {
436  web_ui()->CallJavascriptFunction(
437      "local_discovery.onCloudDeviceListUnavailable");
438}
439
440void LocalDiscoveryUIHandler::Observe(
441    int type,
442    const content::NotificationSource& source,
443    const content::NotificationDetails& details) {
444  switch (type) {
445    case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL:
446    case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
447      CheckUserLoggedIn();
448      break;
449    default:
450      NOTREACHED();
451  }
452}
453
454void LocalDiscoveryUIHandler::SendRegisterError() {
455  web_ui()->CallJavascriptFunction("local_discovery.onRegistrationFailed");
456}
457
458void LocalDiscoveryUIHandler::SendRegisterDone(
459    const DeviceDescription& device) {
460  base::DictionaryValue printer_value;
461
462  printer_value.SetString("id", device.id);
463  printer_value.SetString("display_name", device.name);
464  printer_value.SetString("description", device.description);
465
466  web_ui()->CallJavascriptFunction("local_discovery.onRegistrationSuccess",
467                                   printer_value);
468}
469
470void LocalDiscoveryUIHandler::SetIsVisible(bool visible) {
471  if (visible != is_visible_) {
472    g_num_visible += visible ? 1 : -1;
473    is_visible_ = visible;
474  }
475}
476
477std::string LocalDiscoveryUIHandler::GetSyncAccount() {
478  Profile* profile = Profile::FromWebUI(web_ui());
479  SigninManagerBase* signin_manager =
480      SigninManagerFactory::GetForProfileIfExists(profile);
481
482  if (!signin_manager) {
483    return "";
484  }
485
486  return signin_manager->GetAuthenticatedUsername();
487}
488
489std::string LocalDiscoveryUIHandler::GetCloudPrintBaseUrl() {
490  CloudPrintURL cloud_print_url(Profile::FromWebUI(web_ui()));
491
492  return cloud_print_url.GetCloudPrintServiceURL().spec();
493}
494
495// TODO(noamsml): Create master object for registration flow.
496void LocalDiscoveryUIHandler::ResetCurrentRegistration() {
497  if (current_register_operation_.get()) {
498    current_register_operation_->Cancel();
499    current_register_operation_.reset();
500  }
501
502  confirm_api_call_flow_.reset();
503  privet_resolution_.reset();
504  current_http_client_.reset();
505}
506
507scoped_ptr<base::DictionaryValue> LocalDiscoveryUIHandler::CreatePrinterInfo(
508    const CloudPrintPrinterList::PrinterDetails& description) {
509  scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
510
511  return_value->SetString("id", description.id);
512  return_value->SetString("display_name", description.display_name);
513  return_value->SetString("description", description.description);
514
515  return return_value.Pass();
516}
517
518void LocalDiscoveryUIHandler::CheckUserLoggedIn() {
519  base::FundamentalValue logged_in_value(!GetSyncAccount().empty());
520  web_ui()->CallJavascriptFunction("local_discovery.setUserLoggedIn",
521                                   logged_in_value);
522}
523
524void LocalDiscoveryUIHandler::ScheduleQuery(int timeout_seconds) {
525  if (timeout_seconds <= kMaxRequeryTimeSeconds) {
526    requery_callback_.Reset(base::Bind(&LocalDiscoveryUIHandler::SendQuery,
527                                       base::Unretained(this),
528                                       timeout_seconds * 2));
529
530    base::MessageLoop::current()->PostDelayedTask(
531        FROM_HERE,
532        requery_callback_.callback(),
533        base::TimeDelta::FromSeconds(timeout_seconds));
534  }
535}
536
537void LocalDiscoveryUIHandler::SendQuery(int next_timeout_seconds) {
538  privet_lister_->DiscoverNewDevices(false);
539  ScheduleQuery(next_timeout_seconds);
540}
541
542#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
543void LocalDiscoveryUIHandler::StartCloudPrintConnector() {
544  Profile* profile = Profile::FromWebUI(web_ui());
545
546  base::Closure cloud_print_callback = base::Bind(
547      &LocalDiscoveryUIHandler::OnCloudPrintPrefsChanged,
548          base::Unretained(this));
549
550  if (cloud_print_connector_email_.GetPrefName().empty()) {
551    cloud_print_connector_email_.Init(
552        prefs::kCloudPrintEmail, profile->GetPrefs(), cloud_print_callback);
553  }
554
555  if (cloud_print_connector_enabled_.GetPrefName().empty()) {
556    cloud_print_connector_enabled_.Init(
557        prefs::kCloudPrintProxyEnabled, profile->GetPrefs(),
558        cloud_print_callback);
559  }
560
561  if (cloud_print_connector_ui_enabled_) {
562    SetupCloudPrintConnectorSection();
563    RefreshCloudPrintStatusFromService();
564  } else {
565    RemoveCloudPrintConnectorSection();
566  }
567}
568
569void LocalDiscoveryUIHandler::OnCloudPrintPrefsChanged() {
570  if (cloud_print_connector_ui_enabled_)
571    SetupCloudPrintConnectorSection();
572}
573
574void LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog(const ListValue* args) {
575  content::RecordAction(
576      content::UserMetricsAction("Options_EnableCloudPrintProxy"));
577  // Open the connector enable page in the current tab.
578  Profile* profile = Profile::FromWebUI(web_ui());
579  content::OpenURLParams params(
580      CloudPrintURL(profile).GetCloudPrintServiceEnableURL(
581          CloudPrintProxyServiceFactory::GetForProfile(profile)->proxy_id()),
582      content::Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_LINK, false);
583  web_ui()->GetWebContents()->OpenURL(params);
584}
585
586void LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector(
587    const ListValue* args) {
588  content::RecordAction(
589      content::UserMetricsAction("Options_DisableCloudPrintProxy"));
590  CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()))->
591      DisableForUser();
592}
593
594void LocalDiscoveryUIHandler::SetupCloudPrintConnectorSection() {
595  Profile* profile = Profile::FromWebUI(web_ui());
596
597  if (!CloudPrintProxyServiceFactory::GetForProfile(profile)) {
598    cloud_print_connector_ui_enabled_ = false;
599    RemoveCloudPrintConnectorSection();
600    return;
601  }
602
603  bool cloud_print_connector_allowed =
604      !cloud_print_connector_enabled_.IsManaged() ||
605      cloud_print_connector_enabled_.GetValue();
606  base::FundamentalValue allowed(cloud_print_connector_allowed);
607
608  std::string email;
609  if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
610      cloud_print_connector_allowed) {
611    email = profile->GetPrefs()->GetString(prefs::kCloudPrintEmail);
612  }
613  base::FundamentalValue disabled(email.empty());
614
615  string16 label_str;
616  if (email.empty()) {
617    label_str = l10n_util::GetStringFUTF16(
618        IDS_LOCAL_DISCOVERY_CLOUD_PRINT_CONNECTOR_DISABLED_LABEL,
619        l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
620  } else {
621    label_str = l10n_util::GetStringFUTF16(
622        IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLED_LABEL,
623        l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT),
624        UTF8ToUTF16(email));
625  }
626  StringValue label(label_str);
627
628  web_ui()->CallJavascriptFunction(
629      "local_discovery.setupCloudPrintConnectorSection", disabled, label,
630      allowed);
631}
632
633void LocalDiscoveryUIHandler::RemoveCloudPrintConnectorSection() {
634  web_ui()->CallJavascriptFunction(
635      "local_discovery.removeCloudPrintConnectorSection");
636}
637
638void LocalDiscoveryUIHandler::RefreshCloudPrintStatusFromService() {
639  if (cloud_print_connector_ui_enabled_)
640    CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()))->
641        RefreshStatusFromService();
642}
643#endif // cloud print connector option stuff
644
645}  // namespace local_discovery
646