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