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