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