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.
5 #include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h"
7 #include "base/json/json_writer.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/values.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h"
12 #include "chrome/browser/net/chrome_net_log.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "extensions/browser/event_router.h"
16 #include "extensions/browser/extension_system.h"
17 #include "net/base/net_errors.h"
20 namespace extensions {
22 namespace Close = cast_channel::Close;
23 namespace OnError = cast_channel::OnError;
24 namespace OnMessage = cast_channel::OnMessage;
25 namespace Open = cast_channel::Open;
26 namespace Send = cast_channel::Send;
27 using cast_channel::CastSocket;
28 using cast_channel::ChannelError;
29 using cast_channel::ChannelInfo;
30 using cast_channel::MessageInfo;
31 using cast_channel::ReadyState;
32 using content::BrowserThread;
36 // T is an extension dictionary (MessageInfo or ChannelInfo)
38 std::string ParamToString(const T& info) {
39 scoped_ptr<base::DictionaryValue> dict = info.ToValue();
41 base::JSONWriter::Write(dict.get(), &out);
47 CastChannelAPI::CastChannelAPI(Profile* profile)
53 CastChannelAPI* CastChannelAPI::Get(Profile* profile) {
54 return ProfileKeyedAPIFactory<CastChannelAPI>::GetForProfile(profile);
57 static base::LazyInstance<ProfileKeyedAPIFactory<CastChannelAPI> > g_factory =
58 LAZY_INSTANCE_INITIALIZER;
61 ProfileKeyedAPIFactory<CastChannelAPI>* CastChannelAPI::GetFactoryInstance() {
62 return g_factory.Pointer();
65 scoped_ptr<CastSocket> CastChannelAPI::CreateCastSocket(
66 const std::string& extension_id, const GURL& url) {
67 if (socket_for_test_.get()) {
68 return socket_for_test_.Pass();
70 return scoped_ptr<CastSocket>(
71 new CastSocket(extension_id, url, this,
72 g_browser_process->net_log()));
76 void CastChannelAPI::SetSocketForTest(scoped_ptr<CastSocket> socket_for_test) {
77 socket_for_test_ = socket_for_test.Pass();
80 void CastChannelAPI::OnError(const CastSocket* socket,
81 cast_channel::ChannelError error) {
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
83 ChannelInfo channel_info;
84 socket->FillChannelInfo(&channel_info);
85 channel_info.error_state = error;
86 scoped_ptr<base::ListValue> results = OnError::Create(channel_info);
87 scoped_ptr<Event> event(new Event(OnError::kEventName, results.Pass()));
88 extensions::ExtensionSystem::Get(profile_)->event_router()->
89 DispatchEventToExtension(socket->owner_extension_id(), event.Pass());
92 void CastChannelAPI::OnMessage(const CastSocket* socket,
93 const MessageInfo& message_info) {
94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
95 ChannelInfo channel_info;
96 socket->FillChannelInfo(&channel_info);
97 scoped_ptr<base::ListValue> results =
98 OnMessage::Create(channel_info, message_info);
99 VLOG(1) << "Sending message " << ParamToString(message_info)
100 << " to channel " << ParamToString(channel_info);
101 scoped_ptr<Event> event(new Event(OnMessage::kEventName, results.Pass()));
102 extensions::ExtensionSystem::Get(profile_)->event_router()->
103 DispatchEventToExtension(socket->owner_extension_id(), event.Pass());
106 CastChannelAPI::~CastChannelAPI() {}
108 CastChannelAsyncApiFunction::CastChannelAsyncApiFunction()
109 : manager_(NULL), error_(cast_channel::CHANNEL_ERROR_NONE) { }
111 CastChannelAsyncApiFunction::~CastChannelAsyncApiFunction() { }
113 bool CastChannelAsyncApiFunction::PrePrepare() {
114 manager_ = ApiResourceManager<CastSocket>::Get(GetProfile());
118 bool CastChannelAsyncApiFunction::Respond() {
119 return error_ != cast_channel::CHANNEL_ERROR_NONE;
122 CastSocket* CastChannelAsyncApiFunction::GetSocketOrCompleteWithError(
124 CastSocket* socket = GetSocket(channel_id);
126 SetResultFromError(cast_channel::CHANNEL_ERROR_INVALID_CHANNEL_ID);
127 AsyncWorkCompleted();
132 int CastChannelAsyncApiFunction::AddSocket(CastSocket* socket) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
136 const int id = manager_->Add(socket);
141 void CastChannelAsyncApiFunction::RemoveSocket(int channel_id) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
144 manager_->Remove(extension_->id(), channel_id);
147 void CastChannelAsyncApiFunction::SetResultFromSocket(int channel_id) {
148 CastSocket* socket = GetSocket(channel_id);
150 ChannelInfo channel_info;
151 socket->FillChannelInfo(&channel_info);
152 error_ = socket->error_state();
153 SetResultFromChannelInfo(channel_info);
156 void CastChannelAsyncApiFunction::SetResultFromError(ChannelError error) {
157 ChannelInfo channel_info;
158 channel_info.channel_id = -1;
159 channel_info.url = "";
160 channel_info.ready_state = cast_channel::READY_STATE_CLOSED;
161 channel_info.error_state = error;
162 SetResultFromChannelInfo(channel_info);
166 CastSocket* CastChannelAsyncApiFunction::GetSocket(int channel_id) {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
169 return manager_->Get(extension_->id(), channel_id);
172 void CastChannelAsyncApiFunction::SetResultFromChannelInfo(
173 const ChannelInfo& channel_info) {
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
175 SetResult(channel_info.ToValue().release());
178 CastChannelOpenFunction::CastChannelOpenFunction()
179 : new_channel_id_(0) { }
181 CastChannelOpenFunction::~CastChannelOpenFunction() { }
183 bool CastChannelOpenFunction::PrePrepare() {
184 api_ = CastChannelAPI::Get(GetProfile());
185 return CastChannelAsyncApiFunction::PrePrepare();
188 bool CastChannelOpenFunction::Prepare() {
189 params_ = Open::Params::Create(*args_);
190 EXTENSION_FUNCTION_VALIDATE(params_.get());
194 void CastChannelOpenFunction::AsyncWorkStart() {
196 scoped_ptr<CastSocket> socket = api_->CreateCastSocket(extension_->id(),
198 new_channel_id_ = AddSocket(socket.release());
199 GetSocket(new_channel_id_)->Connect(
200 base::Bind(&CastChannelOpenFunction::OnOpen, this));
203 void CastChannelOpenFunction::OnOpen(int result) {
204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
205 SetResultFromSocket(new_channel_id_);
206 AsyncWorkCompleted();
209 CastChannelSendFunction::CastChannelSendFunction() { }
211 CastChannelSendFunction::~CastChannelSendFunction() { }
213 bool CastChannelSendFunction::Prepare() {
214 params_ = Send::Params::Create(*args_);
215 EXTENSION_FUNCTION_VALIDATE(params_.get());
219 void CastChannelSendFunction::AsyncWorkStart() {
220 CastSocket* socket = GetSocketOrCompleteWithError(
221 params_->channel.channel_id);
223 socket->SendMessage(params_->message,
224 base::Bind(&CastChannelSendFunction::OnSend, this));
227 void CastChannelSendFunction::OnSend(int result) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230 SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
232 SetResultFromSocket(params_->channel.channel_id);
234 AsyncWorkCompleted();
237 CastChannelCloseFunction::CastChannelCloseFunction() { }
239 CastChannelCloseFunction::~CastChannelCloseFunction() { }
241 bool CastChannelCloseFunction::Prepare() {
242 params_ = Close::Params::Create(*args_);
243 EXTENSION_FUNCTION_VALIDATE(params_.get());
247 void CastChannelCloseFunction::AsyncWorkStart() {
248 CastSocket* socket = GetSocketOrCompleteWithError(
249 params_->channel.channel_id);
251 socket->Close(base::Bind(&CastChannelCloseFunction::OnClose, this));
254 void CastChannelCloseFunction::OnClose(int result) {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
256 VLOG(1) << "CastChannelCloseFunction::OnClose result = " << result;
258 SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
260 int channel_id = params_->channel.channel_id;
261 SetResultFromSocket(channel_id);
262 RemoveSocket(channel_id);
264 AsyncWorkCompleted();
267 } // namespace extensions