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