Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(486)

Side by Side Diff: chrome/browser/extensions/api/bluetooth/bluetooth_api.h

Issue 180163009: chrome.bluetooth API improvements. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix threading ownership related to ApiResourceManager<BluetoothApiSocket> and BluetoothSocketEventD… Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_H_ 5 #ifndef CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_H_ 6 #define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_H_
7 7
8 #include <string> 8 #include <string>
9 9
10 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
12 #include "chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h " 13 #include "chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h "
14 #include "chrome/common/extensions/api/bluetooth.h"
13 #include "device/bluetooth/bluetooth_device.h" 15 #include "device/bluetooth/bluetooth_device.h"
14 #include "device/bluetooth/bluetooth_profile.h" 16 #include "device/bluetooth/bluetooth_profile.h"
17 #include "device/bluetooth/bluetooth_socket.h"
18 #include "extensions/browser/api/api_resource_manager.h"
15 #include "extensions/browser/api/async_api_function.h" 19 #include "extensions/browser/api/async_api_function.h"
16 #include "extensions/browser/browser_context_keyed_api_factory.h" 20 #include "extensions/browser/browser_context_keyed_api_factory.h"
17 #include "extensions/browser/event_router.h" 21 #include "extensions/browser/event_router.h"
18 #include "extensions/browser/extension_function.h" 22 #include "extensions/browser/extension_function.h"
19 23
20 namespace content { 24 namespace content {
21 class BrowserContext; 25 class BrowserContext;
22 } 26 }
23 27
24 namespace device { 28 namespace device {
29 class BluetoothAdapter;
30 struct BluetoothOutOfBandPairingData;
31 }
25 32
26 class BluetoothAdapter; 33 namespace net {
27 class BluetoothDevice; 34 class IOBuffer;
28 class BluetoothSocket; 35 }
29 struct BluetoothOutOfBandPairingData;
30
31 } // namespace device
32 36
33 namespace extensions { 37 namespace extensions {
34 38
35 class ExtensionBluetoothEventRouter; 39 class ExtensionBluetoothEventRouter;
36 40
37 // The profile-keyed service that manages the bluetooth extension API. 41 // The profile-keyed service that manages the bluetooth extension API.
42 // All methods of this class must be called on the UI thread.
43 // TODO(rpaquay): Rename this and move to separate file.
38 class BluetoothAPI : public BrowserContextKeyedAPI, 44 class BluetoothAPI : public BrowserContextKeyedAPI,
39 public EventRouter::Observer { 45 public EventRouter::Observer {
40 public: 46 public:
41 // Convenience method to get the BluetoothAPI for a profile. 47 typedef ApiResourceManager<BluetoothApiSocket>::ApiResourceData SocketData;
48
49 struct ConnectionParams {
50 ConnectionParams();
51 ~ConnectionParams();
52
53 content::BrowserThread::ID thread_id;
54 void* browser_context_id;
55 std::string extension_id;
56 std::string device_address;
57 std::string profile_uuid;
58 scoped_refptr<device::BluetoothSocket> socket;
59 scoped_refptr<SocketData> socket_data;
60 };
61
62 // Convenience method to get the BluetoothAPI for a browser context.
42 static BluetoothAPI* Get(content::BrowserContext* context); 63 static BluetoothAPI* Get(content::BrowserContext* context);
43 64
44 static BrowserContextKeyedAPIFactory<BluetoothAPI>* GetFactoryInstance(); 65 static BrowserContextKeyedAPIFactory<BluetoothAPI>* GetFactoryInstance();
45 66
46 explicit BluetoothAPI(content::BrowserContext* context); 67 explicit BluetoothAPI(content::BrowserContext* context);
47 virtual ~BluetoothAPI(); 68 virtual ~BluetoothAPI();
48 69
49 ExtensionBluetoothEventRouter* bluetooth_event_router(); 70 ExtensionBluetoothEventRouter* event_router();
71 scoped_refptr<SocketData> socket_data();
72 scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher();
50 73
51 // BrowserContextKeyedService implementation. 74 // BrowserContextKeyedService implementation.
52 virtual void Shutdown() OVERRIDE; 75 virtual void Shutdown() OVERRIDE;
53 76
54 // EventRouter::Observer implementation. 77 // EventRouter::Observer implementation.
55 virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE; 78 virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE;
56 virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE; 79 virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE;
57 80
81 // Dispatch an event that takes a connection socket as a parameter to the
82 // extension that registered the profile that the socket has connected to.
83 void DispatchConnectionEvent(const std::string& extension_id,
84 const std::string& profile_uuid,
85 const device::BluetoothDevice* device,
86 scoped_refptr<device::BluetoothSocket> socket);
87
58 private: 88 private:
59 friend class BrowserContextKeyedAPIFactory<BluetoothAPI>; 89 static void RegisterSocket(const ConnectionParams& params);
90 static void PostEvent(const ConnectionParams& params,
91 scoped_ptr<extensions::Event> event);
92 static void DispatchEvent(void* browser_context_id,
93 const std::string& extension_id,
94 scoped_ptr<extensions::Event> event);
60 95
61 // BrowserContextKeyedAPI implementation. 96 // BrowserContextKeyedAPI implementation.
97 friend class BrowserContextKeyedAPIFactory<BluetoothAPI>;
62 static const char* service_name() { return "BluetoothAPI"; } 98 static const char* service_name() { return "BluetoothAPI"; }
63 static const bool kServiceRedirectedInIncognito = true; 99 static const bool kServiceRedirectedInIncognito = true;
64 static const bool kServiceIsNULLWhileTesting = true; 100 static const bool kServiceIsNULLWhileTesting = true;
65 101
66 content::BrowserContext* browser_context_; 102 content::BrowserContext* browser_context_;
67 103
68 // Created lazily on first access. 104 // Created lazily on first access.
69 scoped_ptr<ExtensionBluetoothEventRouter> bluetooth_event_router_; 105 scoped_ptr<ExtensionBluetoothEventRouter> event_router_;
106 scoped_refptr<SocketData> socket_data_;
107 scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher_;
70 }; 108 };
71 109
72 namespace api { 110 namespace api {
73 111
112 class BluetoothSocketEventDispatcher;
113
114 class BluetoothSocketApiFunction : public AsyncApiFunction {
115 public:
116 BluetoothSocketApiFunction();
117
118 protected:
119 virtual ~BluetoothSocketApiFunction();
120
121 // AsyncApiFunction:
122 virtual bool PrePrepare() OVERRIDE;
123 virtual bool Respond() OVERRIDE;
124
125 scoped_refptr<BluetoothAPI::SocketData> socket_data_;
126 scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher_;
127 };
128
129 class BluetoothGetAdapterStateFunction : public BluetoothExtensionFunction {
130 public:
131 DECLARE_EXTENSION_FUNCTION("bluetooth.getAdapterState",
132 BLUETOOTH_GETADAPTERSTATE)
133
134 protected:
135 virtual ~BluetoothGetAdapterStateFunction();
136
137 // BluetoothExtensionFunction:
138 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
139 };
140
141 class BluetoothGetDevicesFunction : public BluetoothExtensionFunction {
142 public:
143 DECLARE_EXTENSION_FUNCTION("bluetooth.getDevices", BLUETOOTH_GETDEVICES)
144
145 protected:
146 virtual ~BluetoothGetDevicesFunction();
147
148 // BluetoothExtensionFunction:
149 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
150 };
151
74 class BluetoothAddProfileFunction : public UIThreadExtensionFunction { 152 class BluetoothAddProfileFunction : public UIThreadExtensionFunction {
75 public: 153 public:
76 DECLARE_EXTENSION_FUNCTION("bluetooth.addProfile", BLUETOOTH_ADDPROFILE) 154 DECLARE_EXTENSION_FUNCTION("bluetooth.addProfile", BLUETOOTH_ADDPROFILE)
77 155
78 BluetoothAddProfileFunction(); 156 BluetoothAddProfileFunction();
79 157
80 protected: 158 protected:
81 virtual ~BluetoothAddProfileFunction() {} 159 virtual ~BluetoothAddProfileFunction();
82 virtual bool RunImpl() OVERRIDE; 160 virtual bool RunImpl() OVERRIDE;
83 161
84 virtual void RegisterProfile( 162 virtual void RegisterProfile(
85 const device::BluetoothProfile::Options& options, 163 const device::BluetoothProfile::Options& options,
86 const device::BluetoothProfile::ProfileCallback& callback); 164 const device::BluetoothProfile::ProfileCallback& callback);
87 165
88 private: 166 private:
89 void OnProfileRegistered(device::BluetoothProfile* bluetooth_profile); 167 void OnProfileRegistered(device::BluetoothProfile* bluetooth_profile);
90 168
91 std::string uuid_; 169 std::string uuid_;
92 }; 170 };
93 171
94 class BluetoothRemoveProfileFunction : public SyncExtensionFunction { 172 class BluetoothRemoveProfileFunction : public SyncExtensionFunction {
95 public: 173 public:
96 DECLARE_EXTENSION_FUNCTION("bluetooth.removeProfile", 174 DECLARE_EXTENSION_FUNCTION("bluetooth.removeProfile",
97 BLUETOOTH_REMOVEPROFILE) 175 BLUETOOTH_REMOVEPROFILE)
98 176
99 protected: 177 protected:
100 virtual ~BluetoothRemoveProfileFunction() {} 178 virtual ~BluetoothRemoveProfileFunction();
101 virtual bool RunImpl() OVERRIDE; 179 virtual bool RunImpl() OVERRIDE;
102 }; 180 };
103 181
104 class BluetoothGetProfilesFunction : public BluetoothExtensionFunction { 182 class BluetoothGetProfilesFunction : public BluetoothExtensionFunction {
105 public: 183 public:
106 DECLARE_EXTENSION_FUNCTION("bluetooth.getProfiles", BLUETOOTH_GETPROFILES) 184 DECLARE_EXTENSION_FUNCTION("bluetooth.getProfiles", BLUETOOTH_GETPROFILES)
107 185
108 protected: 186 protected:
109 virtual ~BluetoothGetProfilesFunction() {} 187 virtual ~BluetoothGetProfilesFunction();
110 188
111 // BluetoothExtensionFunction: 189 // BluetoothExtensionFunction:
112 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; 190 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
113 }; 191 };
114 192
115 class BluetoothGetAdapterStateFunction : public BluetoothExtensionFunction {
116 public:
117 DECLARE_EXTENSION_FUNCTION("bluetooth.getAdapterState",
118 BLUETOOTH_GETADAPTERSTATE)
119
120 protected:
121 virtual ~BluetoothGetAdapterStateFunction() {}
122
123 // BluetoothExtensionFunction:
124 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
125 };
126
127 class BluetoothGetDevicesFunction : public BluetoothExtensionFunction {
128 public:
129 DECLARE_EXTENSION_FUNCTION("bluetooth.getDevices", BLUETOOTH_GETDEVICES)
130
131 protected:
132 virtual ~BluetoothGetDevicesFunction() {}
133
134 // BluetoothExtensionFunction:
135 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
136 };
137
138 class BluetoothGetServicesFunction : public BluetoothExtensionFunction {
139 public:
140 DECLARE_EXTENSION_FUNCTION("bluetooth.getServices", BLUETOOTH_GETSERVICES)
141
142 protected:
143 virtual ~BluetoothGetServicesFunction() {}
144
145 // BluetoothExtensionFunction:
146 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
147
148 private:
149 void GetServiceRecordsCallback(
150 base::ListValue* services,
151 const device::BluetoothDevice::ServiceRecordList& records);
152 void OnErrorCallback();
153 };
154
155 class BluetoothConnectFunction : public BluetoothExtensionFunction { 193 class BluetoothConnectFunction : public BluetoothExtensionFunction {
156 public: 194 public:
157 DECLARE_EXTENSION_FUNCTION("bluetooth.connect", BLUETOOTH_CONNECT) 195 DECLARE_EXTENSION_FUNCTION("bluetooth.connect", BLUETOOTH_CONNECT)
158 196
159 protected: 197 protected:
160 virtual ~BluetoothConnectFunction() {} 198 virtual ~BluetoothConnectFunction();
161 199
162 // BluetoothExtensionFunction: 200 // BluetoothExtensionFunction:
163 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; 201 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
164 202
165 private: 203 private:
166 void OnSuccessCallback(); 204 void OnSuccessCallback();
167 void OnErrorCallback(); 205 void OnErrorCallback(const std::string& error);
168 }; 206 };
169 207
170 class BluetoothDisconnectFunction : public SyncExtensionFunction { 208 class BluetoothDisconnectFunction : public BluetoothSocketApiFunction {
171 public: 209 public:
172 DECLARE_EXTENSION_FUNCTION("bluetooth.disconnect", BLUETOOTH_DISCONNECT) 210 DECLARE_EXTENSION_FUNCTION("bluetooth.disconnect", BLUETOOTH_DISCONNECT)
211 BluetoothDisconnectFunction();
173 212
174 protected: 213 protected:
175 virtual ~BluetoothDisconnectFunction() {} 214 virtual ~BluetoothDisconnectFunction();
176
177 // ExtensionFunction:
178 virtual bool RunImpl() OVERRIDE;
179 };
180
181 class BluetoothReadFunction : public AsyncApiFunction {
182 public:
183 DECLARE_EXTENSION_FUNCTION("bluetooth.read", BLUETOOTH_READ)
184 BluetoothReadFunction();
185
186 protected:
187 virtual ~BluetoothReadFunction();
188 215
189 // AsyncApiFunction: 216 // AsyncApiFunction:
190 virtual bool Prepare() OVERRIDE; 217 virtual bool Prepare() OVERRIDE;
191 virtual bool Respond() OVERRIDE; 218 virtual void AsyncWorkStart() OVERRIDE;
219
220 private:
221 void OnSuccess();
222
223 scoped_ptr<bluetooth::Disconnect::Params> params_;
224 };
225
226 class BluetoothSendFunction : public BluetoothSocketApiFunction {
227 public:
228 DECLARE_EXTENSION_FUNCTION("bluetooth.send", BLUETOOTH_SEND)
229 BluetoothSendFunction();
230
231 protected:
232 virtual ~BluetoothSendFunction();
233
234 // AsyncApiFunction:
235 virtual bool Prepare() OVERRIDE;
236 virtual void AsyncWorkStart() OVERRIDE;
237
238 private:
239 void OnSendSuccess(int bytes_sent);
240 void OnSendError(const std::string& message);
241
242 scoped_ptr<bluetooth::Send::Params> params_;
243 scoped_refptr<net::IOBuffer> io_buffer_;
244 size_t io_buffer_size_;
245 };
246
247 class BluetoothUpdateSocketFunction : public BluetoothSocketApiFunction {
248 public:
249 DECLARE_EXTENSION_FUNCTION("bluetooth.updateSocket", BLUETOOTH_UPDATE_SOCKET)
250 BluetoothUpdateSocketFunction();
251
252 protected:
253 virtual ~BluetoothUpdateSocketFunction();
254
255 // AsyncApiFunction:
256 virtual bool Prepare() OVERRIDE;
192 virtual void Work() OVERRIDE; 257 virtual void Work() OVERRIDE;
193 258
194 private: 259 private:
195 bool success_; 260 scoped_ptr<bluetooth::UpdateSocket::Params> params_;
196 scoped_refptr<device::BluetoothSocket> socket_;
197 }; 261 };
198 262
199 class BluetoothWriteFunction : public AsyncApiFunction { 263 class BluetoothSetSocketPausedFunction : public BluetoothSocketApiFunction {
200 public: 264 public:
201 DECLARE_EXTENSION_FUNCTION("bluetooth.write", BLUETOOTH_WRITE) 265 DECLARE_EXTENSION_FUNCTION("bluetooth.setSocketPaused",
202 BluetoothWriteFunction(); 266 BLUETOOTH_SET_SOCKET_PAUSED)
267 BluetoothSetSocketPausedFunction();
203 268
204 protected: 269 protected:
205 virtual ~BluetoothWriteFunction(); 270 virtual ~BluetoothSetSocketPausedFunction();
206 271
207 // AsyncApiFunction: 272 // AsyncApiFunction:
208 virtual bool Prepare() OVERRIDE; 273 virtual bool Prepare() OVERRIDE;
209 virtual bool Respond() OVERRIDE;
210 virtual void Work() OVERRIDE; 274 virtual void Work() OVERRIDE;
211 275
212 private: 276 private:
213 bool success_; 277 scoped_ptr<bluetooth::SetSocketPaused::Params> params_;
214 const base::BinaryValue* data_to_write_; // memory is owned by args_ 278 };
215 scoped_refptr<device::BluetoothSocket> socket_; 279
280 class BluetoothGetSocketFunction : public BluetoothSocketApiFunction {
281 public:
282 DECLARE_EXTENSION_FUNCTION("bluetooth.getSocket", BLUETOOTH_GET_SOCKET)
283
284 BluetoothGetSocketFunction();
285
286 protected:
287 virtual ~BluetoothGetSocketFunction();
288
289 // AsyncApiFunction:
290 virtual bool Prepare() OVERRIDE;
291 virtual void Work() OVERRIDE;
292
293 private:
294 scoped_ptr<bluetooth::GetSocket::Params> params_;
295 };
296
297 class BluetoothGetSocketsFunction : public BluetoothSocketApiFunction {
298 public:
299 DECLARE_EXTENSION_FUNCTION("bluetooth.getSockets", BLUETOOTH_GET_SOCKETS)
300
301 BluetoothGetSocketsFunction();
302
303 protected:
304 virtual ~BluetoothGetSocketsFunction();
305
306 // AsyncApiFunction:
307 virtual bool Prepare() OVERRIDE;
308 virtual void Work() OVERRIDE;
309 };
310
311 class BluetoothGetLocalOutOfBandPairingDataFunction
312 : public BluetoothExtensionFunction {
313 public:
314 DECLARE_EXTENSION_FUNCTION("bluetooth.getLocalOutOfBandPairingData",
315 BLUETOOTH_GETLOCALOUTOFBANDPAIRINGDATA)
316
317 protected:
318 virtual ~BluetoothGetLocalOutOfBandPairingDataFunction() {}
319
320 void ReadCallback(const device::BluetoothOutOfBandPairingData& data);
321 void ErrorCallback();
322
323 // BluetoothExtensionFunction:
324 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
216 }; 325 };
217 326
218 class BluetoothSetOutOfBandPairingDataFunction 327 class BluetoothSetOutOfBandPairingDataFunction
219 : public BluetoothExtensionFunction { 328 : public BluetoothExtensionFunction {
220 public: 329 public:
221 DECLARE_EXTENSION_FUNCTION("bluetooth.setOutOfBandPairingData", 330 DECLARE_EXTENSION_FUNCTION("bluetooth.setOutOfBandPairingData",
222 BLUETOOTH_SETOUTOFBANDPAIRINGDATA) 331 BLUETOOTH_SETOUTOFBANDPAIRINGDATA)
223 332
224 protected: 333 protected:
225 virtual ~BluetoothSetOutOfBandPairingDataFunction() {} 334 virtual ~BluetoothSetOutOfBandPairingDataFunction() {}
226 335
227 void OnSuccessCallback(); 336 void OnSuccessCallback();
228 void OnErrorCallback(); 337 void OnErrorCallback(const std::string& error);
229 338
230 // BluetoothExtensionFunction: 339 // BluetoothExtensionFunction:
231 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; 340 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
232 };
233
234 class BluetoothGetLocalOutOfBandPairingDataFunction
235 : public BluetoothExtensionFunction {
236 public:
237 DECLARE_EXTENSION_FUNCTION("bluetooth.getLocalOutOfBandPairingData",
238 BLUETOOTH_GETLOCALOUTOFBANDPAIRINGDATA)
239
240 protected:
241 virtual ~BluetoothGetLocalOutOfBandPairingDataFunction() {}
242
243 void ReadCallback(
244 const device::BluetoothOutOfBandPairingData& data);
245 void ErrorCallback();
246
247 // BluetoothExtensionFunction:
248 virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE;
249 }; 341 };
250 342
251 class BluetoothStartDiscoveryFunction : public BluetoothExtensionFunction { 343 class BluetoothStartDiscoveryFunction : public BluetoothExtensionFunction {
252 public: 344 public:
253 DECLARE_EXTENSION_FUNCTION("bluetooth.startDiscovery", 345 DECLARE_EXTENSION_FUNCTION("bluetooth.startDiscovery",
254 BLUETOOTH_STARTDISCOVERY) 346 BLUETOOTH_STARTDISCOVERY)
255 347
256 protected: 348 protected:
257 virtual ~BluetoothStartDiscoveryFunction() {} 349 virtual ~BluetoothStartDiscoveryFunction() {}
258 350
(...skipping 17 matching lines...) Expand all
276 368
277 private: 369 private:
278 void OnSuccessCallback(); 370 void OnSuccessCallback();
279 void OnErrorCallback(); 371 void OnErrorCallback();
280 }; 372 };
281 373
282 } // namespace api 374 } // namespace api
283 } // namespace extensions 375 } // namespace extensions
284 376
285 #endif // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_H_ 377 #endif // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_H_
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/extensions/api/bluetooth/bluetooth_api.cc » ('j') | chrome/common/extensions/api/bluetooth.idl » ('J')

Powered by Google App Engine
This is Rietveld 408576698