| Index: chrome/browser/extensions/api/cast_channel/cast_channel_api.cc
|
| diff --git a/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc b/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc
|
| deleted file mode 100644
|
| index 1c3a3116bf262d7d38c5e87b9945f5be132d8a3b..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc
|
| +++ /dev/null
|
| @@ -1,425 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h"
|
| -
|
| -#include <limits>
|
| -#include <string>
|
| -
|
| -#include "base/json/json_writer.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/values.h"
|
| -#include "chrome/browser/browser_process.h"
|
| -#include "chrome/browser/extensions/api/cast_channel/cast_socket.h"
|
| -#include "chrome/browser/net/chrome_net_log.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "extensions/browser/event_router.h"
|
| -#include "net/base/ip_endpoint.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/base/net_util.h"
|
| -#include "url/gurl.h"
|
| -
|
| -// Default timeout interval for connection setup.
|
| -// Used if not otherwise specified at ConnectInfo::timeout.
|
| -const int kDefaultConnectTimeoutMillis = 5000; // 5 seconds.
|
| -
|
| -namespace extensions {
|
| -
|
| -namespace Close = cast_channel::Close;
|
| -namespace OnError = cast_channel::OnError;
|
| -namespace OnMessage = cast_channel::OnMessage;
|
| -namespace Open = cast_channel::Open;
|
| -namespace Send = cast_channel::Send;
|
| -using cast_channel::CastSocket;
|
| -using cast_channel::ChannelAuthType;
|
| -using cast_channel::ChannelError;
|
| -using cast_channel::ChannelInfo;
|
| -using cast_channel::ConnectInfo;
|
| -using cast_channel::MessageInfo;
|
| -using cast_channel::ReadyState;
|
| -using content::BrowserThread;
|
| -
|
| -namespace {
|
| -
|
| -// T is an extension dictionary (MessageInfo or ChannelInfo)
|
| -template <class T>
|
| -std::string ParamToString(const T& info) {
|
| - scoped_ptr<base::DictionaryValue> dict = info.ToValue();
|
| - std::string out;
|
| - base::JSONWriter::Write(dict.get(), &out);
|
| - return out;
|
| -}
|
| -
|
| -// Fills |channel_info| from the destination and state of |socket|.
|
| -void FillChannelInfo(const CastSocket& socket, ChannelInfo* channel_info) {
|
| - DCHECK(channel_info);
|
| - channel_info->channel_id = socket.id();
|
| - channel_info->url = socket.CastUrl();
|
| - const net::IPEndPoint& ip_endpoint = socket.ip_endpoint();
|
| - channel_info->connect_info.ip_address = ip_endpoint.ToStringWithoutPort();
|
| - channel_info->connect_info.port = ip_endpoint.port();
|
| - channel_info->connect_info.auth = socket.channel_auth();
|
| - channel_info->ready_state = socket.ready_state();
|
| - channel_info->error_state = socket.error_state();
|
| -}
|
| -
|
| -bool IsValidConnectInfoPort(const ConnectInfo& connect_info) {
|
| - return connect_info.port > 0 && connect_info.port <
|
| - std::numeric_limits<unsigned short>::max();
|
| -}
|
| -
|
| -bool IsValidConnectInfoAuth(const ConnectInfo& connect_info) {
|
| - return connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED ||
|
| - connect_info.auth == cast_channel::CHANNEL_AUTH_TYPE_SSL;
|
| -}
|
| -
|
| -bool IsValidConnectInfoIpAddress(const ConnectInfo& connect_info) {
|
| - net::IPAddressNumber ip_address;
|
| - return net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -CastChannelAPI::CastChannelAPI(content::BrowserContext* context)
|
| - : browser_context_(context) {
|
| - DCHECK(browser_context_);
|
| -}
|
| -
|
| -// static
|
| -CastChannelAPI* CastChannelAPI::Get(content::BrowserContext* context) {
|
| - return BrowserContextKeyedAPIFactory<CastChannelAPI>::Get(context);
|
| -}
|
| -
|
| -static base::LazyInstance<BrowserContextKeyedAPIFactory<CastChannelAPI> >
|
| - g_factory = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -// static
|
| -BrowserContextKeyedAPIFactory<CastChannelAPI>*
|
| -CastChannelAPI::GetFactoryInstance() {
|
| - return g_factory.Pointer();
|
| -}
|
| -
|
| -scoped_ptr<CastSocket> CastChannelAPI::CreateCastSocket(
|
| - const std::string& extension_id, const net::IPEndPoint& ip_endpoint,
|
| - ChannelAuthType channel_auth, const base::TimeDelta& timeout) {
|
| - if (socket_for_test_.get()) {
|
| - return socket_for_test_.Pass();
|
| - } else {
|
| - return scoped_ptr<CastSocket>(
|
| - new CastSocket(extension_id, ip_endpoint, channel_auth, this,
|
| - g_browser_process->net_log(),
|
| - timeout));
|
| - }
|
| -}
|
| -
|
| -void CastChannelAPI::SetSocketForTest(scoped_ptr<CastSocket> socket_for_test) {
|
| - socket_for_test_ = socket_for_test.Pass();
|
| -}
|
| -
|
| -void CastChannelAPI::OnError(const CastSocket* socket,
|
| - cast_channel::ChannelError error) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - ChannelInfo channel_info;
|
| - FillChannelInfo(*socket, &channel_info);
|
| - channel_info.error_state = error;
|
| - scoped_ptr<base::ListValue> results = OnError::Create(channel_info);
|
| - scoped_ptr<Event> event(new Event(OnError::kEventName, results.Pass()));
|
| - extensions::EventRouter::Get(browser_context_)
|
| - ->DispatchEventToExtension(socket->owner_extension_id(), event.Pass());
|
| -}
|
| -
|
| -void CastChannelAPI::OnMessage(const CastSocket* socket,
|
| - const MessageInfo& message_info) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - ChannelInfo channel_info;
|
| - FillChannelInfo(*socket, &channel_info);
|
| - scoped_ptr<base::ListValue> results =
|
| - OnMessage::Create(channel_info, message_info);
|
| - VLOG(1) << "Sending message " << ParamToString(message_info)
|
| - << " to channel " << ParamToString(channel_info);
|
| - scoped_ptr<Event> event(new Event(OnMessage::kEventName, results.Pass()));
|
| - extensions::EventRouter::Get(browser_context_)
|
| - ->DispatchEventToExtension(socket->owner_extension_id(), event.Pass());
|
| -}
|
| -
|
| -CastChannelAPI::~CastChannelAPI() {}
|
| -
|
| -CastChannelAsyncApiFunction::CastChannelAsyncApiFunction()
|
| - : manager_(NULL), error_(cast_channel::CHANNEL_ERROR_NONE) { }
|
| -
|
| -CastChannelAsyncApiFunction::~CastChannelAsyncApiFunction() { }
|
| -
|
| -bool CastChannelAsyncApiFunction::PrePrepare() {
|
| - manager_ = ApiResourceManager<CastSocket>::Get(browser_context());
|
| - return true;
|
| -}
|
| -
|
| -bool CastChannelAsyncApiFunction::Respond() {
|
| - return error_ != cast_channel::CHANNEL_ERROR_NONE;
|
| -}
|
| -
|
| -CastSocket* CastChannelAsyncApiFunction::GetSocketOrCompleteWithError(
|
| - int channel_id) {
|
| - CastSocket* socket = GetSocket(channel_id);
|
| - if (!socket) {
|
| - SetResultFromError(cast_channel::CHANNEL_ERROR_INVALID_CHANNEL_ID);
|
| - AsyncWorkCompleted();
|
| - }
|
| - return socket;
|
| -}
|
| -
|
| -int CastChannelAsyncApiFunction::AddSocket(CastSocket* socket) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(socket);
|
| - DCHECK(manager_);
|
| - const int id = manager_->Add(socket);
|
| - socket->set_id(id);
|
| - return id;
|
| -}
|
| -
|
| -void CastChannelAsyncApiFunction::RemoveSocket(int channel_id) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(manager_);
|
| - manager_->Remove(extension_->id(), channel_id);
|
| -}
|
| -
|
| -void CastChannelAsyncApiFunction::SetResultFromSocket(int channel_id) {
|
| - CastSocket* socket = GetSocket(channel_id);
|
| - DCHECK(socket);
|
| - ChannelInfo channel_info;
|
| - FillChannelInfo(*socket, &channel_info);
|
| - error_ = socket->error_state();
|
| - SetResultFromChannelInfo(channel_info);
|
| -}
|
| -
|
| -void CastChannelAsyncApiFunction::SetResultFromError(ChannelError error) {
|
| - ChannelInfo channel_info;
|
| - channel_info.channel_id = -1;
|
| - channel_info.url = "";
|
| - channel_info.ready_state = cast_channel::READY_STATE_CLOSED;
|
| - channel_info.error_state = error;
|
| - SetResultFromChannelInfo(channel_info);
|
| - error_ = error;
|
| -}
|
| -
|
| -CastSocket* CastChannelAsyncApiFunction::GetSocket(int channel_id) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(manager_);
|
| - return manager_->Get(extension_->id(), channel_id);
|
| -}
|
| -
|
| -void CastChannelAsyncApiFunction::SetResultFromChannelInfo(
|
| - const ChannelInfo& channel_info) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - SetResult(channel_info.ToValue().release());
|
| -}
|
| -
|
| -CastChannelOpenFunction::CastChannelOpenFunction()
|
| - : new_channel_id_(0) { }
|
| -
|
| -CastChannelOpenFunction::~CastChannelOpenFunction() { }
|
| -
|
| -// TODO(mfoltz): Remove URL parsing when clients have converted to use
|
| -// ConnectInfo.
|
| -
|
| -// Allowed schemes for Cast device URLs.
|
| -const char kCastInsecureScheme[] = "cast";
|
| -const char kCastSecureScheme[] = "casts";
|
| -
|
| -bool CastChannelOpenFunction::ParseChannelUrl(const GURL& url,
|
| - ConnectInfo* connect_info) {
|
| - DCHECK(connect_info);
|
| - VLOG(2) << "ParseChannelUrl";
|
| - bool auth_required = false;
|
| - if (url.SchemeIs(kCastSecureScheme)) {
|
| - auth_required = true;
|
| - } else if (!url.SchemeIs(kCastInsecureScheme)) {
|
| - return false;
|
| - }
|
| - // TODO(mfoltz): Test for IPv6 addresses. Brackets or no brackets?
|
| - // TODO(mfoltz): Maybe enforce restriction to IPv4 private and IPv6
|
| - // link-local networks
|
| - const std::string& path = url.path();
|
| - // Shortest possible: //A:B
|
| - if (path.size() < 5) {
|
| - return false;
|
| - }
|
| - if (path.find("//") != 0) {
|
| - return false;
|
| - }
|
| - size_t colon = path.find_last_of(':');
|
| - if (colon == std::string::npos || colon < 3 || colon > path.size() - 2) {
|
| - return false;
|
| - }
|
| - const std::string& ip_address_str = path.substr(2, colon - 2);
|
| - const std::string& port_str = path.substr(colon + 1);
|
| - VLOG(2) << "IP: " << ip_address_str << " Port: " << port_str;
|
| - int port;
|
| - if (!base::StringToInt(port_str, &port))
|
| - return false;
|
| - connect_info->ip_address = ip_address_str;
|
| - connect_info->port = port;
|
| - connect_info->auth = auth_required ?
|
| - cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED :
|
| - cast_channel::CHANNEL_AUTH_TYPE_SSL;
|
| - return true;
|
| -}
|
| -
|
| -net::IPEndPoint* CastChannelOpenFunction::ParseConnectInfo(
|
| - const ConnectInfo& connect_info) {
|
| - net::IPAddressNumber ip_address;
|
| - CHECK(net::ParseIPLiteralToNumber(connect_info.ip_address, &ip_address));
|
| - return new net::IPEndPoint(ip_address, connect_info.port);
|
| -}
|
| -
|
| -bool CastChannelOpenFunction::PrePrepare() {
|
| - api_ = CastChannelAPI::Get(browser_context());
|
| - return CastChannelAsyncApiFunction::PrePrepare();
|
| -}
|
| -
|
| -bool CastChannelOpenFunction::Prepare() {
|
| - params_ = Open::Params::Create(*args_);
|
| - EXTENSION_FUNCTION_VALIDATE(params_.get());
|
| - // The connect_info parameter may be a string URL like cast:// or casts:// or
|
| - // a ConnectInfo object.
|
| - std::string cast_url;
|
| - switch (params_->connect_info->GetType()) {
|
| - case base::Value::TYPE_STRING:
|
| - CHECK(params_->connect_info->GetAsString(&cast_url));
|
| - connect_info_.reset(new ConnectInfo);
|
| - if (!ParseChannelUrl(GURL(cast_url), connect_info_.get())) {
|
| - connect_info_.reset();
|
| - SetError("Invalid connect_info (invalid Cast URL " + cast_url + ")");
|
| - }
|
| - break;
|
| - case base::Value::TYPE_DICTIONARY:
|
| - connect_info_ = ConnectInfo::FromValue(*(params_->connect_info));
|
| - if (!connect_info_.get()) {
|
| - SetError("connect_info.auth is required");
|
| - }
|
| - break;
|
| - default:
|
| - SetError("Invalid connect_info (unknown type)");
|
| - break;
|
| - }
|
| - if (!connect_info_.get()) {
|
| - return false;
|
| - }
|
| - if (!IsValidConnectInfoPort(*connect_info_)) {
|
| - SetError("Invalid connect_info (invalid port)");
|
| - } else if (!IsValidConnectInfoAuth(*connect_info_)) {
|
| - SetError("Invalid connect_info (invalid auth)");
|
| - } else if (!IsValidConnectInfoIpAddress(*connect_info_)) {
|
| - SetError("Invalid connect_info (invalid IP address)");
|
| - }
|
| - if (!GetError().empty()) {
|
| - return false;
|
| - }
|
| - channel_auth_ = connect_info_->auth;
|
| - ip_endpoint_.reset(ParseConnectInfo(*connect_info_));
|
| - return true;
|
| -}
|
| -
|
| -void CastChannelOpenFunction::AsyncWorkStart() {
|
| - DCHECK(api_);
|
| - DCHECK(ip_endpoint_.get());
|
| - scoped_ptr<CastSocket> socket = api_->CreateCastSocket(
|
| - extension_->id(),
|
| - *ip_endpoint_,
|
| - channel_auth_,
|
| - base::TimeDelta::FromMilliseconds(connect_info_->timeout.get()
|
| - ? *connect_info_->timeout
|
| - : kDefaultConnectTimeoutMillis));
|
| - new_channel_id_ = AddSocket(socket.release());
|
| - GetSocket(new_channel_id_)->Connect(
|
| - base::Bind(&CastChannelOpenFunction::OnOpen, this));
|
| -}
|
| -
|
| -void CastChannelOpenFunction::OnOpen(int result) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - VLOG(1) << "Connect finished, OnOpen invoked.";
|
| - SetResultFromSocket(new_channel_id_);
|
| - AsyncWorkCompleted();
|
| -}
|
| -
|
| -CastChannelSendFunction::CastChannelSendFunction() { }
|
| -
|
| -CastChannelSendFunction::~CastChannelSendFunction() { }
|
| -
|
| -bool CastChannelSendFunction::Prepare() {
|
| - params_ = Send::Params::Create(*args_);
|
| - EXTENSION_FUNCTION_VALIDATE(params_.get());
|
| - if (params_->message.namespace_.empty()) {
|
| - SetError("message_info.namespace_ is required");
|
| - return false;
|
| - }
|
| - if (params_->message.source_id.empty()) {
|
| - SetError("message_info.source_id is required");
|
| - return false;
|
| - }
|
| - if (params_->message.destination_id.empty()) {
|
| - SetError("message_info.destination_id is required");
|
| - return false;
|
| - }
|
| - switch (params_->message.data->GetType()) {
|
| - case base::Value::TYPE_STRING:
|
| - case base::Value::TYPE_BINARY:
|
| - break;
|
| - default:
|
| - SetError("Invalid type of message_info.data");
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void CastChannelSendFunction::AsyncWorkStart() {
|
| - CastSocket* socket = GetSocketOrCompleteWithError(
|
| - params_->channel.channel_id);
|
| - if (socket)
|
| - socket->SendMessage(params_->message,
|
| - base::Bind(&CastChannelSendFunction::OnSend, this));
|
| -}
|
| -
|
| -void CastChannelSendFunction::OnSend(int result) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (result < 0) {
|
| - SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
|
| - } else {
|
| - SetResultFromSocket(params_->channel.channel_id);
|
| - }
|
| - AsyncWorkCompleted();
|
| -}
|
| -
|
| -CastChannelCloseFunction::CastChannelCloseFunction() { }
|
| -
|
| -CastChannelCloseFunction::~CastChannelCloseFunction() { }
|
| -
|
| -bool CastChannelCloseFunction::Prepare() {
|
| - params_ = Close::Params::Create(*args_);
|
| - EXTENSION_FUNCTION_VALIDATE(params_.get());
|
| - return true;
|
| -}
|
| -
|
| -void CastChannelCloseFunction::AsyncWorkStart() {
|
| - CastSocket* socket = GetSocketOrCompleteWithError(
|
| - params_->channel.channel_id);
|
| - if (socket)
|
| - socket->Close(base::Bind(&CastChannelCloseFunction::OnClose, this));
|
| -}
|
| -
|
| -void CastChannelCloseFunction::OnClose(int result) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - VLOG(1) << "CastChannelCloseFunction::OnClose result = " << result;
|
| - if (result < 0) {
|
| - SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
|
| - } else {
|
| - int channel_id = params_->channel.channel_id;
|
| - SetResultFromSocket(channel_id);
|
| - RemoveSocket(channel_id);
|
| - }
|
| - AsyncWorkCompleted();
|
| -}
|
| -
|
| -} // namespace extensions
|
|
|