blob: 6419a9e594a96362099b22ecc11d465224443cd9 [file] [log] [blame]
// Copyright 2014 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.
#ifndef EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_CHANNEL_API_H_
#define EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_CHANNEL_API_H_
#include <memory>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "components/cast_channel/cast_channel_enum.h"
#include "components/cast_channel/cast_socket.h"
#include "extensions/browser/api/async_api_function.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/api/cast_channel.h"
class CastChannelAPITest;
namespace content {
class BrowserContext;
}
namespace net {
class IPEndPoint;
}
namespace cast_channel {
class CastSocketService;
} // namespace cast_channel
namespace extensions {
struct Event;
class CastChannelAPI : public BrowserContextKeyedAPI,
public EventRouter::Observer,
public base::SupportsWeakPtr<CastChannelAPI> {
public:
explicit CastChannelAPI(content::BrowserContext* context);
static CastChannelAPI* Get(content::BrowserContext* context);
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<CastChannelAPI>* GetFactoryInstance();
// Sets the CastSocket instance to be used for testing.
void SetSocketForTest(
std::unique_ptr<cast_channel::CastSocket> socket_for_test);
// Returns a test CastSocket instance, if it is defined.
// Otherwise returns a scoped_ptr with a nullptr value.
std::unique_ptr<cast_channel::CastSocket> GetSocketForTest();
// Returns the API browser context.
content::BrowserContext* GetBrowserContext() const;
// Sends an event to the extension's EventRouter, if it exists.
void SendEvent(const std::string& extension_id, std::unique_ptr<Event> event);
cast_channel::CastSocketService* cast_socket_service() {
return cast_socket_service_;
}
private:
friend class BrowserContextKeyedAPIFactory<CastChannelAPI>;
friend class ::CastChannelAPITest;
friend class CastTransportDelegate;
// Defines a callback used to send events to the extension's
// EventRouter.
// Parameter #0 is a unique pointer to the event payload.
using EventDispatchCallback = base::Callback<void(std::unique_ptr<Event>)>;
// Receives incoming messages and errors and provides additional API context.
// Created on the UI thread. All methods, including the destructor, must be
// invoked on the SeqeuncedTaskRunner given by |cast_socket_service_|.
class CastMessageHandler : public cast_channel::CastSocket::Observer {
public:
CastMessageHandler(const EventDispatchCallback& ui_dispatch_cb,
cast_channel::CastSocketService* cast_socket_service);
~CastMessageHandler() override;
// Adds |this| as an observer to |cast_socket_service_|.
void Init();
// CastSocket::Observer implementation.
void OnError(const cast_channel::CastSocket& socket,
cast_channel::ChannelError error_state) override;
void OnMessage(const cast_channel::CastSocket& socket,
const cast_channel::CastMessage& message) override;
private:
// Callback for sending events to the extension.
// Should be bound to a weak pointer, to prevent any use-after-free
// conditions.
EventDispatchCallback const ui_dispatch_cb_;
// The CastSocketService to observe.
cast_channel::CastSocketService* const cast_socket_service_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(CastMessageHandler);
};
~CastChannelAPI() override;
// EventRouter::Observer:
void OnListenerAdded(const EventListenerInfo& details) override;
void OnListenerRemoved(const EventListenerInfo& details) override;
// BrowserContextKeyedAPI implementation.
static const char* service_name() { return "CastChannelAPI"; }
static const bool kServiceIsNULLWhileTesting = true;
content::BrowserContext* const browser_context_;
std::unique_ptr<cast_channel::CastSocket> socket_for_test_;
// Created on UI thread, accessed and destroyed on |cast_socket_service_|'s
// task runner.
std::unique_ptr<CastMessageHandler> message_handler_;
cast_channel::CastSocketService* const cast_socket_service_;
DISALLOW_COPY_AND_ASSIGN(CastChannelAPI);
};
template <>
void BrowserContextKeyedAPIFactory<
CastChannelAPI>::DeclareFactoryDependencies();
class CastChannelAsyncApiFunction : public AsyncApiFunction {
public:
CastChannelAsyncApiFunction();
protected:
~CastChannelAsyncApiFunction() override;
// AsyncApiFunction:
bool PrePrepare() override;
bool Respond() override;
// Sets the function result to a ChannelInfo obtained from the state of
// |socket|.
void SetResultFromSocket(const cast_channel::CastSocket& socket);
// Sets the function result to a ChannelInfo populated with |channel_id| and
// |error|.
void SetResultFromError(int channel_id,
api::cast_channel::ChannelError error);
// Raw pointer of leaky singleton CastSocketService, which manages creating
// and removing Cast sockets.
cast_channel::CastSocketService* cast_socket_service_;
private:
// Sets the function result from |channel_info|.
void SetResultFromChannelInfo(
const api::cast_channel::ChannelInfo& channel_info);
};
class CastChannelOpenFunction : public CastChannelAsyncApiFunction {
public:
CastChannelOpenFunction();
protected:
~CastChannelOpenFunction() override;
// AsyncApiFunction:
bool PrePrepare() override;
bool Prepare() override;
void AsyncWorkStart() override;
private:
DECLARE_EXTENSION_FUNCTION("cast.channel.open", CAST_CHANNEL_OPEN)
// Validates that |connect_info| represents a valid IP end point and returns a
// new IPEndPoint if so. Otherwise returns nullptr.
static net::IPEndPoint* ParseConnectInfo(
const api::cast_channel::ConnectInfo& connect_info);
// |socket|: raw pointer of newly created cast channel. Does not take
// ownership of |socket|.
void OnOpen(cast_channel::CastSocket* socket);
std::unique_ptr<api::cast_channel::Open::Params> params_;
CastChannelAPI* api_;
std::unique_ptr<net::IPEndPoint> ip_endpoint_;
base::TimeDelta liveness_timeout_;
base::TimeDelta ping_interval_;
FRIEND_TEST_ALL_PREFIXES(CastChannelOpenFunctionTest, TestParseConnectInfo);
DISALLOW_COPY_AND_ASSIGN(CastChannelOpenFunction);
};
class CastChannelSendFunction : public CastChannelAsyncApiFunction {
public:
CastChannelSendFunction();
protected:
~CastChannelSendFunction() override;
// AsyncApiFunction:
bool Prepare() override;
void AsyncWorkStart() override;
private:
DECLARE_EXTENSION_FUNCTION("cast.channel.send", CAST_CHANNEL_SEND)
void OnSend(int result);
std::unique_ptr<api::cast_channel::Send::Params> params_;
DISALLOW_COPY_AND_ASSIGN(CastChannelSendFunction);
};
class CastChannelCloseFunction : public CastChannelAsyncApiFunction {
public:
CastChannelCloseFunction();
protected:
~CastChannelCloseFunction() override;
// AsyncApiFunction:
bool PrePrepare() override;
bool Prepare() override;
void AsyncWorkStart() override;
private:
DECLARE_EXTENSION_FUNCTION("cast.channel.close", CAST_CHANNEL_CLOSE)
void OnClose(int result);
std::unique_ptr<api::cast_channel::Close::Params> params_;
DISALLOW_COPY_AND_ASSIGN(CastChannelCloseFunction);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_CAST_CHANNEL_CAST_CHANNEL_API_H_