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