summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortguilbert <tguilbert@chromium.org>2016-09-21 04:11:41 (GMT)
committerCommit bot <commit-bot@chromium.org>2016-09-21 04:15:49 (GMT)
commitf08485bfd9514a905dda4ca23eca02e4f1f3d72c (patch)
treef25424b58ae5d1c6c45566b1946530a7e7dd0c58
parent5f34c35d0c98b88cf71e25e5215288d97b258735 (diff)
downloadchromium-lkgr.tar.gz
chromium-lkgr.tar.xz
Add ScopedSurfaceRequestManagerlkgr
WebMediaPlayerAndroid (WMPA) used the EstablishSurfacePeer construct and the BrowserMediaPlayerManager to send a SurfaceTexture from the GPU process to a MediaPlayer in the BrowserProcess. MediaPlayerRender does not use a BrowserMediaPlayerManager, but needs a way to receive surface textures from the GPU. This change introduces the ScopedSurfaceRequestManager and the ScopedSurfaceRequestConduit. The Manager allows the registration of a callback in the Browser process, which can receive a ScopedJavaSurface. Upon registration, the manager creates a token that can be used at a later time to fulfill the request. The Conduit forwards surface texture to the Manager, using the issued token to route the ScopedJavaSurface to the right request. From the GPU process, surfaces are sent via the ChildProcessServices and the IChildProcessCallback, the same way that EstablishSurfacePeer currently does. In single process mode, the Manager directly implements the Conduit interface. Security recommended 128 bits as the token size. It is represented by base::Nonce class, which supports serialization accross IPC and Mojo, and is easy to send as two uint64_t through JNI and AIDL. The CL that covers the integration within StreamTexture and MediaPlayerRenderer is tracked by the same bug, and can be found at https://codereview.chromium.org/2282633002/. Adding palmer@ as TBR, since he is the only owner for aidl files, but is unavailable ATM. TBR=palmer BUG=627658 TEST=Added UTs, manually verified that it worked in the prototype. CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel Review-Url: https://codereview.chromium.org/2285593002 Cr-Commit-Position: refs/heads/master@{#419971}
-rw-r--r--content/app/android/child_process_service_impl.cc18
-rw-r--r--content/browser/BUILD.gn2
-rw-r--r--content/browser/android/child_process_launcher_android.cc21
-rw-r--r--content/browser/android/scoped_surface_request_manager.cc90
-rw-r--r--content/browser/android/scoped_surface_request_manager.h84
-rw-r--r--content/browser/android/scoped_surface_request_manager_unittest.cc186
-rw-r--r--content/browser/browser_main_loop.cc3
-rw-r--r--content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java21
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java15
-rw-r--r--content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl3
-rw-r--r--content/test/BUILD.gn1
-rw-r--r--gpu/ipc/common/BUILD.gn2
-rw-r--r--gpu/ipc/common/android/scoped_surface_request_conduit.cc29
-rw-r--r--gpu/ipc/common/android/scoped_surface_request_conduit.h39
14 files changed, 514 insertions, 0 deletions
diff --git a/content/app/android/child_process_service_impl.cc b/content/app/android/child_process_service_impl.cc
index 99ae3f8..083c320 100644
--- a/content/app/android/child_process_service_impl.cc
+++ b/content/app/android/child_process_service_impl.cc
@@ -13,8 +13,10 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/posix/global_descriptors.h"
+#include "base/unguessable_token.h"
#include "content/child/child_thread_impl.h"
#include "content/public/common/content_descriptors.h"
+#include "gpu/ipc/common/android/scoped_surface_request_conduit.h"
#include "gpu/ipc/common/android/surface_texture_manager.h"
#include "gpu/ipc/common/android/surface_texture_peer.h"
#include "gpu/ipc/common/gpu_surface_lookup.h"
@@ -35,6 +37,7 @@ namespace {
// we're in a renderer or gpu process.
class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
public gpu::SurfaceTexturePeer,
+ public gpu::ScopedSurfaceRequestConduit,
public gpu::GpuSurfaceLookup {
public:
// |service impl| is the instance of
@@ -44,10 +47,12 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
: service_impl_(service_impl) {
SurfaceTexturePeer::InitInstance(this);
gpu::GpuSurfaceLookup::InitInstance(this);
+ gpu::ScopedSurfaceRequestConduit::SetInstance(this);
}
~SurfaceTextureManagerImpl() override {
SurfaceTexturePeer::InitInstance(NULL);
gpu::GpuSurfaceLookup::InitInstance(NULL);
+ gpu::ScopedSurfaceRequestConduit::SetInstance(nullptr);
}
// Overridden from SurfaceTextureManager:
@@ -97,6 +102,19 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
primary_id, secondary_id);
}
+ // Overriden from ScopedSurfaceRequestConduit:
+ void ForwardSurfaceTextureForSurfaceRequest(
+ const base::UnguessableToken& request_token,
+ const gl::SurfaceTexture* surface_texture) override {
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ content::
+ Java_ChildProcessServiceImpl_forwardSurfaceTextureForSurfaceRequest(
+ env, service_impl_, request_token.GetHighForSerialization(),
+ request_token.GetLowForSerialization(),
+ surface_texture->j_surface_texture());
+ }
+
// Overridden from GpuSurfaceLookup:
gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 4984e4d..c61f691 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -205,6 +205,8 @@ source_set("browser") {
"android/interface_registry_android_impl.h",
"android/java_interfaces_impl.cc",
"android/java_interfaces_impl.h",
+ "android/scoped_surface_request_manager.cc",
+ "android/scoped_surface_request_manager.h",
"android/url_request_content_job.cc",
"android/url_request_content_job.h",
"appcache/appcache.cc",
diff --git a/content/browser/android/child_process_launcher_android.cc b/content/browser/android/child_process_launcher_android.cc
index e66ed00..f3ae448 100644
--- a/content/browser/android/child_process_launcher_android.cc
+++ b/content/browser/android/child_process_launcher_android.cc
@@ -14,6 +14,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/logging.h"
+#include "content/browser/android/scoped_surface_request_manager.h"
#include "content/browser/file_descriptor_info_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
@@ -237,6 +238,26 @@ void EstablishSurfacePeer(JNIEnv* env,
&SetSurfacePeer, jsurface, pid, primary_id, secondary_id));
}
+void CompleteScopedSurfaceRequest(JNIEnv* env,
+ const JavaParamRef<jclass>& clazz,
+ jlong request_token_high,
+ jlong request_token_low,
+ const JavaParamRef<jobject>& surface) {
+ if (request_token_high == 0 && request_token_low == 0) {
+ DLOG(ERROR) << "Received invalid surface request token.";
+ return;
+ }
+
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ ScopedJavaGlobalRef<jobject> jsurface;
+ jsurface.Reset(env, surface);
+ ScopedSurfaceRequestManager::GetInstance()->FulfillScopedSurfaceRequest(
+ base::UnguessableToken::Deserialize(request_token_high,
+ request_token_low),
+ gl::ScopedJavaSurface(jsurface));
+}
+
void RegisterViewSurface(int surface_id, const JavaRef<jobject>& j_surface) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
diff --git a/content/browser/android/scoped_surface_request_manager.cc b/content/browser/android/scoped_surface_request_manager.cc
new file mode 100644
index 0000000..0a092c5
--- /dev/null
+++ b/content/browser/android/scoped_surface_request_manager.cc
@@ -0,0 +1,90 @@
+// Copyright 2016 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/android/scoped_surface_request_manager.h"
+
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+// static
+ScopedSurfaceRequestManager* ScopedSurfaceRequestManager::GetInstance() {
+ return base::Singleton<
+ ScopedSurfaceRequestManager,
+ base::LeakySingletonTraits<ScopedSurfaceRequestManager>>::get();
+}
+
+base::UnguessableToken
+ScopedSurfaceRequestManager::RegisterScopedSurfaceRequest(
+ const ScopedSurfaceRequestCB& request_cb) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!request_cb.is_null());
+
+ base::UnguessableToken request_token = base::UnguessableToken::Create();
+
+ DCHECK(!request_callbacks_.count(request_token));
+ request_callbacks_.insert(std::make_pair(request_token, request_cb));
+
+ return request_token;
+}
+
+void ScopedSurfaceRequestManager::UnregisterScopedSurfaceRequest(
+ const base::UnguessableToken& request_token) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ GetAndUnregisterInternal(request_token);
+}
+
+ScopedSurfaceRequestManager::ScopedSurfaceRequestCB
+ScopedSurfaceRequestManager::GetAndUnregisterInternal(
+ const base::UnguessableToken& request_token) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!request_token.is_empty());
+
+ ScopedSurfaceRequestManager::ScopedSurfaceRequestCB request;
+
+ auto it = request_callbacks_.find(request_token);
+ if (it != request_callbacks_.end()) {
+ request = it->second;
+ request_callbacks_.erase(it);
+ }
+
+ return request;
+}
+
+void ScopedSurfaceRequestManager::ForwardSurfaceTextureForSurfaceRequest(
+ const base::UnguessableToken& request_token,
+ const gl::SurfaceTexture* surface_texture) {
+ FulfillScopedSurfaceRequest(request_token,
+ gl::ScopedJavaSurface(surface_texture));
+}
+
+void ScopedSurfaceRequestManager::FulfillScopedSurfaceRequest(
+ const base::UnguessableToken& request_token,
+ gl::ScopedJavaSurface surface) {
+ // base::Unretained is safe because the lifetime of this object is tied to
+ // the lifetime of the browser process.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&ScopedSurfaceRequestManager::CompleteRequestOnUiThread,
+ base::Unretained(this), request_token,
+ base::Passed(&surface)));
+}
+
+void ScopedSurfaceRequestManager::CompleteRequestOnUiThread(
+ const base::UnguessableToken& request_token,
+ gl::ScopedJavaSurface surface) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ ScopedSurfaceRequestManager::ScopedSurfaceRequestCB request =
+ GetAndUnregisterInternal(request_token);
+
+ if (!request.is_null())
+ request.Run(std::move(surface));
+}
+
+ScopedSurfaceRequestManager::ScopedSurfaceRequestManager() {}
+
+ScopedSurfaceRequestManager::~ScopedSurfaceRequestManager() {}
+
+} // namespace content
diff --git a/content/browser/android/scoped_surface_request_manager.h b/content/browser/android/scoped_surface_request_manager.h
new file mode 100644
index 0000000..aee96e9
--- /dev/null
+++ b/content/browser/android/scoped_surface_request_manager.h
@@ -0,0 +1,84 @@
+// Copyright 2016 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_ANDROID_SCOPED_SURFACE_REQUEST_MANAGER_H_
+#define CONTENT_BROWSER_ANDROID_SCOPED_SURFACE_REQUEST_MANAGER_H_
+
+#include <unordered_map>
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "base/unguessable_token.h"
+#include "content/common/content_export.h"
+#include "gpu/ipc/common/android/scoped_surface_request_conduit.h"
+#include "ui/gl/android/scoped_java_surface.h"
+
+namespace content {
+
+class CONTENT_EXPORT ScopedSurfaceRequestManager
+ : public gpu::ScopedSurfaceRequestConduit {
+ public:
+ static ScopedSurfaceRequestManager* GetInstance();
+
+ using ScopedSurfaceRequestCB = base::Callback<void(gl::ScopedJavaSurface)>;
+
+ // Registers a request, and returns the |request_token| that should be used to
+ // call Fulfill at a later time. The caller is responsible for unregistering
+ // the request, if it is destroyed before the request is fulfilled.
+ // It is the requester's responsibility to check the validity of the final
+ // ScopedJavaSurface (as passing an empty surface is a valid operation).
+ // Must be called on the UI thread.
+ base::UnguessableToken RegisterScopedSurfaceRequest(
+ const ScopedSurfaceRequestCB& request_cb);
+
+ // Unregisters a request registered under |request_token| if it exists,
+ // no-ops otherwise.
+ // Must be called on the UI thread.
+ void UnregisterScopedSurfaceRequest(
+ const base::UnguessableToken& request_token);
+
+ // Unregisters and runs the request callback identified by |request_token| if
+ // one exists, no-ops otherwise.
+ // Passing an empty |surface| is a valid operation that will complete the
+ // request.
+ // Can be called from any thread. The request will be posted to the UI thread.
+ void FulfillScopedSurfaceRequest(const base::UnguessableToken& request_token,
+ gl::ScopedJavaSurface surface);
+
+ // Implementation of ScopedSurfaceRequestConduit.
+ // To be used in the single process case.
+ // Can be called from any thread.
+ void ForwardSurfaceTextureForSurfaceRequest(
+ const base::UnguessableToken& request_token,
+ const gl::SurfaceTexture* surface_texture) override;
+
+ void clear_requests_for_testing() { request_callbacks_.clear(); }
+
+ int request_count_for_testing() { return request_callbacks_.size(); }
+
+ private:
+ friend struct base::DefaultSingletonTraits<ScopedSurfaceRequestManager>;
+
+ // Unregisters and returns the request identified by |request_token|.
+ ScopedSurfaceRequestCB GetAndUnregisterInternal(
+ const base::UnguessableToken& request_token);
+
+ void CompleteRequestOnUiThread(const base::UnguessableToken& request_token,
+ gl::ScopedJavaSurface surface);
+
+ // Map used to hold references to the registered callbacks.
+ std::unordered_map<base::UnguessableToken,
+ ScopedSurfaceRequestCB,
+ base::UnguessableTokenHash>
+ request_callbacks_;
+
+ ScopedSurfaceRequestManager();
+ ~ScopedSurfaceRequestManager() override;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSurfaceRequestManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_SCOPED_SURFACE_REQUEST_MANAGER_H_
diff --git a/content/browser/android/scoped_surface_request_manager_unittest.cc b/content/browser/android/scoped_surface_request_manager_unittest.cc
new file mode 100644
index 0000000..30e8fa3
--- /dev/null
+++ b/content/browser/android/scoped_surface_request_manager_unittest.cc
@@ -0,0 +1,186 @@
+// Copyright 2016 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/android/scoped_surface_request_manager.h"
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/android/scoped_java_surface.h"
+#include "ui/gl/android/surface_texture.h"
+
+namespace content {
+
+class ScopedSurfaceRequestManagerUnitTest : public testing::Test {
+ public:
+ ScopedSurfaceRequestManagerUnitTest() {
+ manager_ = ScopedSurfaceRequestManager::GetInstance();
+
+ // The need to reset the callbacks because the
+ // ScopedSurfaceRequestManager's lifetime outlive the tests.
+ manager_->clear_requests_for_testing();
+
+ last_received_request_ = 0;
+ dummy_token_ = base::UnguessableToken::Deserialize(123, 456);
+
+ surface_texture = gl::SurfaceTexture::Create(0);
+ dummy_request_ =
+ base::Bind(&ScopedSurfaceRequestManagerUnitTest::DummyCallback,
+ base::Unretained(this));
+ specific_logging_request_ =
+ base::Bind(&ScopedSurfaceRequestManagerUnitTest::LoggingCallback,
+ base::Unretained(this), kSpecificCallbackId);
+ }
+
+ // No-op callback.
+ void DummyCallback(gl::ScopedJavaSurface surface) {}
+
+ // Callback that updates |last_received_request_| to allow differentiation
+ // between callback instances in tests.
+ void LoggingCallback(int request_id, gl::ScopedJavaSurface surface) {
+ last_received_request_ = request_id;
+ }
+
+ ScopedSurfaceRequestManager::ScopedSurfaceRequestCB dummy_request_;
+ ScopedSurfaceRequestManager::ScopedSurfaceRequestCB specific_logging_request_;
+ scoped_refptr<gl::SurfaceTexture> surface_texture;
+
+ int last_received_request_;
+ const int kSpecificCallbackId = 1357;
+ base::UnguessableToken dummy_token_;
+
+ ScopedSurfaceRequestManager* manager_;
+
+ content::TestBrowserThreadBundle thread_bundle_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSurfaceRequestManagerUnitTest);
+};
+
+// Makes sure we can successfully register a callback.
+TEST_F(ScopedSurfaceRequestManagerUnitTest, RegisterRequest_ShouldSucceed) {
+ EXPECT_EQ(0, manager_->request_count_for_testing());
+
+ base::UnguessableToken token =
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+
+ EXPECT_EQ(1, manager_->request_count_for_testing());
+ EXPECT_FALSE(token.is_empty());
+}
+
+// Makes sure we can successfully register multiple callbacks, and that they
+// return distinct request tokens.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ RegisterMultipleRequests_ShouldSucceed) {
+ base::UnguessableToken token1 =
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+ base::UnguessableToken token2 =
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+
+ EXPECT_EQ(2, manager_->request_count_for_testing());
+ EXPECT_NE(token1, token2);
+}
+
+// Makes sure GetInstance() is idempotent/that the class is a proper singleton.
+TEST_F(ScopedSurfaceRequestManagerUnitTest, VerifySingleton_ShouldSucceed) {
+ EXPECT_EQ(manager_, ScopedSurfaceRequestManager::GetInstance());
+}
+
+// Makes sure we can unregister a callback after registering it.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ GetRegisteredRequest_ShouldSucceed) {
+ base::UnguessableToken token =
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+ EXPECT_EQ(1, manager_->request_count_for_testing());
+
+ manager_->UnregisterScopedSurfaceRequest(token);
+
+ EXPECT_EQ(0, manager_->request_count_for_testing());
+}
+
+// Makes sure that unregistering a callback only affects the specified callback.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ GetRegisteredRequestFromMultipleRequests_ShouldSucceed) {
+ base::UnguessableToken token =
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+ EXPECT_EQ(2, manager_->request_count_for_testing());
+
+ manager_->UnregisterScopedSurfaceRequest(token);
+
+ EXPECT_EQ(1, manager_->request_count_for_testing());
+}
+
+// Makes sure that unregistration is a noop permitted when there are no
+// registered requests.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ UnregisteredRequest_ShouldReturnNullCallback) {
+ manager_->UnregisterScopedSurfaceRequest(dummy_token_);
+
+ EXPECT_EQ(0, manager_->request_count_for_testing());
+}
+
+// Makes sure that unregistering an invalid |request_token| doesn't affect
+// other registered callbacks.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ GetUnregisteredRequestFromMultipleRequests_ShouldReturnNullCallback) {
+ manager_->RegisterScopedSurfaceRequest(dummy_request_);
+
+ manager_->UnregisterScopedSurfaceRequest(dummy_token_);
+
+ EXPECT_EQ(1, manager_->request_count_for_testing());
+}
+
+// Makes sure that trying to fulfill a request for an invalid |request_token|
+// does nothing, and does not affect other callbacks.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ FulfillUnregisteredRequest_ShouldDoNothing) {
+ manager_->RegisterScopedSurfaceRequest(specific_logging_request_);
+
+ manager_->FulfillScopedSurfaceRequest(
+ dummy_token_, gl::ScopedJavaSurface(surface_texture.get()));
+
+ EXPECT_EQ(1, manager_->request_count_for_testing());
+ EXPECT_NE(kSpecificCallbackId, last_received_request_);
+}
+
+// Makes sure that trying to fulfill a request fulfills the right request, and
+// does not affect other registered requests.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ FulfillRegisteredRequest_ShouldSucceed) {
+ base::UnguessableToken specific_token =
+ manager_->RegisterScopedSurfaceRequest(specific_logging_request_);
+
+ const uint64_t kOtherCallbackId = 5678;
+ manager_->RegisterScopedSurfaceRequest(
+ base::Bind(&ScopedSurfaceRequestManagerUnitTest::LoggingCallback,
+ base::Unretained(this), kOtherCallbackId));
+
+ manager_->FulfillScopedSurfaceRequest(
+ specific_token, gl::ScopedJavaSurface(surface_texture.get()));
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, manager_->request_count_for_testing());
+ EXPECT_EQ(kSpecificCallbackId, last_received_request_);
+}
+
+// Makes sure that the ScopedSurfaceRequestConduit implementation properly
+// fulfills requests.
+TEST_F(ScopedSurfaceRequestManagerUnitTest,
+ ForwardSurfaceTexture_ShouldFulfillRequest) {
+ base::UnguessableToken token =
+ manager_->RegisterScopedSurfaceRequest(specific_logging_request_);
+
+ manager_->ForwardSurfaceTextureForSurfaceRequest(token,
+ surface_texture.get());
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0, manager_->request_count_for_testing());
+ EXPECT_EQ(kSpecificCallbackId, last_received_request_);
+}
+
+} // Content
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 4a34f1a..1653f80 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -107,6 +107,7 @@
#include "components/tracing/common/graphics_memory_dump_provider_android.h"
#include "content/browser/android/browser_startup_controller.h"
#include "content/browser/android/browser_surface_texture_manager.h"
+#include "content/browser/android/scoped_surface_request_manager.h"
#include "content/browser/android/tracing_controller_android.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
@@ -628,6 +629,8 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
if (parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
gpu::SurfaceTextureManager::SetInstance(
gpu::InProcessSurfaceTextureManager::GetInstance());
+ gpu::ScopedSurfaceRequestConduit::SetInstance(
+ ScopedSurfaceRequestManager::GetInstance());
} else {
gpu::SurfaceTextureManager::SetInstance(
BrowserSurfaceTextureManager::GetInstance());
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
index 9bf884a..a43219c 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
@@ -369,6 +369,27 @@ public class ChildProcessServiceImpl {
@SuppressWarnings("unused")
@CalledByNative
+ private void forwardSurfaceTextureForSurfaceRequest(
+ long requestTokenHigh, long requestTokenLow, SurfaceTexture surfaceTexture) {
+ if (mCallback == null) {
+ Log.e(TAG, "No callback interface has been provided.");
+ return;
+ }
+
+ Surface surface = new Surface(surfaceTexture);
+
+ try {
+ mCallback.forwardSurfaceForSurfaceRequest(requestTokenHigh, requestTokenLow, surface);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to call forwardSurfaceForSurfaceRequest: %s", e);
+ return;
+ } finally {
+ surface.release();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @CalledByNative
private Surface getViewSurface(int surfaceId) {
if (mCallback == null) {
Log.e(TAG, "No callback interface has been provided.");
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index e32af9f..c9c3eb2 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -913,6 +913,19 @@ public class ChildProcessLauncher {
}
@Override
+ public void forwardSurfaceForSurfaceRequest(
+ long requestTokenHigh, long requestTokenLow, Surface surface) {
+ // Do not allow a malicious renderer to connect to a producer. This is only used
+ // from stream textures managed by the GPU process.
+ if (callbackType != CALLBACK_FOR_GPU_PROCESS) {
+ Log.e(TAG, "Illegal callback for non-GPU process.");
+ return;
+ }
+
+ nativeCompleteScopedSurfaceRequest(requestTokenHigh, requestTokenLow, surface);
+ }
+
+ @Override
public SurfaceWrapper getViewSurface(int surfaceId) {
// Do not allow a malicious renderer to get to our view surface.
if (callbackType != CALLBACK_FOR_GPU_PROCESS) {
@@ -1060,5 +1073,7 @@ public class ChildProcessLauncher {
private static native void nativeOnChildProcessStarted(long clientContext, int pid);
private static native void nativeEstablishSurfacePeer(
int pid, Surface surface, int primaryID, int secondaryID);
+ private static native void nativeCompleteScopedSurfaceRequest(
+ long requestTokenHigh, long requestTokenLow, Surface surface);
private static native boolean nativeIsSingleProcess();
}
diff --git a/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl b/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl
index 36983b0..964bcea 100644
--- a/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl
+++ b/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl
@@ -13,6 +13,9 @@ interface IChildProcessCallback {
void establishSurfacePeer(
int pid, in Surface surface, int primaryID, int secondaryID);
+ void forwardSurfaceForSurfaceRequest(
+ long requestTokenHigh, long requestTokenLow, in Surface surface);
+
SurfaceWrapper getViewSurface(int surfaceId);
void registerSurfaceTextureSurface(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index cf7de1e..9e9901b 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1579,6 +1579,7 @@ test("content_unittests") {
"../browser/android/java/gin_java_method_invocation_helper_unittest.cc",
"../browser/android/java/java_type_unittest.cc",
"../browser/android/java/jni_helper_unittest.cc",
+ "../browser/android/scoped_surface_request_manager_unittest.cc",
"../browser/android/url_request_content_job_unittest.cc",
"../renderer/java/gin_java_bridge_value_converter_unittest.cc",
"../renderer/media/android/stream_texture_wrapper_impl_unittest.cc",
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn
index a5cff51..f352382 100644
--- a/gpu/ipc/common/BUILD.gn
+++ b/gpu/ipc/common/BUILD.gn
@@ -105,6 +105,8 @@ source_set("ipc_common_sources") {
if (is_android) {
sources += [
+ "android/scoped_surface_request_conduit.cc",
+ "android/scoped_surface_request_conduit.h",
"android/surface_texture_manager.cc",
"android/surface_texture_manager.h",
"android/surface_texture_peer.cc",
diff --git a/gpu/ipc/common/android/scoped_surface_request_conduit.cc b/gpu/ipc/common/android/scoped_surface_request_conduit.cc
new file mode 100644
index 0000000..655eb0d
--- /dev/null
+++ b/gpu/ipc/common/android/scoped_surface_request_conduit.cc
@@ -0,0 +1,29 @@
+// Copyright 2016 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 "gpu/ipc/common/android/scoped_surface_request_conduit.h"
+
+#include "base/logging.h"
+
+namespace gpu {
+namespace {
+
+ScopedSurfaceRequestConduit* g_instance = nullptr;
+
+} // namespace
+
+// static
+ScopedSurfaceRequestConduit* ScopedSurfaceRequestConduit::GetInstance() {
+ DCHECK(g_instance);
+ return g_instance;
+}
+
+// static
+void ScopedSurfaceRequestConduit::SetInstance(
+ ScopedSurfaceRequestConduit* instance) {
+ DCHECK(!g_instance || !instance);
+ g_instance = instance;
+}
+
+} // namespace gpu
diff --git a/gpu/ipc/common/android/scoped_surface_request_conduit.h b/gpu/ipc/common/android/scoped_surface_request_conduit.h
new file mode 100644
index 0000000..d5b3393
--- /dev/null
+++ b/gpu/ipc/common/android/scoped_surface_request_conduit.h
@@ -0,0 +1,39 @@
+// Copyright 2016 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 GPU_IPC_COMMON_ANDROID_SCOPED_SURFACE_REQUEST_CONDUIT_H_
+#define GPU_IPC_COMMON_ANDROID_SCOPED_SURFACE_REQUEST_CONDUIT_H_
+
+#include "gpu/gpu_export.h"
+
+namespace base {
+class UnguessableToken;
+}
+
+namespace gl {
+class SurfaceTexture;
+}
+
+namespace gpu {
+
+// Allows the forwarding of SurfaceTextures from the GPU or the browser process
+// to fulfill requests registered by the ScopedSurfaceRequestManager.
+class GPU_EXPORT ScopedSurfaceRequestConduit {
+ public:
+ static ScopedSurfaceRequestConduit* GetInstance();
+ static void SetInstance(ScopedSurfaceRequestConduit* instance);
+
+ // Sends the surface texture to the ScopedSurfaceRequestManager in the browser
+ // process, to fulfill the request registered under the |request_token| key.
+ virtual void ForwardSurfaceTextureForSurfaceRequest(
+ const base::UnguessableToken& request_token,
+ const gl::SurfaceTexture* surface_texture) = 0;
+
+ protected:
+ virtual ~ScopedSurfaceRequestConduit() {}
+};
+
+} // namespace gpu
+
+#endif // GPU_IPC_COMMON_ANDROID_SCOPED_SURFACE_REQUEST_CONDUIT_H_