Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 #include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h" | 5 #include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <string> | |
| 8 | 9 |
| 9 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
| 10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/values.h" | 13 #include "base/values.h" |
| 13 #include "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
| 14 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" | 15 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" |
| 15 #include "chrome/browser/net/chrome_net_log.h" | 16 #include "chrome/browser/net/chrome_net_log.h" |
| 16 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 17 #include "extensions/browser/event_router.h" | 18 #include "extensions/browser/event_router.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 channel_info->channel_id = socket.id(); | 54 channel_info->channel_id = socket.id(); |
| 54 channel_info->url = socket.CastUrl(); | 55 channel_info->url = socket.CastUrl(); |
| 55 const net::IPEndPoint& ip_endpoint = socket.ip_endpoint(); | 56 const net::IPEndPoint& ip_endpoint = socket.ip_endpoint(); |
| 56 channel_info->connect_info.ip_address = ip_endpoint.ToStringWithoutPort(); | 57 channel_info->connect_info.ip_address = ip_endpoint.ToStringWithoutPort(); |
| 57 channel_info->connect_info.port = ip_endpoint.port(); | 58 channel_info->connect_info.port = ip_endpoint.port(); |
| 58 channel_info->connect_info.auth = socket.channel_auth(); | 59 channel_info->connect_info.auth = socket.channel_auth(); |
| 59 channel_info->ready_state = socket.ready_state(); | 60 channel_info->ready_state = socket.ready_state(); |
| 60 channel_info->error_state = socket.error_state(); | 61 channel_info->error_state = socket.error_state(); |
| 61 } | 62 } |
| 62 | 63 |
| 64 bool IsValidConnectInfoPort(const ConnectInfo& connect_info) { | |
| 65 return connect_info.port > 0 && connect_info.port < | |
| 66 std::numeric_limits<unsigned short>::max(); | |
| 67 } | |
| 68 | |
| 69 bool IsValidConnectInfoAuth(const ConnectInfo& connect_info) { | |
| 70 return connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED || | |
| 71 connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL; | |
| 72 } | |
| 73 | |
| 74 bool IsValidConnectInfoIpAddress(const ConnectInfo& connect_info) { | |
| 75 net::IPAddressNumber ip_address; | |
| 76 return net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address); | |
| 77 } | |
| 78 | |
| 63 } // namespace | 79 } // namespace |
| 64 | 80 |
| 65 CastChannelAPI::CastChannelAPI(content::BrowserContext* context) | 81 CastChannelAPI::CastChannelAPI(content::BrowserContext* context) |
| 66 : browser_context_(context) { | 82 : browser_context_(context) { |
| 67 DCHECK(browser_context_); | 83 DCHECK(browser_context_); |
| 68 } | 84 } |
| 69 | 85 |
| 70 // static | 86 // static |
| 71 CastChannelAPI* CastChannelAPI::Get(content::BrowserContext* context) { | 87 CastChannelAPI* CastChannelAPI::Get(content::BrowserContext* context) { |
| 72 return BrowserContextKeyedAPIFactory<CastChannelAPI>::Get(context); | 88 return BrowserContextKeyedAPIFactory<CastChannelAPI>::Get(context); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 VLOG(2) << "IP: " << ip_address_str << " Port: " << port_str; | 253 VLOG(2) << "IP: " << ip_address_str << " Port: " << port_str; |
| 238 int port; | 254 int port; |
| 239 if (!base::StringToInt(port_str, &port)) | 255 if (!base::StringToInt(port_str, &port)) |
| 240 return false; | 256 return false; |
| 241 connect_info->ip_address = ip_address_str; | 257 connect_info->ip_address = ip_address_str; |
| 242 connect_info->port = port; | 258 connect_info->port = port; |
| 243 connect_info->auth = auth_required ? | 259 connect_info->auth = auth_required ? |
| 244 cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED : | 260 cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED : |
| 245 cast_channel::CHANNEL_AUTH_TYPE_SSL; | 261 cast_channel::CHANNEL_AUTH_TYPE_SSL; |
| 246 return true; | 262 return true; |
| 247 }; | 263 } |
| 248 | 264 |
| 249 net::IPEndPoint* CastChannelOpenFunction::ParseConnectInfo( | 265 net::IPEndPoint* CastChannelOpenFunction::ParseConnectInfo( |
| 250 const ConnectInfo& connect_info) { | 266 const ConnectInfo& connect_info) { |
| 251 net::IPAddressNumber ip_address; | 267 net::IPAddressNumber ip_address; |
| 252 if (!net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address)) { | 268 CHECK(net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address)); |
| 253 return NULL; | |
| 254 } | |
| 255 if (connect_info.port < 0 || connect_info.port > | |
| 256 std::numeric_limits<unsigned short>::max()) { | |
| 257 return NULL; | |
| 258 } | |
| 259 if (connect_info.auth != cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED && | |
| 260 connect_info.auth != cast_channel::CHANNEL_AUTH_TYPE_SSL) { | |
| 261 return NULL; | |
| 262 } | |
| 263 return new net::IPEndPoint(ip_address, connect_info.port); | 269 return new net::IPEndPoint(ip_address, connect_info.port); |
| 264 } | 270 } |
| 265 | 271 |
| 266 bool CastChannelOpenFunction::PrePrepare() { | 272 bool CastChannelOpenFunction::PrePrepare() { |
| 267 api_ = CastChannelAPI::Get(browser_context()); | 273 api_ = CastChannelAPI::Get(browser_context()); |
| 268 return CastChannelAsyncApiFunction::PrePrepare(); | 274 return CastChannelAsyncApiFunction::PrePrepare(); |
| 269 } | 275 } |
| 270 | 276 |
| 271 bool CastChannelOpenFunction::Prepare() { | 277 bool CastChannelOpenFunction::Prepare() { |
| 272 params_ = Open::Params::Create(*args_); | 278 params_ = Open::Params::Create(*args_); |
| 273 EXTENSION_FUNCTION_VALIDATE(params_.get()); | 279 EXTENSION_FUNCTION_VALIDATE(params_.get()); |
| 274 // The connect_info parameter may be a string URL like cast:// or casts:// or | 280 // The connect_info parameter may be a string URL like cast:// or casts:// or |
| 275 // a ConnectInfo object. | 281 // a ConnectInfo object. |
| 276 std::string cast_url; | 282 std::string cast_url; |
| 283 bool is_connect_info_url = false; | |
| 284 bool is_connect_info_dict = false; | |
| 277 switch (params_->connect_info->GetType()) { | 285 switch (params_->connect_info->GetType()) { |
| 278 case base::Value::TYPE_STRING: | 286 case base::Value::TYPE_STRING: |
| 287 is_connect_info_url = true; | |
| 279 CHECK(params_->connect_info->GetAsString(&cast_url)); | 288 CHECK(params_->connect_info->GetAsString(&cast_url)); |
| 280 connect_info_.reset(new ConnectInfo); | 289 connect_info_.reset(new ConnectInfo); |
| 281 if (!ParseChannelUrl(GURL(cast_url), connect_info_.get())) { | 290 if (!ParseChannelUrl(GURL(cast_url), connect_info_.get())) { |
| 282 connect_info_.reset(); | 291 connect_info_.reset(); |
| 283 } | 292 } |
| 284 break; | 293 break; |
| 285 case base::Value::TYPE_DICTIONARY: | 294 case base::Value::TYPE_DICTIONARY: |
| 295 is_connect_info_dict = true; | |
| 286 connect_info_ = ConnectInfo::FromValue(*(params_->connect_info)); | 296 connect_info_ = ConnectInfo::FromValue(*(params_->connect_info)); |
| 287 break; | 297 break; |
| 288 default: | 298 default: |
| 289 break; | 299 break; |
| 290 } | 300 } |
| 291 if (connect_info_.get()) { | 301 |
| 292 channel_auth_ = connect_info_->auth; | 302 DCHECK(!is_connect_info_dict || !is_connect_info_url); |
| 293 ip_endpoint_.reset(ParseConnectInfo(*connect_info_)); | 303 if (!connect_info_.get()) { |
| 294 return ip_endpoint_.get() != NULL; | 304 if (!is_connect_info_dict && !is_connect_info_url) { |
| 305 SetError("Invalid connect_info (unknown type)"); | |
|
Wez
2014/07/17 21:16:47
This can just go in the default: case, surely?
mark a. foltz
2014/07/17 22:23:40
Done.
| |
| 306 } else if (is_connect_info_dict) { | |
| 307 SetError("connect_info.auth is required"); | |
|
Wez
2014/07/17 21:16:47
I was actually thinking we could just get rid of t
mark a. foltz
2014/07/17 22:23:40
FromValue() is generated code that can't be change
| |
| 308 } else { | |
| 309 SetError("Invalid connect_info (invalid Cast URL " + cast_url + ")"); | |
|
Wez
2014/07/17 21:16:47
This could go in the TYPE_STRING failure block, if
mark a. foltz
2014/07/17 22:23:40
Done.
| |
| 310 } | |
| 311 return false; | |
| 295 } | 312 } |
| 296 return false; | 313 |
| 314 if (!IsValidConnectInfoPort(*connect_info_)) { | |
| 315 SetError("Invalid connect_info (invalid port)"); | |
| 316 } else if (!IsValidConnectInfoAuth(*connect_info_)) { | |
| 317 SetError("Invalid connect_info (invalid auth)"); | |
| 318 } else if (!IsValidConnectInfoIpAddress(*connect_info_)) { | |
| 319 SetError("Invalid connect_info (invalid IP address)"); | |
| 320 } | |
| 321 if (!GetError().empty()) { | |
| 322 return false; | |
| 323 } | |
| 324 channel_auth_ = connect_info_->auth; | |
| 325 ip_endpoint_.reset(ParseConnectInfo(*connect_info_)); | |
| 326 return true; | |
| 297 } | 327 } |
| 298 | 328 |
| 299 void CastChannelOpenFunction::AsyncWorkStart() { | 329 void CastChannelOpenFunction::AsyncWorkStart() { |
| 300 DCHECK(api_); | 330 DCHECK(api_); |
| 301 DCHECK(ip_endpoint_.get()); | 331 DCHECK(ip_endpoint_.get()); |
| 302 scoped_ptr<CastSocket> socket = api_->CreateCastSocket( | 332 scoped_ptr<CastSocket> socket = api_->CreateCastSocket( |
| 303 extension_->id(), *ip_endpoint_, channel_auth_); | 333 extension_->id(), *ip_endpoint_, channel_auth_); |
| 304 new_channel_id_ = AddSocket(socket.release()); | 334 new_channel_id_ = AddSocket(socket.release()); |
| 305 GetSocket(new_channel_id_)->Connect( | 335 GetSocket(new_channel_id_)->Connect( |
| 306 base::Bind(&CastChannelOpenFunction::OnOpen, this)); | 336 base::Bind(&CastChannelOpenFunction::OnOpen, this)); |
| 307 } | 337 } |
| 308 | 338 |
| 309 void CastChannelOpenFunction::OnOpen(int result) { | 339 void CastChannelOpenFunction::OnOpen(int result) { |
| 310 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 340 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 311 SetResultFromSocket(new_channel_id_); | 341 SetResultFromSocket(new_channel_id_); |
| 312 AsyncWorkCompleted(); | 342 AsyncWorkCompleted(); |
| 313 } | 343 } |
| 314 | 344 |
| 315 CastChannelSendFunction::CastChannelSendFunction() { } | 345 CastChannelSendFunction::CastChannelSendFunction() { } |
| 316 | 346 |
| 317 CastChannelSendFunction::~CastChannelSendFunction() { } | 347 CastChannelSendFunction::~CastChannelSendFunction() { } |
| 318 | 348 |
| 319 bool CastChannelSendFunction::Prepare() { | 349 bool CastChannelSendFunction::Prepare() { |
| 320 params_ = Send::Params::Create(*args_); | 350 params_ = Send::Params::Create(*args_); |
| 321 EXTENSION_FUNCTION_VALIDATE(params_.get()); | 351 EXTENSION_FUNCTION_VALIDATE(params_.get()); |
| 352 if (params_->message.namespace_.empty()) { | |
| 353 SetError("message_info.namespace_ is required"); | |
| 354 return false; | |
| 355 } | |
| 356 if (params_->message.source_id.empty()) { | |
| 357 SetError("message_info.source_id is required"); | |
| 358 return false; | |
| 359 } | |
| 360 if (params_->message.destination_id.empty()) { | |
| 361 SetError("message_info.destination_id is required"); | |
| 362 return false; | |
| 363 } | |
| 364 switch (params_->message.data->GetType()) { | |
| 365 case base::Value::TYPE_STRING: | |
| 366 case base::Value::TYPE_BINARY: | |
| 367 break; | |
| 368 default: | |
| 369 SetError("Invalid type of message_info.data"); | |
| 370 return false; | |
| 371 } | |
| 322 return true; | 372 return true; |
| 323 } | 373 } |
| 324 | 374 |
| 325 void CastChannelSendFunction::AsyncWorkStart() { | 375 void CastChannelSendFunction::AsyncWorkStart() { |
| 326 CastSocket* socket = GetSocketOrCompleteWithError( | 376 CastSocket* socket = GetSocketOrCompleteWithError( |
| 327 params_->channel.channel_id); | 377 params_->channel.channel_id); |
| 328 if (socket) | 378 if (socket) |
| 329 socket->SendMessage(params_->message, | 379 socket->SendMessage(params_->message, |
| 330 base::Bind(&CastChannelSendFunction::OnSend, this)); | 380 base::Bind(&CastChannelSendFunction::OnSend, this)); |
| 331 } | 381 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR); | 414 SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR); |
| 365 } else { | 415 } else { |
| 366 int channel_id = params_->channel.channel_id; | 416 int channel_id = params_->channel.channel_id; |
| 367 SetResultFromSocket(channel_id); | 417 SetResultFromSocket(channel_id); |
| 368 RemoveSocket(channel_id); | 418 RemoveSocket(channel_id); |
| 369 } | 419 } |
| 370 AsyncWorkCompleted(); | 420 AsyncWorkCompleted(); |
| 371 } | 421 } |
| 372 | 422 |
| 373 } // namespace extensions | 423 } // namespace extensions |
| OLD | NEW |