dial_api.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.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 18using base::TimeDelta; 19 20namespace { 21 22const char kDialServiceError[] = "Dial service error."; 23 24// How often to poll for devices. 25const int kDialRefreshIntervalSecs = 120; 26 27// We prune a device if it does not respond after this time. 28const int kDialExpirationSecs = 240; 29 30// The maximum number of devices retained at once in the registry. 31const size_t kDialMaxDevices = 256; 32 33} // namespace 34 35namespace extensions { 36 37DialAPI::DialAPI(Profile* profile) 38 : RefcountedProfileKeyedService(content::BrowserThread::IO), 39 profile_(profile) { 40 ExtensionSystem::Get(profile)->event_router()->RegisterObserver( 41 this, extensions::event_names::kOnDialDeviceList); 42} 43 44DialAPI::~DialAPI() {} 45 46DialRegistry* DialAPI::dial_registry() { 47 DCHECK(BrowserThread::CurrentlyOn(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 57void DialAPI::OnListenerAdded(const EventListenerInfo& details) { 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 59 BrowserThread::PostTask( 60 BrowserThread::IO, FROM_HERE, 61 base::Bind(&DialAPI::NotifyListenerAddedOnIOThread, this)); 62} 63 64void DialAPI::OnListenerRemoved(const EventListenerInfo& details) { 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 66 BrowserThread::PostTask( 67 BrowserThread::IO, FROM_HERE, 68 base::Bind(&DialAPI::NotifyListenerRemovedOnIOThread, this)); 69} 70 71void DialAPI::NotifyListenerAddedOnIOThread() { 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 73 DVLOG(1) << "DIAL device event listener added."; 74 dial_registry()->OnListenerAdded(); 75} 76 77void DialAPI::NotifyListenerRemovedOnIOThread() { 78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 79 DVLOG(1) << "DIAL device event listener removed"; 80 dial_registry()->OnListenerRemoved(); 81} 82 83void DialAPI::OnDialDeviceEvent(const DialRegistry::DeviceList& devices) { 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 85 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 86 base::Bind(&DialAPI::SendEventOnUIThread, this, devices)); 87} 88 89void DialAPI::OnDialError(const DialRegistry::DialErrorCode code) { 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 91 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 92 base::Bind(&DialAPI::SendErrorOnUIThread, this, code)); 93} 94 95void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList& devices) { 96 DCHECK(BrowserThread::CurrentlyOn(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(event_names::kOnDialDeviceList, results.Pass())); 109 extensions::ExtensionSystem::Get(profile_)->event_router()-> 110 BroadcastEvent(event.Pass()); 111} 112 113void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code) { 114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 115 116 api::dial::DialError dial_error; 117 switch (code) { 118 case DialRegistry::DIAL_NO_LISTENERS: 119 dial_error.code = api::dial::DIAL_ERROR_CODE_NO_LISTENERS; 120 break; 121 case DialRegistry::DIAL_NO_INTERFACES: 122 dial_error.code = api::dial::DIAL_ERROR_CODE_NO_VALID_NETWORK_INTERFACES; 123 break; 124 case DialRegistry::DIAL_CELLULAR_NETWORK: 125 dial_error.code = api::dial::DIAL_ERROR_CODE_CELLULAR_NETWORK; 126 break; 127 case DialRegistry::DIAL_NETWORK_DISCONNECTED: 128 dial_error.code = api::dial::DIAL_ERROR_CODE_NETWORK_DISCONNECTED; 129 break; 130 case DialRegistry::DIAL_SOCKET_ERROR: 131 dial_error.code = api::dial::DIAL_ERROR_CODE_SOCKET_ERROR; 132 break; 133 default: 134 dial_error.code = api::dial::DIAL_ERROR_CODE_UNKNOWN; 135 break; 136 } 137 138 scoped_ptr<base::ListValue> results = api::dial::OnError::Create(dial_error); 139 scoped_ptr<Event> event(new Event(event_names::kOnDialError, results.Pass())); 140 extensions::ExtensionSystem::Get(profile_)->event_router()-> 141 BroadcastEvent(event.Pass()); 142} 143 144void DialAPI::ShutdownOnUIThread() {} 145 146namespace api { 147 148DialDiscoverNowFunction::DialDiscoverNowFunction() 149 : dial_(NULL), result_(false) { 150} 151 152bool DialDiscoverNowFunction::Prepare() { 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 154 DCHECK(profile()); 155 dial_ = DialAPIFactory::GetInstance()->GetForProfile(profile()); 156 return true; 157} 158 159void DialDiscoverNowFunction::Work() { 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 161 result_ = dial_->dial_registry()->DiscoverNow(); 162} 163 164bool DialDiscoverNowFunction::Respond() { 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 166 if (!result_) 167 error_ = kDialServiceError; 168 169 SetResult(base::Value::CreateBooleanValue(result_)); 170 return true; 171} 172 173} // namespace api 174 175} // namespace extensions 176