Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / serial / serial_event_dispatcher.cc
1 // Copyright 2013 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/serial/serial_event_dispatcher.h"
6
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/extensions/api/serial/serial_connection.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/profiles/profile_manager.h"
11 #include "extensions/browser/event_router.h"
12
13 namespace extensions {
14
15 namespace api {
16
17 namespace {
18
19 bool ShouldPauseOnReceiveError(serial::ReceiveError error) {
20   return error == serial::RECEIVE_ERROR_DEVICE_LOST ||
21       error == serial::RECEIVE_ERROR_SYSTEM_ERROR ||
22       error == serial::RECEIVE_ERROR_DISCONNECTED;
23 }
24
25 }  // namespace
26
27 static base::LazyInstance<BrowserContextKeyedAPIFactory<SerialEventDispatcher> >
28     g_factory = LAZY_INSTANCE_INITIALIZER;
29
30 // static
31 BrowserContextKeyedAPIFactory<SerialEventDispatcher>*
32 SerialEventDispatcher::GetFactoryInstance() {
33   return g_factory.Pointer();
34 }
35
36 // static
37 SerialEventDispatcher* SerialEventDispatcher::Get(
38     content::BrowserContext* context) {
39   return BrowserContextKeyedAPIFactory<SerialEventDispatcher>::Get(context);
40 }
41
42 SerialEventDispatcher::SerialEventDispatcher(content::BrowserContext* context)
43     : thread_id_(SerialConnection::kThreadId),
44       profile_(Profile::FromBrowserContext(context)) {
45   ApiResourceManager<SerialConnection>* manager =
46       ApiResourceManager<SerialConnection>::Get(profile_);
47   DCHECK(manager) << "No serial connection manager.";
48   connections_ = manager->data_;
49 }
50
51 SerialEventDispatcher::~SerialEventDispatcher() {}
52
53 SerialEventDispatcher::ReceiveParams::ReceiveParams() {}
54
55 SerialEventDispatcher::ReceiveParams::~ReceiveParams() {}
56
57 void SerialEventDispatcher::PollConnection(const std::string& extension_id,
58                                            int connection_id) {
59   DCHECK_CURRENTLY_ON(thread_id_);
60
61   ReceiveParams params;
62   params.thread_id = thread_id_;
63   params.profile_id = profile_;
64   params.extension_id = extension_id;
65   params.connections = connections_;
66   params.connection_id = connection_id;
67
68   StartReceive(params);
69 }
70
71 // static
72 void SerialEventDispatcher::StartReceive(const ReceiveParams& params) {
73   DCHECK_CURRENTLY_ON(params.thread_id);
74
75   SerialConnection* connection =
76       params.connections->Get(params.extension_id, params.connection_id);
77   if (!connection)
78     return;
79   DCHECK(params.extension_id == connection->owner_extension_id());
80
81   if (connection->paused())
82     return;
83
84   connection->Receive(base::Bind(&ReceiveCallback, params));
85 }
86
87 // static
88 void SerialEventDispatcher::ReceiveCallback(const ReceiveParams& params,
89                                             const std::string& data,
90                                             serial::ReceiveError error) {
91   DCHECK_CURRENTLY_ON(params.thread_id);
92
93   // Note that an error (e.g. timeout) does not necessarily mean that no data
94   // was read, so we may fire an onReceive regardless of any error code.
95   if (data.length() > 0) {
96     serial::ReceiveInfo receive_info;
97     receive_info.connection_id = params.connection_id;
98     receive_info.data = data;
99     scoped_ptr<base::ListValue> args = serial::OnReceive::Create(receive_info);
100     scoped_ptr<extensions::Event> event(
101         new extensions::Event(serial::OnReceive::kEventName, args.Pass()));
102     PostEvent(params, event.Pass());
103   }
104
105   if (error != serial::RECEIVE_ERROR_NONE) {
106     serial::ReceiveErrorInfo error_info;
107     error_info.connection_id = params.connection_id;
108     error_info.error = error;
109     scoped_ptr<base::ListValue> args =
110         serial::OnReceiveError::Create(error_info);
111     scoped_ptr<extensions::Event> event(
112         new extensions::Event(serial::OnReceiveError::kEventName, args.Pass()));
113     PostEvent(params, event.Pass());
114     if (ShouldPauseOnReceiveError(error)) {
115       SerialConnection* connection =
116           params.connections->Get(params.extension_id, params.connection_id);
117       if (connection)
118         connection->set_paused(true);
119     }
120   }
121
122   // Queue up the next read operation.
123   BrowserThread::PostTask(params.thread_id,
124                           FROM_HERE,
125                           base::Bind(&StartReceive, params));
126 }
127
128 // static
129 void SerialEventDispatcher::PostEvent(const ReceiveParams& params,
130                                       scoped_ptr<extensions::Event> event) {
131   DCHECK_CURRENTLY_ON(params.thread_id);
132
133   BrowserThread::PostTask(
134       BrowserThread::UI, FROM_HERE,
135       base::Bind(&DispatchEvent,
136                  params.profile_id,
137                  params.extension_id,
138                  base::Passed(event.Pass())));
139 }
140
141 // static
142 void SerialEventDispatcher::DispatchEvent(void* profile_id,
143                                           const std::string& extension_id,
144                                           scoped_ptr<extensions::Event> event) {
145   DCHECK_CURRENTLY_ON(BrowserThread::UI);
146
147   Profile* profile = reinterpret_cast<Profile*>(profile_id);
148   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
149     return;
150
151   EventRouter* router = EventRouter::Get(profile);
152   if (router)
153     router->DispatchEventToExtension(extension_id, event.Pass());
154 }
155
156 }  // namespace api
157
158 }  // namespace extensions