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.
5 #include "chrome/browser/extensions/api/dial/dial_api.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/extensions/api/dial/dial_api_factory.h"
11 #include "chrome/browser/extensions/extension_system.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/common/extensions/api/dial.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "extensions/browser/event_router.h"
17 using base::TimeDelta;
18 using content::BrowserThread;
22 const char kDialServiceError[] = "Dial service error.";
24 // How often to poll for devices.
25 const int kDialRefreshIntervalSecs = 120;
27 // We prune a device if it does not respond after this time.
28 const int kDialExpirationSecs = 240;
30 // The maximum number of devices retained at once in the registry.
31 const size_t kDialMaxDevices = 256;
35 namespace extensions {
37 namespace dial = api::dial;
39 DialAPI::DialAPI(Profile* profile)
40 : RefcountedBrowserContextKeyedService(BrowserThread::IO),
42 ExtensionSystem::Get(profile)->event_router()->RegisterObserver(
43 this, dial::OnDeviceList::kEventName);
46 DialAPI::~DialAPI() {}
48 DialRegistry* DialAPI::dial_registry() {
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
50 if (!dial_registry_.get()) {
51 dial_registry_.reset(new DialRegistry(this,
52 TimeDelta::FromSeconds(kDialRefreshIntervalSecs),
53 TimeDelta::FromSeconds(kDialExpirationSecs),
56 return dial_registry_.get();
59 void DialAPI::OnListenerAdded(const EventListenerInfo& details) {
60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
61 BrowserThread::PostTask(
62 BrowserThread::IO, FROM_HERE,
63 base::Bind(&DialAPI::NotifyListenerAddedOnIOThread, this));
66 void DialAPI::OnListenerRemoved(const EventListenerInfo& details) {
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
68 BrowserThread::PostTask(
69 BrowserThread::IO, FROM_HERE,
70 base::Bind(&DialAPI::NotifyListenerRemovedOnIOThread, this));
73 void DialAPI::NotifyListenerAddedOnIOThread() {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
75 VLOG(1) << "DIAL device event listener added.";
76 dial_registry()->OnListenerAdded();
79 void DialAPI::NotifyListenerRemovedOnIOThread() {
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
81 VLOG(1) << "DIAL device event listener removed";
82 dial_registry()->OnListenerRemoved();
85 void DialAPI::OnDialDeviceEvent(const DialRegistry::DeviceList& devices) {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
87 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
88 base::Bind(&DialAPI::SendEventOnUIThread, this, devices));
91 void DialAPI::OnDialError(const DialRegistry::DialErrorCode code) {
92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
93 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
94 base::Bind(&DialAPI::SendErrorOnUIThread, this, code));
97 void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList& devices) {
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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);
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 extensions::ExtensionSystem::Get(profile_)->event_router()->
112 BroadcastEvent(event.Pass());
115 void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
118 api::dial::DialError dial_error;
120 case DialRegistry::DIAL_NO_LISTENERS:
121 dial_error.code = api::dial::DIAL_ERROR_CODE_NO_LISTENERS;
123 case DialRegistry::DIAL_NO_INTERFACES:
124 dial_error.code = api::dial::DIAL_ERROR_CODE_NO_VALID_NETWORK_INTERFACES;
126 case DialRegistry::DIAL_CELLULAR_NETWORK:
127 dial_error.code = api::dial::DIAL_ERROR_CODE_CELLULAR_NETWORK;
129 case DialRegistry::DIAL_NETWORK_DISCONNECTED:
130 dial_error.code = api::dial::DIAL_ERROR_CODE_NETWORK_DISCONNECTED;
132 case DialRegistry::DIAL_SOCKET_ERROR:
133 dial_error.code = api::dial::DIAL_ERROR_CODE_SOCKET_ERROR;
136 dial_error.code = api::dial::DIAL_ERROR_CODE_UNKNOWN;
140 scoped_ptr<base::ListValue> results = api::dial::OnError::Create(dial_error);
141 scoped_ptr<Event> event(new Event(dial::OnError::kEventName, results.Pass()));
142 extensions::ExtensionSystem::Get(profile_)->event_router()->
143 BroadcastEvent(event.Pass());
146 void DialAPI::ShutdownOnUIThread() {}
150 DialDiscoverNowFunction::DialDiscoverNowFunction()
151 : dial_(NULL), result_(false) {
154 bool DialDiscoverNowFunction::Prepare() {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156 DCHECK(GetProfile());
157 dial_ = DialAPIFactory::GetForProfile(GetProfile()).get();
161 void DialDiscoverNowFunction::Work() {
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
163 result_ = dial_->dial_registry()->DiscoverNow();
166 bool DialDiscoverNowFunction::Respond() {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
169 error_ = kDialServiceError;
171 SetResult(new base::FundamentalValue(result_));
177 } // namespace extensions