dial_api.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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
17using base::TimeDelta;
18using content::BrowserThread;
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
37namespace dial = api::dial;
38
39DialAPI::DialAPI(Profile* profile)
40    : RefcountedBrowserContextKeyedService(BrowserThread::IO),
41      profile_(profile) {
42  ExtensionSystem::Get(profile)->event_router()->RegisterObserver(
43      this, dial::OnDeviceList::kEventName);
44}
45
46DialAPI::~DialAPI() {}
47
48DialRegistry* 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),
54        kDialMaxDevices));
55  }
56  return dial_registry_.get();
57}
58
59void 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));
64}
65
66void 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));
71}
72
73void DialAPI::NotifyListenerAddedOnIOThread() {
74  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
75  VLOG(1) << "DIAL device event listener added.";
76  dial_registry()->OnListenerAdded();
77}
78
79void DialAPI::NotifyListenerRemovedOnIOThread() {
80  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
81  VLOG(1) << "DIAL device event listener removed";
82  dial_registry()->OnListenerRemoved();
83}
84
85void 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));
89}
90
91void 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));
95}
96
97void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList& devices) {
98  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
99
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);
107  }
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());
113}
114
115void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code) {
116  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117
118  api::dial::DialError dial_error;
119  switch (code) {
120    case DialRegistry::DIAL_NO_LISTENERS:
121      dial_error.code = api::dial::DIAL_ERROR_CODE_NO_LISTENERS;
122      break;
123    case DialRegistry::DIAL_NO_INTERFACES:
124      dial_error.code = api::dial::DIAL_ERROR_CODE_NO_VALID_NETWORK_INTERFACES;
125      break;
126    case DialRegistry::DIAL_CELLULAR_NETWORK:
127      dial_error.code = api::dial::DIAL_ERROR_CODE_CELLULAR_NETWORK;
128      break;
129    case DialRegistry::DIAL_NETWORK_DISCONNECTED:
130      dial_error.code = api::dial::DIAL_ERROR_CODE_NETWORK_DISCONNECTED;
131      break;
132    case DialRegistry::DIAL_SOCKET_ERROR:
133      dial_error.code = api::dial::DIAL_ERROR_CODE_SOCKET_ERROR;
134      break;
135    default:
136      dial_error.code = api::dial::DIAL_ERROR_CODE_UNKNOWN;
137      break;
138  }
139
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());
144}
145
146void DialAPI::ShutdownOnUIThread() {}
147
148namespace api {
149
150DialDiscoverNowFunction::DialDiscoverNowFunction()
151    : dial_(NULL), result_(false) {
152}
153
154bool DialDiscoverNowFunction::Prepare() {
155  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156  DCHECK(browser_context());
157  dial_ = DialAPIFactory::GetForBrowserContext(browser_context()).get();
158  return true;
159}
160
161void DialDiscoverNowFunction::Work() {
162  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
163  result_ = dial_->dial_registry()->DiscoverNow();
164}
165
166bool DialDiscoverNowFunction::Respond() {
167  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168  if (!result_)
169    error_ = kDialServiceError;
170
171  SetResult(new base::FundamentalValue(result_));
172  return true;
173}
174
175}  // namespace api
176
177}  // namespace extensions
178