Upstream version 5.34.104.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 #include "extensions/browser/extension_system.h"
13
14 namespace extensions {
15
16 namespace api {
17
18 namespace {
19
20 bool ShouldPauseOnReceiveError(serial::ReceiveError error) {
21   return error == serial::RECEIVE_ERROR_DEVICE_LOST ||
22       error == serial::RECEIVE_ERROR_SYSTEM_ERROR ||
23       error == serial::RECEIVE_ERROR_DISCONNECTED;
24 }
25
26 }  // namespace
27
28 static base::LazyInstance<ProfileKeyedAPIFactory<SerialEventDispatcher> >
29     g_factory = LAZY_INSTANCE_INITIALIZER;
30
31 // static
32 ProfileKeyedAPIFactory<SerialEventDispatcher>*
33     SerialEventDispatcher::GetFactoryInstance() {
34   return g_factory.Pointer();
35 }
36
37 // static
38 SerialEventDispatcher* SerialEventDispatcher::Get(Profile* profile) {
39   return ProfileKeyedAPIFactory<SerialEventDispatcher>::GetForProfile(profile);
40 }
41
42 SerialEventDispatcher::SerialEventDispatcher(Profile* profile)
43     : thread_id_(SerialConnection::kThreadId),
44       profile_(profile) {
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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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 = ExtensionSystem::Get(profile)->event_router();
152   if (router)
153     router->DispatchEventToExtension(extension_id, event.Pass());
154 }
155
156 }  // namespace api
157
158 }  // namespace extensions