Home | History | Annotate | Download | only in dial
      1 // Copyright (c) 2012 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/extensions/api/dial/dial_api.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/time/time.h"
     10 #include "chrome/browser/extensions/api/dial/dial_api_factory.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/common/extensions/api/dial.h"
     13 #include "content/public/browser/browser_thread.h"
     14 #include "extensions/browser/event_router.h"
     15 #include "extensions/browser/extension_system.h"
     16 
     17 using base::TimeDelta;
     18 using content::BrowserThread;
     19 
     20 namespace {
     21 
     22 const char kDialServiceError[] = "Dial service error.";
     23 
     24 // How often to poll for devices.
     25 const int kDialRefreshIntervalSecs = 120;
     26 
     27 // We prune a device if it does not respond after this time.
     28 const int kDialExpirationSecs = 240;
     29 
     30 // The maximum number of devices retained at once in the registry.
     31 const size_t kDialMaxDevices = 256;
     32 
     33 }  // namespace
     34 
     35 namespace extensions {
     36 
     37 namespace dial = api::dial;
     38 
     39 DialAPI::DialAPI(Profile* profile)
     40     : RefcountedBrowserContextKeyedService(BrowserThread::IO),
     41       profile_(profile) {
     42   EventRouter::Get(profile)
     43       ->RegisterObserver(this, dial::OnDeviceList::kEventName);
     44 }
     45 
     46 DialAPI::~DialAPI() {}
     47 
     48 DialRegistry* DialAPI::dial_registry() {
     49   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     50   if (!dial_registry_.get()) {
     51     dial_registry_.reset(new DialRegistry(this,
     52         TimeDelta::FromSeconds(kDialRefreshIntervalSecs),
     53         TimeDelta::FromSeconds(kDialExpirationSecs),
     54         kDialMaxDevices));
     55   }
     56   return dial_registry_.get();
     57 }
     58 
     59 void DialAPI::OnListenerAdded(const EventListenerInfo& details) {
     60   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     61   BrowserThread::PostTask(
     62       BrowserThread::IO, FROM_HERE,
     63       base::Bind(&DialAPI::NotifyListenerAddedOnIOThread, this));
     64 }
     65 
     66 void DialAPI::OnListenerRemoved(const EventListenerInfo& details) {
     67   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     68   BrowserThread::PostTask(
     69       BrowserThread::IO, FROM_HERE,
     70       base::Bind(&DialAPI::NotifyListenerRemovedOnIOThread, this));
     71 }
     72 
     73 void DialAPI::NotifyListenerAddedOnIOThread() {
     74   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     75   VLOG(1) << "DIAL device event listener added.";
     76   dial_registry()->OnListenerAdded();
     77 }
     78 
     79 void DialAPI::NotifyListenerRemovedOnIOThread() {
     80   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     81   VLOG(1) << "DIAL device event listener removed";
     82   dial_registry()->OnListenerRemoved();
     83 }
     84 
     85 void DialAPI::OnDialDeviceEvent(const DialRegistry::DeviceList& devices) {
     86   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     87   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
     88       base::Bind(&DialAPI::SendEventOnUIThread, this, devices));
     89 }
     90 
     91 void DialAPI::OnDialError(const DialRegistry::DialErrorCode code) {
     92   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     93   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
     94       base::Bind(&DialAPI::SendErrorOnUIThread, this, code));
     95 }
     96 
     97 void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList& devices) {
     98   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     99 
    100   std::vector<linked_ptr<api::dial::DialDevice> > args;
    101   for (DialRegistry::DeviceList::const_iterator it = devices.begin();
    102        it != devices.end(); ++it) {
    103     linked_ptr<api::dial::DialDevice> api_device =
    104         make_linked_ptr(new api::dial::DialDevice);
    105     it->FillDialDevice(api_device.get());
    106     args.push_back(api_device);
    107   }
    108   scoped_ptr<base::ListValue> results = api::dial::OnDeviceList::Create(args);
    109   scoped_ptr<Event> event(
    110       new Event(dial::OnDeviceList::kEventName, results.Pass()));
    111   EventRouter::Get(profile_)->BroadcastEvent(event.Pass());
    112 }
    113 
    114 void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code) {
    115   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    116 
    117   api::dial::DialError dial_error;
    118   switch (code) {
    119     case DialRegistry::DIAL_NO_LISTENERS:
    120       dial_error.code = api::dial::DIAL_ERROR_CODE_NO_LISTENERS;
    121       break;
    122     case DialRegistry::DIAL_NO_INTERFACES:
    123       dial_error.code = api::dial::DIAL_ERROR_CODE_NO_VALID_NETWORK_INTERFACES;
    124       break;
    125     case DialRegistry::DIAL_CELLULAR_NETWORK:
    126       dial_error.code = api::dial::DIAL_ERROR_CODE_CELLULAR_NETWORK;
    127       break;
    128     case DialRegistry::DIAL_NETWORK_DISCONNECTED:
    129       dial_error.code = api::dial::DIAL_ERROR_CODE_NETWORK_DISCONNECTED;
    130       break;
    131     case DialRegistry::DIAL_SOCKET_ERROR:
    132       dial_error.code = api::dial::DIAL_ERROR_CODE_SOCKET_ERROR;
    133       break;
    134     default:
    135       dial_error.code = api::dial::DIAL_ERROR_CODE_UNKNOWN;
    136       break;
    137   }
    138 
    139   scoped_ptr<base::ListValue> results = api::dial::OnError::Create(dial_error);
    140   scoped_ptr<Event> event(new Event(dial::OnError::kEventName, results.Pass()));
    141   EventRouter::Get(profile_)->BroadcastEvent(event.Pass());
    142 }
    143 
    144 void DialAPI::ShutdownOnUIThread() {}
    145 
    146 namespace api {
    147 
    148 DialDiscoverNowFunction::DialDiscoverNowFunction()
    149     : dial_(NULL), result_(false) {
    150 }
    151 
    152 bool DialDiscoverNowFunction::Prepare() {
    153   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    154   DCHECK(browser_context());
    155   dial_ = DialAPIFactory::GetForBrowserContext(browser_context()).get();
    156   return true;
    157 }
    158 
    159 void DialDiscoverNowFunction::Work() {
    160   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    161   result_ = dial_->dial_registry()->DiscoverNow();
    162 }
    163 
    164 bool DialDiscoverNowFunction::Respond() {
    165   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    166   if (!result_)
    167     error_ = kDialServiceError;
    168 
    169   SetResult(new base::FundamentalValue(result_));
    170   return true;
    171 }
    172 
    173 }  // namespace api
    174 
    175 }  // namespace extensions
    176