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