• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/local_discovery/privet_confirm_api_flow.h"
17 #include "chrome/browser/local_discovery/privet_constants.h"
18 #include "chrome/browser/local_discovery/privet_device_lister_impl.h"
19 #include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h"
20 #include "chrome/browser/local_discovery/privet_http_impl.h"
21 #include "chrome/browser/local_discovery/service_discovery_shared_client.h"
22 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
23 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
26 #include "chrome/browser/signin/signin_manager_factory.h"
27 #include "chrome/browser/signin/signin_promo.h"
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/browser_tabstrip.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/grit/generated_resources.h"
33 #include "components/cloud_devices/common/cloud_devices_switches.h"
34 #include "components/cloud_devices/common/cloud_devices_urls.h"
35 #include "components/signin/core/browser/profile_oauth2_token_service.h"
36 #include "components/signin/core/browser/signin_manager_base.h"
37 #include "content/public/browser/user_metrics.h"
38 #include "content/public/browser/web_ui.h"
39 #include "net/base/host_port_pair.h"
40 #include "net/base/net_util.h"
41 #include "net/base/url_util.h"
42 #include "net/http/http_status_code.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/page_transition_types.h"
45 
46 #if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS)
47 #define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
48 #endif
49 
50 namespace local_discovery {
51 
52 namespace {
53 
54 const char kDictionaryKeyServiceName[] = "service_name";
55 const char kDictionaryKeyDisplayName[] = "display_name";
56 const char kDictionaryKeyDescription[] = "description";
57 const char kDictionaryKeyType[] = "type";
58 const char kDictionaryKeyIsWifi[] = "is_wifi";
59 const char kDictionaryKeyID[] = "id";
60 
61 const char kKeyPrefixMDns[] = "MDns:";
62 
63 #if defined(ENABLE_WIFI_BOOTSTRAPPING)
64 const char kKeyPrefixWifi[] = "WiFi:";
65 #endif  // ENABLE_WIFI_BOOTSTRAPPING
66 
67 int g_num_visible = 0;
68 
69 const int kCloudDevicesPrivetVersion = 3;
70 
CreateDeviceInfo(const CloudDeviceListDelegate::Device & description)71 scoped_ptr<base::DictionaryValue> CreateDeviceInfo(
72     const CloudDeviceListDelegate::Device& description) {
73   scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
74 
75   return_value->SetString(kDictionaryKeyID, description.id);
76   return_value->SetString(kDictionaryKeyDisplayName, description.display_name);
77   return_value->SetString(kDictionaryKeyDescription, description.description);
78   return_value->SetString(kDictionaryKeyType, description.type);
79 
80   return return_value.Pass();
81 }
82 
ReadDevicesList(const std::vector<CloudDeviceListDelegate::Device> & devices,const std::set<std::string> & local_ids,base::ListValue * devices_list)83 void ReadDevicesList(
84     const std::vector<CloudDeviceListDelegate::Device>& devices,
85     const std::set<std::string>& local_ids,
86     base::ListValue* devices_list) {
87   for (CloudDeviceList::iterator i = devices.begin(); i != devices.end(); i++) {
88     if (local_ids.count(i->id) > 0) {
89       devices_list->Append(CreateDeviceInfo(*i).release());
90     }
91   }
92 
93   for (CloudDeviceList::iterator i = devices.begin(); i != devices.end(); i++) {
94     if (local_ids.count(i->id) == 0) {
95       devices_list->Append(CreateDeviceInfo(*i).release());
96     }
97   }
98 }
99 
100 }  // namespace
101 
LocalDiscoveryUIHandler()102 LocalDiscoveryUIHandler::LocalDiscoveryUIHandler()
103     : is_visible_(false),
104       failed_list_count_(0),
105       succeded_list_count_(0) {
106 #if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
107 #if !defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN)
108   // On Windows, we need the PDF plugin which is only guaranteed to exist on
109   // Google Chrome builds. Use a command-line switch for Windows non-Google
110   //  Chrome builds.
111   cloud_print_connector_ui_enabled_ =
112       CommandLine::ForCurrentProcess()->HasSwitch(
113       switches::kEnableCloudPrintProxy);
114 #else
115   // Always enabled for Linux and Google Chrome Windows builds.
116   // Never enabled for Chrome OS, we don't even need to indicate it.
117   cloud_print_connector_ui_enabled_ = true;
118 #endif
119 #endif  // defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
120 }
121 
~LocalDiscoveryUIHandler()122 LocalDiscoveryUIHandler::~LocalDiscoveryUIHandler() {
123   Profile* profile = Profile::FromWebUI(web_ui());
124   SigninManagerBase* signin_manager =
125       SigninManagerFactory::GetInstance()->GetForProfile(profile);
126   if (signin_manager)
127     signin_manager->RemoveObserver(this);
128   ResetCurrentRegistration();
129   SetIsVisible(false);
130 }
131 
132 // static
GetHasVisible()133 bool LocalDiscoveryUIHandler::GetHasVisible() {
134   return g_num_visible != 0;
135 }
136 
RegisterMessages()137 void LocalDiscoveryUIHandler::RegisterMessages() {
138   web_ui()->RegisterMessageCallback("start", base::Bind(
139       &LocalDiscoveryUIHandler::HandleStart,
140       base::Unretained(this)));
141   web_ui()->RegisterMessageCallback("isVisible", base::Bind(
142       &LocalDiscoveryUIHandler::HandleIsVisible,
143       base::Unretained(this)));
144   web_ui()->RegisterMessageCallback("registerDevice", base::Bind(
145       &LocalDiscoveryUIHandler::HandleRegisterDevice,
146       base::Unretained(this)));
147   web_ui()->RegisterMessageCallback(
148       "confirmCode",
149       base::Bind(&LocalDiscoveryUIHandler::HandleConfirmCode,
150                  base::Unretained(this)));
151   web_ui()->RegisterMessageCallback("cancelRegistration", base::Bind(
152       &LocalDiscoveryUIHandler::HandleCancelRegistration,
153       base::Unretained(this)));
154   web_ui()->RegisterMessageCallback(
155       "requestDeviceList",
156       base::Bind(&LocalDiscoveryUIHandler::HandleRequestDeviceList,
157                  base::Unretained(this)));
158   web_ui()->RegisterMessageCallback("openCloudPrintURL", base::Bind(
159       &LocalDiscoveryUIHandler::HandleOpenCloudPrintURL,
160       base::Unretained(this)));
161   web_ui()->RegisterMessageCallback("showSyncUI", base::Bind(
162       &LocalDiscoveryUIHandler::HandleShowSyncUI,
163       base::Unretained(this)));
164 
165   // Cloud print connector related messages
166 #if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
167   if (cloud_print_connector_ui_enabled_) {
168     web_ui()->RegisterMessageCallback(
169         "showCloudPrintSetupDialog",
170         base::Bind(&LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog,
171                    base::Unretained(this)));
172     web_ui()->RegisterMessageCallback(
173         "disableCloudPrintConnector",
174         base::Bind(&LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector,
175                    base::Unretained(this)));
176   }
177 #endif  // defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
178 }
179 
HandleStart(const base::ListValue * args)180 void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) {
181   Profile* profile = Profile::FromWebUI(web_ui());
182 
183   // If privet_lister_ is already set, it is a mock used for tests or the result
184   // of a reload.
185   if (!privet_lister_) {
186     service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
187     privet_lister_.reset(
188         new PrivetDeviceListerImpl(service_discovery_client_.get(), this));
189     privet_http_factory_ = PrivetHTTPAsynchronousFactory::CreateInstance(
190         service_discovery_client_.get(), profile->GetRequestContext());
191 
192     SigninManagerBase* signin_manager =
193         SigninManagerFactory::GetInstance()->GetForProfile(profile);
194     if (signin_manager)
195       signin_manager->AddObserver(this);
196   }
197 
198   privet_lister_->Start();
199   privet_lister_->DiscoverNewDevices(false);
200 
201 #if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
202   StartCloudPrintConnector();
203 #endif
204 
205 #if defined(ENABLE_WIFI_BOOTSTRAPPING)
206   if (CommandLine::ForCurrentProcess()->HasSwitch(
207           switches::kEnableCloudDevices)) {
208     StartWifiBootstrapping();
209   }
210 #endif
211 
212   CheckUserLoggedIn();
213 }
214 
HandleIsVisible(const base::ListValue * args)215 void LocalDiscoveryUIHandler::HandleIsVisible(const base::ListValue* args) {
216   bool is_visible = false;
217   bool rv = args->GetBoolean(0, &is_visible);
218   DCHECK(rv);
219   SetIsVisible(is_visible);
220 }
221 
HandleRegisterDevice(const base::ListValue * args)222 void LocalDiscoveryUIHandler::HandleRegisterDevice(
223     const base::ListValue* args) {
224   std::string device;
225 
226   bool rv = args->GetString(0, &device);
227   DCHECK(rv);
228 
229   DeviceDescriptionMap::iterator found = device_descriptions_.find(device);
230   if (found == device_descriptions_.end()) {
231     OnSetupError();
232     return;
233   }
234 
235   if (found->second.version == kCloudDevicesPrivetVersion) {
236     current_setup_operation_.reset(new PrivetV3SetupFlow(this));
237     current_setup_operation_->Register(device);
238   } else if (found->second.version <= 2) {
239     privet_resolution_ = privet_http_factory_->CreatePrivetHTTP(
240         device,
241         found->second.address,
242         base::Bind(&LocalDiscoveryUIHandler::StartRegisterHTTP,
243                    base::Unretained(this)));
244     privet_resolution_->Start();
245   } else {
246     OnSetupError();
247   }
248 }
249 
HandleConfirmCode(const base::ListValue * args)250 void LocalDiscoveryUIHandler::HandleConfirmCode(const base::ListValue* args) {
251   device_code_callback_.Run(true);
252 }
253 
HandleCancelRegistration(const base::ListValue * args)254 void LocalDiscoveryUIHandler::HandleCancelRegistration(
255     const base::ListValue* args) {
256   ResetCurrentRegistration();
257 }
258 
HandleRequestDeviceList(const base::ListValue * args)259 void LocalDiscoveryUIHandler::HandleRequestDeviceList(
260     const base::ListValue* args) {
261   failed_list_count_ = 0;
262   succeded_list_count_ = 0;
263   cloud_devices_.clear();
264 
265   cloud_print_printer_list_ = CreateApiFlow();
266   if (CommandLine::ForCurrentProcess()->HasSwitch(
267       switches::kEnableCloudDevices)) {
268     cloud_device_list_ = CreateApiFlow();
269   }
270 
271   if (cloud_print_printer_list_) {
272     cloud_print_printer_list_->Start(
273         make_scoped_ptr<GCDApiFlow::Request>(new CloudPrintPrinterList(this)));
274   }
275   if (cloud_device_list_) {
276     cloud_device_list_->Start(
277         make_scoped_ptr<GCDApiFlow::Request>(new CloudDeviceList(this)));
278   }
279   CheckListingDone();
280 }
281 
HandleOpenCloudPrintURL(const base::ListValue * args)282 void LocalDiscoveryUIHandler::HandleOpenCloudPrintURL(
283     const base::ListValue* args) {
284   std::string id;
285   bool rv = args->GetString(0, &id);
286   DCHECK(rv);
287 
288   Browser* browser = chrome::FindBrowserWithWebContents(
289       web_ui()->GetWebContents());
290   DCHECK(browser);
291 
292   chrome::AddSelectedTabWithURL(browser,
293                                 cloud_devices::GetCloudPrintManageDeviceURL(id),
294                                 ui::PAGE_TRANSITION_FROM_API);
295 }
296 
HandleShowSyncUI(const base::ListValue * args)297 void LocalDiscoveryUIHandler::HandleShowSyncUI(
298     const base::ListValue* args) {
299   Browser* browser = chrome::FindBrowserWithWebContents(
300       web_ui()->GetWebContents());
301   DCHECK(browser);
302 
303   GURL url(signin::GetPromoURL(signin::SOURCE_DEVICES_PAGE,
304                                true));  // auto close after success.
305 
306   browser->OpenURL(
307       content::OpenURLParams(url, content::Referrer(), SINGLETON_TAB,
308                              ui::PAGE_TRANSITION_AUTO_BOOKMARK, false));
309 }
310 
StartRegisterHTTP(scoped_ptr<PrivetHTTPClient> http_client)311 void LocalDiscoveryUIHandler::StartRegisterHTTP(
312     scoped_ptr<PrivetHTTPClient> http_client) {
313   current_http_client_ = PrivetV1HTTPClient::CreateDefault(http_client.Pass());
314 
315   std::string user = GetSyncAccount();
316 
317   if (!current_http_client_) {
318     SendRegisterError();
319     return;
320   }
321 
322   current_register_operation_ =
323       current_http_client_->CreateRegisterOperation(user, this);
324   current_register_operation_->Start();
325 }
326 
OnPrivetRegisterClaimToken(PrivetRegisterOperation * operation,const std::string & token,const GURL & url)327 void LocalDiscoveryUIHandler::OnPrivetRegisterClaimToken(
328     PrivetRegisterOperation* operation,
329     const std::string& token,
330     const GURL& url) {
331   web_ui()->CallJavascriptFunction(
332       "local_discovery.onRegistrationConfirmedOnPrinter");
333   if (device_descriptions_.count(current_http_client_->GetName()) == 0) {
334     SendRegisterError();
335     return;
336   }
337 
338   confirm_api_call_flow_ = CreateApiFlow();
339   if (!confirm_api_call_flow_) {
340     SendRegisterError();
341     return;
342   }
343   confirm_api_call_flow_->Start(
344       make_scoped_ptr<GCDApiFlow::Request>(new PrivetConfirmApiCallFlow(
345           token,
346           base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone,
347                      base::Unretained(this)))));
348 }
349 
OnPrivetRegisterError(PrivetRegisterOperation * operation,const std::string & action,PrivetRegisterOperation::FailureReason reason,int printer_http_code,const base::DictionaryValue * json)350 void LocalDiscoveryUIHandler::OnPrivetRegisterError(
351     PrivetRegisterOperation* operation,
352     const std::string& action,
353     PrivetRegisterOperation::FailureReason reason,
354     int printer_http_code,
355     const base::DictionaryValue* json) {
356   std::string error;
357 
358   if (reason == PrivetRegisterOperation::FAILURE_JSON_ERROR &&
359       json->GetString(kPrivetKeyError, &error)) {
360     if (error == kPrivetErrorTimeout) {
361         web_ui()->CallJavascriptFunction(
362             "local_discovery.onRegistrationTimeout");
363       return;
364     } else if (error == kPrivetErrorCancel) {
365       web_ui()->CallJavascriptFunction(
366             "local_discovery.onRegistrationCanceledPrinter");
367       return;
368     }
369   }
370 
371   SendRegisterError();
372 }
373 
OnPrivetRegisterDone(PrivetRegisterOperation * operation,const std::string & device_id)374 void LocalDiscoveryUIHandler::OnPrivetRegisterDone(
375     PrivetRegisterOperation* operation,
376     const std::string& device_id) {
377   std::string name = operation->GetHTTPClient()->GetName();
378   current_setup_operation_.reset();
379   current_register_operation_.reset();
380   current_http_client_.reset();
381   SendRegisterDone(name);
382 }
383 
GetWiFiCredentials(const CredentialsCallback & callback)384 void LocalDiscoveryUIHandler::GetWiFiCredentials(
385     const CredentialsCallback& callback) {
386   callback.Run("", "");
387 }
388 
SwitchToSetupWiFi(const ResultCallback & callback)389 void LocalDiscoveryUIHandler::SwitchToSetupWiFi(
390     const ResultCallback& callback) {
391   callback.Run(true);
392 }
393 
ConfirmSecurityCode(const std::string & confirmation_code,const ResultCallback & callback)394 void LocalDiscoveryUIHandler::ConfirmSecurityCode(
395     const std::string& confirmation_code,
396     const ResultCallback& callback) {
397   device_code_callback_ = callback;
398   web_ui()->CallJavascriptFunction(
399       "local_discovery.onRegistrationConfirmDeviceCode",
400       base::StringValue(confirmation_code));
401 }
402 
RestoreWifi(const ResultCallback & callback)403 void LocalDiscoveryUIHandler::RestoreWifi(const ResultCallback& callback) {
404   callback.Run(true);
405 }
406 
OnSetupDone()407 void LocalDiscoveryUIHandler::OnSetupDone() {
408   std::string service_name = current_setup_operation_->service_name();
409   current_setup_operation_.reset();
410   current_register_operation_.reset();
411   current_http_client_.reset();
412   SendRegisterDone(service_name);
413 }
414 
OnSetupError()415 void LocalDiscoveryUIHandler::OnSetupError() {
416   ResetCurrentRegistration();
417   SendRegisterError();
418 }
419 
OnConfirmDone(GCDApiFlow::Status status)420 void LocalDiscoveryUIHandler::OnConfirmDone(GCDApiFlow::Status status) {
421   if (status == GCDApiFlow::SUCCESS) {
422     confirm_api_call_flow_.reset();
423     current_register_operation_->CompleteRegistration();
424   } else {
425     SendRegisterError();
426   }
427 }
428 
DeviceChanged(bool added,const std::string & name,const DeviceDescription & description)429 void LocalDiscoveryUIHandler::DeviceChanged(
430     bool added,
431     const std::string& name,
432     const DeviceDescription& description) {
433   device_descriptions_[name] = description;
434 
435   base::DictionaryValue info;
436 
437   base::StringValue service_key(kKeyPrefixMDns + name);
438 
439   if (description.id.empty()) {
440     info.SetString(kDictionaryKeyServiceName, name);
441     info.SetString(kDictionaryKeyDisplayName, description.name);
442     info.SetString(kDictionaryKeyDescription, description.description);
443     info.SetString(kDictionaryKeyType, description.type);
444     info.SetBoolean(kDictionaryKeyIsWifi, false);
445 
446     web_ui()->CallJavascriptFunction(
447         "local_discovery.onUnregisteredDeviceUpdate", service_key, info);
448   } else {
449     scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
450 
451     web_ui()->CallJavascriptFunction(
452         "local_discovery.onUnregisteredDeviceUpdate", service_key, *null_value);
453   }
454 }
455 
DeviceRemoved(const std::string & name)456 void LocalDiscoveryUIHandler::DeviceRemoved(const std::string& name) {
457   device_descriptions_.erase(name);
458   scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
459   base::StringValue name_value(kKeyPrefixMDns + name);
460 
461   web_ui()->CallJavascriptFunction("local_discovery.onUnregisteredDeviceUpdate",
462                                    name_value, *null_value);
463 }
464 
DeviceCacheFlushed()465 void LocalDiscoveryUIHandler::DeviceCacheFlushed() {
466   web_ui()->CallJavascriptFunction("local_discovery.onDeviceCacheFlushed");
467   privet_lister_->DiscoverNewDevices(false);
468 }
469 
OnDeviceListReady(const std::vector<Device> & devices)470 void LocalDiscoveryUIHandler::OnDeviceListReady(
471     const std::vector<Device>& devices) {
472   cloud_devices_.insert(cloud_devices_.end(), devices.begin(), devices.end());
473   ++succeded_list_count_;
474   CheckListingDone();
475 }
476 
OnDeviceListUnavailable()477 void LocalDiscoveryUIHandler::OnDeviceListUnavailable() {
478   ++failed_list_count_;
479   CheckListingDone();
480 }
481 
GoogleSigninSucceeded(const std::string & account_id,const std::string & username,const std::string & password)482 void LocalDiscoveryUIHandler::GoogleSigninSucceeded(
483     const std::string& account_id,
484     const std::string& username,
485     const std::string& password) {
486   CheckUserLoggedIn();
487 }
488 
GoogleSignedOut(const std::string & account_id,const std::string & username)489 void LocalDiscoveryUIHandler::GoogleSignedOut(const std::string& account_id,
490                                               const std::string& username) {
491   CheckUserLoggedIn();
492 }
493 
SendRegisterError()494 void LocalDiscoveryUIHandler::SendRegisterError() {
495   web_ui()->CallJavascriptFunction("local_discovery.onRegistrationFailed");
496 }
497 
SendRegisterDone(const std::string & service_name)498 void LocalDiscoveryUIHandler::SendRegisterDone(
499     const std::string& service_name) {
500   // HACK(noamsml): Generate network traffic so the Windows firewall doesn't
501   // block the printer's announcement.
502   privet_lister_->DiscoverNewDevices(false);
503 
504   DeviceDescriptionMap::iterator found =
505       device_descriptions_.find(service_name);
506 
507   if (found == device_descriptions_.end()) {
508     // TODO(noamsml): Handle the case where a printer's record is not present at
509     // the end of registration.
510     SendRegisterError();
511     return;
512   }
513 
514   const DeviceDescription& device = found->second;
515   base::DictionaryValue device_value;
516 
517   device_value.SetString(kDictionaryKeyType, device.type);
518   device_value.SetString(kDictionaryKeyID, device.id);
519   device_value.SetString(kDictionaryKeyDisplayName, device.name);
520   device_value.SetString(kDictionaryKeyDescription, device.description);
521   device_value.SetString(kDictionaryKeyServiceName, service_name);
522 
523   web_ui()->CallJavascriptFunction("local_discovery.onRegistrationSuccess",
524                                    device_value);
525 }
526 
SetIsVisible(bool visible)527 void LocalDiscoveryUIHandler::SetIsVisible(bool visible) {
528   if (visible != is_visible_) {
529     g_num_visible += visible ? 1 : -1;
530     is_visible_ = visible;
531   }
532 }
533 
GetSyncAccount()534 std::string LocalDiscoveryUIHandler::GetSyncAccount() {
535   Profile* profile = Profile::FromWebUI(web_ui());
536   SigninManagerBase* signin_manager =
537       SigninManagerFactory::GetForProfileIfExists(profile);
538 
539   if (!signin_manager) {
540     return "";
541   }
542 
543   return signin_manager->GetAuthenticatedUsername();
544 }
545 
546 // TODO(noamsml): Create master object for registration flow.
ResetCurrentRegistration()547 void LocalDiscoveryUIHandler::ResetCurrentRegistration() {
548   if (current_register_operation_) {
549     current_register_operation_->Cancel();
550     current_register_operation_.reset();
551   }
552 
553   current_setup_operation_.reset();
554   confirm_api_call_flow_.reset();
555   privet_resolution_.reset();
556   current_http_client_.reset();
557 }
558 
PrivetClientToV3(const PrivetClientCallback & callback,scoped_ptr<PrivetHTTPClient> client)559 void LocalDiscoveryUIHandler::PrivetClientToV3(
560     const PrivetClientCallback& callback,
561     scoped_ptr<PrivetHTTPClient> client) {
562   callback.Run(client.Pass());
563 }
564 
CheckUserLoggedIn()565 void LocalDiscoveryUIHandler::CheckUserLoggedIn() {
566   base::FundamentalValue logged_in_value(!GetSyncAccount().empty());
567   base::FundamentalValue is_supervised_value(IsUserSupervisedOrOffTheRecord());
568   web_ui()->CallJavascriptFunction(
569       "local_discovery.setUserLoggedIn", logged_in_value, is_supervised_value);
570 }
571 
CheckListingDone()572 void LocalDiscoveryUIHandler::CheckListingDone() {
573   int started = 0;
574   if (cloud_print_printer_list_)
575     ++started;
576   if (cloud_device_list_)
577     ++started;
578 
579   if (started > failed_list_count_ + succeded_list_count_)
580     return;
581 
582   if (succeded_list_count_ <= 0) {
583     web_ui()->CallJavascriptFunction(
584         "local_discovery.onCloudDeviceListUnavailable");
585     return;
586   }
587 
588   base::ListValue devices_list;
589   std::set<std::string> local_ids;
590 
591   for (DeviceDescriptionMap::iterator i = device_descriptions_.begin();
592        i != device_descriptions_.end(); i++) {
593     local_ids.insert(i->second.id);
594   }
595 
596   ReadDevicesList(cloud_devices_, local_ids, &devices_list);
597 
598   web_ui()->CallJavascriptFunction(
599       "local_discovery.onCloudDeviceListAvailable", devices_list);
600   cloud_print_printer_list_.reset();
601   cloud_device_list_.reset();
602 }
603 
CreateApiFlow()604 scoped_ptr<GCDApiFlow> LocalDiscoveryUIHandler::CreateApiFlow() {
605   Profile* profile = Profile::FromWebUI(web_ui());
606   if (!profile)
607     return scoped_ptr<GCDApiFlow>();
608   ProfileOAuth2TokenService* token_service =
609       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
610   if (!token_service)
611     return scoped_ptr<GCDApiFlow>();
612   SigninManagerBase* signin_manager =
613       SigninManagerFactory::GetInstance()->GetForProfile(profile);
614   if (!signin_manager)
615     return scoped_ptr<GCDApiFlow>();
616   return GCDApiFlow::Create(profile->GetRequestContext(),
617                             token_service,
618                             signin_manager->GetAuthenticatedAccountId());
619 }
620 
CreatePrivetV3Client(const std::string & device,const PrivetClientCallback & callback)621 void LocalDiscoveryUIHandler::CreatePrivetV3Client(
622     const std::string& device,
623     const PrivetClientCallback& callback) {
624   DeviceDescriptionMap::iterator found = device_descriptions_.find(device);
625   if (found == device_descriptions_.end())
626     return callback.Run(scoped_ptr<PrivetHTTPClient>());
627   PrivetHTTPAsynchronousFactory::ResultCallback new_callback =
628       base::Bind(&LocalDiscoveryUIHandler::PrivetClientToV3,
629                  base::Unretained(this),
630                  callback);
631   privet_resolution_ =
632       privet_http_factory_->CreatePrivetHTTP(device,
633                                              found->second.address,
634                                              new_callback).Pass();
635   if (!privet_resolution_)
636     return callback.Run(scoped_ptr<PrivetHTTPClient>());
637   privet_resolution_->Start();
638 }
639 
IsUserSupervisedOrOffTheRecord()640 bool LocalDiscoveryUIHandler::IsUserSupervisedOrOffTheRecord() {
641   Profile* profile = Profile::FromWebUI(web_ui());
642 
643   return profile->IsSupervised() || profile->IsOffTheRecord();
644 }
645 
646 #if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
StartCloudPrintConnector()647 void LocalDiscoveryUIHandler::StartCloudPrintConnector() {
648   Profile* profile = Profile::FromWebUI(web_ui());
649 
650   base::Closure cloud_print_callback = base::Bind(
651       &LocalDiscoveryUIHandler::OnCloudPrintPrefsChanged,
652           base::Unretained(this));
653 
654   if (cloud_print_connector_email_.GetPrefName().empty()) {
655     cloud_print_connector_email_.Init(
656         prefs::kCloudPrintEmail, profile->GetPrefs(), cloud_print_callback);
657   }
658 
659   if (cloud_print_connector_enabled_.GetPrefName().empty()) {
660     cloud_print_connector_enabled_.Init(
661         prefs::kCloudPrintProxyEnabled, profile->GetPrefs(),
662         cloud_print_callback);
663   }
664 
665   if (cloud_print_connector_ui_enabled_) {
666     SetupCloudPrintConnectorSection();
667     RefreshCloudPrintStatusFromService();
668   } else {
669     RemoveCloudPrintConnectorSection();
670   }
671 }
672 
OnCloudPrintPrefsChanged()673 void LocalDiscoveryUIHandler::OnCloudPrintPrefsChanged() {
674   if (cloud_print_connector_ui_enabled_)
675     SetupCloudPrintConnectorSection();
676 }
677 
ShowCloudPrintSetupDialog(const base::ListValue * args)678 void LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog(
679     const base::ListValue* args) {
680   content::RecordAction(
681       base::UserMetricsAction("Options_EnableCloudPrintProxy"));
682   // Open the connector enable page in the current tab.
683   Profile* profile = Profile::FromWebUI(web_ui());
684   content::OpenURLParams params(
685       cloud_devices::GetCloudPrintEnableURL(
686           CloudPrintProxyServiceFactory::GetForProfile(profile)->proxy_id()),
687       content::Referrer(),
688       CURRENT_TAB,
689       ui::PAGE_TRANSITION_LINK,
690       false);
691   web_ui()->GetWebContents()->OpenURL(params);
692 }
693 
HandleDisableCloudPrintConnector(const base::ListValue * args)694 void LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector(
695     const base::ListValue* args) {
696   content::RecordAction(
697       base::UserMetricsAction("Options_DisableCloudPrintProxy"));
698   CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()))->
699       DisableForUser();
700 }
701 
SetupCloudPrintConnectorSection()702 void LocalDiscoveryUIHandler::SetupCloudPrintConnectorSection() {
703   Profile* profile = Profile::FromWebUI(web_ui());
704 
705   if (!CloudPrintProxyServiceFactory::GetForProfile(profile)) {
706     cloud_print_connector_ui_enabled_ = false;
707     RemoveCloudPrintConnectorSection();
708     return;
709   }
710 
711   bool cloud_print_connector_allowed =
712       !cloud_print_connector_enabled_.IsManaged() ||
713       cloud_print_connector_enabled_.GetValue();
714   base::FundamentalValue allowed(cloud_print_connector_allowed);
715 
716   std::string email;
717   if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
718       cloud_print_connector_allowed) {
719     email = profile->GetPrefs()->GetString(prefs::kCloudPrintEmail);
720   }
721   base::FundamentalValue disabled(email.empty());
722 
723   base::string16 label_str;
724   if (email.empty()) {
725     label_str = l10n_util::GetStringFUTF16(
726         IDS_LOCAL_DISCOVERY_CLOUD_PRINT_CONNECTOR_DISABLED_LABEL,
727         l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT));
728   } else {
729     label_str = l10n_util::GetStringFUTF16(
730         IDS_OPTIONS_CLOUD_PRINT_CONNECTOR_ENABLED_LABEL,
731         l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT),
732         base::UTF8ToUTF16(email));
733   }
734   base::StringValue label(label_str);
735 
736   web_ui()->CallJavascriptFunction(
737       "local_discovery.setupCloudPrintConnectorSection", disabled, label,
738       allowed);
739 }
740 
RemoveCloudPrintConnectorSection()741 void LocalDiscoveryUIHandler::RemoveCloudPrintConnectorSection() {
742   web_ui()->CallJavascriptFunction(
743       "local_discovery.removeCloudPrintConnectorSection");
744 }
745 
RefreshCloudPrintStatusFromService()746 void LocalDiscoveryUIHandler::RefreshCloudPrintStatusFromService() {
747   if (cloud_print_connector_ui_enabled_)
748     CloudPrintProxyServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()))->
749         RefreshStatusFromService();
750 }
751 
752 #endif // cloud print connector option stuff
753 
754 #if defined(ENABLE_WIFI_BOOTSTRAPPING)
755 
StartWifiBootstrapping()756 void LocalDiscoveryUIHandler::StartWifiBootstrapping() {
757   // Since LocalDiscoveryUIHandler isn't destroyed every time the page is
758   // refreshed, reset bootstrapping_device_lister_ so it's destoryed before
759   // wifi_manager_ is.
760   bootstrapping_device_lister_.reset();
761 
762   wifi_manager_ = wifi::WifiManager::Create();
763   bootstrapping_device_lister_.reset(new wifi::BootstrappingDeviceLister(
764       wifi_manager_.get(),
765       base::Bind(&LocalDiscoveryUIHandler::OnBootstrappingDeviceChanged,
766                  base::Unretained(this))));
767 
768   wifi_manager_->Start();
769   bootstrapping_device_lister_->Start();
770   wifi_manager_->RequestScan();
771 }
772 
OnBootstrappingDeviceChanged(bool available,const wifi::BootstrappingDeviceDescription & description)773 void LocalDiscoveryUIHandler::OnBootstrappingDeviceChanged(
774     bool available,
775     const wifi::BootstrappingDeviceDescription& description) {
776   base::DictionaryValue info;
777 
778   base::StringValue service_key(kKeyPrefixWifi + description.device_ssid);
779 
780   if (available) {
781     info.SetString(kDictionaryKeyServiceName, description.device_ssid);
782     info.SetString(kDictionaryKeyDisplayName, description.device_name);
783     info.SetString(kDictionaryKeyDescription, std::string());
784     info.SetString(kDictionaryKeyType, description.device_kind);
785     info.SetBoolean(kDictionaryKeyIsWifi, true);
786 
787     web_ui()->CallJavascriptFunction(
788         "local_discovery.onUnregisteredDeviceUpdate", service_key, info);
789   } else {
790     scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
791 
792     web_ui()->CallJavascriptFunction(
793         "local_discovery.onUnregisteredDeviceUpdate", service_key, *null_value);
794   }
795 }
796 
797 #endif  // ENABLE_WIFI_BOOTSTRAPPING
798 
799 }  // namespace local_discovery
800