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