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/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"
17 using base::TimeDelta
;
18 using content::BrowserThread
;
22 // How often to poll for devices.
23 const int kDialRefreshIntervalSecs
= 120;
25 // We prune a device if it does not respond after this time.
26 const int kDialExpirationSecs
= 240;
28 // The maximum number of devices retained at once in the registry.
29 const size_t kDialMaxDevices
= 256;
33 namespace extensions
{
35 namespace dial
= api::dial
;
37 DialAPI::DialAPI(Profile
* profile
)
38 : RefcountedKeyedService(
39 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
)),
41 EventRouter::Get(profile
)
42 ->RegisterObserver(this, dial::OnDeviceList::kEventName
);
45 DialAPI::~DialAPI() {}
47 DialRegistry
* DialAPI::dial_registry() {
48 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
49 if (!dial_registry_
.get()) {
50 dial_registry_
.reset(new DialRegistry(this,
51 TimeDelta::FromSeconds(kDialRefreshIntervalSecs
),
52 TimeDelta::FromSeconds(kDialExpirationSecs
),
55 return dial_registry_
.get();
58 void DialAPI::OnListenerAdded(const EventListenerInfo
& details
) {
59 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
60 BrowserThread::PostTask(
61 BrowserThread::IO
, FROM_HERE
,
62 base::Bind(&DialAPI::NotifyListenerAddedOnIOThread
, this));
65 void DialAPI::OnListenerRemoved(const EventListenerInfo
& details
) {
66 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
67 BrowserThread::PostTask(
68 BrowserThread::IO
, FROM_HERE
,
69 base::Bind(&DialAPI::NotifyListenerRemovedOnIOThread
, this));
72 void DialAPI::NotifyListenerAddedOnIOThread() {
73 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
74 VLOG(2) << "DIAL device event listener added.";
75 dial_registry()->OnListenerAdded();
78 void DialAPI::NotifyListenerRemovedOnIOThread() {
79 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
80 VLOG(2) << "DIAL device event listener removed";
81 dial_registry()->OnListenerRemoved();
84 void DialAPI::OnDialDeviceEvent(const DialRegistry::DeviceList
& devices
) {
85 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
86 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
87 base::Bind(&DialAPI::SendEventOnUIThread
, this, devices
));
90 void DialAPI::OnDialError(const DialRegistry::DialErrorCode code
) {
91 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
92 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
93 base::Bind(&DialAPI::SendErrorOnUIThread
, this, code
));
96 void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList
& devices
) {
97 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
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
);
107 scoped_ptr
<base::ListValue
> results
= api::dial::OnDeviceList::Create(args
);
108 scoped_ptr
<Event
> event(new Event(events::DIAL_ON_DEVICE_LIST
,
109 dial::OnDeviceList::kEventName
,
111 EventRouter::Get(profile_
)->BroadcastEvent(event
.Pass());
114 void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code
) {
115 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
117 api::dial::DialError dial_error
;
119 case DialRegistry::DIAL_NO_LISTENERS
:
120 dial_error
.code
= api::dial::DIAL_ERROR_CODE_NO_LISTENERS
;
122 case DialRegistry::DIAL_NO_INTERFACES
:
123 dial_error
.code
= api::dial::DIAL_ERROR_CODE_NO_VALID_NETWORK_INTERFACES
;
125 case DialRegistry::DIAL_CELLULAR_NETWORK
:
126 dial_error
.code
= api::dial::DIAL_ERROR_CODE_CELLULAR_NETWORK
;
128 case DialRegistry::DIAL_NETWORK_DISCONNECTED
:
129 dial_error
.code
= api::dial::DIAL_ERROR_CODE_NETWORK_DISCONNECTED
;
131 case DialRegistry::DIAL_SOCKET_ERROR
:
132 dial_error
.code
= api::dial::DIAL_ERROR_CODE_SOCKET_ERROR
;
135 dial_error
.code
= api::dial::DIAL_ERROR_CODE_UNKNOWN
;
139 scoped_ptr
<base::ListValue
> results
= api::dial::OnError::Create(dial_error
);
140 scoped_ptr
<Event
> event(new Event(events::DIAL_ON_ERROR
,
141 dial::OnError::kEventName
, results
.Pass()));
142 EventRouter::Get(profile_
)->BroadcastEvent(event
.Pass());
145 void DialAPI::ShutdownOnUIThread() {}
149 DialDiscoverNowFunction::DialDiscoverNowFunction()
150 : dial_(NULL
), result_(false) {
153 bool DialDiscoverNowFunction::Prepare() {
154 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
155 DCHECK(browser_context());
156 dial_
= DialAPIFactory::GetForBrowserContext(browser_context()).get();
160 void DialDiscoverNowFunction::Work() {
161 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
162 result_
= dial_
->dial_registry()->DiscoverNow();
165 bool DialDiscoverNowFunction::Respond() {
166 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
167 SetResult(new base::FundamentalValue(result_
));
173 } // namespace extensions