summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authordavve <davve@opera.com>2015-12-11 04:05:22 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-11 12:06:48 +0000
commit2536c36bebcb87fa8b2f18bd4da9b9951eb63607 (patch)
tree904dcc4dde5adfad4b6ea7c843659faabbd61415 /content
parent9f815753bd4c99e2209965cf8ac724aa0803db45 (diff)
downloadchromium_src-2536c36bebcb87fa8b2f18bd4da9b9951eb63607.zip
chromium_src-2536c36bebcb87fa8b2f18bd4da9b9951eb63607.tar.gz
chromium_src-2536c36bebcb87fa8b2f18bd4da9b9951eb63607.tar.bz2
Hook up RendererMediaSessionManager with browser side
Implements the basic IPC messages for activation and deactivation back and forth. The browser side is still unimplemented. BUG=497735 Review URL: https://codereview.chromium.org/1441883003 Cr-Commit-Position: refs/heads/master@{#364673}
Diffstat (limited to 'content')
-rw-r--r--content/browser/media/android/browser_media_session_manager.cc34
-rw-r--r--content/browser/media/android/browser_media_session_manager.h38
-rw-r--r--content/browser/media/media_web_contents_observer.cc21
-rw-r--r--content/browser/media/media_web_contents_observer.h10
-rw-r--r--content/common/content_message_generator.h1
-rw-r--r--content/common/media/media_session_messages_android.h33
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/renderer/media/android/renderer_media_session_manager.cc46
-rw-r--r--content/renderer/media/android/renderer_media_session_manager.h22
-rw-r--r--content/renderer/media/android/webmediasession_android.cc14
-rw-r--r--content/renderer/media/android/webmediasession_android_unittest.cc166
12 files changed, 378 insertions, 10 deletions
diff --git a/content/browser/media/android/browser_media_session_manager.cc b/content/browser/media/android/browser_media_session_manager.cc
new file mode 100644
index 0000000..146a60fe
--- /dev/null
+++ b/content/browser/media/android/browser_media_session_manager.cc
@@ -0,0 +1,34 @@
+// Copyright 2015 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 "content/browser/media/android/browser_media_session_manager.h"
+
+#include "content/common/media/media_session_messages_android.h"
+#include "content/public/browser/render_frame_host.h"
+
+namespace content {
+
+BrowserMediaSessionManager::BrowserMediaSessionManager(
+ RenderFrameHost* render_frame_host)
+ : render_frame_host_(render_frame_host) {}
+
+void BrowserMediaSessionManager::OnActivate(int session_id, int request_id) {
+ NOTIMPLEMENTED();
+ Send(new MediaSessionMsg_DidActivate(GetRoutingID(), request_id, false));
+}
+
+void BrowserMediaSessionManager::OnDeactivate(int session_id, int request_id) {
+ NOTIMPLEMENTED();
+ Send(new MediaSessionMsg_DidDeactivate(GetRoutingID(), request_id));
+}
+
+int BrowserMediaSessionManager::GetRoutingID() const {
+ return render_frame_host_->GetRoutingID();
+}
+
+bool BrowserMediaSessionManager::Send(IPC::Message* msg) {
+ return render_frame_host_->Send(msg);
+}
+
+} // namespace content
diff --git a/content/browser/media/android/browser_media_session_manager.h b/content/browser/media/android/browser_media_session_manager.h
new file mode 100644
index 0000000..c03bf1b
--- /dev/null
+++ b/content/browser/media/android/browser_media_session_manager.h
@@ -0,0 +1,38 @@
+// Copyright 2015 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 CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_
+
+#include "base/basictypes.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+
+class RenderFrameHost;
+
+class BrowserMediaSessionManager {
+ public:
+ BrowserMediaSessionManager(RenderFrameHost* render_frame_host);
+
+ // Message handlers.
+ void OnActivate(int session_id, int request_id);
+ void OnDeactivate(int session_id, int request_id);
+
+ int GetRoutingID() const;
+
+ bool Send(IPC::Message* msg);
+
+ private:
+ RenderFrameHost* const render_frame_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserMediaSessionManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index dc79efa..42dcf93 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -16,7 +16,9 @@
#if defined(OS_ANDROID)
#include "content/browser/media/android/browser_media_player_manager.h"
+#include "content/browser/media/android/browser_media_session_manager.h"
#include "content/common/media/media_player_messages_android.h"
+#include "content/common/media/media_session_messages_android.h"
#include "media/base/android/media_player_android.h"
#endif // defined(OS_ANDROID)
@@ -35,6 +37,7 @@ void MediaWebContentsObserver::RenderFrameDeleted(
// Always destroy the media players before CDMs because we do not support
// detaching CDMs from media players yet. See http://crbug.com/330324
media_player_managers_.erase(render_frame_host);
+ media_session_managers_.erase(render_frame_host);
// TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager
// and BrowserCdmManager all run on browser UI thread. So this call is okay.
@@ -295,6 +298,12 @@ bool MediaWebContentsObserver::OnMediaPlayerMessageReceived(
GetMediaPlayerManager(render_frame_host),
BrowserMediaPlayerManager::OnNotifyExternalSurface)
#endif // defined(VIDEO_HOLE)
+ IPC_MESSAGE_FORWARD(MediaSessionHostMsg_Activate,
+ GetMediaSessionManager(render_frame_host),
+ BrowserMediaSessionManager::OnActivate)
+ IPC_MESSAGE_FORWARD(MediaSessionHostMsg_Deactivate,
+ GetMediaSessionManager(render_frame_host),
+ BrowserMediaSessionManager::OnDeactivate)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -354,6 +363,18 @@ BrowserMediaPlayerManager* MediaWebContentsObserver::GetMediaPlayerManager(
return manager;
}
+BrowserMediaSessionManager* MediaWebContentsObserver::GetMediaSessionManager(
+ RenderFrameHost* render_frame_host) {
+ auto it = media_session_managers_.find(render_frame_host);
+ if (it != media_session_managers_.end())
+ return it->second;
+
+ BrowserMediaSessionManager* manager =
+ new BrowserMediaSessionManager(render_frame_host);
+ media_session_managers_.set(render_frame_host, make_scoped_ptr(manager));
+ return manager;
+}
+
#if defined(VIDEO_HOLE)
void MediaWebContentsObserver::OnFrameInfoUpdated() {
for (auto it = media_player_managers_.begin();
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h
index 0a24913..4af84a4 100644
--- a/content/browser/media/media_web_contents_observer.h
+++ b/content/browser/media/media_web_contents_observer.h
@@ -19,6 +19,7 @@ namespace content {
class BrowserCdmManager;
class BrowserMediaPlayerManager;
+class BrowserMediaSessionManager;
// This class manages all RenderFrame based media related managers at the
// browser side. It receives IPC messages from media RenderFrameObservers and
@@ -46,6 +47,9 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
BrowserMediaPlayerManager* GetMediaPlayerManager(
RenderFrameHost* render_frame_host);
+ BrowserMediaSessionManager* GetMediaSessionManager(
+ RenderFrameHost* render_frame_host);
+
#if defined(VIDEO_HOLE)
void OnFrameInfoUpdated();
#endif // defined(VIDEO_HOLE)
@@ -113,6 +117,12 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
base::ScopedPtrHashMap<RenderFrameHost*,
scoped_ptr<BrowserMediaPlayerManager>>;
MediaPlayerManagerMap media_player_managers_;
+
+ // Map from RenderFrameHost* to BrowserMediaSessionManager.
+ using MediaSessionManagerMap =
+ base::ScopedPtrHashMap<RenderFrameHost*,
+ scoped_ptr<BrowserMediaSessionManager>>;
+ MediaSessionManagerMap media_session_managers_;
#endif // defined(OS_ANDROID)
// Tracking variables and associated power save blockers for media playback.
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index aa7d25c..a3b31ad 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -72,4 +72,5 @@
#include "content/common/android/sync_compositor_messages.h"
#include "content/common/gin_java_bridge_messages.h"
#include "content/common/media/media_player_messages_android.h"
+#include "content/common/media/media_session_messages_android.h"
#endif // defined(OS_ANDROID)
diff --git a/content/common/media/media_session_messages_android.h b/content/common/media/media_session_messages_android.h
new file mode 100644
index 0000000..3ea4a7e
--- /dev/null
+++ b/content/common/media/media_session_messages_android.h
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+// IPC messages for the Media Session API.
+// Multiply-included message file, hence no include guard.
+
+#include "base/basictypes.h"
+#include "content/common/android/gin_java_bridge_errors.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START MediaSessionMsgStart
+
+// Messages for notifying the render process of media session status -------
+
+IPC_MESSAGE_ROUTED2(MediaSessionMsg_DidActivate,
+ int /* request_id */,
+ bool /* success */)
+
+IPC_MESSAGE_ROUTED1(MediaSessionMsg_DidDeactivate, int /* request_id */)
+
+// Messages for controlling the media session in browser process ----------
+
+IPC_MESSAGE_ROUTED2(MediaSessionHostMsg_Activate,
+ int /* session_id */,
+ int /* request_id */)
+
+IPC_MESSAGE_ROUTED2(MediaSessionHostMsg_Deactivate,
+ int /* session_id */,
+ int /* request_id */)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index d708336..6cea7d4 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -980,6 +980,8 @@
'browser/media/android/browser_demuxer_android.h',
'browser/media/android/browser_media_player_manager.cc',
'browser/media/android/browser_media_player_manager.h',
+ 'browser/media/android/browser_media_session_manager.cc',
+ 'browser/media/android/browser_media_session_manager.h',
'browser/media/android/media_resource_getter_impl.cc',
'browser/media/android/media_resource_getter_impl.h',
'browser/media/android/media_session.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index b809c35..d1fb8a7 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -428,6 +428,7 @@
'common/media/media_param_traits.h',
'common/media/media_player_messages_android.h',
'common/media/media_player_messages_enums_android.h',
+ 'common/media/media_session_messages_android.h',
'common/media/media_stream_messages.h',
'common/media/media_stream_options.cc',
'common/media/media_stream_options.h',
diff --git a/content/renderer/media/android/renderer_media_session_manager.cc b/content/renderer/media/android/renderer_media_session_manager.cc
index c39c0dc..58b0888 100644
--- a/content/renderer/media/android/renderer_media_session_manager.cc
+++ b/content/renderer/media/android/renderer_media_session_manager.cc
@@ -5,6 +5,8 @@
#include "content/renderer/media/android/renderer_media_session_manager.h"
#include "base/logging.h"
+#include "content/common/media/media_session_messages_android.h"
+#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/android/webmediasession_android.h"
namespace content {
@@ -22,6 +24,16 @@ RendererMediaSessionManager::~RendererMediaSessionManager() {
"destroyed only after all media sessions are destroyed.";
}
+bool RendererMediaSessionManager::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RendererMediaSessionManager, msg)
+ IPC_MESSAGE_HANDLER(MediaSessionMsg_DidActivate, OnDidActivate)
+ IPC_MESSAGE_HANDLER(MediaSessionMsg_DidDeactivate, OnDidDeactivate)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
int RendererMediaSessionManager::RegisterMediaSession(
WebMediaSessionAndroid* session) {
sessions_[next_session_id_] = session;
@@ -32,4 +44,38 @@ void RendererMediaSessionManager::UnregisterMediaSession(int session_id) {
sessions_.erase(session_id);
}
+void RendererMediaSessionManager::Activate(
+ int session_id,
+ scoped_ptr<blink::WebMediaSessionActivateCallback> callback) {
+ int request_id = pending_activation_requests_.Add(callback.release());
+ Send(new MediaSessionHostMsg_Activate(routing_id(), session_id, request_id));
+}
+
+void RendererMediaSessionManager::Deactivate(
+ int session_id,
+ scoped_ptr<blink::WebMediaSessionDeactivateCallback> callback) {
+ int request_id = pending_deactivation_requests_.Add(callback.release());
+ Send(
+ new MediaSessionHostMsg_Deactivate(routing_id(), session_id, request_id));
+}
+
+void RendererMediaSessionManager::OnDidActivate(int request_id, bool success) {
+ DCHECK(pending_activation_requests_.Lookup(request_id)) << request_id;
+ blink::WebMediaSessionActivateCallback* callback =
+ pending_activation_requests_.Lookup(request_id);
+ if (success) {
+ callback->onSuccess();
+ } else {
+ callback->onError(
+ blink::WebMediaSessionError(blink::WebMediaSessionError::Activate));
+ }
+ pending_activation_requests_.Remove(request_id);
+}
+
+void RendererMediaSessionManager::OnDidDeactivate(int request_id) {
+ DCHECK(pending_deactivation_requests_.Lookup(request_id)) << request_id;
+ pending_deactivation_requests_.Lookup(request_id)->onSuccess();
+ pending_deactivation_requests_.Remove(request_id);
+}
+
} // namespace content
diff --git a/content/renderer/media/android/renderer_media_session_manager.h b/content/renderer/media/android/renderer_media_session_manager.h
index f07b230c..c7f7504 100644
--- a/content/renderer/media/android/renderer_media_session_manager.h
+++ b/content/renderer/media/android/renderer_media_session_manager.h
@@ -7,9 +7,11 @@
#include <map>
+#include "base/id_map.h"
#include "base/macros.h"
#include "content/common/content_export.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "third_party/WebKit/public/platform/modules/mediasession/WebMediaSession.h"
namespace content {
@@ -20,15 +22,35 @@ class CONTENT_EXPORT RendererMediaSessionManager : public RenderFrameObserver {
RendererMediaSessionManager(RenderFrame* render_frame);
~RendererMediaSessionManager() override;
+ // RenderFrameObserver override.
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
int RegisterMediaSession(WebMediaSessionAndroid* session);
void UnregisterMediaSession(int session_id);
+ void Activate(int session_id,
+ scoped_ptr<blink::WebMediaSessionActivateCallback> callback);
+ void Deactivate(
+ int session_id,
+ scoped_ptr<blink::WebMediaSessionDeactivateCallback> callback);
+
+ void OnDidActivate(int request_id, bool success);
+ void OnDidDeactivate(int request_id);
+
private:
friend class WebMediaSessionTest;
std::map<int, WebMediaSessionAndroid*> sessions_;
int next_session_id_;
+ using ActivationRequests =
+ IDMap<blink::WebMediaSessionActivateCallback, IDMapOwnPointer>;
+ ActivationRequests pending_activation_requests_;
+
+ using DeactivationRequests =
+ IDMap<blink::WebMediaSessionDeactivateCallback, IDMapOwnPointer>;
+ DeactivationRequests pending_deactivation_requests_;
+
DISALLOW_COPY_AND_ASSIGN(RendererMediaSessionManager);
};
diff --git a/content/renderer/media/android/webmediasession_android.cc b/content/renderer/media/android/webmediasession_android.cc
index 7eddd31..b10d5f2 100644
--- a/content/renderer/media/android/webmediasession_android.cc
+++ b/content/renderer/media/android/webmediasession_android.cc
@@ -22,19 +22,13 @@ WebMediaSessionAndroid::~WebMediaSessionAndroid() {
}
void WebMediaSessionAndroid::activate(
- blink::WebMediaSessionActivateCallback* raw_callback) {
- NOTIMPLEMENTED();
-
- scoped_ptr<blink::WebMediaSessionActivateCallback> callback(raw_callback);
- callback->onError(blink::WebMediaSessionError::Activate);
+ blink::WebMediaSessionActivateCallback* callback) {
+ session_manager_->Activate(session_id_, make_scoped_ptr(callback));
}
void WebMediaSessionAndroid::deactivate(
- blink::WebMediaSessionDeactivateCallback* raw_callback) {
- NOTIMPLEMENTED();
-
- scoped_ptr<blink::WebMediaSessionDeactivateCallback> callback(raw_callback);
- callback->onSuccess();
+ blink::WebMediaSessionDeactivateCallback* callback) {
+ session_manager_->Deactivate(session_id_, make_scoped_ptr(callback));
}
void WebMediaSessionAndroid::setMetadata(
diff --git a/content/renderer/media/android/webmediasession_android_unittest.cc b/content/renderer/media/android/webmediasession_android_unittest.cc
index fb153f7..69e8138 100644
--- a/content/renderer/media/android/webmediasession_android_unittest.cc
+++ b/content/renderer/media/android/webmediasession_android_unittest.cc
@@ -5,13 +5,23 @@
#include "content/renderer/media/android/webmediasession_android.h"
#include "base/memory/scoped_ptr.h"
+#include "content/common/media/media_session_messages_android.h"
#include "content/renderer/media/android/renderer_media_session_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace content {
+namespace {
+
+const int kRouteId = 0;
+
+} // anonymous namespace
+
class WebMediaSessionTest : public testing::Test {
public:
+ void OnSuccess() { ++success_count_; }
+ void OnError() { ++error_count_; }
+
bool SessionManagerHasSession(RendererMediaSessionManager* session_manager,
WebMediaSessionAndroid* session) {
for (auto& iter : session_manager->sessions_) {
@@ -24,6 +34,34 @@ class WebMediaSessionTest : public testing::Test {
bool IsSessionManagerEmpty(RendererMediaSessionManager* session_manager) {
return session_manager->sessions_.empty();
}
+
+ protected:
+ int success_count_ = 0;
+ int error_count_ = 0;
+};
+
+class TestActivateCallback : public blink::WebMediaSessionActivateCallback {
+ public:
+ TestActivateCallback(WebMediaSessionTest* test) : test_(test) {}
+
+ private:
+ void onSuccess() override { test_->OnSuccess(); }
+ void onError(const blink::WebMediaSessionError&) override {
+ test_->OnError();
+ }
+
+ WebMediaSessionTest* test_;
+};
+
+class TestDeactivateCallback : public blink::WebMediaSessionDeactivateCallback {
+ public:
+ TestDeactivateCallback(WebMediaSessionTest* test) : test_(test) {}
+
+ private:
+ void onSuccess() override { test_->OnSuccess(); }
+ void onError() override { test_->OnError(); }
+
+ WebMediaSessionTest* test_;
};
TEST_F(WebMediaSessionTest, TestRegistration) {
@@ -83,4 +121,132 @@ TEST_F(WebMediaSessionTest, TestMultipleRegistrationOutOfOrder) {
EXPECT_TRUE(IsSessionManagerEmpty(session_manager.get()));
}
+TEST_F(WebMediaSessionTest, ActivationOutOfOrder) {
+ scoped_ptr<RendererMediaSessionManager> session_manager(
+ new RendererMediaSessionManager(nullptr));
+
+ scoped_ptr<WebMediaSessionAndroid> session(
+ new WebMediaSessionAndroid(session_manager.get()));
+
+ // Request activate three times
+ session->activate(new TestActivateCallback(this)); // request 1
+ session->activate(new TestActivateCallback(this)); // request 2
+ session->activate(new TestActivateCallback(this)); // request 3
+
+ // Confirm activation out of order
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 3, true));
+
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 2, true));
+
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 1, true));
+
+ EXPECT_EQ(3, success_count_);
+ EXPECT_EQ(0, error_count_);
+}
+
+TEST_F(WebMediaSessionTest, ActivationInOrder) {
+ scoped_ptr<RendererMediaSessionManager> session_manager(
+ new RendererMediaSessionManager(nullptr));
+
+ scoped_ptr<WebMediaSessionAndroid> session(
+ new WebMediaSessionAndroid(session_manager.get()));
+
+ // Request activate three times
+ session->activate(new TestActivateCallback(this)); // request 1
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 1, true));
+
+ session->activate(new TestActivateCallback(this)); // request 2
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 2, true));
+
+ session->activate(new TestActivateCallback(this)); // request 3
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 3, true));
+
+ EXPECT_EQ(3, success_count_);
+ EXPECT_EQ(0, error_count_);
+}
+
+TEST_F(WebMediaSessionTest, ActivationInFlight) {
+ scoped_ptr<RendererMediaSessionManager> session_manager(
+ new RendererMediaSessionManager(nullptr));
+
+ scoped_ptr<WebMediaSessionAndroid> session(
+ new WebMediaSessionAndroid(session_manager.get()));
+
+ session->activate(new TestActivateCallback(this)); // request 1
+ session->activate(new TestActivateCallback(this)); // request 2
+ session->activate(new TestActivateCallback(this)); // request 3
+
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 1, true));
+
+ session->activate(new TestActivateCallback(this)); // request 4
+ session->activate(new TestActivateCallback(this)); // request 5
+
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 3, true));
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 2, true));
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 5, true));
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 4, true));
+
+ EXPECT_EQ(5, success_count_);
+ EXPECT_EQ(0, error_count_);
+}
+
+TEST_F(WebMediaSessionTest, ActivationFailure) {
+ scoped_ptr<RendererMediaSessionManager> session_manager(
+ new RendererMediaSessionManager(nullptr));
+
+ scoped_ptr<WebMediaSessionAndroid> session(
+ new WebMediaSessionAndroid(session_manager.get()));
+
+ session->activate(new TestActivateCallback(this)); // request 1
+ session->activate(new TestActivateCallback(this)); // request 2
+ session->activate(new TestActivateCallback(this)); // request 3
+
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 1, true));
+ EXPECT_EQ(1, success_count_);
+ EXPECT_EQ(0, error_count_);
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 2, false));
+ EXPECT_EQ(1, success_count_);
+ EXPECT_EQ(1, error_count_);
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidActivate(kRouteId, 3, true));
+ EXPECT_EQ(2, success_count_);
+ EXPECT_EQ(1, error_count_);
+}
+
+TEST_F(WebMediaSessionTest, Deactivation) {
+ scoped_ptr<RendererMediaSessionManager> session_manager(
+ new RendererMediaSessionManager(nullptr));
+
+ scoped_ptr<WebMediaSessionAndroid> session(
+ new WebMediaSessionAndroid(session_manager.get()));
+
+ // Request deactivate three times
+ session->deactivate(new TestDeactivateCallback(this)); // request 1
+ session->deactivate(new TestDeactivateCallback(this)); // request 2
+ session->deactivate(new TestDeactivateCallback(this)); // request 3
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidDeactivate(kRouteId, 1));
+ EXPECT_EQ(1, success_count_);
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidDeactivate(kRouteId, 2));
+ EXPECT_EQ(2, success_count_);
+ session_manager->OnMessageReceived(
+ MediaSessionMsg_DidDeactivate(kRouteId, 3));
+ EXPECT_EQ(3, success_count_);
+ EXPECT_EQ(0, error_count_);
+}
+
} // namespace content