15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/api/cast_channel/cast_channel_api.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include <limits> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string> 90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/json/json_writer.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/lazy_instance.h" 120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/strings/string_number_conversions.h" 146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/time/default_tick_clock.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/values.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/api/cast_channel/cast_socket.h" 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "extensions/browser/api/cast_channel/logger.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/api/cast_channel/logging.pb.h" 210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/base/ip_endpoint.h" 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/base/net_errors.h" 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/base/net_util.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "url/gurl.h" 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Default timeout interval for connection setup. 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Used if not otherwise specified at ConnectInfo::timeout. 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kDefaultConnectTimeoutMillis = 5000; // 5 seconds. 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace extensions { 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace Close = cast_channel::Close; 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace OnError = cast_channel::OnError; 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace OnMessage = cast_channel::OnMessage; 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace Open = cast_channel::Open; 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace Send = cast_channel::Send; 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using cast_channel::CastSocket; 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochusing cast_channel::ChannelAuthType; 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using cast_channel::ChannelError; 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using cast_channel::ChannelInfo; 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochusing cast_channel::ConnectInfo; 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using cast_channel::ErrorInfo; 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using cast_channel::LastErrors; 446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using cast_channel::Logger; 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using cast_channel::MessageInfo; 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using cast_channel::ReadyState; 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using content::BrowserThread; 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// T is an extension dictionary (MessageInfo or ChannelInfo) 528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)template <class T> 538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::string ParamToString(const T& info) { 548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) scoped_ptr<base::DictionaryValue> dict = info.ToValue(); 558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string out; 568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::JSONWriter::Write(dict.get(), &out); 578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return out; 588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Fills |channel_info| from the destination and state of |socket|. 610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FillChannelInfo(const CastSocket& socket, ChannelInfo* channel_info) { 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(channel_info); 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->channel_id = socket.id(); 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->url = socket.CastUrl(); 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const net::IPEndPoint& ip_endpoint = socket.ip_endpoint(); 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->connect_info.ip_address = ip_endpoint.ToStringWithoutPort(); 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->connect_info.port = ip_endpoint.port(); 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->connect_info.auth = socket.channel_auth(); 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->ready_state = socket.ready_state(); 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch channel_info->error_state = socket.error_state(); 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Fills |error_info| from |error_state| and |last_errors|. 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void FillErrorInfo(ChannelError error_state, 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const LastErrors& last_errors, 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ErrorInfo* error_info) { 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) error_info->error_state = error_state; 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (last_errors.event_type != cast_channel::proto::EVENT_TYPE_UNKNOWN) 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) error_info->event_type.reset(new int(last_errors.event_type)); 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (last_errors.challenge_reply_error_type != 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cast_channel::proto::CHALLENGE_REPLY_ERROR_NONE) { 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) error_info->challenge_reply_error_type.reset( 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new int(last_errors.challenge_reply_error_type)); 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (last_errors.net_return_value <= 0) 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) error_info->net_return_value.reset(new int(last_errors.net_return_value)); 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (last_errors.nss_error_code < 0) 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) error_info->nss_error_code.reset(new int(last_errors.nss_error_code)); 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsValidConnectInfoPort(const ConnectInfo& connect_info) { 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return connect_info.port > 0 && connect_info.port < 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::numeric_limits<uint16_t>::max(); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsValidConnectInfoAuth(const ConnectInfo& connect_info) { 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED || 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL; 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsValidConnectInfoIpAddress(const ConnectInfo& connect_info) { 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::IPAddressNumber ip_address; 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address); 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)CastChannelAPI::CastChannelAPI(content::BrowserContext* context) 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : browser_context_(context), 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) logger_( 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new Logger(scoped_ptr<base::TickClock>(new base::DefaultTickClock), 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks::UnixEpoch())) { 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(browser_context_); 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)CastChannelAPI* CastChannelAPI::Get(content::BrowserContext* context) { 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return BrowserContextKeyedAPIFactory<CastChannelAPI>::Get(context); 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)scoped_refptr<Logger> CastChannelAPI::GetLogger() { 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return logger_; 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<CastChannelAPI> > 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<CastChannelAPI>* 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)CastChannelAPI::GetFactoryInstance() { 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CastChannelAPI::SetSocketForTest(scoped_ptr<CastSocket> socket_for_test) { 1350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) socket_for_test_ = socket_for_test.Pass(); 1360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<cast_channel::CastSocket> CastChannelAPI::GetSocketForTest() { 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return socket_for_test_.Pass(); 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelAPI::OnError(const CastSocket* socket, 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cast_channel::ChannelError error_state, 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const cast_channel::LastErrors& last_errors) { 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChannelInfo channel_info; 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FillChannelInfo(*socket, &channel_info); 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) channel_info.error_state = error_state; 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ErrorInfo error_info; 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FillErrorInfo(error_state, last_errors, &error_info); 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<base::ListValue> results = 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnError::Create(channel_info, error_info); 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<Event> event(new Event(OnError::kEventName, results.Pass())); 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extensions::EventRouter::Get(browser_context_) 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ->DispatchEventToExtension(socket->owner_extension_id(), event.Pass()); 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelAPI::OnMessage(const CastSocket* socket, 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const MessageInfo& message_info) { 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChannelInfo channel_info; 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FillChannelInfo(*socket, &channel_info); 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<base::ListValue> results = 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnMessage::Create(channel_info, message_info); 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(1) << "Sending message " << ParamToString(message_info) 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << " to channel " << ParamToString(channel_info); 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<Event> event(new Event(OnMessage::kEventName, results.Pass())); 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extensions::EventRouter::Get(browser_context_) 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ->DispatchEventToExtension(socket->owner_extension_id(), event.Pass()); 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelAPI::~CastChannelAPI() {} 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelAsyncApiFunction::CastChannelAsyncApiFunction() 1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : manager_(NULL), error_(cast_channel::CHANNEL_ERROR_NONE) { } 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelAsyncApiFunction::~CastChannelAsyncApiFunction() { } 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CastChannelAsyncApiFunction::PrePrepare() { 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) manager_ = ApiResourceManager<CastSocket>::Get(browser_context()); 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CastChannelAsyncApiFunction::Respond() { 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return error_ == cast_channel::CHANNEL_ERROR_NONE; 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CastSocket* CastChannelAsyncApiFunction::GetSocketOrCompleteWithError( 1898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int channel_id) { 1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CastSocket* socket = GetSocket(channel_id); 1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!socket) { 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromError(channel_id, 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cast_channel::CHANNEL_ERROR_INVALID_CHANNEL_ID); 1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) AsyncWorkCompleted(); 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return socket; 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int CastChannelAsyncApiFunction::AddSocket(CastSocket* socket) { 200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(socket); 2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(manager_); 2030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const int id = manager_->Add(socket); 2040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) socket->set_id(id); 2050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return id; 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void CastChannelAsyncApiFunction::RemoveSocket(int channel_id) { 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(manager_); 2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) manager_->Remove(extension_->id(), channel_id); 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void CastChannelAsyncApiFunction::SetResultFromSocket( 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const CastSocket& socket) { 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChannelInfo channel_info; 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FillChannelInfo(socket, &channel_info); 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_ = socket.error_state(); 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SetResultFromChannelInfo(channel_info); 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void CastChannelAsyncApiFunction::SetResultFromError(int channel_id, 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ChannelError error) { 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChannelInfo channel_info; 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel_info.channel_id = channel_id; 2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) channel_info.url = ""; 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) channel_info.ready_state = cast_channel::READY_STATE_CLOSED; 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) channel_info.error_state = error; 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel_info.connect_info.ip_address = ""; 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel_info.connect_info.port = 0; 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel_info.connect_info.auth = cast_channel::CHANNEL_AUTH_TYPE_SSL; 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SetResultFromChannelInfo(channel_info); 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) error_ = error; 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CastSocket* CastChannelAsyncApiFunction::GetSocket(int channel_id) { 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(manager_); 2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return manager_->Get(extension_->id(), channel_id); 2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void CastChannelAsyncApiFunction::SetResultFromChannelInfo( 2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const ChannelInfo& channel_info) { 244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SetResult(channel_info.ToValue().release()); 2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CastChannelOpenFunction::CastChannelOpenFunction() 2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : new_channel_id_(0) { } 2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelOpenFunction::~CastChannelOpenFunction() { } 2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// TODO(mfoltz): Remove URL parsing when clients have converted to use 2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// ConnectInfo. 2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Allowed schemes for Cast device URLs. 2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst char kCastInsecureScheme[] = "cast"; 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst char kCastSecureScheme[] = "casts"; 2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool CastChannelOpenFunction::ParseChannelUrl(const GURL& url, 2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ConnectInfo* connect_info) { 2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(connect_info); 2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch VLOG(2) << "ParseChannelUrl"; 2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool auth_required = false; 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url.SchemeIs(kCastSecureScheme)) { 2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch auth_required = true; 2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else if (!url.SchemeIs(kCastInsecureScheme)) { 2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(mfoltz): Test for IPv6 addresses. Brackets or no brackets? 2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(mfoltz): Maybe enforce restriction to IPv4 private and IPv6 2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // link-local networks 2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& path = url.path(); 2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Shortest possible: //A:B 2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (path.size() < 5) { 2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (path.find("//") != 0) { 2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch size_t colon = path.find_last_of(':'); 2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (colon == std::string::npos || colon < 3 || colon > path.size() - 2) { 2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& ip_address_str = path.substr(2, colon - 2); 2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& port_str = path.substr(colon + 1); 2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch VLOG(2) << "IP: " << ip_address_str << " Port: " << port_str; 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int port; 2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!base::StringToInt(port_str, &port)) 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connect_info->ip_address = ip_address_str; 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connect_info->port = port; 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connect_info->auth = auth_required ? 2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED : 2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch cast_channel::CHANNEL_AUTH_TYPE_SSL; 2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return true; 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnet::IPEndPoint* CastChannelOpenFunction::ParseConnectInfo( 3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ConnectInfo& connect_info) { 3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::IPAddressNumber ip_address; 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address)); 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return new net::IPEndPoint(ip_address, connect_info.port); 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CastChannelOpenFunction::PrePrepare() { 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) api_ = CastChannelAPI::Get(browser_context()); 3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return CastChannelAsyncApiFunction::PrePrepare(); 3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CastChannelOpenFunction::Prepare() { 3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) params_ = Open::Params::Create(*args_); 3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params_.get()); 3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The connect_info parameter may be a string URL like cast:// or casts:// or 3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // a ConnectInfo object. 3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string cast_url; 3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch switch (params_->connect_info->GetType()) { 3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case base::Value::TYPE_STRING: 3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CHECK(params_->connect_info->GetAsString(&cast_url)); 3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connect_info_.reset(new ConnectInfo); 3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!ParseChannelUrl(GURL(cast_url), connect_info_.get())) { 3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connect_info_.reset(); 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("Invalid connect_info (invalid Cast URL " + cast_url + ")"); 3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case base::Value::TYPE_DICTIONARY: 3270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connect_info_ = ConnectInfo::FromValue(*(params_->connect_info)); 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!connect_info_.get()) { 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("connect_info.auth is required"); 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 3320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch default: 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("Invalid connect_info (unknown type)"); 3340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!connect_info_.get()) { 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!IsValidConnectInfoPort(*connect_info_)) { 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("Invalid connect_info (invalid port)"); 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (!IsValidConnectInfoAuth(*connect_info_)) { 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("Invalid connect_info (invalid auth)"); 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (!IsValidConnectInfoIpAddress(*connect_info_)) { 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("Invalid connect_info (invalid IP address)"); 3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!GetError().empty()) { 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) channel_auth_ = connect_info_->auth; 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ip_endpoint_.reset(ParseConnectInfo(*connect_info_)); 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelOpenFunction::AsyncWorkStart() { 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(api_); 3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(ip_endpoint_.get()); 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<CastSocket> socket = api_->GetSocketForTest(); 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!socket.get()) { 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket.reset(new CastSocket( 3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_->id(), 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *ip_endpoint_, 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci channel_auth_, 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci api_, 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionsBrowserClient::Get()->GetNetLog(), 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeDelta::FromMilliseconds(connect_info_->timeout.get() 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ? *connect_info_->timeout 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : kDefaultConnectTimeoutMillis), 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci api_->GetLogger())); 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) new_channel_id_ = AddSocket(socket.release()); 3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CastSocket* new_socket = GetSocket(new_channel_id_); 3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) api_->GetLogger()->LogNewSocketEvent(*new_socket); 3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new_socket->Connect(base::Bind(&CastChannelOpenFunction::OnOpen, this)); 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelOpenFunction::OnOpen(int result) { 377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "Connect finished, OnOpen invoked."; 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CastSocket* socket = GetSocket(new_channel_id_); 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!socket) { 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromError(new_channel_id_, 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cast_channel::CHANNEL_ERROR_CONNECT_ERROR); 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromSocket(*socket); 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AsyncWorkCompleted(); 3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelSendFunction::CastChannelSendFunction() { } 3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelSendFunction::~CastChannelSendFunction() { } 3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CastChannelSendFunction::Prepare() { 3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) params_ = Send::Params::Create(*args_); 3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params_.get()); 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (params_->message.namespace_.empty()) { 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("message_info.namespace_ is required"); 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (params_->message.source_id.empty()) { 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("message_info.source_id is required"); 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (params_->message.destination_id.empty()) { 4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("message_info.destination_id is required"); 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) switch (params_->message.data->GetType()) { 4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case base::Value::TYPE_STRING: 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case base::Value::TYPE_BINARY: 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default: 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetError("Invalid type of message_info.data"); 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelSendFunction::AsyncWorkStart() { 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CastSocket* socket = GetSocket(params_->channel.channel_id); 4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!socket) { 4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetResultFromError(params_->channel.channel_id, 4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cast_channel::CHANNEL_ERROR_INVALID_CHANNEL_ID); 4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AsyncWorkCompleted(); 4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket->SendMessage(params_->message, 4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&CastChannelSendFunction::OnSend, this)); 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelSendFunction::OnSend(int result) { 432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int channel_id = params_->channel.channel_id; 4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CastSocket* socket = GetSocket(channel_id); 4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result < 0 || !socket) { 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromError(channel_id, 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cast_channel::CHANNEL_ERROR_SOCKET_ERROR); 4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromSocket(*socket); 4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AsyncWorkCompleted(); 4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelCloseFunction::CastChannelCloseFunction() { } 4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)CastChannelCloseFunction::~CastChannelCloseFunction() { } 4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool CastChannelCloseFunction::Prepare() { 4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) params_ = Close::Params::Create(*args_); 4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params_.get()); 4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelCloseFunction::AsyncWorkStart() { 4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CastSocket* socket = GetSocket(params_->channel.channel_id); 4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!socket) { 4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetResultFromError(params_->channel.channel_id, 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cast_channel::CHANNEL_ERROR_INVALID_CHANNEL_ID); 4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AsyncWorkCompleted(); 4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 4618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) socket->Close(base::Bind(&CastChannelCloseFunction::OnClose, this)); 4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CastChannelCloseFunction::OnClose(int result) { 466effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(1) << "CastChannelCloseFunction::OnClose result = " << result; 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int channel_id = params_->channel.channel_id; 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CastSocket* socket = GetSocket(channel_id); 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result < 0 || !socket) { 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromError(channel_id, 4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cast_channel::CHANNEL_ERROR_SOCKET_ERROR); 4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetResultFromSocket(*socket); 4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This will delete |socket|. 4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) RemoveSocket(channel_id); 4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket = NULL; 4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AsyncWorkCompleted(); 4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)CastChannelGetLogsFunction::CastChannelGetLogsFunction() { 4836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)CastChannelGetLogsFunction::~CastChannelGetLogsFunction() { 4866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastChannelGetLogsFunction::PrePrepare() { 4896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) api_ = CastChannelAPI::Get(browser_context()); 4906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return CastChannelAsyncApiFunction::PrePrepare(); 4916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastChannelGetLogsFunction::Prepare() { 4946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 4956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CastChannelGetLogsFunction::AsyncWorkStart() { 4986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(api_); 4996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) size_t length = 0; 5016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<char[]> out = api_->GetLogger()->GetLogs(&length); 5026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (out.get()) { 5036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SetResult(new base::BinaryValue(out.Pass(), length)); 5046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 5056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SetError("Unable to get logs."); 5066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 5076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) api_->GetLogger()->Reset(); 5096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AsyncWorkCompleted(); 5116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 5126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace extensions 514