Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / serial / serial_event_dispatcher.cc
blob7afa26816be7b2bbf9226f9f43a2577d41ce307c
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.
5 #include "extensions/browser/api/serial/serial_event_dispatcher.h"
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"
12 namespace extensions {
14 namespace api {
16 namespace {
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 error == serial::RECEIVE_ERROR_BREAK ||
23 error == serial::RECEIVE_ERROR_FRAME_ERROR ||
24 error == serial::RECEIVE_ERROR_OVERRUN ||
25 error == serial::RECEIVE_ERROR_BUFFER_OVERFLOW ||
26 error == serial::RECEIVE_ERROR_PARITY_ERROR;
29 } // namespace
31 static base::LazyInstance<BrowserContextKeyedAPIFactory<SerialEventDispatcher> >
32 g_factory = LAZY_INSTANCE_INITIALIZER;
34 // static
35 BrowserContextKeyedAPIFactory<SerialEventDispatcher>*
36 SerialEventDispatcher::GetFactoryInstance() {
37 return g_factory.Pointer();
40 // static
41 SerialEventDispatcher* SerialEventDispatcher::Get(
42 content::BrowserContext* context) {
43 return BrowserContextKeyedAPIFactory<SerialEventDispatcher>::Get(context);
46 SerialEventDispatcher::SerialEventDispatcher(content::BrowserContext* context)
47 : thread_id_(SerialConnection::kThreadId), context_(context) {
48 ApiResourceManager<SerialConnection>* manager =
49 ApiResourceManager<SerialConnection>::Get(context_);
50 DCHECK(manager) << "No serial connection manager.";
51 connections_ = manager->data_;
54 SerialEventDispatcher::~SerialEventDispatcher() {
57 SerialEventDispatcher::ReceiveParams::ReceiveParams() {
60 SerialEventDispatcher::ReceiveParams::~ReceiveParams() {
63 void SerialEventDispatcher::PollConnection(const std::string& extension_id,
64 int connection_id) {
65 DCHECK_CURRENTLY_ON(thread_id_);
67 ReceiveParams params;
68 params.thread_id = thread_id_;
69 params.browser_context_id = context_;
70 params.extension_id = extension_id;
71 params.connections = connections_;
72 params.connection_id = connection_id;
74 StartReceive(params);
77 // static
78 void SerialEventDispatcher::StartReceive(const ReceiveParams& params) {
79 DCHECK_CURRENTLY_ON(params.thread_id);
81 SerialConnection* connection =
82 params.connections->Get(params.extension_id, params.connection_id);
83 if (!connection)
84 return;
85 DCHECK(params.extension_id == connection->owner_extension_id());
87 if (connection->paused())
88 return;
90 connection->Receive(base::Bind(&ReceiveCallback, params));
93 // static
94 void SerialEventDispatcher::ReceiveCallback(const ReceiveParams& params,
95 const std::vector<char>& data,
96 serial::ReceiveError error) {
97 DCHECK_CURRENTLY_ON(params.thread_id);
99 // Note that an error (e.g. timeout) does not necessarily mean that no data
100 // was read, so we may fire an onReceive regardless of any error code.
101 if (data.size() > 0) {
102 serial::ReceiveInfo receive_info;
103 receive_info.connection_id = params.connection_id;
104 receive_info.data = data;
105 scoped_ptr<base::ListValue> args = serial::OnReceive::Create(receive_info);
106 scoped_ptr<extensions::Event> event(
107 new extensions::Event(extensions::events::SERIAL_ON_RECEIVE,
108 serial::OnReceive::kEventName, args.Pass()));
109 PostEvent(params, event.Pass());
112 if (error != serial::RECEIVE_ERROR_NONE) {
113 serial::ReceiveErrorInfo error_info;
114 error_info.connection_id = params.connection_id;
115 error_info.error = error;
116 scoped_ptr<base::ListValue> args =
117 serial::OnReceiveError::Create(error_info);
118 scoped_ptr<extensions::Event> event(
119 new extensions::Event(extensions::events::SERIAL_ON_RECEIVE_ERROR,
120 serial::OnReceiveError::kEventName, args.Pass()));
121 PostEvent(params, event.Pass());
122 if (ShouldPauseOnReceiveError(error)) {
123 SerialConnection* connection =
124 params.connections->Get(params.extension_id, params.connection_id);
125 if (connection)
126 connection->set_paused(true);
130 // Queue up the next read operation.
131 BrowserThread::PostTask(
132 params.thread_id, FROM_HERE, base::Bind(&StartReceive, params));
135 // static
136 void SerialEventDispatcher::PostEvent(const ReceiveParams& params,
137 scoped_ptr<extensions::Event> event) {
138 DCHECK_CURRENTLY_ON(params.thread_id);
140 BrowserThread::PostTask(BrowserThread::UI,
141 FROM_HERE,
142 base::Bind(&DispatchEvent,
143 params.browser_context_id,
144 params.extension_id,
145 base::Passed(event.Pass())));
148 // static
149 void SerialEventDispatcher::DispatchEvent(void* browser_context_id,
150 const std::string& extension_id,
151 scoped_ptr<extensions::Event> event) {
152 DCHECK_CURRENTLY_ON(BrowserThread::UI);
154 content::BrowserContext* context =
155 reinterpret_cast<content::BrowserContext*>(browser_context_id);
156 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context))
157 return;
159 EventRouter* router = EventRouter::Get(context);
160 if (router)
161 router->DispatchEventToExtension(extension_id, event.Pass());
164 } // namespace api
166 } // namespace extensions