diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ppapi/proxy | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ppapi/proxy')
126 files changed, 7409 insertions, 1800 deletions
diff --git a/chromium/ppapi/proxy/DEPS b/chromium/ppapi/proxy/DEPS index e56cd3def11..6183b609ef4 100644 --- a/chromium/ppapi/proxy/DEPS +++ b/chromium/ppapi/proxy/DEPS @@ -1,11 +1,12 @@ include_rules = [ "+base", - "+components/tracing", "+gpu", "+ipc", "+media/audio", + "+media/base", "+skia", "+ui/surface", + "+ui/events", # We don't want the proxy to depend on the C++ layer, which is appropriate # for plugins only. However, the completion callback factory is a very useful @@ -14,9 +15,4 @@ include_rules = [ "-ppapi/cpp", "+ppapi/cpp/completion_callback.h", "+ppapi/cpp/output_traits.h", - - # The untrusted build references the NaCl integrated runtime (IRT). - "+native_client/src/shared", - "+native_client/src/untrusted" ] - diff --git a/chromium/ppapi/proxy/OWNERS b/chromium/ppapi/proxy/OWNERS index 7d2c40a5e8b..6064b918dd6 100644 --- a/chromium/ppapi/proxy/OWNERS +++ b/chromium/ppapi/proxy/OWNERS @@ -3,9 +3,12 @@ piman@chromium.org # Changes to IPC messages require a security review to avoid introducing # new sandbox escapes. per-file *_messages*.h=set noparent -per-file *_messages*.h=cdn@chromium.org per-file *_messages*.h=cevans@chromium.org +per-file *_messages*.h=dcheng@chromium.org +per-file *_messages*.h=inferno@chromium.org per-file *_messages*.h=jln@chromium.org per-file *_messages*.h=jschuh@chromium.org +per-file *_messages*.h=kenrb@chromium.org +per-file *_messages*.h=nasko@chromium.org per-file *_messages*.h=palmer@chromium.org per-file *_messages*.h=tsepez@chromium.org diff --git a/chromium/ppapi/proxy/audio_buffer_resource.cc b/chromium/ppapi/proxy/audio_buffer_resource.cc new file mode 100644 index 00000000000..1435b4cee75 --- /dev/null +++ b/chromium/ppapi/proxy/audio_buffer_resource.cc @@ -0,0 +1,112 @@ +// 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. + +#include "ppapi/proxy/audio_buffer_resource.h" + +#include "base/logging.h" +#include "ppapi/c/pp_bool.h" +#include "ppapi/shared_impl/media_stream_buffer.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +AudioBufferResource::AudioBufferResource(PP_Instance instance, + int32_t index, + MediaStreamBuffer* buffer) + : Resource(OBJECT_IS_PROXY, instance), + index_(index), + buffer_(buffer) { + DCHECK_EQ(buffer_->header.type, MediaStreamBuffer::TYPE_AUDIO); +} + +AudioBufferResource::~AudioBufferResource() { + CHECK(!buffer_) << "An unused (or unrecycled) buffer is destroyed."; +} + +thunk::PPB_AudioBuffer_API* AudioBufferResource::AsPPB_AudioBuffer_API() { + return this; +} + +PP_TimeDelta AudioBufferResource::GetTimestamp() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return 0.0; + } + return buffer_->audio.timestamp; +} + +void AudioBufferResource::SetTimestamp(PP_TimeDelta timestamp) { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return; + } + buffer_->audio.timestamp = timestamp; +} + +PP_AudioBuffer_SampleRate AudioBufferResource::GetSampleRate() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN; + } + return buffer_->audio.sample_rate; +} + +PP_AudioBuffer_SampleSize AudioBufferResource::GetSampleSize() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return PP_AUDIOBUFFER_SAMPLESIZE_UNKNOWN; + } + return PP_AUDIOBUFFER_SAMPLESIZE_16_BITS; +} + +uint32_t AudioBufferResource::GetNumberOfChannels() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return 0; + } + return buffer_->audio.number_of_channels; +} + +uint32_t AudioBufferResource::GetNumberOfSamples() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return 0; + } + return buffer_->audio.number_of_samples; +} + +void* AudioBufferResource::GetDataBuffer() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return NULL; + } + return buffer_->audio.data; +} + +uint32_t AudioBufferResource::GetDataBufferSize() { + if (!buffer_) { + VLOG(1) << "Buffer is invalid"; + return 0; + } + return buffer_->audio.data_size; +} + +MediaStreamBuffer* AudioBufferResource::GetBuffer() { + return buffer_; +} + +int32_t AudioBufferResource::GetBufferIndex() { + return index_; +} + +void AudioBufferResource::Invalidate() { + DCHECK(buffer_); + DCHECK_GE(index_, 0); + buffer_ = NULL; + index_ = -1; +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/audio_buffer_resource.h b/chromium/ppapi/proxy/audio_buffer_resource.h new file mode 100644 index 00000000000..b4ef3eb760c --- /dev/null +++ b/chromium/ppapi/proxy/audio_buffer_resource.h @@ -0,0 +1,57 @@ +// 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 PPAPI_PROXY_AUDIO_BUFFER_RESOURCE_H_ +#define PPAPI_PROXY_AUDIO_BUFFER_RESOURCE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_audio_buffer_api.h" + +namespace ppapi { + +union MediaStreamBuffer; + +namespace proxy { + +class PPAPI_PROXY_EXPORT AudioBufferResource + : public Resource, + public thunk::PPB_AudioBuffer_API { + public: + AudioBufferResource(PP_Instance instance, + int32_t index, + MediaStreamBuffer* buffer); + + virtual ~AudioBufferResource(); + + // PluginResource overrides: + virtual thunk::PPB_AudioBuffer_API* AsPPB_AudioBuffer_API() OVERRIDE; + + // PPB_AudioBuffer_API overrides: + virtual PP_TimeDelta GetTimestamp() OVERRIDE; + virtual void SetTimestamp(PP_TimeDelta timestamp) OVERRIDE; + virtual PP_AudioBuffer_SampleRate GetSampleRate() OVERRIDE; + virtual PP_AudioBuffer_SampleSize GetSampleSize() OVERRIDE; + virtual uint32_t GetNumberOfChannels() OVERRIDE; + virtual uint32_t GetNumberOfSamples() OVERRIDE; + virtual void* GetDataBuffer() OVERRIDE; + virtual uint32_t GetDataBufferSize() OVERRIDE; + virtual MediaStreamBuffer* GetBuffer() OVERRIDE; + virtual int32_t GetBufferIndex() OVERRIDE; + virtual void Invalidate() OVERRIDE; + + // Buffer index + int32_t index_; + + MediaStreamBuffer* buffer_; + + DISALLOW_COPY_AND_ASSIGN(AudioBufferResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_AUDIO_BUFFER_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/audio_input_resource.cc b/chromium/ppapi/proxy/audio_input_resource.cc index 7c29df5b744..7f1f81983e6 100644 --- a/chromium/ppapi/proxy/audio_input_resource.cc +++ b/chromium/ppapi/proxy/audio_input_resource.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "ipc/ipc_platform_file.h" #include "media/audio/audio_parameters.h" +#include "media/base/audio_bus.h" #include "ppapi/c/pp_errors.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/resource_message_params.h" @@ -22,18 +23,19 @@ namespace ppapi { namespace proxy { -AudioInputResource::AudioInputResource( - Connection connection, - PP_Instance instance) +AudioInputResource::AudioInputResource(Connection connection, + PP_Instance instance) : PluginResource(connection, instance), open_state_(BEFORE_OPEN), capturing_(false), shared_memory_size_(0), - audio_input_callback_0_2_(NULL), + audio_input_callback_0_3_(NULL), audio_input_callback_(NULL), user_data_(NULL), enumeration_helper_(this), - bytes_per_second_(0) { + bytes_per_second_(0), + sample_frame_count_(0), + client_buffer_size_bytes_(0) { SendCreate(RENDERER, PpapiHostMsg_AudioInput_Create()); } @@ -52,12 +54,6 @@ void AudioInputResource::OnReplyReceived( PluginResource::OnReplyReceived(params, msg); } -int32_t AudioInputResource::EnumerateDevices0_2( - PP_Resource* devices, - scoped_refptr<TrackedCallback> callback) { - return enumeration_helper_.EnumerateDevices0_2(devices, callback); -} - int32_t AudioInputResource::EnumerateDevices( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) { @@ -70,13 +66,13 @@ int32_t AudioInputResource::MonitorDeviceChange( return enumeration_helper_.MonitorDeviceChange(callback, user_data); } -int32_t AudioInputResource::Open0_2( +int32_t AudioInputResource::Open0_3( PP_Resource device_ref, PP_Resource config, - PPB_AudioInput_Callback_0_2 audio_input_callback_0_2, + PPB_AudioInput_Callback_0_3 audio_input_callback_0_3, void* user_data, scoped_refptr<TrackedCallback> callback) { - return CommonOpen(device_ref, config, audio_input_callback_0_2, NULL, + return CommonOpen(device_ref, config, audio_input_callback_0_3, NULL, user_data, callback); } @@ -187,14 +183,33 @@ void AudioInputResource::SetStreamInfo( socket_.reset(new base::CancelableSyncSocket(socket_handle)); shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); shared_memory_size_ = shared_memory_size; + DCHECK(!shared_memory_->memory()); - if (!shared_memory_->Map(shared_memory_size_)) { - PpapiGlobals::Get()->LogWithSource( - pp_instance(), - PP_LOGLEVEL_WARNING, - std::string(), - "Failed to map shared memory for PPB_AudioInput_Shared."); - } + // If we fail to map the shared memory into the caller's address space we + // might as well fail here since nothing will work if this is the case. + CHECK(shared_memory_->Map(shared_memory_size_)); + + // Create a new audio bus and wrap the audio data section in shared memory. + media::AudioInputBuffer* buffer = + static_cast<media::AudioInputBuffer*>(shared_memory_->memory()); + audio_bus_ = media::AudioBus::WrapMemory( + kAudioInputChannels, sample_frame_count_, buffer->audio); + + // Ensure that the size of the created audio bus matches the allocated + // size in shared memory. + // Example: DCHECK_EQ(8208 - 16, 8192) for |sample_frame_count_| = 2048. + const uint32_t audio_bus_size_bytes = media::AudioBus::CalculateMemorySize( + audio_bus_->channels(), audio_bus_->frames()); + DCHECK_EQ(shared_memory_size_ - sizeof(media::AudioInputBufferParameters), + audio_bus_size_bytes); + + // Create an extra integer audio buffer for user audio data callbacks. + // Data in shared memory will be copied to this buffer, after interleaving + // and truncation, before each input callback to match the format expected + // by the client. + client_buffer_size_bytes_ = audio_bus_->frames() * audio_bus_->channels() * + kBitsPerAudioInputSample / 8; + client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); // There is a pending capture request before SetStreamInfo(). if (capturing_) { @@ -207,8 +222,9 @@ void AudioInputResource::SetStreamInfo( void AudioInputResource::StartThread() { // Don't start the thread unless all our state is set up correctly. - if ((!audio_input_callback_0_2_ && !audio_input_callback_) || - !socket_.get() || !capturing_ || !shared_memory_->memory()) { + if ((!audio_input_callback_0_3_ && !audio_input_callback_) || + !socket_.get() || !capturing_ || !shared_memory_->memory() || + !audio_bus_.get() || !client_buffer_.get()) { return; } DCHECK(!audio_input_thread_.get()); @@ -229,28 +245,42 @@ void AudioInputResource::StopThread() { void AudioInputResource::Run() { // The shared memory represents AudioInputBufferParameters and the actual data - // buffer. + // buffer stored as an audio bus. media::AudioInputBuffer* buffer = static_cast<media::AudioInputBuffer*>(shared_memory_->memory()); - uint32_t data_buffer_size = + const uint32_t audio_bus_size_bytes = shared_memory_size_ - sizeof(media::AudioInputBufferParameters); - int pending_data; - while (sizeof(pending_data) == socket_->Receive(&pending_data, - sizeof(pending_data)) && - pending_data >= 0) { + while (true) { + int pending_data = 0; + size_t bytes_read = socket_->Receive(&pending_data, sizeof(pending_data)); + if (bytes_read != sizeof(pending_data)) { + DCHECK_EQ(bytes_read, 0U); + break; + } + if (pending_data < 0) + break; + + // Convert an AudioBus from deinterleaved float to interleaved integer data. + // Store the result in a preallocated |client_buffer_|. + audio_bus_->ToInterleaved(audio_bus_->frames(), + kBitsPerAudioInputSample / 8, + client_buffer_.get()); + // While closing the stream, we may receive buffers whose size is different // from |data_buffer_size|. - CHECK_LE(buffer->params.size, data_buffer_size); + CHECK_LE(buffer->params.size, audio_bus_size_bytes); if (buffer->params.size > 0) { if (audio_input_callback_) { PP_TimeDelta latency = static_cast<double>(pending_data) / bytes_per_second_; - audio_input_callback_(&buffer->audio[0], buffer->params.size, latency, + audio_input_callback_(client_buffer_.get(), + client_buffer_size_bytes_, + latency, user_data_); } else { - audio_input_callback_0_2_(&buffer->audio[0], buffer->params.size, - user_data_); + audio_input_callback_0_3_( + client_buffer_.get(), client_buffer_size_bytes_, user_data_); } } } @@ -259,7 +289,7 @@ void AudioInputResource::Run() { int32_t AudioInputResource::CommonOpen( PP_Resource device_ref, PP_Resource config, - PPB_AudioInput_Callback_0_2 audio_input_callback_0_2, + PPB_AudioInput_Callback_0_3 audio_input_callback_0_3, PPB_AudioInput_Callback audio_input_callback, void* user_data, scoped_refptr<TrackedCallback> callback) { @@ -279,7 +309,7 @@ int32_t AudioInputResource::CommonOpen( if (open_state_ != BEFORE_OPEN) return PP_ERROR_FAILED; - if (!audio_input_callback_0_2 && !audio_input_callback) + if (!audio_input_callback_0_3 && !audio_input_callback) return PP_ERROR_BADARGUMENT; thunk::EnterResourceNoLock<thunk::PPB_AudioConfig_API> enter_config(config, true); @@ -287,12 +317,13 @@ int32_t AudioInputResource::CommonOpen( return PP_ERROR_BADARGUMENT; config_ = config; - audio_input_callback_0_2_ = audio_input_callback_0_2; + audio_input_callback_0_3_ = audio_input_callback_0_3; audio_input_callback_ = audio_input_callback; user_data_ = user_data; open_callback_ = callback; bytes_per_second_ = kAudioInputChannels * (kBitsPerAudioInputSample / 8) * enter_config.object()->GetSampleRate(); + sample_frame_count_ = enter_config.object()->GetSampleFrameCount(); PpapiHostMsg_AudioInput_Open msg( device_id, enter_config.object()->GetSampleRate(), diff --git a/chromium/ppapi/proxy/audio_input_resource.h b/chromium/ppapi/proxy/audio_input_resource.h index 84785d08052..0184260c359 100644 --- a/chromium/ppapi/proxy/audio_input_resource.h +++ b/chromium/ppapi/proxy/audio_input_resource.h @@ -17,6 +17,10 @@ #include "ppapi/shared_impl/scoped_pp_resource.h" #include "ppapi/thunk/ppb_audio_input_api.h" +namespace media { +class AudioBus; +} + namespace ppapi { namespace proxy { @@ -35,18 +39,15 @@ class AudioInputResource : public PluginResource, const IPC::Message& msg) OVERRIDE; // PPB_AudioInput_API implementation. - virtual int32_t EnumerateDevices0_2( - PP_Resource* devices, - scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t EnumerateDevices( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t MonitorDeviceChange( PP_MonitorDeviceChangeCallback callback, void* user_data) OVERRIDE; - virtual int32_t Open0_2(PP_Resource device_ref, + virtual int32_t Open0_3(PP_Resource device_ref, PP_Resource config, - PPB_AudioInput_Callback_0_2 audio_input_callback_0_2, + PPB_AudioInput_Callback_0_3 audio_input_callback_0_3, void* user_data, scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t Open(PP_Resource device_ref, @@ -90,7 +91,7 @@ class AudioInputResource : public PluginResource, int32_t CommonOpen(PP_Resource device_ref, PP_Resource config, - PPB_AudioInput_Callback_0_2 audio_input_callback_0_2, + PPB_AudioInput_Callback_0_3 audio_input_callback_0_3, PPB_AudioInput_Callback audio_input_callback, void* user_data, scoped_refptr<TrackedCallback> callback); @@ -116,7 +117,7 @@ class AudioInputResource : public PluginResource, scoped_ptr<base::DelegateSimpleThread> audio_input_thread_; // Callback to call when new samples are available. - PPB_AudioInput_Callback_0_2 audio_input_callback_0_2_; + PPB_AudioInput_Callback_0_3 audio_input_callback_0_3_; PPB_AudioInput_Callback audio_input_callback_; // User data pointer passed verbatim to the callback function. @@ -136,6 +137,14 @@ class AudioInputResource : public PluginResource, // latency. size_t bytes_per_second_; + // AudioBus for shuttling data across the shared memory. + scoped_ptr<media::AudioBus> audio_bus_; + int sample_frame_count_; + + // Internal buffer for client's integer audio data. + int client_buffer_size_bytes_; + scoped_ptr<uint8_t[]> client_buffer_; + DISALLOW_COPY_AND_ASSIGN(AudioInputResource); }; diff --git a/chromium/ppapi/proxy/compositor_layer_resource.cc b/chromium/ppapi/proxy/compositor_layer_resource.cc new file mode 100644 index 00000000000..17bc7b2fe42 --- /dev/null +++ b/chromium/ppapi/proxy/compositor_layer_resource.cc @@ -0,0 +1,368 @@ +// 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. + +#include "ppapi/proxy/compositor_layer_resource.h" + +#include "base/logging.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/common/mailbox.h" +#include "ppapi/proxy/compositor_resource.h" +#include "ppapi/shared_impl/ppb_graphics_3d_shared.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_graphics_3d_api.h" +#include "ppapi/thunk/ppb_image_data_api.h" + +using gpu::gles2::GLES2Implementation; +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_ImageData_API; +using ppapi::thunk::PPB_Graphics3D_API; + +namespace ppapi { +namespace proxy { + +namespace { + +float clamp(float value) { + return std::min(std::max(value, 0.0f), 1.0f); +} + +void OnTextureReleased( + const ScopedPPResource& layer, + const ScopedPPResource& context, + uint32_t texture, + const scoped_refptr<TrackedCallback>& release_callback, + int32_t result, + uint32_t sync_point, + bool is_lost) { + if (!TrackedCallback::IsPending(release_callback)) + return; + + if (result != PP_OK) { + release_callback->Run(result); + return; + } + + do { + if (!sync_point) + break; + + EnterResourceNoLock<PPB_Graphics3D_API> enter(context.get(), true); + if (enter.failed()) + break; + + PPB_Graphics3D_Shared* graphics = + static_cast<PPB_Graphics3D_Shared*>(enter.object()); + + GLES2Implementation* gl = graphics->gles2_impl(); + gl->WaitSyncPointCHROMIUM(sync_point); + } while (false); + + release_callback->Run(is_lost ? PP_ERROR_FAILED : PP_OK); +} + +void OnImageReleased( + const ScopedPPResource& layer, + const ScopedPPResource& image, + const scoped_refptr<TrackedCallback>& release_callback, + int32_t result, + uint32_t sync_point, + bool is_lost) { + if (!TrackedCallback::IsPending(release_callback)) + return; + release_callback->Run(result); +} + +} // namespace + +CompositorLayerResource::CompositorLayerResource( + Connection connection, + PP_Instance instance, + const CompositorResource* compositor) + : PluginResource(connection, instance), + compositor_(compositor), + source_size_(PP_MakeFloatSize(0.0f, 0.0f)) { +} + +CompositorLayerResource::~CompositorLayerResource() { + DCHECK(!compositor_); + DCHECK(release_callback_.is_null()); +} + +thunk::PPB_CompositorLayer_API* +CompositorLayerResource::AsPPB_CompositorLayer_API() { + return this; +} + +int32_t CompositorLayerResource::SetColor(float red, + float green, + float blue, + float alpha, + const PP_Size* size) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + if (!SetType(TYPE_COLOR)) + return PP_ERROR_BADARGUMENT; + DCHECK(data_.color); + + if (!size) + return PP_ERROR_BADARGUMENT; + + data_.color->red = clamp(red); + data_.color->green = clamp(green); + data_.color->blue = clamp(blue); + data_.color->alpha = clamp(alpha); + data_.common.size = *size; + + return PP_OK; +} + +int32_t CompositorLayerResource::SetTexture( + PP_Resource context, + uint32_t texture, + const PP_Size* size, + const scoped_refptr<TrackedCallback>& release_callback) { + int32_t rv = CheckForSetTextureAndImage(TYPE_TEXTURE, release_callback); + if (rv != PP_OK) + return rv; + DCHECK(data_.texture); + + EnterResourceNoLock<PPB_Graphics3D_API> enter(context, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + + if (!size || size->width <= 0 || size->height <= 0) + return PP_ERROR_BADARGUMENT; + + PPB_Graphics3D_Shared* graphics = + static_cast<PPB_Graphics3D_Shared*>(enter.object()); + + GLES2Implementation* gl = graphics->gles2_impl(); + + // Generate a Mailbox for the texture. + gl->GenMailboxCHROMIUM( + reinterpret_cast<GLbyte*>(data_.texture->mailbox.name)); + gl->ProduceTextureDirectCHROMIUM( + texture, GL_TEXTURE_2D, + reinterpret_cast<const GLbyte*>(data_.texture->mailbox.name)); + + // Set the source size to (1, 1). It will be used to verify the source_rect + // passed to SetSourceRect(). + source_size_ = PP_MakeFloatSize(1.0f, 1.0f); + + data_.common.size = *size; + data_.common.resource_id = compositor_->GenerateResourceId(); + data_.texture->sync_point = gl->InsertSyncPointCHROMIUM(); + data_.texture->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f); + data_.texture->source_rect.size = source_size_; + + // If the PP_Resource of this layer is released by the plugin, the + // release_callback will be aborted immediately, but the texture or image + // in this layer may still being used by chromium compositor. So we have to + // use ScopedPPResource to keep this resource alive until the texture or image + // is released by the chromium compositor. + release_callback_ = base::Bind( + &OnTextureReleased, + ScopedPPResource(pp_resource()), // Keep layer alive. + ScopedPPResource(context), // Keep context alive + texture, + release_callback); + + return PP_OK_COMPLETIONPENDING; +} + +int32_t CompositorLayerResource::SetImage( + PP_Resource image_data, + const PP_Size* size, + const scoped_refptr<TrackedCallback>& release_callback) { + int32_t rv = CheckForSetTextureAndImage(TYPE_IMAGE, release_callback); + if (rv != PP_OK) + return rv; + DCHECK(data_.image); + + EnterResourceNoLock<PPB_ImageData_API> enter(image_data, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + + PP_ImageDataDesc desc; + if (!enter.object()->Describe(&desc)) + return PP_ERROR_BADARGUMENT; + + // TODO(penghuang): Support image which width * 4 != stride. + if (desc.size.width * 4 != desc.stride) + return PP_ERROR_BADARGUMENT; + + // TODO(penghuang): Support all formats. + if (desc.format != PP_IMAGEDATAFORMAT_RGBA_PREMUL) + return PP_ERROR_BADARGUMENT; + + if (!size || size->width <= 0 || size->height <= 0) + return PP_ERROR_BADARGUMENT; + + // Set the source size to image's size. It will be used to verify + // the source_rect passed to SetSourceRect(). + source_size_ = PP_MakeFloatSize(desc.size.width, desc.size.height); + + data_.common.size = size ? *size : desc.size; + data_.common.resource_id = compositor_->GenerateResourceId(); + data_.image->resource = enter.resource()->host_resource().host_resource(); + data_.image->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f); + data_.image->source_rect.size = source_size_; + + // If the PP_Resource of this layer is released by the plugin, the + // release_callback will be aborted immediately, but the texture or image + // in this layer may still being used by chromium compositor. So we have to + // use ScopedPPResource to keep this resource alive until the texture or image + // is released by the chromium compositor. + release_callback_ = base::Bind( + &OnImageReleased, + ScopedPPResource(pp_resource()), // Keep layer alive. + ScopedPPResource(image_data), // Keep image_data alive. + release_callback); + + return PP_OK_COMPLETIONPENDING; +} + +int32_t CompositorLayerResource::SetClipRect(const PP_Rect* rect) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + data_.common.clip_rect = rect ? *rect : PP_MakeRectFromXYWH(0, 0, 0, 0); + return PP_OK; +} + +int32_t CompositorLayerResource::SetTransform(const float matrix[16]) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + std::copy(matrix, matrix + 16, data_.common.transform.matrix); + return PP_OK; +} + +int32_t CompositorLayerResource::SetOpacity(float opacity) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + data_.common.opacity = clamp(opacity); + return PP_OK; +} + +int32_t CompositorLayerResource::SetBlendMode(PP_BlendMode mode) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + switch (mode) { + case PP_BLENDMODE_NONE: + case PP_BLENDMODE_SRC_OVER: + data_.common.blend_mode = mode; + return PP_OK; + } + return PP_ERROR_BADARGUMENT; +} + +int32_t CompositorLayerResource::SetSourceRect( + const PP_FloatRect* rect) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + if (!rect || + rect->point.x < 0.0f || + rect->point.y < 0.0f || + rect->point.x + rect->size.width > source_size_.width || + rect->point.y + rect->size.height > source_size_.height) { + return PP_ERROR_BADARGUMENT; + } + + if (data_.texture) { + data_.texture->source_rect = *rect; + return PP_OK; + } + if (data_.image) { + data_.image->source_rect = *rect; + return PP_OK; + } + return PP_ERROR_BADARGUMENT; +} + +int32_t CompositorLayerResource::SetPremultipliedAlpha(PP_Bool premult) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + if (data_.texture) { + data_.texture->premult_alpha = PP_ToBool(premult); + return PP_OK; + } + return PP_ERROR_BADARGUMENT; +} + +bool CompositorLayerResource::SetType(LayerType type) { + if (type == TYPE_COLOR) { + if (data_.is_null()) + data_.color.reset(new CompositorLayerData::ColorLayer()); + return data_.color; + } + + if (type == TYPE_TEXTURE) { + if (data_.is_null()) + data_.texture.reset(new CompositorLayerData::TextureLayer()); + return data_.texture; + } + + if (type == TYPE_IMAGE) { + if (data_.is_null()) + data_.image.reset(new CompositorLayerData::ImageLayer()); + return data_.image; + } + + // Should not be reached. + DCHECK(false); + return false; +} + +int32_t CompositorLayerResource::CheckForSetTextureAndImage( + LayerType type, + const scoped_refptr<TrackedCallback>& release_callback) { + if (!compositor_) + return PP_ERROR_BADRESOURCE; + + if (compositor_->IsInProgress()) + return PP_ERROR_INPROGRESS; + + if (!SetType(type)) + return PP_ERROR_BADARGUMENT; + + // The layer's image has been set and it is not committed. + if (!release_callback_.is_null()) + return PP_ERROR_INPROGRESS; + + // Do not allow using a block callback as a release callback. + if (release_callback->is_blocking()) + return PP_ERROR_BADARGUMENT; + + return PP_OK; +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/compositor_layer_resource.h b/chromium/ppapi/proxy/compositor_layer_resource.h new file mode 100644 index 00000000000..a31d8fe7c8a --- /dev/null +++ b/chromium/ppapi/proxy/compositor_layer_resource.h @@ -0,0 +1,99 @@ +// 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 PPAPI_PROXY_COMPOSITOR_LAYER_RESOURCE_H_ +#define PPAPI_PROXY_COMPOSITOR_LAYER_RESOURCE_H_ + +#include "ppapi/c/ppb_compositor_layer.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/compositor_layer_data.h" +#include "ppapi/shared_impl/scoped_pp_resource.h" +#include "ppapi/thunk/ppb_compositor_layer_api.h" + +namespace ppapi { +namespace proxy { + +class CompositorResource; + +class PPAPI_PROXY_EXPORT CompositorLayerResource + : public PluginResource, + public thunk::PPB_CompositorLayer_API { + public: + // Release callback for texture or image layer. + typedef base::Callback<void(int32_t, uint32_t, bool)> ReleaseCallback; + + CompositorLayerResource(Connection connection, + PP_Instance instance, + const CompositorResource* compositor); + + const CompositorLayerData& data() const { return data_; } + const ReleaseCallback& release_callback() const { + return release_callback_; + } + void ResetReleaseCallback() { release_callback_.Reset(); } + void Invalidate() { compositor_ = NULL; } + + private: + enum LayerType { + TYPE_COLOR, + TYPE_TEXTURE, + TYPE_IMAGE, + }; + + virtual ~CompositorLayerResource(); + + // Resource overrides: + virtual thunk::PPB_CompositorLayer_API* AsPPB_CompositorLayer_API() OVERRIDE; + + // thunk::PPB_Compositor_API overrides: + virtual int32_t SetColor(float red, + float green, + float blue, + float alpha, + const PP_Size* size) OVERRIDE; + virtual int32_t SetTexture( + PP_Resource context, + uint32_t texture, + const PP_Size* size, + const scoped_refptr<TrackedCallback>& callback) OVERRIDE; + virtual int32_t SetImage( + PP_Resource image_data, + const PP_Size* size, + const scoped_refptr<TrackedCallback>& callback) OVERRIDE; + virtual int32_t SetClipRect(const PP_Rect* rect) OVERRIDE; + virtual int32_t SetTransform(const float matrix[16]) OVERRIDE; + virtual int32_t SetOpacity(float opacity) OVERRIDE; + virtual int32_t SetBlendMode(PP_BlendMode mode) OVERRIDE; + virtual int32_t SetSourceRect(const PP_FloatRect* rect) OVERRIDE; + virtual int32_t SetPremultipliedAlpha(PP_Bool premult) OVERRIDE; + + bool SetType(LayerType type); + int32_t CheckForSetTextureAndImage( + LayerType type, + const scoped_refptr<TrackedCallback>& release_callback); + + // The CompositorResource which own the layer. The layer is invalidated if + // compositor_ is NULL. + const CompositorResource* compositor_; + + // Release callback for uncommitted texture or image. When CommitLayers() on + // the compositor_ is called, the callback will be copied into a map in the + // compositor_, and it will be reset to NULL. + ReleaseCallback release_callback_; + + // Size of texture or image. It is used to verify the rect arg of + // SetSourceRect(). + PP_FloatSize source_size_; + + // Layer data. + CompositorLayerData data_; + + DISALLOW_COPY_AND_ASSIGN(CompositorLayerResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_COMPOSITOR_LAYER_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/compositor_resource.cc b/chromium/ppapi/proxy/compositor_resource.cc new file mode 100644 index 00000000000..443d7a949e9 --- /dev/null +++ b/chromium/ppapi/proxy/compositor_resource.cc @@ -0,0 +1,154 @@ +// 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. + +#include "ppapi/proxy/compositor_resource.h" + +#include "base/logging.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/thunk/enter.h" + +namespace ppapi { +namespace proxy { + +CompositorResource::CompositorResource(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance), + layer_reset_(true), + last_resource_id_(0) { + SendCreate(RENDERER, PpapiHostMsg_Compositor_Create()); +} + +bool CompositorResource::IsInProgress() const { + ProxyLock::AssertAcquiredDebugOnly(); + return TrackedCallback::IsPending(commit_callback_); +} + +int32_t CompositorResource::GenerateResourceId() const { + ProxyLock::AssertAcquiredDebugOnly(); + return ++last_resource_id_; +} + +CompositorResource::~CompositorResource() { + ResetLayersInternal(true); + + // Abort all release callbacks. + for (ReleaseCallbackMap::iterator it = release_callback_map_.begin(); + it != release_callback_map_.end(); ++it) { + if (!it->second.is_null()) + it->second.Run(PP_ERROR_ABORTED, 0, false); + } +} + +thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() { + return this; +} + +void CompositorResource::OnReplyReceived( + const ResourceMessageReplyParams& params, + const IPC::Message& msg) { + PPAPI_BEGIN_MESSAGE_MAP(CompositorResource, msg) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_Compositor_ReleaseResource, + OnPluginMsgReleaseResource) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( + PluginResource::OnReplyReceived(params, msg)) + PPAPI_END_MESSAGE_MAP() +} + +PP_Resource CompositorResource::AddLayer() { + scoped_refptr<CompositorLayerResource> resource(new CompositorLayerResource( + connection(), pp_instance(), this)); + layers_.push_back(resource); + return resource->GetReference(); +} + +int32_t CompositorResource::CommitLayers( + const scoped_refptr<ppapi::TrackedCallback>& callback) { + if (IsInProgress()) + return PP_ERROR_INPROGRESS; + + std::vector<CompositorLayerData> layers; + layers.reserve(layers_.size()); + + for (LayerList::const_iterator it = layers_.begin(); + it != layers_.end(); ++it) { + if ((*it)->data().is_null()) + return PP_ERROR_FAILED; + layers.push_back((*it)->data()); + } + + commit_callback_ = callback; + Call<PpapiPluginMsg_Compositor_CommitLayersReply>( + RENDERER, + PpapiHostMsg_Compositor_CommitLayers(layers, layer_reset_), + base::Bind(&CompositorResource::OnPluginMsgCommitLayersReply, + base::Unretained(this)), + callback); + + return PP_OK_COMPLETIONPENDING; +} + +int32_t CompositorResource::ResetLayers() { + if (IsInProgress()) + return PP_ERROR_INPROGRESS; + + ResetLayersInternal(false); + return PP_OK; +} + +void CompositorResource::OnPluginMsgCommitLayersReply( + const ResourceMessageReplyParams& params) { + if (!TrackedCallback::IsPending(commit_callback_)) + return; + + // On success, we put layers' release_callbacks into a map, + // otherwise we will do nothing. So plugin may change layers and + // call CommitLayers() again. + if (params.result() == PP_OK) { + layer_reset_ = false; + for (LayerList::iterator it = layers_.begin(); + it != layers_.end(); ++it) { + ReleaseCallback release_callback = (*it)->release_callback(); + if (!release_callback.is_null()) { + release_callback_map_.insert(ReleaseCallbackMap::value_type( + (*it)->data().common.resource_id, release_callback)); + (*it)->ResetReleaseCallback(); + } + } + } + + scoped_refptr<TrackedCallback> callback; + callback.swap(commit_callback_); + callback->Run(params.result()); +} + +void CompositorResource::OnPluginMsgReleaseResource( + const ResourceMessageReplyParams& params, + int32_t id, + uint32_t sync_point, + bool is_lost) { + ReleaseCallbackMap::iterator it = release_callback_map_.find(id); + DCHECK(it != release_callback_map_.end()) << + "Can not found release_callback_ by id(" << id << ")!"; + it->second.Run(PP_OK, sync_point, is_lost); + release_callback_map_.erase(it); +} + +void CompositorResource::ResetLayersInternal(bool is_aborted) { + for (LayerList::iterator it = layers_.begin(); + it != layers_.end(); ++it) { + ReleaseCallback release_callback = (*it)->release_callback(); + if (!release_callback.is_null()) { + release_callback.Run(is_aborted ? PP_ERROR_ABORTED : PP_OK, 0, false); + (*it)->ResetReleaseCallback(); + } + (*it)->Invalidate(); + } + + layers_.clear(); + layer_reset_ = true; +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/compositor_resource.h b/chromium/ppapi/proxy/compositor_resource.h new file mode 100644 index 00000000000..8bdeb3f650e --- /dev/null +++ b/chromium/ppapi/proxy/compositor_resource.h @@ -0,0 +1,80 @@ +// 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 PPAPI_PROXY_COMPOSITOR_RESOURCE_H_ +#define PPAPI_PROXY_COMPOSITOR_RESOURCE_H_ + +#include <map> + +#include "ppapi/proxy/compositor_layer_resource.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/thunk/ppb_compositor_api.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT CompositorResource + : public PluginResource, + public thunk::PPB_Compositor_API { + public: + CompositorResource(Connection connection, + PP_Instance instance); + + bool IsInProgress() const; + + int32_t GenerateResourceId() const; + + private: + virtual ~CompositorResource(); + + // Resource overrides: + virtual thunk::PPB_Compositor_API* AsPPB_Compositor_API() OVERRIDE; + + // PluginResource overrides: + virtual void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) OVERRIDE; + + // thunk::PPB_Compositor_API overrides: + virtual PP_Resource AddLayer() OVERRIDE; + virtual int32_t CommitLayers( + const scoped_refptr<TrackedCallback>& callback) OVERRIDE; + virtual int32_t ResetLayers() OVERRIDE; + + // IPC msg handlers: + void OnPluginMsgCommitLayersReply(const ResourceMessageReplyParams& params); + void OnPluginMsgReleaseResource( + const ResourceMessageReplyParams& params, + int32_t id, + uint32_t sync_point, + bool is_lost); + + void ResetLayersInternal(bool is_aborted); + + // Callback for CommitLayers(). + scoped_refptr<TrackedCallback> commit_callback_; + + // True if layers_ has been reset by ResetLayers(). + bool layer_reset_; + + // Layer stack. + typedef std::vector<scoped_refptr<CompositorLayerResource> > LayerList; + LayerList layers_; + + // Release callback map for texture and image. + typedef CompositorLayerResource::ReleaseCallback ReleaseCallback; + typedef std::map<int32_t, ReleaseCallback> ReleaseCallbackMap; + ReleaseCallbackMap release_callback_map_; + + // The last resource id for texture or image. + mutable int32_t last_resource_id_; + + DISALLOW_COPY_AND_ASSIGN(CompositorResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_COMPOSITOR_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/device_enumeration_resource_helper.cc b/chromium/ppapi/proxy/device_enumeration_resource_helper.cc index e8d63e1dbdf..18b1939d5ba 100644 --- a/chromium/ppapi/proxy/device_enumeration_resource_helper.cc +++ b/chromium/ppapi/proxy/device_enumeration_resource_helper.cc @@ -36,24 +36,6 @@ DeviceEnumerationResourceHelper::DeviceEnumerationResourceHelper( DeviceEnumerationResourceHelper::~DeviceEnumerationResourceHelper() { } -int32_t DeviceEnumerationResourceHelper::EnumerateDevices0_2( - PP_Resource* devices, - scoped_refptr<TrackedCallback> callback) { - if (pending_enumerate_devices_) - return PP_ERROR_INPROGRESS; - if (!devices) - return PP_ERROR_BADARGUMENT; - - pending_enumerate_devices_ = true; - PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg; - owner_->Call<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>( - PluginResource::RENDERER, msg, - base::Bind( - &DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply0_2, - AsWeakPtr(), devices, callback)); - return PP_OK_COMPLETIONPENDING; -} - int32_t DeviceEnumerationResourceHelper::EnumerateDevices( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) { @@ -111,12 +93,12 @@ int32_t DeviceEnumerationResourceHelper::MonitorDeviceChange( bool DeviceEnumerationResourceHelper::HandleReply( const ResourceMessageReplyParams& params, const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(DeviceEnumerationResourceHelper, msg) + PPAPI_BEGIN_MESSAGE_MAP(DeviceEnumerationResourceHelper, msg) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange, OnPluginMsgNotifyDeviceChange) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(return false) - IPC_END_MESSAGE_MAP() + PPAPI_END_MESSAGE_MAP() return true; } @@ -132,27 +114,6 @@ void DeviceEnumerationResourceHelper::LastPluginRefWasDeleted() { // that properly. } -void DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply0_2( - PP_Resource* devices_resource, - scoped_refptr<TrackedCallback> callback, - const ResourceMessageReplyParams& params, - const std::vector<DeviceRefData>& devices) { - pending_enumerate_devices_ = false; - - // We shouldn't access |devices_resource| if the callback has been called, - // which is possible if the last plugin reference to the corresponding - // resource has gone away, and the callback has been aborted. - if (!TrackedCallback::IsPending(callback)) - return; - - if (params.result() == PP_OK) { - *devices_resource = PPB_DeviceRef_Shared::CreateResourceArray( - OBJECT_IS_PROXY, owner_->pp_instance(), devices); - } - - callback->Run(params.result()); -} - void DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback, diff --git a/chromium/ppapi/proxy/device_enumeration_resource_helper.h b/chromium/ppapi/proxy/device_enumeration_resource_helper.h index a2574ec6461..cea31537df2 100644 --- a/chromium/ppapi/proxy/device_enumeration_resource_helper.h +++ b/chromium/ppapi/proxy/device_enumeration_resource_helper.h @@ -37,8 +37,6 @@ class PPAPI_PROXY_EXPORT DeviceEnumerationResourceHelper explicit DeviceEnumerationResourceHelper(PluginResource* owner); ~DeviceEnumerationResourceHelper(); - int32_t EnumerateDevices0_2(PP_Resource* devices, - scoped_refptr<TrackedCallback> callback); int32_t EnumerateDevices(const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback); int32_t EnumerateDevicesSync(const PP_ArrayOutput& output); @@ -52,11 +50,6 @@ class PPAPI_PROXY_EXPORT DeviceEnumerationResourceHelper void LastPluginRefWasDeleted(); private: - void OnPluginMsgEnumerateDevicesReply0_2( - PP_Resource* devices_resource, - scoped_refptr<TrackedCallback> callback, - const ResourceMessageReplyParams& params, - const std::vector<DeviceRefData>& devices); void OnPluginMsgEnumerateDevicesReply( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback, diff --git a/chromium/ppapi/proxy/dispatch_reply_message.h b/chromium/ppapi/proxy/dispatch_reply_message.h index a380cdcf97b..1a53e864fd6 100644 --- a/chromium/ppapi/proxy/dispatch_reply_message.h +++ b/chromium/ppapi/proxy/dispatch_reply_message.h @@ -129,6 +129,16 @@ void DispatchResourceReplyOrDefaultParams( (obj->*method)(reply_params); } +// When using PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL* below, use this macro to +// begin the map instead of IPC_BEGIN_MESSAGE_MAP. The reason is that the macros +// in src/ipc are all closely tied together, and there might be errors for +// unused variables or other errors if they're used with these macros. +#define PPAPI_BEGIN_MESSAGE_MAP(class_name, msg) \ + { \ + typedef class_name _IpcMessageHandlerClass; \ + const IPC::Message& ipc_message__ = msg; \ + switch (ipc_message__.type()) { \ + // Note that this only works for message with 1 or more parameters. For // 0-parameter messages you need to use the _0 version below (since there are // no params in the message). @@ -158,6 +168,10 @@ void DispatchResourceReplyOrDefaultParams( } \ break; +#define PPAPI_END_MESSAGE_MAP() \ + } \ +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/dispatcher.cc b/chromium/ppapi/proxy/dispatcher.cc index 3b18932447a..786c24d8b07 100644 --- a/chromium/ppapi/proxy/dispatcher.cc +++ b/chromium/ppapi/proxy/dispatcher.cc @@ -14,6 +14,10 @@ #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/var_serialization_rules.h" +namespace IPC { +class MessageFilter; +} + namespace ppapi { namespace proxy { @@ -26,10 +30,6 @@ Dispatcher::Dispatcher(PP_GetInterface_Func local_get_interface, Dispatcher::~Dispatcher() { } -void Dispatcher::AddFilter(IPC::Listener* listener) { - filters_.push_back(listener); -} - InterfaceProxy* Dispatcher::GetInterfaceProxy(ApiID id) { InterfaceProxy* proxy = proxies_[id].get(); if (!proxy) { @@ -47,12 +47,7 @@ InterfaceProxy* Dispatcher::GetInterfaceProxy(ApiID id) { return proxy; } -base::MessageLoopProxy* Dispatcher::GetIPCMessageLoop() { - return delegate()->GetIPCMessageLoop(); -} - -void Dispatcher::AddIOThreadMessageFilter( - IPC::ChannelProxy::MessageFilter* filter) { +void Dispatcher::AddIOThreadMessageFilter(IPC::MessageFilter* filter) { // Our filter is refcounted. The channel will call the destruct method on the // filter when the channel is done with it, so the corresponding Release() // happens there. diff --git a/chromium/ppapi/proxy/dispatcher.h b/chromium/ppapi/proxy/dispatcher.h index 7bb2c7ec2a7..68d67fe4d8b 100644 --- a/chromium/ppapi/proxy/dispatcher.h +++ b/chromium/ppapi/proxy/dispatcher.h @@ -13,7 +13,6 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/tracked_objects.h" -#include "ipc/ipc_channel_proxy.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_module.h" #include "ppapi/c/ppp.h" @@ -23,8 +22,11 @@ #include "ppapi/proxy/plugin_var_tracker.h" #include "ppapi/shared_impl/api_id.h" -namespace ppapi { +namespace IPC { +class MessageFilter; +} +namespace ppapi { namespace proxy { class VarSerializationRules; @@ -51,8 +53,6 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel { // browser side. virtual bool IsPlugin() const = 0; - void AddFilter(IPC::Listener* listener); - VarSerializationRules* serialization_rules() const { return serialization_rules_.get(); } @@ -62,19 +62,8 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel { // created so far. InterfaceProxy* GetInterfaceProxy(ApiID id); - // Returns the pointer to the IO thread for processing IPC messages. - // TODO(brettw) remove this. It's a hack to support the Flash - // ModuleLocalThreadAdapter. When the thread stuff is sorted out, this - // implementation detail should be hidden. - base::MessageLoopProxy* GetIPCMessageLoop(); - // Adds the given filter to the IO thread. Takes ownership of the pointer. - void AddIOThreadMessageFilter(IPC::ChannelProxy::MessageFilter* filter); - - // TODO(brettw): What is this comment referring to? - // Called if the remote side is declaring to us which interfaces it supports - // so we don't have to query for each one. We'll pre-create proxies for - // each of the given interfaces. + void AddIOThreadMessageFilter(IPC::MessageFilter* filter); // IPC::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; @@ -97,18 +86,12 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel { // default implementation does nothing, derived classes can override. virtual void OnInvalidMessageReceived(); - protected: - std::vector<IPC::Listener*> filters_; - private: - friend class HostDispatcherTest; friend class PluginDispatcherTest; // Lists all lazily-created interface proxies. scoped_ptr<InterfaceProxy> proxies_[API_ID_COUNT]; - bool disallow_trusted_interfaces_; - PP_GetInterface_Func local_get_interface_; scoped_refptr<VarSerializationRules> serialization_rules_; diff --git a/chromium/ppapi/proxy/extensions_common_resource.cc b/chromium/ppapi/proxy/extensions_common_resource.cc deleted file mode 100644 index 40d03f97822..00000000000 --- a/chromium/ppapi/proxy/extensions_common_resource.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 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 "ppapi/proxy/extensions_common_resource.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/resource_message_params.h" -#include "ppapi/shared_impl/tracked_callback.h" -#include "ppapi/shared_impl/var_value_conversions.h" - -namespace ppapi { -namespace proxy { - -ExtensionsCommonResource::ExtensionsCommonResource(Connection connection, - PP_Instance instance) - : PluginResource(connection, instance) { - SendCreate(RENDERER, PpapiHostMsg_ExtensionsCommon_Create()); - SendCreate(BROWSER, PpapiHostMsg_ExtensionsCommon_Create()); -} - -ExtensionsCommonResource::~ExtensionsCommonResource() { -} - -thunk::ExtensionsCommon_API* -ExtensionsCommonResource::AsExtensionsCommon_API() { - return this; -} - -int32_t ExtensionsCommonResource::CallRenderer( - const std::string& request_name, - const std::vector<PP_Var>& input_args, - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback) { - return CommonCall(RENDERER, request_name, input_args, output_args, callback); -} - -void ExtensionsCommonResource::PostRenderer(const std::string& request_name, - const std::vector<PP_Var>& args) { - CommonPost(RENDERER, request_name, args); -} - -int32_t ExtensionsCommonResource::CallBrowser( - const std::string& request_name, - const std::vector<PP_Var>& input_args, - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback) { - return CommonCall(BROWSER, request_name, input_args, output_args, callback); -} - -void ExtensionsCommonResource::PostBrowser(const std::string& request_name, - const std::vector<PP_Var>& args) { - CommonPost(BROWSER, request_name, args); -} - -int32_t ExtensionsCommonResource::CommonCall( - Destination dest, - const std::string& request_name, - const std::vector<PP_Var>& input_args, - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback) { - // TODO(yzshen): CreateValueFromVar() doesn't generate null fields for - // dictionary values. That is the expected behavior for most APIs. If later we - // want to support APIs that require to preserve null fields in dictionaries, - // we should change the behavior to always preserve null fields at the plugin - // side, and figure out whether they should be stripped at the renderer side. - scoped_ptr<base::ListValue> input_args_value( - CreateListValueFromVarVector(input_args)); - if (!input_args_value.get()) { - LOG(WARNING) << "Failed to convert PP_Var input arguments."; - return PP_ERROR_BADARGUMENT; - } - - PluginResource::Call<PpapiPluginMsg_ExtensionsCommon_CallReply>( - dest, - PpapiHostMsg_ExtensionsCommon_Call(request_name, *input_args_value), - base::Bind(&ExtensionsCommonResource::OnPluginMsgCallReply, - base::Unretained(this), output_args, callback)); - return PP_OK_COMPLETIONPENDING; -} - -void ExtensionsCommonResource::CommonPost(Destination dest, - const std::string& request_name, - const std::vector<PP_Var>& args) { - scoped_ptr<base::ListValue> args_value(CreateListValueFromVarVector(args)); - if (!args_value.get()) { - LOG(WARNING) << "Failed to convert PP_Var input arguments."; - return; - } - - PluginResource::Post( - dest, PpapiHostMsg_ExtensionsCommon_Post(request_name, *args_value)); -} - -void ExtensionsCommonResource::OnPluginMsgCallReply( - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback, - const ResourceMessageReplyParams& params, - const base::ListValue& output) { - // |output_args| may be invalid and shouldn't be accessed if the callback has - // been called. - if (!TrackedCallback::IsPending(callback)) - return; - - int32_t result = params.result(); - - // If the size doesn't match, something must be really wrong. - CHECK_EQ(output_args.size(), output.GetSize()); - - std::vector<PP_Var> output_vars; - if (CreateVarVectorFromListValue(output, &output_vars)) { - DCHECK_EQ(output_args.size(), output_vars.size()); - std::vector<PP_Var>::const_iterator src_iter = output_vars.begin(); - std::vector<PP_Var*>::const_iterator dest_iter = output_args.begin(); - for (; src_iter != output_vars.end() && dest_iter != output_args.end(); - ++src_iter, ++dest_iter) { - **dest_iter = *src_iter; - } - } else { - NOTREACHED(); - result = PP_ERROR_FAILED; - for (std::vector<PP_Var*>::const_iterator dest_iter = output_args.begin(); - dest_iter != output_args.end(); - ++dest_iter) { - **dest_iter = PP_MakeUndefined(); - } - } - - callback->Run(result); -} - -} // namespace proxy -} // namespace ppapi diff --git a/chromium/ppapi/proxy/extensions_common_resource.h b/chromium/ppapi/proxy/extensions_common_resource.h deleted file mode 100644 index b3ec366a0d9..00000000000 --- a/chromium/ppapi/proxy/extensions_common_resource.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 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. - -#ifndef PPAPI_PROXY_EXTENSIONS_COMMON_RESOURCE_H_ -#define PPAPI_PROXY_EXTENSIONS_COMMON_RESOURCE_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ppapi/proxy/connection.h" -#include "ppapi/proxy/plugin_resource.h" -#include "ppapi/thunk/extensions_common_api.h" - -namespace base { -class ListValue; -} - -namespace ppapi { -namespace proxy { - -class ResourceMessageReplyParams; - -class ExtensionsCommonResource : public PluginResource, - public thunk::ExtensionsCommon_API { - public: - ExtensionsCommonResource(Connection connection, PP_Instance instance); - virtual ~ExtensionsCommonResource(); - - // Resource overrides. - virtual thunk::ExtensionsCommon_API* AsExtensionsCommon_API() OVERRIDE; - - // ExtensionsCommon_API implementation. - virtual int32_t CallRenderer( - const std::string& request_name, - const std::vector<PP_Var>& input_args, - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual void PostRenderer(const std::string& request_name, - const std::vector<PP_Var>& args) OVERRIDE; - virtual int32_t CallBrowser(const std::string& request_name, - const std::vector<PP_Var>& input_args, - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual void PostBrowser(const std::string& request_name, - const std::vector<PP_Var>& args) OVERRIDE; - - private: - int32_t CommonCall(Destination dest, - const std::string& request_name, - const std::vector<PP_Var>& input_args, - const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback); - void CommonPost(Destination dest, - const std::string& request_name, - const std::vector<PP_Var>& args); - - void OnPluginMsgCallReply(const std::vector<PP_Var*>& output_args, - scoped_refptr<TrackedCallback> callback, - const ResourceMessageReplyParams& params, - const base::ListValue& output); - - DISALLOW_COPY_AND_ASSIGN(ExtensionsCommonResource); -}; - -} // namespace proxy -} // namespace ppapi - -#endif // PPAPI_PROXY_EXTENSIONS_COMMON_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/file_chooser_resource.cc b/chromium/ppapi/proxy/file_chooser_resource.cc index 9847e295c9c..06425686cf7 100644 --- a/chromium/ppapi/proxy/file_chooser_resource.cc +++ b/chromium/ppapi/proxy/file_chooser_resource.cc @@ -84,7 +84,7 @@ void FileChooserResource::PopulateAcceptTypes( for (size_t i = 0; i < type_list.size(); ++i) { std::string type = type_list[i]; - TrimWhitespaceASCII(type, TRIM_ALL, &type); + base::TrimWhitespaceASCII(type, base::TRIM_ALL, &type); // If the type is a single character, it definitely cannot be valid. In the // case of a file extension it would be a single ".". In the case of a MIME diff --git a/chromium/ppapi/proxy/file_io_resource.cc b/chromium/ppapi/proxy/file_io_resource.cc index ad0718709c3..29335ba90f4 100644 --- a/chromium/ppapi/proxy/file_io_resource.cc +++ b/chromium/ppapi/proxy/file_io_resource.cc @@ -39,8 +39,7 @@ void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) { } // File thread task to close the file handle. -void DoClose(base::PlatformFile file) { - base::ClosePlatformFile(file); +void DoClose(base::File auto_close_file) { } } // namespace @@ -48,26 +47,25 @@ void DoClose(base::PlatformFile file) { namespace ppapi { namespace proxy { -FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHandleHolder> file_handle) - : file_handle_(file_handle) { - DCHECK(file_handle_); +FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHolder> file_holder) + : file_holder_(file_holder) { + DCHECK(file_holder_); } FileIOResource::QueryOp::~QueryOp() { } int32_t FileIOResource::QueryOp::DoWork() { - return base::GetPlatformFileInfo(file_handle_->raw_handle(), &file_info_) ? - PP_OK : PP_ERROR_FAILED; + return file_holder_->file()->GetInfo(&file_info_) ? PP_OK : PP_ERROR_FAILED; } -FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHandleHolder> file_handle, +FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHolder> file_holder, int64_t offset, int32_t bytes_to_read) - : file_handle_(file_handle), + : file_holder_(file_holder), offset_(offset), bytes_to_read_(bytes_to_read) { - DCHECK(file_handle_); + DCHECK(file_holder_); } FileIOResource::ReadOp::~ReadOp() { @@ -76,13 +74,42 @@ FileIOResource::ReadOp::~ReadOp() { int32_t FileIOResource::ReadOp::DoWork() { DCHECK(!buffer_.get()); buffer_.reset(new char[bytes_to_read_]); - return base::ReadPlatformFile( - file_handle_->raw_handle(), offset_, buffer_.get(), bytes_to_read_); + return file_holder_->file()->Read(offset_, buffer_.get(), bytes_to_read_); +} + +FileIOResource::WriteOp::WriteOp(scoped_refptr<FileHolder> file_holder, + int64_t offset, + scoped_ptr<char[]> buffer, + int32_t bytes_to_write, + bool append) + : file_holder_(file_holder), + offset_(offset), + buffer_(buffer.Pass()), + bytes_to_write_(bytes_to_write), + append_(append) { +} + +FileIOResource::WriteOp::~WriteOp() { +} + +int32_t FileIOResource::WriteOp::DoWork() { + // In append mode, we can't call Write, since NaCl doesn't implement fcntl, + // causing the function to call pwrite, which is incorrect. + if (append_) { + return file_holder_->file()->WriteAtCurrentPos(buffer_.get(), + bytes_to_write_); + } else { + return file_holder_->file()->Write(offset_, buffer_.get(), bytes_to_write_); + } } FileIOResource::FileIOResource(Connection connection, PP_Instance instance) : PluginResource(connection, instance), file_system_type_(PP_FILESYSTEMTYPE_INVALID), + open_flags_(0), + max_written_offset_(0), + append_mode_write_amount_(0), + check_quota_(false), called_close_(false) { SendCreate(BROWSER, PpapiHostMsg_FileIO_Create()); } @@ -113,6 +140,7 @@ int32_t FileIOResource::Open(PP_Resource file_ref, if (rv != PP_OK) return rv; + open_flags_ = open_flags; file_system_type_ = create_info.file_system_type; if (create_info.file_system_plugin_resource) { @@ -148,7 +176,7 @@ int32_t FileIOResource::Query(PP_FileInfo* info, return rv; if (!info) return PP_ERROR_BADARGUMENT; - if (!FileHandleHolder::IsValid(file_handle_)) + if (!FileHolder::IsValid(file_holder_)) return PP_ERROR_FAILED; state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); @@ -156,21 +184,21 @@ int32_t FileIOResource::Query(PP_FileInfo* info, // If the callback is blocking, perform the task on the calling thread. if (callback->is_blocking()) { int32_t result = PP_ERROR_FAILED; - base::PlatformFileInfo file_info; + base::File::Info file_info; // The plugin could release its reference to this instance when we release // the proxy lock below. scoped_refptr<FileIOResource> protect(this); { // Release the proxy lock while making a potentially slow file call. ProxyAutoUnlock unlock; - if (base::GetPlatformFileInfo(file_handle_->raw_handle(), &file_info)) + if (file_holder_->file()->GetInfo(&file_info)) result = PP_OK; } if (result == PP_OK) { // This writes the file info into the plugin's PP_FileInfo struct. - ppapi::PlatformFileInfoToPepperFileInfo(file_info, - file_system_type_, - info); + ppapi::FileInfoToPepperFileInfo(file_info, + file_system_type_, + info); } state_manager_.SetOperationFinished(); return result; @@ -178,7 +206,7 @@ int32_t FileIOResource::Query(PP_FileInfo* info, // For the non-blocking case, post a task to the file thread and add a // completion task to write the result. - scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_)); + scoped_refptr<QueryOp> query_op(new QueryOp(file_holder_)); base::PostTaskAndReplyWithResult( PpapiGlobals::Get()->GetFileTaskRunner(), FROM_HERE, @@ -239,22 +267,58 @@ int32_t FileIOResource::Write(int64_t offset, const char* buffer, int32_t bytes_to_write, scoped_refptr<TrackedCallback> callback) { + if (!buffer) + return PP_ERROR_FAILED; + if (offset < 0 || bytes_to_write < 0) + return PP_ERROR_FAILED; + if (!FileHolder::IsValid(file_holder_)) + return PP_ERROR_FAILED; + int32_t rv = state_manager_.CheckOperationState( FileIOStateManager::OPERATION_WRITE, true); if (rv != PP_OK) return rv; - // TODO(brettw) it would be nice to use a shared memory buffer for large - // writes rather than having to copy to a string (which will involve a number - // of extra copies to serialize over IPC). - bytes_to_write = std::min(bytes_to_write, kMaxReadWriteSize); - Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, - PpapiHostMsg_FileIO_Write(offset, std::string(buffer, bytes_to_write)), - base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, - callback)); - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); - return PP_OK_COMPLETIONPENDING; + + if (check_quota_) { + int64_t increase = 0; + uint64_t max_offset = 0; + bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; + if (append) { + increase = bytes_to_write; + } else { + uint64_t max_offset = offset + bytes_to_write; + if (max_offset > static_cast<uint64_t>(kint64max)) + return PP_ERROR_FAILED; // amount calculation would overflow. + increase = static_cast<int64_t>(max_offset) - max_written_offset_; + } + + if (increase > 0) { + // Request a quota reservation. This makes the Write asynchronous, so we + // must copy the plugin's buffer. + scoped_ptr<char[]> copy(new char[bytes_to_write]); + memcpy(copy.get(), buffer, bytes_to_write); + int64_t result = + file_system_resource_->AsPPB_FileSystem_API()->RequestQuota( + increase, + base::Bind(&FileIOResource::OnRequestWriteQuotaComplete, + this, + offset, + base::Passed(©), + bytes_to_write, + callback)); + if (result == PP_OK_COMPLETIONPENDING) + return PP_OK_COMPLETIONPENDING; + DCHECK(result == increase); + + if (append) + append_mode_write_amount_ += bytes_to_write; + else + max_written_offset_ = max_offset; + } + } + return WriteValidated(offset, buffer, bytes_to_write, callback); } int32_t FileIOResource::SetLength(int64_t length, @@ -263,13 +327,30 @@ int32_t FileIOResource::SetLength(int64_t length, FileIOStateManager::OPERATION_EXCLUSIVE, true); if (rv != PP_OK) return rv; + if (length < 0) + return PP_ERROR_FAILED; - Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, - PpapiHostMsg_FileIO_SetLength(length), - base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, - callback)); + if (check_quota_) { + int64_t increase = length - max_written_offset_; + if (increase > 0) { + int32_t result = + file_system_resource_->AsPPB_FileSystem_API()->RequestQuota( + increase, + base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete, + this, + length, callback)); + if (result == PP_OK_COMPLETIONPENDING) { + state_manager_.SetPendingOperation( + FileIOStateManager::OPERATION_EXCLUSIVE); + return PP_OK_COMPLETIONPENDING; + } + DCHECK(result == increase); + max_written_offset_ = length; + } + } state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); + SetLengthValidated(length, callback); return PP_OK_COMPLETIONPENDING; } @@ -288,15 +369,39 @@ int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) { return PP_OK_COMPLETIONPENDING; } +int64_t FileIOResource::GetMaxWrittenOffset() const { + return max_written_offset_; +} + +int64_t FileIOResource::GetAppendModeWriteAmount() const { + return append_mode_write_amount_; +} + +void FileIOResource::SetMaxWrittenOffset(int64_t max_written_offset) { + max_written_offset_ = max_written_offset; +} + +void FileIOResource::SetAppendModeWriteAmount( + int64_t append_mode_write_amount) { + append_mode_write_amount_ = append_mode_write_amount; +} + void FileIOResource::Close() { if (called_close_) return; called_close_ = true; - if (file_handle_) - file_handle_ = NULL; + if (check_quota_) { + check_quota_ = false; + file_system_resource_->AsPPB_FileSystem_API()->CloseQuotaFile( + pp_resource()); + } + + if (file_holder_) + file_holder_ = NULL; - Post(BROWSER, PpapiHostMsg_FileIO_Close()); + Post(BROWSER, PpapiHostMsg_FileIO_Close( + FileGrowth(max_written_offset_, append_mode_write_amount_))); } int32_t FileIOResource::RequestOSFileHandle( @@ -316,22 +421,22 @@ int32_t FileIOResource::RequestOSFileHandle( return PP_OK_COMPLETIONPENDING; } -FileIOResource::FileHandleHolder::FileHandleHolder(PP_FileHandle file_handle) - : raw_handle_(file_handle) { +FileIOResource::FileHolder::FileHolder(PP_FileHandle file_handle) + : file_(file_handle) { } // static -bool FileIOResource::FileHandleHolder::IsValid( - const scoped_refptr<FileIOResource::FileHandleHolder>& handle) { - return handle && (handle->raw_handle() != base::kInvalidPlatformFileValue); +bool FileIOResource::FileHolder::IsValid( + const scoped_refptr<FileIOResource::FileHolder>& handle) { + return handle && handle->file_.IsValid(); } -FileIOResource::FileHandleHolder::~FileHandleHolder() { - if (raw_handle_ != base::kInvalidPlatformFileValue) { +FileIOResource::FileHolder::~FileHolder() { + if (file_.IsValid()) { base::TaskRunner* file_task_runner = PpapiGlobals::Get()->GetFileTaskRunner(); file_task_runner->PostTask(FROM_HERE, - base::Bind(&DoClose, raw_handle_)); + base::Bind(&DoClose, Passed(&file_))); } } @@ -341,7 +446,7 @@ int32_t FileIOResource::ReadValidated(int64_t offset, scoped_refptr<TrackedCallback> callback) { if (bytes_to_read < 0) return PP_ERROR_FAILED; - if (!FileHandleHolder::IsValid(file_handle_)) + if (!FileHolder::IsValid(file_holder_)) return PP_ERROR_FAILED; state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); @@ -357,8 +462,7 @@ int32_t FileIOResource::ReadValidated(int64_t offset, if (buffer) { // Release the proxy lock while making a potentially slow file call. ProxyAutoUnlock unlock; - result = base::ReadPlatformFile( - file_handle_->raw_handle(), offset, buffer, bytes_to_read); + result = file_holder_->file()->Read(offset, buffer, bytes_to_read); if (result < 0) result = PP_ERROR_FAILED; } @@ -368,7 +472,7 @@ int32_t FileIOResource::ReadValidated(int64_t offset, // For the non-blocking case, post a task to the file thread. scoped_refptr<ReadOp> read_op( - new ReadOp(file_handle_, offset, bytes_to_read)); + new ReadOp(file_holder_, offset, bytes_to_read)); base::PostTaskAndReplyWithResult( PpapiGlobals::Get()->GetFileTaskRunner(), FROM_HERE, @@ -380,6 +484,62 @@ int32_t FileIOResource::ReadValidated(int64_t offset, return PP_OK_COMPLETIONPENDING; } +int32_t FileIOResource::WriteValidated( + int64_t offset, + const char* buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback) { + bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; + if (callback->is_blocking()) { + int32_t result; + { + // Release the proxy lock while making a potentially slow file call. + ProxyAutoUnlock unlock; + if (append) { + result = file_holder_->file()->WriteAtCurrentPos(buffer, + bytes_to_write); + } else { + result = file_holder_->file()->Write(offset, buffer, bytes_to_write); + } + } + if (result < 0) + result = PP_ERROR_FAILED; + + state_manager_.SetOperationFinished(); + return result; + } + + // For the non-blocking case, post a task to the file thread. We must copy the + // plugin's buffer at this point. + scoped_ptr<char[]> copy(new char[bytes_to_write]); + memcpy(copy.get(), buffer, bytes_to_write); + scoped_refptr<WriteOp> write_op( + new WriteOp(file_holder_, offset, copy.Pass(), bytes_to_write, append)); + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(), + FROM_HERE, + Bind(&FileIOResource::WriteOp::DoWork, write_op), + RunWhileLocked(Bind(&TrackedCallback::Run, callback))); + callback->set_completion_task(Bind(&FileIOResource::OnWriteComplete, this)); + + return PP_OK_COMPLETIONPENDING; +} + +void FileIOResource::SetLengthValidated( + int64_t length, + scoped_refptr<TrackedCallback> callback) { + Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, + PpapiHostMsg_FileIO_SetLength(length), + base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, + callback)); + + // On the browser side we grow |max_written_offset_| monotonically, due to the + // unpredictable ordering of plugin side Write and SetLength calls. Match that + // behavior here. + if (max_written_offset_ < length) + max_written_offset_ = length; +} + int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op, PP_FileInfo* info, int32_t result) { @@ -388,9 +548,9 @@ int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op, if (result == PP_OK) { // This writes the file info into the plugin's PP_FileInfo struct. - ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(), - file_system_type_, - info); + ppapi::FileInfoToPepperFileInfo(query_op->file_info(), + file_system_type_, + info); } state_manager_.SetOperationFinished(); return result; @@ -416,6 +576,73 @@ int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op, return result; } +void FileIOResource::OnRequestWriteQuotaComplete( + int64_t offset, + scoped_ptr<char[]> buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback, + int64_t granted) { + DCHECK(granted >= 0); + if (granted == 0) { + callback->Run(PP_ERROR_NOQUOTA); + return; + } + if (open_flags_ & PP_FILEOPENFLAG_APPEND) { + DCHECK_LE(bytes_to_write, granted); + append_mode_write_amount_ += bytes_to_write; + } else { + DCHECK_LE(offset + bytes_to_write - max_written_offset_, granted); + + int64_t max_offset = offset + bytes_to_write; + if (max_written_offset_ < max_offset) + max_written_offset_ = max_offset; + } + + if (callback->is_blocking()) { + int32_t result = + WriteValidated(offset, buffer.get(), bytes_to_write, callback); + DCHECK(result != PP_OK_COMPLETIONPENDING); + callback->Run(result); + } else { + bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; + scoped_refptr<WriteOp> write_op(new WriteOp( + file_holder_, offset, buffer.Pass(), bytes_to_write, append)); + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(), + FROM_HERE, + Bind(&FileIOResource::WriteOp::DoWork, write_op), + RunWhileLocked(Bind(&TrackedCallback::Run, callback))); + callback->set_completion_task(Bind(&FileIOResource::OnWriteComplete, this)); + } +} + +void FileIOResource::OnRequestSetLengthQuotaComplete( + int64_t length, + scoped_refptr<TrackedCallback> callback, + int64_t granted) { + DCHECK(granted >= 0); + if (granted == 0) { + callback->Run(PP_ERROR_NOQUOTA); + return; + } + + DCHECK_LE(length - max_written_offset_, granted); + if (max_written_offset_ < length) + max_written_offset_ = length; + SetLengthValidated(length, callback); +} + +int32_t FileIOResource::OnWriteComplete(int32_t result) { + DCHECK(state_manager_.get_pending_operation() == + FileIOStateManager::OPERATION_WRITE); + // |result| is the return value of WritePlatformFile; -1 indicates failure. + if (result < 0) + result = PP_ERROR_FAILED; + + state_manager_.SetOperationFinished(); + return result; +} + void FileIOResource::OnPluginMsgGeneralComplete( scoped_refptr<TrackedCallback> callback, const ResourceMessageReplyParams& params) { @@ -431,20 +658,31 @@ void FileIOResource::OnPluginMsgGeneralComplete( void FileIOResource::OnPluginMsgOpenFileComplete( scoped_refptr<TrackedCallback> callback, - const ResourceMessageReplyParams& params) { + const ResourceMessageReplyParams& params, + PP_Resource quota_file_system, + int64_t max_written_offset) { DCHECK(state_manager_.get_pending_operation() == FileIOStateManager::OPERATION_EXCLUSIVE); // Release the FileRef resource. file_ref_ = NULL; - if (params.result() == PP_OK) + int32_t result = params.result(); + if (result == PP_OK) { state_manager_.SetOpenSucceed(); - int32_t result = params.result(); - IPC::PlatformFileForTransit transit_file; - if ((result == PP_OK) && params.TakeFileHandleAtIndex(0, &transit_file)) { - file_handle_ = new FileHandleHolder( - IPC::PlatformFileForTransitToPlatformFile(transit_file)); + if (quota_file_system) { + DCHECK(quota_file_system == file_system_resource_->pp_resource()); + check_quota_ = true; + max_written_offset_ = max_written_offset; + file_system_resource_->AsPPB_FileSystem_API()->OpenQuotaFile( + pp_resource()); + } + + IPC::PlatformFileForTransit transit_file; + if (params.TakeFileHandleAtIndex(0, &transit_file)) { + file_holder_ = new FileHolder( + IPC::PlatformFileForTransitToPlatformFile(transit_file)); + } } // End this operation now, so the user's callback can execute another FileIO // operation, assuming there are no other pending operations. diff --git a/chromium/ppapi/proxy/file_io_resource.h b/chromium/ppapi/proxy/file_io_resource.h index bfdf24fb602..c9e15df01db 100644 --- a/chromium/ppapi/proxy/file_io_resource.h +++ b/chromium/ppapi/proxy/file_io_resource.h @@ -7,6 +7,7 @@ #include <string> +#include "base/files/file.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "ppapi/c/private/pp_file_handle.h" @@ -57,15 +58,19 @@ class PPAPI_PROXY_EXPORT FileIOResource scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t SetLength(int64_t length, scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int64_t GetMaxWrittenOffset() const OVERRIDE; + virtual int64_t GetAppendModeWriteAmount() const OVERRIDE; + virtual void SetMaxWrittenOffset(int64_t max_written_offset) OVERRIDE; + virtual void SetAppendModeWriteAmount( + int64_t append_mode_write_amount) OVERRIDE; virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual void Close() OVERRIDE; virtual int32_t RequestOSFileHandle( PP_FileHandle* handle, scoped_refptr<TrackedCallback> callback) OVERRIDE; - private: - // FileHandleHolder is used to guarantee that file operations will have a - // valid FD to operate on, even if they're in a different thread. + // FileHolder is used to guarantee that file operations will have a valid FD + // to operate on, even if they're in a different thread. // If instead we just passed the raw FD, the FD could be closed before the // file operation has a chance to run. It could interact with an invalid FD, // or worse, the FD value could be reused if another file is opened quickly @@ -75,51 +80,56 @@ class PPAPI_PROXY_EXPORT FileIOResource // // Operations that run on a background thread should hold one of these to // ensure they have a valid file descriptor. The file handle is only closed - // when the last reference to the FileHandleHolder is removed, so we are - // guaranteed to operate on the correct file descriptor. It *is* still - // possible that the FileIOResource will be destroyed and "Abort" callbacks - // just before the operation does its task (e.g., Reading). In that case, we - // might for example Read from a file even though the FileIO has been - // destroyed and the plugin's callback got a PP_ERROR_ABORTED result. In the - // case of a write, we could write some data to the file despite the plugin - // receiving a PP_ERROR_ABORTED instead of a successful result. - class FileHandleHolder : public base::RefCountedThreadSafe<FileHandleHolder> { + // when the last reference to the FileHolder is removed, so we are guaranteed + // to operate on the correct file descriptor. It *is* still possible that the + // FileIOResource will be destroyed and "Abort" callbacks just before the + // operation does its task (e.g., Reading). In that case, we might for example + // Read from a file even though the FileIO has been destroyed and the plugin's + // callback got a PP_ERROR_ABORTED result. In the case of a write, we could + // write some data to the file despite the plugin receiving a + // PP_ERROR_ABORTED instead of a successful result. + class FileHolder : public base::RefCountedThreadSafe<FileHolder> { public: - explicit FileHandleHolder(PP_FileHandle file_handle_); - PP_FileHandle raw_handle() { - return raw_handle_; + explicit FileHolder(PP_FileHandle file_handle); + base::File* file() { + return &file_; } static bool IsValid( - const scoped_refptr<FileIOResource::FileHandleHolder>& handle); + const scoped_refptr<FileIOResource::FileHolder>& handle); private: - friend class base::RefCountedThreadSafe<FileHandleHolder>; - ~FileHandleHolder(); - PP_FileHandle raw_handle_; + friend class base::RefCountedThreadSafe<FileHolder>; + ~FileHolder(); + base::File file_; }; + scoped_refptr<FileHolder> file_holder() { + return file_holder_; + } + + private: // Class to perform file query operations across multiple threads. class QueryOp : public base::RefCountedThreadSafe<QueryOp> { public: - explicit QueryOp(scoped_refptr<FileHandleHolder> file_handle); + explicit QueryOp(scoped_refptr<FileHolder> file_holder); // Queries the file. Called on the file thread (non-blocking) or the plugin // thread (blocking). This should not be called when we hold the proxy lock. int32_t DoWork(); - const base::PlatformFileInfo& file_info() const { return file_info_; } + const base::File::Info& file_info() const { return file_info_; } private: friend class base::RefCountedThreadSafe<QueryOp>; ~QueryOp(); - scoped_refptr<FileHandleHolder> file_handle_; - base::PlatformFileInfo file_info_; + scoped_refptr<FileHolder> file_holder_; + base::File::Info file_info_; }; // Class to perform file read operations across multiple threads. class ReadOp : public base::RefCountedThreadSafe<ReadOp> { public: - ReadOp(scoped_refptr<FileHandleHolder> file_handle, + ReadOp(scoped_refptr<FileHolder> file_holder, int64_t offset, int32_t bytes_to_read); @@ -133,16 +143,55 @@ class PPAPI_PROXY_EXPORT FileIOResource friend class base::RefCountedThreadSafe<ReadOp>; ~ReadOp(); - scoped_refptr<FileHandleHolder> file_handle_; + scoped_refptr<FileHolder> file_holder_; int64_t offset_; int32_t bytes_to_read_; scoped_ptr<char[]> buffer_; }; + // Class to perform file write operations across multiple threads. + class WriteOp : public base::RefCountedThreadSafe<WriteOp> { + public: + WriteOp(scoped_refptr<FileHolder> file_holder, + int64_t offset, + scoped_ptr<char[]> buffer, + int32_t bytes_to_write, + bool append); + + // Writes the file. Called on the file thread (non-blocking) or the plugin + // thread (blocking). This should not be called when we hold the proxy lock. + int32_t DoWork(); + + private: + friend class base::RefCountedThreadSafe<WriteOp>; + ~WriteOp(); + + scoped_refptr<FileHolder> file_holder_; + int64_t offset_; + scoped_ptr<char[]> buffer_; + int32_t bytes_to_write_; + bool append_; + }; + + void OnRequestWriteQuotaComplete(int64_t offset, + scoped_ptr<char[]> buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback, + int64_t granted); + void OnRequestSetLengthQuotaComplete(int64_t length, + scoped_refptr<TrackedCallback> callback, + int64_t granted); + int32_t ReadValidated(int64_t offset, int32_t bytes_to_read, const PP_ArrayOutput& array_output, scoped_refptr<TrackedCallback> callback); + int32_t WriteValidated(int64_t offset, + const char* buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback); + void SetLengthValidated(int64_t length, + scoped_refptr<TrackedCallback> callback); // Completion tasks for file operations that are done in the plugin. int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op, @@ -151,25 +200,33 @@ class PPAPI_PROXY_EXPORT FileIOResource int32_t OnReadComplete(scoped_refptr<ReadOp> read_op, PP_ArrayOutput array_output, int32_t result); + int32_t OnWriteComplete(int32_t result); // Reply message handlers for operations that are done in the host. void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback, const ResourceMessageReplyParams& params); void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback, - const ResourceMessageReplyParams& params); + const ResourceMessageReplyParams& params, + PP_Resource quota_file_system, + int64_t max_written_offset); void OnPluginMsgRequestOSFileHandleComplete( scoped_refptr<TrackedCallback> callback, PP_FileHandle* output_handle, const ResourceMessageReplyParams& params); - scoped_refptr<FileHandleHolder> file_handle_; + scoped_refptr<FileHolder> file_holder_; PP_FileSystemType file_system_type_; scoped_refptr<Resource> file_system_resource_; - bool called_close_; FileIOStateManager state_manager_; scoped_refptr<Resource> file_ref_; + int32_t open_flags_; + int64_t max_written_offset_; + int64_t append_mode_write_amount_; + bool check_quota_; + bool called_close_; + DISALLOW_COPY_AND_ASSIGN(FileIOResource); }; diff --git a/chromium/ppapi/proxy/file_mapping_resource.cc b/chromium/ppapi/proxy/file_mapping_resource.cc new file mode 100644 index 00000000000..c620c06dd29 --- /dev/null +++ b/chromium/ppapi/proxy/file_mapping_resource.cc @@ -0,0 +1,160 @@ +// 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. + +#include "ppapi/proxy/file_mapping_resource.h" + +#include "base/bind.h" +#include "base/numerics/safe_conversions.h" +#include "base/task_runner_util.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/shared_impl/var.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_file_io_api.h" + +namespace ppapi { +namespace proxy { + +FileMappingResource::FileMappingResource(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance) { +} + +FileMappingResource::~FileMappingResource() { +} + +thunk::PPB_FileMapping_API* FileMappingResource::AsPPB_FileMapping_API() { + return this; +} + +int32_t FileMappingResource::Map(PP_Instance /* instance */, + PP_Resource file_io, + int64_t length, + uint32_t protection, + uint32_t flags, + int64_t offset, + void** address, + scoped_refptr<TrackedCallback> callback) { + thunk::EnterResourceNoLock<thunk::PPB_FileIO_API> enter(file_io, true); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + FileIOResource* file_io_resource = + static_cast<FileIOResource*>(enter.object()); + scoped_refptr<FileIOResource::FileHolder> file_holder = + file_io_resource->file_holder(); + if (!FileIOResource::FileHolder::IsValid(file_holder)) + return PP_ERROR_FAILED; + if (length < 0 || offset < 0 || + !base::IsValueInRangeForNumericType<off_t>(offset)) { + return PP_ERROR_BADARGUMENT; + } + if (!base::IsValueInRangeForNumericType<size_t>(length)) { + return PP_ERROR_NOMEMORY; + } + + // Ensure any bits we don't recognize are zero. + if (protection & + ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) { + return PP_ERROR_BADARGUMENT; + } + if (flags & + ~(PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE | + PP_FILEMAPFLAG_FIXED)) { + return PP_ERROR_BADARGUMENT; + } + // Ensure at least one of SHARED and PRIVATE is set. + if (!(flags & (PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE))) + return PP_ERROR_BADARGUMENT; + // Ensure at most one of SHARED and PRIVATE is set. + if ((flags & PP_FILEMAPFLAG_SHARED) && + (flags & PP_FILEMAPFLAG_PRIVATE)) { + return PP_ERROR_BADARGUMENT; + } + if (!address) + return PP_ERROR_BADARGUMENT; + + base::Callback<MapResult()> map_cb( + base::Bind(&FileMappingResource::DoMapBlocking, file_holder, *address, + length, protection, flags, offset)); + if (callback->is_blocking()) { + // The plugin could release its reference to this instance when we release + // the proxy lock below. + scoped_refptr<FileMappingResource> protect(this); + MapResult map_result; + { + // Release the proxy lock while making a potentially slow file call. + ProxyAutoUnlock unlock; + map_result = map_cb.Run(); + } + OnMapCompleted(address, length, callback, map_result); + return map_result.result; + } else { + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(), + FROM_HERE, + map_cb, + RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted, + this, + base::Unretained(address), + length, + callback))); + return PP_OK_COMPLETIONPENDING; + } +} + +int32_t FileMappingResource::Unmap(PP_Instance /* instance */, + const void* address, + int64_t length, + scoped_refptr<TrackedCallback> callback) { + if (!address) + return PP_ERROR_BADARGUMENT; + if (!base::IsValueInRangeForNumericType<size_t>(length)) + return PP_ERROR_BADARGUMENT; + + base::Callback<int32_t()> unmap_cb( + base::Bind(&FileMappingResource::DoUnmapBlocking, address, length)); + if (callback->is_blocking()) { + // Release the proxy lock while making a potentially slow file call. + ProxyAutoUnlock unlock; + return unmap_cb.Run(); + } else { + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(), + FROM_HERE, + unmap_cb, + RunWhileLocked(Bind(&TrackedCallback::Run, callback))); + return PP_OK_COMPLETIONPENDING; + } +} + +int64_t FileMappingResource::GetMapPageSize(PP_Instance /* instance */) { + return DoGetMapPageSize(); +} + +void FileMappingResource::OnMapCompleted( + void** mapped_address_out_param, + int64_t length, + scoped_refptr<TrackedCallback> callback, + const MapResult& map_result) { + if (callback->aborted()) { + if (map_result.result == PP_OK) { + // If the Map operation was successful, we need to Unmap to avoid leaks. + // The plugin won't get the address, so doesn't have a chance to do the + // Unmap. + PpapiGlobals::Get()->GetFileTaskRunner()->PostTask( + FROM_HERE, + base::Bind(base::IgnoreResult(&FileMappingResource::DoUnmapBlocking), + map_result.address, + length)); + } + return; + } + if (map_result.result == PP_OK) + *mapped_address_out_param = map_result.address; + if (!callback->is_blocking()) + callback->Run(map_result.result); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/file_mapping_resource.h b/chromium/ppapi/proxy/file_mapping_resource.h new file mode 100644 index 00000000000..31c49f9d17b --- /dev/null +++ b/chromium/ppapi/proxy/file_mapping_resource.h @@ -0,0 +1,77 @@ +// 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 PPAPI_PROXY_FILE_MAPPING_RESOURCE_H_ +#define PPAPI_PROXY_FILE_MAPPING_RESOURCE_H_ + +#include "ppapi/proxy/file_io_resource.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/thunk/ppb_file_mapping_api.h" + +namespace ppapi { +namespace proxy { + +// The proxy-side resource for PPB_FileMapping. +class PPAPI_PROXY_EXPORT FileMappingResource + : public PluginResource, + public thunk::PPB_FileMapping_API { + public: + FileMappingResource(Connection connection, PP_Instance instance); + + private: + virtual ~FileMappingResource(); + + // Resource implementation. + virtual thunk::PPB_FileMapping_API* AsPPB_FileMapping_API() OVERRIDE; + + // PPB_FileMapping_API implementation. + virtual int32_t Map(PP_Instance instance, + PP_Resource file_io, + int64_t length, + uint32_t protection, + uint32_t flags, + int64_t offset, + void** address, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t Unmap(PP_Instance instance, + const void* address, + int64_t length, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int64_t GetMapPageSize(PP_Instance instance) OVERRIDE; + + struct MapResult { + MapResult() : result(PP_ERROR_FAILED), address(NULL) { + } + int32_t result; + void* address; + }; + void OnMapCompleted(void** mapped_address_out_param, + int64_t length, + scoped_refptr<TrackedCallback> callback, + const MapResult& map_result); + + // These functions perform potentially blocking operations so they should not + // be called on the main thread or while we hold the proxy lock. Their + // implementation is platform specific. See file_mapping_resource_posix.cc and + // file_mapping_resource_win.cc. + static MapResult DoMapBlocking( + scoped_refptr<FileIOResource::FileHolder> file_holder, + void* address_hint, + int64_t length, + uint32_t protection, + uint32_t flags, + int64_t offset); + static int32_t DoUnmapBlocking(const void* address, int64_t length); + // DoGetMapPageSize is platform-specific, but fast enough that we can call it + // on the main thread with the lock. + static int64_t DoGetMapPageSize(); + + DISALLOW_COPY_AND_ASSIGN(FileMappingResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_FILE_MAPPING_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/file_mapping_resource_posix.cc b/chromium/ppapi/proxy/file_mapping_resource_posix.cc new file mode 100644 index 00000000000..24ce546916c --- /dev/null +++ b/chromium/ppapi/proxy/file_mapping_resource_posix.cc @@ -0,0 +1,89 @@ +// 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. + +#include "ppapi/proxy/file_mapping_resource.h" + +#include <stdio.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "ppapi/c/pp_errors.h" + +namespace ppapi { +namespace proxy { + +namespace { + +int32_t ErrnoToPPError(int error_code) { + switch (error_code) { + case EACCES: + return PP_ERROR_NOACCESS; + case EAGAIN: + return PP_ERROR_NOMEMORY; + case EINVAL: + return PP_ERROR_BADARGUMENT; + case ENFILE: + case ENOMEM: + return PP_ERROR_NOMEMORY; + default: + return PP_ERROR_FAILED; + } +} + +} // namespace + +// static +FileMappingResource::MapResult FileMappingResource::DoMapBlocking( + scoped_refptr<FileIOResource::FileHolder> file_holder, + void* address_hint, + int64_t length, + uint32_t map_protection, + uint32_t map_flags, + int64_t offset) { + int prot_for_mmap = 0; + if (map_protection & PP_FILEMAPPROTECTION_READ) + prot_for_mmap |= PROT_READ; + if (map_protection & PP_FILEMAPPROTECTION_WRITE) + prot_for_mmap |= PROT_WRITE; + if (prot_for_mmap == 0) + prot_for_mmap = PROT_NONE; + + int flags_for_mmap = 0; + if (map_flags & PP_FILEMAPFLAG_SHARED) + flags_for_mmap |= MAP_SHARED; + if (map_flags & PP_FILEMAPFLAG_PRIVATE) + flags_for_mmap |= MAP_PRIVATE; + if (map_flags & PP_FILEMAPFLAG_FIXED) + flags_for_mmap |= MAP_FIXED; + + MapResult map_result; + map_result.address = + mmap(address_hint, + static_cast<size_t>(length), + prot_for_mmap, + flags_for_mmap, + file_holder->file()->GetPlatformFile(), + static_cast<off_t>(offset)); + if (map_result.address != MAP_FAILED) + map_result.result = PP_OK; + else + map_result.result = ErrnoToPPError(errno); + return map_result; +} + +// static +int32_t FileMappingResource::DoUnmapBlocking(const void* address, + int64_t length) { + if (munmap(const_cast<void*>(address), static_cast<size_t>(length))) + return ErrnoToPPError(errno); + return PP_OK; +} + +// static +int64_t FileMappingResource::DoGetMapPageSize() { + return getpagesize(); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/file_mapping_resource_win.cc b/chromium/ppapi/proxy/file_mapping_resource_win.cc new file mode 100644 index 00000000000..c5d9353f3d4 --- /dev/null +++ b/chromium/ppapi/proxy/file_mapping_resource_win.cc @@ -0,0 +1,40 @@ +// 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. + +#include "ppapi/proxy/file_mapping_resource.h" + +#include "ppapi/c/pp_errors.h" + +namespace ppapi { +namespace proxy { + +// static +FileMappingResource::MapResult FileMappingResource::DoMapBlocking( + scoped_refptr<FileIOResource::FileHolder> file_holder, + void* address_hint, + int64_t length, + uint32_t map_protection, + uint32_t map_flags, + int64_t offset) { + // TODO(dmichael): Implement for Windows (crbug.com/83774). + MapResult map_result; + map_result.result = PP_ERROR_NOTSUPPORTED; + return map_result; +} + +// static +int32_t FileMappingResource::DoUnmapBlocking(const void* address, + int64_t length) { + // TODO(dmichael): Implement for Windows (crbug.com/83774). + return PP_ERROR_NOTSUPPORTED; +} + +// static +int64_t FileMappingResource::DoGetMapPageSize() { + // TODO(dmichael): Implement for Windows (crbug.com/83774). + return 0; +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/file_ref_resource.cc b/chromium/ppapi/proxy/file_ref_resource.cc index 7cd96bc60a0..098ef5f336a 100644 --- a/chromium/ppapi/proxy/file_ref_resource.cc +++ b/chromium/ppapi/proxy/file_ref_resource.cc @@ -26,7 +26,7 @@ FileRefResource::FileRefResource( : PluginResource(connection, instance), create_info_(create_info), file_system_resource_(create_info.file_system_plugin_resource) { - if (create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL) { + if (uses_internal_paths()) { // If path ends with a slash, then normalize it away unless path is // the root path. int path_size = create_info_.internal_path.size(); @@ -36,6 +36,8 @@ FileRefResource::FileRefResource( path_var_ = new StringVar(create_info_.internal_path); create_info_.display_name = GetNameForInternalFilePath( create_info_.internal_path); + } else { + DCHECK(!create_info_.display_name.empty()); } name_var_ = new StringVar(create_info_.display_name); @@ -45,13 +47,13 @@ FileRefResource::FileRefResource( AttachToPendingHost(RENDERER, create_info_.renderer_pending_host_resource_id); } else { - CHECK(create_info_.browser_pending_host_resource_id == 0); - CHECK(create_info_.renderer_pending_host_resource_id == 0); - CHECK(create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL); - SendCreate(BROWSER, PpapiHostMsg_FileRef_CreateInternal( + CHECK_EQ(0, create_info_.browser_pending_host_resource_id); + CHECK_EQ(0, create_info_.renderer_pending_host_resource_id); + CHECK(uses_internal_paths()); + SendCreate(BROWSER, PpapiHostMsg_FileRef_CreateForFileAPI( create_info.file_system_plugin_resource, create_info.internal_path)); - SendCreate(RENDERER, PpapiHostMsg_FileRef_CreateInternal( + SendCreate(RENDERER, PpapiHostMsg_FileRef_CreateForFileAPI( create_info.file_system_plugin_resource, create_info.internal_path)); } @@ -60,7 +62,7 @@ FileRefResource::FileRefResource( FileRefResource::~FileRefResource() { } -//static +// static PP_Resource FileRefResource::CreateFileRef( Connection connection, PP_Instance instance, @@ -101,13 +103,13 @@ PP_Var FileRefResource::GetName() const { } PP_Var FileRefResource::GetPath() const { - if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL) + if (!uses_internal_paths()) return PP_MakeUndefined(); return path_var_->GetPPVar(); } PP_Resource FileRefResource::GetParent() { - if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL) + if (!uses_internal_paths()) return 0; size_t pos = create_info_.internal_path.rfind('/'); @@ -129,11 +131,11 @@ PP_Resource FileRefResource::GetParent() { } int32_t FileRefResource::MakeDirectory( - PP_Bool make_ancestors, + int32_t make_directory_flags, scoped_refptr<TrackedCallback> callback) { Call<PpapiPluginMsg_FileRef_MakeDirectoryReply>( BROWSER, - PpapiHostMsg_FileRef_MakeDirectory(PP_TRUE == make_ancestors), + PpapiHostMsg_FileRef_MakeDirectory(make_directory_flags), base::Bind(&FileRefResource::RunTrackedCallback, this, callback)); return PP_OK_COMPLETIONPENDING; } @@ -256,5 +258,10 @@ void FileRefResource::OnDirectoryEntriesReply( callback->Run(params.result()); } +bool FileRefResource::uses_internal_paths() const { + return (create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL) || + !create_info_.internal_path.empty(); +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/file_ref_resource.h b/chromium/ppapi/proxy/file_ref_resource.h index f982438fb0d..0437b23ab94 100644 --- a/chromium/ppapi/proxy/file_ref_resource.h +++ b/chromium/ppapi/proxy/file_ref_resource.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PPAPI_PROXY_PPB_FILE_REF_PROXY_H_ -#define PPAPI_PROXY_PPB_FILE_REF_PROXY_H_ +#ifndef PPAPI_PROXY_FILE_REF_RESOURCE_H_ +#define PPAPI_PROXY_FILE_REF_RESOURCE_H_ #include <string> @@ -42,8 +42,8 @@ class PPAPI_PROXY_EXPORT FileRefResource virtual PP_Var GetPath() const OVERRIDE; virtual PP_Resource GetParent() OVERRIDE; virtual int32_t MakeDirectory( - PP_Bool make_ancestors, - scoped_refptr<TrackedCallback> callback) OVERRIDE; + int32_t make_directory_flags, + scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t Touch(PP_Time last_access_time, PP_Time last_modified_time, scoped_refptr<TrackedCallback> callback) OVERRIDE; @@ -80,6 +80,8 @@ class PPAPI_PROXY_EXPORT FileRefResource const std::vector<ppapi::FileRefCreateInfo>& infos, const std::vector<PP_FileType>& file_types); + bool uses_internal_paths() const; + // Populated after creation. FileRefCreateInfo create_info_; @@ -98,4 +100,4 @@ class PPAPI_PROXY_EXPORT FileRefResource } // namespace proxy } // namespace ppapi -#endif // PPAPI_PROXY_PPB_FILE_REF_PROXY_H_ +#endif // PPAPI_PROXY_FILE_REF_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/file_system_resource.cc b/chromium/ppapi/proxy/file_system_resource.cc index df8c3907751..0be0ea52e5e 100644 --- a/chromium/ppapi/proxy/file_system_resource.cc +++ b/chromium/ppapi/proxy/file_system_resource.cc @@ -5,16 +5,32 @@ #include "ppapi/proxy/file_system_resource.h" #include "base/bind.h" +#include "base/stl_util.h" #include "ipc/ipc_message.h" #include "ppapi/c/pp_errors.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/file_growth.h" #include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_file_io_api.h" +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_FileIO_API; using ppapi::thunk::PPB_FileSystem_API; namespace ppapi { namespace proxy { +FileSystemResource::QuotaRequest::QuotaRequest( + int64_t amount_arg, + const RequestQuotaCallback& callback_arg) + : amount(amount_arg), + callback(callback_arg) { +} + +FileSystemResource::QuotaRequest::~QuotaRequest() { +} + FileSystemResource::FileSystemResource(Connection connection, PP_Instance instance, PP_FileSystemType type) @@ -22,7 +38,9 @@ FileSystemResource::FileSystemResource(Connection connection, type_(type), called_open_(false), callback_count_(0), - callback_result_(PP_OK) { + callback_result_(PP_OK), + reserved_quota_(0), + reserving_quota_(false) { DCHECK(type_ != PP_FILESYSTEMTYPE_INVALID); SendCreate(RENDERER, PpapiHostMsg_FileSystem_Create(type_)); SendCreate(BROWSER, PpapiHostMsg_FileSystem_Create(type_)); @@ -37,7 +55,9 @@ FileSystemResource::FileSystemResource(Connection connection, type_(type), called_open_(true), callback_count_(0), - callback_result_(PP_OK) { + callback_result_(PP_OK), + reserved_quota_(0), + reserving_quota_(false) { DCHECK(type_ != PP_FILESYSTEMTYPE_INVALID); AttachToPendingHost(RENDERER, pending_renderer_id); AttachToPendingHost(BROWSER, pending_browser_id); @@ -74,6 +94,35 @@ PP_FileSystemType FileSystemResource::GetType() { return type_; } +void FileSystemResource::OpenQuotaFile(PP_Resource file_io) { + DCHECK(!ContainsKey(files_, file_io)); + files_.insert(file_io); +} + +void FileSystemResource::CloseQuotaFile(PP_Resource file_io) { + DCHECK(ContainsKey(files_, file_io)); + files_.erase(file_io); +} + +int64_t FileSystemResource::RequestQuota( + int64_t amount, + const RequestQuotaCallback& callback) { + DCHECK(amount >= 0); + if (!reserving_quota_ && reserved_quota_ >= amount) { + reserved_quota_ -= amount; + return amount; + } + + // Queue up a pending quota request. + pending_quota_requests_.push(QuotaRequest(amount, callback)); + + // Reserve more quota if we haven't already. + if (!reserving_quota_) + ReserveQuota(amount); + + return PP_OK_COMPLETIONPENDING; +} + int32_t FileSystemResource::InitIsolatedFileSystem( const std::string& fsid, PP_IsolatedFileSystemType_Private type, @@ -122,5 +171,71 @@ void FileSystemResource::InitIsolatedFileSystemComplete( callback.Run(callback_result_); } +void FileSystemResource::ReserveQuota(int64_t amount) { + DCHECK(!reserving_quota_); + reserving_quota_ = true; + + FileGrowthMap file_growths; + for (std::set<PP_Resource>::iterator it = files_.begin(); + it != files_.end(); ++it) { + EnterResourceNoLock<PPB_FileIO_API> enter(*it, true); + if (enter.failed()) { + NOTREACHED(); + continue; + } + PPB_FileIO_API* file_io_api = enter.object(); + file_growths[*it] = FileGrowth( + file_io_api->GetMaxWrittenOffset(), + file_io_api->GetAppendModeWriteAmount()); + } + Call<PpapiPluginMsg_FileSystem_ReserveQuotaReply>(BROWSER, + PpapiHostMsg_FileSystem_ReserveQuota(amount, file_growths), + base::Bind(&FileSystemResource::ReserveQuotaComplete, + this)); +} + +void FileSystemResource::ReserveQuotaComplete( + const ResourceMessageReplyParams& params, + int64_t amount, + const FileSizeMap& file_sizes) { + DCHECK(reserving_quota_); + reserving_quota_ = false; + reserved_quota_ = amount; + + for (FileSizeMap::const_iterator it = file_sizes.begin(); + it != file_sizes.end(); ++it) { + EnterResourceNoLock<PPB_FileIO_API> enter(it->first, true); + + // It is possible that the host has sent an offset for a file that has been + // destroyed in the plugin. Ignore it. + if (enter.failed()) + continue; + PPB_FileIO_API* file_io_api = enter.object(); + file_io_api->SetMaxWrittenOffset(it->second); + file_io_api->SetAppendModeWriteAmount(0); + } + + DCHECK(!pending_quota_requests_.empty()); + // If we can't grant the first request after refreshing reserved_quota_, then + // fail all pending quota requests to avoid an infinite refresh/fail loop. + bool fail_all = reserved_quota_ < pending_quota_requests_.front().amount; + while (!pending_quota_requests_.empty()) { + QuotaRequest& request = pending_quota_requests_.front(); + if (fail_all) { + request.callback.Run(0); + pending_quota_requests_.pop(); + } else if (reserved_quota_ >= request.amount) { + reserved_quota_ -= request.amount; + request.callback.Run(request.amount); + pending_quota_requests_.pop(); + } else { + // Refresh the quota reservation for the first pending request that we + // can't satisfy. + ReserveQuota(request.amount); + break; + } + } +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/file_system_resource.h b/chromium/ppapi/proxy/file_system_resource.h index 9029583c819..d54e8afff32 100644 --- a/chromium/ppapi/proxy/file_system_resource.h +++ b/chromium/ppapi/proxy/file_system_resource.h @@ -5,10 +5,13 @@ #ifndef PPAPI_PROXY_FILE_SYSTEM_RESOURCE_H_ #define PPAPI_PROXY_FILE_SYSTEM_RESOURCE_H_ +#include <map> +#include <queue> #include <string> #include "base/memory/ref_counted.h" #include "ppapi/c/pp_file_info.h" +#include "ppapi/c/pp_resource.h" #include "ppapi/c/private/ppb_isolated_file_system_private.h" #include "ppapi/proxy/connection.h" #include "ppapi/proxy/plugin_resource.h" @@ -48,11 +51,25 @@ class PPAPI_PROXY_EXPORT FileSystemResource virtual int32_t Open(int64_t expected_size, scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual PP_FileSystemType GetType() OVERRIDE; + virtual void OpenQuotaFile(PP_Resource file_io) OVERRIDE; + virtual void CloseQuotaFile(PP_Resource file_io) OVERRIDE; + typedef base::Callback<void(int64_t)> RequestQuotaCallback; + virtual int64_t RequestQuota(int64_t amount, + const RequestQuotaCallback& callback) OVERRIDE; int32_t InitIsolatedFileSystem(const std::string& fsid, PP_IsolatedFileSystemType_Private type, const base::Callback<void(int32_t)>& callback); private: + struct QuotaRequest { + QuotaRequest(int64_t amount, + const RequestQuotaCallback& callback); + ~QuotaRequest(); + + int64_t amount; + RequestQuotaCallback callback; + }; + // Called when the host has responded to our open request. void OpenComplete(scoped_refptr<TrackedCallback> callback, const ResourceMessageReplyParams& params); @@ -62,11 +79,22 @@ class PPAPI_PROXY_EXPORT FileSystemResource const base::Callback<void(int32_t)>& callback, const ResourceMessageReplyParams& params); + void ReserveQuota(int64_t amount); + typedef std::map<int32_t, int64_t> OffsetMap; + void ReserveQuotaComplete(const ResourceMessageReplyParams& params, + int64_t amount, + const OffsetMap& max_written_offsets); + PP_FileSystemType type_; bool called_open_; uint32_t callback_count_; int32_t callback_result_; + std::set<PP_Resource> files_; + std::queue<QuotaRequest> pending_quota_requests_; + int64_t reserved_quota_; + bool reserving_quota_; + DISALLOW_COPY_AND_ASSIGN(FileSystemResource); }; diff --git a/chromium/ppapi/proxy/file_system_resource_unittest.cc b/chromium/ppapi/proxy/file_system_resource_unittest.cc new file mode 100644 index 00000000000..9b5d981242d --- /dev/null +++ b/chromium/ppapi/proxy/file_system_resource_unittest.cc @@ -0,0 +1,369 @@ +// 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. + +#include "base/message_loop/message_loop.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppb_file_io.h" +#include "ppapi/c/ppb_file_ref.h" +#include "ppapi/c/ppb_file_system.h" +#include "ppapi/proxy/file_system_resource.h" +#include "ppapi/proxy/locking_resource_releaser.h" +#include "ppapi/proxy/plugin_message_filter.h" +#include "ppapi/proxy/ppapi_message_utils.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/shared_impl/scoped_pp_var.h" +#include "ppapi/shared_impl/var.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_file_system_api.h" +#include "ppapi/thunk/thunk.h" + +using ppapi::proxy::ResourceMessageTestSink; +using ppapi::thunk::EnterResource; +using ppapi::thunk::PPB_FileSystem_API; + +namespace ppapi { +namespace proxy { + +namespace { + +const int64_t kExpectedFileSystemSize = 100; +const int64_t kQuotaRequestAmount1 = 10; +const int64_t kQuotaRequestAmount2 = 20; + +class MockCompletionCallback { + public: + MockCompletionCallback() : called_(false) {} + + bool called() { return called_; } + int32_t result() { return result_; } + + static void Callback(void* user_data, int32_t result) { + MockCompletionCallback* that = + reinterpret_cast<MockCompletionCallback*>(user_data); + that->called_ = true; + that->result_ = result; + } + + private: + bool called_; + int32_t result_; +}; + +class MockRequestQuotaCallback { + public: + MockRequestQuotaCallback() : called_(false) {} + + bool called() { return called_; } + int64_t result() { return result_; } + + void Reset() { called_ = false; } + + void Callback(int64_t result) { + ASSERT_FALSE(called_); + called_ = true; + result_ = result; + } + + private: + bool called_; + int64_t result_; +}; + +class FileSystemResourceTest : public PluginProxyTest { + public: + const PPB_FileSystem_1_0* file_system_iface; + const PPB_FileRef_1_1* file_ref_iface; + const PPB_FileIO_1_1* file_io_iface; + + FileSystemResourceTest() + : file_system_iface(thunk::GetPPB_FileSystem_1_0_Thunk()), + file_ref_iface(thunk::GetPPB_FileRef_1_1_Thunk()), + file_io_iface(thunk::GetPPB_FileIO_1_1_Thunk()) { + } + + void SendReply(const ResourceMessageCallParams& params, + int32_t result, + const IPC::Message& nested_message) { + ResourceMessageReplyParams reply_params(params.pp_resource(), + params.sequence()); + reply_params.set_result(result); + PluginMessageFilter::DispatchResourceReplyForTest( + reply_params, nested_message); + } + + void SendOpenReply(const ResourceMessageCallParams& params, int32_t result) { + SendReply(params, result, PpapiPluginMsg_FileSystem_OpenReply()); + } + + // Opens the given file system. + void OpenFileSystem(PP_Resource file_system) { + MockCompletionCallback cb; + int32_t result = file_system_iface->Open( + file_system, + kExpectedFileSystemSize, + PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + // Should have sent two new "open" messages to the browser and renderer. + ResourceMessageTestSink::ResourceCallVector open_messages = + sink().GetAllResourceCallsMatching(PpapiHostMsg_FileSystem_Open::ID); + ASSERT_EQ(2U, open_messages.size()); + sink().ClearMessages(); + + // The resource is expecting two replies. + SendOpenReply(open_messages[0].first, PP_OK); + SendOpenReply(open_messages[1].first, PP_OK); + + ASSERT_TRUE(cb.called()); + ASSERT_EQ(PP_OK, cb.result()); + } + + // Opens the given file in the given file system. Since there is no host, + // the file handle will be invalid. + void OpenFile(PP_Resource file_io, + PP_Resource file_ref, + PP_Resource file_system) { + MockCompletionCallback cb; + int32_t result = file_io_iface->Open( + file_io, + file_ref, + PP_FILEOPENFLAG_WRITE, + PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + // Should have sent an "open" message. + ResourceMessageCallParams params; + IPC::Message msg; + ASSERT_TRUE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_FileIO_Open::ID, ¶ms, &msg)); + sink().ClearMessages(); + + // Send a success reply. + ResourceMessageReplyParams reply_params(params.pp_resource(), + params.sequence()); + reply_params.set_result(PP_OK); + PluginMessageFilter::DispatchResourceReplyForTest( + reply_params, + PpapiPluginMsg_FileIO_OpenReply(file_system, + 0 /* max_written_offset */)); + } +}; + +} // namespace + +// Test that Open fails if either host returns failure. The other tests exercise +// the case where both hosts return PP_OK. +TEST_F(FileSystemResourceTest, OpenFailure) { + // Fail if the first reply doesn't return PP_OK. + { + LockingResourceReleaser file_system( + file_system_iface->Create(pp_instance(), + PP_FILESYSTEMTYPE_LOCALTEMPORARY)); + + MockCompletionCallback cb; + int32_t result = file_system_iface->Open( + file_system.get(), + kExpectedFileSystemSize, + PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + ResourceMessageTestSink::ResourceCallVector open_messages = + sink().GetAllResourceCallsMatching(PpapiHostMsg_FileSystem_Open::ID); + ASSERT_EQ(2U, open_messages.size()); + sink().ClearMessages(); + + SendOpenReply(open_messages[0].first, PP_ERROR_FAILED); + SendOpenReply(open_messages[1].first, PP_OK); + + ASSERT_TRUE(cb.called()); + ASSERT_EQ(PP_ERROR_FAILED, cb.result()); + } + // Fail if the second reply doesn't return PP_OK. + { + LockingResourceReleaser file_system( + file_system_iface->Create(pp_instance(), + PP_FILESYSTEMTYPE_LOCALTEMPORARY)); + + MockCompletionCallback cb; + int32_t result = file_system_iface->Open( + file_system.get(), + kExpectedFileSystemSize, + PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb)); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + ResourceMessageTestSink::ResourceCallVector open_messages = + sink().GetAllResourceCallsMatching(PpapiHostMsg_FileSystem_Open::ID); + ASSERT_EQ(2U, open_messages.size()); + sink().ClearMessages(); + + SendOpenReply(open_messages[0].first, PP_OK); + SendOpenReply(open_messages[1].first, PP_ERROR_FAILED); + + ASSERT_TRUE(cb.called()); + ASSERT_EQ(PP_ERROR_FAILED, cb.result()); + } +} + +TEST_F(FileSystemResourceTest, RequestQuota) { + LockingResourceReleaser file_system( + file_system_iface->Create(pp_instance(), + PP_FILESYSTEMTYPE_LOCALTEMPORARY)); + + OpenFileSystem(file_system.get()); + + // Create and open two files in the file system. FileIOResource calls + // FileSystemResource::OpenQuotaFile on success. + LockingResourceReleaser file_ref1( + file_ref_iface->Create(file_system.get(), "/file1")); + LockingResourceReleaser file_io1(file_io_iface->Create(pp_instance())); + OpenFile(file_io1.get(), file_ref1.get(), file_system.get()); + LockingResourceReleaser file_ref2( + file_ref_iface->Create(file_system.get(), "/file2")); + LockingResourceReleaser file_io2(file_io_iface->Create(pp_instance())); + OpenFile(file_io2.get(), file_ref2.get(), file_system.get()); + + EnterResource<PPB_FileSystem_API> enter(file_system.get(), true); + ASSERT_FALSE(enter.failed()); + PPB_FileSystem_API* file_system_api = enter.object(); + + MockRequestQuotaCallback cb1; + int64_t result = file_system_api->RequestQuota( + kQuotaRequestAmount1, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1))); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + // Should have sent a "reserve quota" message, with the amount of the request + // and a map of all currently open files to their max written offsets. + ResourceMessageCallParams params; + IPC::Message msg; + ASSERT_TRUE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_FileSystem_ReserveQuota::ID, ¶ms, &msg)); + sink().ClearMessages(); + + int64_t amount = 0; + FileGrowthMap file_growths; + ASSERT_TRUE(UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>( + msg, &amount, &file_growths)); + ASSERT_EQ(kQuotaRequestAmount1, amount); + ASSERT_EQ(2U, file_growths.size()); + ASSERT_EQ(0, file_growths[file_io1.get()].max_written_offset); + ASSERT_EQ(0, file_growths[file_io2.get()].max_written_offset); + + // Make another request while the "reserve quota" message is pending. + MockRequestQuotaCallback cb2; + result = file_system_api->RequestQuota( + kQuotaRequestAmount2, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb2))); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + // No new "reserve quota" message should be sent while one is pending. + ASSERT_FALSE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_FileSystem_ReserveQuota::ID, ¶ms, &msg)); + { + ProxyAutoUnlock unlock_to_prevent_deadlock; + // Reply with quota reservation amount sufficient to cover both requests. + // Both callbacks should be called with the requests granted. + SendReply(params, + PP_OK, + PpapiPluginMsg_FileSystem_ReserveQuotaReply( + kQuotaRequestAmount1 + kQuotaRequestAmount2, + FileGrowthMapToFileSizeMapForTesting(file_growths))); + } + ASSERT_TRUE(cb1.called()); + ASSERT_EQ(kQuotaRequestAmount1, cb1.result()); + ASSERT_TRUE(cb2.called()); + ASSERT_EQ(kQuotaRequestAmount2, cb2.result()); + cb1.Reset(); + cb2.Reset(); + + // All requests should fail when insufficient quota is returned to satisfy + // the first request. + result = file_system_api->RequestQuota( + kQuotaRequestAmount1, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1))); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + result = file_system_api->RequestQuota( + kQuotaRequestAmount2, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb2))); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + ASSERT_TRUE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_FileSystem_ReserveQuota::ID, ¶ms, &msg)); + sink().ClearMessages(); + { + ProxyAutoUnlock unlock_to_prevent_deadlock; + // Reply with quota reservation amount insufficient to cover the first + // request. + SendReply(params, + PP_OK, + PpapiPluginMsg_FileSystem_ReserveQuotaReply( + kQuotaRequestAmount1 - 1, + FileGrowthMapToFileSizeMapForTesting(file_growths))); + } + ASSERT_TRUE(cb1.called()); + ASSERT_EQ(0, cb1.result()); + ASSERT_TRUE(cb2.called()); + ASSERT_EQ(0, cb2.result()); + cb1.Reset(); + cb2.Reset(); + + // A new request should be made if the quota reservation is enough to satisfy + // at least one request. + result = file_system_api->RequestQuota( + kQuotaRequestAmount1, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1))); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + result = file_system_api->RequestQuota( + kQuotaRequestAmount2, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb2))); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + + ASSERT_TRUE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_FileSystem_ReserveQuota::ID, ¶ms, &msg)); + sink().ClearMessages(); + { + ProxyAutoUnlock unlock_to_prevent_deadlock; + // Reply with quota reservation amount sufficient only to cover the first + // request. + SendReply(params, + PP_OK, + PpapiPluginMsg_FileSystem_ReserveQuotaReply( + kQuotaRequestAmount1, + FileGrowthMapToFileSizeMapForTesting(file_growths))); + } + ASSERT_TRUE(cb1.called()); + ASSERT_EQ(kQuotaRequestAmount1, cb1.result()); + ASSERT_FALSE(cb2.called()); + + // Another request message should have been sent. + ASSERT_TRUE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_FileSystem_ReserveQuota::ID, ¶ms, &msg)); + sink().ClearMessages(); + { + ProxyAutoUnlock unlock_to_prevent_deadlock; + // Reply with quota reservation amount sufficient to cover the second + // request and some extra. + SendReply(params, + PP_OK, + PpapiPluginMsg_FileSystem_ReserveQuotaReply( + kQuotaRequestAmount1 + kQuotaRequestAmount2, + FileGrowthMapToFileSizeMapForTesting(file_growths))); + } + + ASSERT_TRUE(cb2.called()); + ASSERT_EQ(kQuotaRequestAmount2, cb2.result()); + cb1.Reset(); + cb2.Reset(); + + // There is kQuotaRequestAmount1 of quota left, and a request for it should + // succeed immediately. + result = file_system_api->RequestQuota( + kQuotaRequestAmount1, + base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1))); + ASSERT_EQ(kQuotaRequestAmount1, result); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/flash_clipboard_resource.cc b/chromium/ppapi/proxy/flash_clipboard_resource.cc index 5f064023f35..2b665bfa059 100644 --- a/chromium/ppapi/proxy/flash_clipboard_resource.cc +++ b/chromium/ppapi/proxy/flash_clipboard_resource.cc @@ -152,5 +152,17 @@ int32_t FlashClipboardResource::WriteData( return PP_OK; } +PP_Bool FlashClipboardResource::GetSequenceNumber( + PP_Instance instance, + PP_Flash_Clipboard_Type clipboard_type, + uint64_t* sequence_number) { + int32_t result = + SyncCall<PpapiPluginMsg_FlashClipboard_GetSequenceNumberReply>( + BROWSER, + PpapiHostMsg_FlashClipboard_GetSequenceNumber(clipboard_type), + sequence_number); + return PP_FromBool(result == PP_OK); +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/flash_clipboard_resource.h b/chromium/ppapi/proxy/flash_clipboard_resource.h index fdb7e79a48e..3c12f550062 100644 --- a/chromium/ppapi/proxy/flash_clipboard_resource.h +++ b/chromium/ppapi/proxy/flash_clipboard_resource.h @@ -37,6 +37,10 @@ class FlashClipboardResource uint32_t data_item_count, const uint32_t formats[], const PP_Var data_items[]) OVERRIDE; + virtual PP_Bool GetSequenceNumber( + PP_Instance instance, + PP_Flash_Clipboard_Type clipboard_type, + uint64_t* sequence_number) OVERRIDE; private: FlashClipboardFormatRegistry clipboard_formats_; diff --git a/chromium/ppapi/proxy/flash_file_resource.cc b/chromium/ppapi/proxy/flash_file_resource.cc index ce7a2cee110..6b8fc6cc796 100644 --- a/chromium/ppapi/proxy/flash_file_resource.cc +++ b/chromium/ppapi/proxy/flash_file_resource.cc @@ -206,7 +206,7 @@ int32_t FlashFileResource::QueryFileHelper(const std::string& path, if (path.empty() || !info) return PP_ERROR_BADARGUMENT; - base::PlatformFileInfo file_info; + base::File::Info file_info; PepperFilePath pepper_path(domain_type, base::FilePath::FromUTF8Unsafe(path)); int32_t error = SyncCall<PpapiPluginMsg_FlashFile_QueryFileReply>(BROWSER, diff --git a/chromium/ppapi/proxy/graphics_2d_resource.cc b/chromium/ppapi/proxy/graphics_2d_resource.cc index f545364f1e7..ea8a9c52ce4 100644 --- a/chromium/ppapi/proxy/graphics_2d_resource.cc +++ b/chromium/ppapi/proxy/graphics_2d_resource.cc @@ -103,7 +103,7 @@ void Graphics2DResource::ReplaceContents(PP_Resource image_data) { PP_Bool Graphics2DResource::SetScale(float scale) { if (scale <= 0.0f) return PP_FALSE; - Post(RENDERER, PpapiHostMsg_Graphics2D_Dev_SetScale(scale)); + Post(RENDERER, PpapiHostMsg_Graphics2D_SetScale(scale)); scale_ = scale; return PP_TRUE; } @@ -112,15 +112,6 @@ float Graphics2DResource::GetScale() { return scale_; } -void Graphics2DResource::SetOffset(const PP_Point* offset) { - Post(RENDERER, PpapiHostMsg_Graphics2D_SetOffset(*offset)); -} - -void Graphics2DResource::SetResizeMode( - PP_Graphics2D_Dev_ResizeMode resize_mode) { - Post(RENDERER, PpapiHostMsg_Graphics2D_SetResizeMode(resize_mode)); -} - int32_t Graphics2DResource::Flush(scoped_refptr<TrackedCallback> callback) { // If host is not even created, return failure immediately. This can happen // when failed to initialize (in constructor). @@ -131,20 +122,12 @@ int32_t Graphics2DResource::Flush(scoped_refptr<TrackedCallback> callback) { return PP_ERROR_INPROGRESS; // Can't have >1 flush pending. current_flush_callback_ = callback; - // Send the current view data with the Flush() message. This allows the - // renderer to know what the plugin's view of the renderer is at the time - // Flush was called. - PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance( - pp_instance()); - ppapi::ViewData view_data; - if (dispatcher) { - InstanceData* data = dispatcher->GetInstanceData(pp_instance()); - if (data) - view_data = data->view; - } + std::vector<ui::LatencyInfo> latency_info; + PpapiGlobals::Get()->TransferLatencyInfoTo(&latency_info, pp_instance()); + Call<PpapiPluginMsg_Graphics2D_FlushAck>( RENDERER, - PpapiHostMsg_Graphics2D_Flush(view_data), + PpapiHostMsg_Graphics2D_Flush(latency_info), base::Bind(&Graphics2DResource::OnPluginMsgFlushACK, this)); return PP_OK_COMPLETIONPENDING; } diff --git a/chromium/ppapi/proxy/graphics_2d_resource.h b/chromium/ppapi/proxy/graphics_2d_resource.h index 93d182b65a5..b7ec30c710d 100644 --- a/chromium/ppapi/proxy/graphics_2d_resource.h +++ b/chromium/ppapi/proxy/graphics_2d_resource.h @@ -40,8 +40,6 @@ class PPAPI_PROXY_EXPORT Graphics2DResource virtual void ReplaceContents(PP_Resource image_data) OVERRIDE; virtual PP_Bool SetScale(float scale) OVERRIDE; virtual float GetScale() OVERRIDE; - virtual void SetOffset(const PP_Point* offset) OVERRIDE; - virtual void SetResizeMode(PP_Graphics2D_Dev_ResizeMode resize_mode) OVERRIDE; virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual bool ReadImageData(PP_Resource image, const PP_Point* top_left) OVERRIDE; diff --git a/chromium/ppapi/proxy/host_dispatcher.cc b/chromium/ppapi/proxy/host_dispatcher.cc index cea7ab31f08..8f3833f5ddf 100644 --- a/chromium/ppapi/proxy/host_dispatcher.cc +++ b/chromium/ppapi/proxy/host_dispatcher.cc @@ -240,6 +240,10 @@ const void* HostDispatcher::GetProxiedInterface(const std::string& iface_name) { return NULL; } +void HostDispatcher::AddFilter(IPC::Listener* listener) { + filters_.push_back(listener); +} + void HostDispatcher::OnInvalidMessageReceived() { // TODO(brettw) bug 95345 kill the plugin when an invalid message is // received. diff --git a/chromium/ppapi/proxy/host_dispatcher.h b/chromium/ppapi/proxy/host_dispatcher.h index ebd6ef96587..c1ba15feb11 100644 --- a/chromium/ppapi/proxy/host_dispatcher.h +++ b/chromium/ppapi/proxy/host_dispatcher.h @@ -12,7 +12,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/process/process.h" -#include "ipc/ipc_channel_proxy.h" +#include "ipc/message_filter.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/dispatcher.h" @@ -31,7 +31,7 @@ class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher { // // Note that there can be nested sync messages, so the begin/end status // actually represents a stack of blocking messages. - class SyncMessageStatusReceiver : public IPC::ChannelProxy::MessageFilter { + class SyncMessageStatusReceiver : public IPC::MessageFilter { public: // Notification that a sync message is about to be sent out. virtual void BeginBlockOnSyncMessage() = 0; @@ -102,6 +102,8 @@ class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher { // Returns the proxy interface for talking to the implementation. const PPB_Proxy_Private* ppb_proxy() const { return ppb_proxy_; } + void AddFilter(IPC::Listener* listener); + protected: // Overridden from Dispatcher. virtual void OnInvalidMessageReceived(); @@ -131,6 +133,8 @@ class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher { // ultimately call back into the plugin. bool allow_plugin_reentrancy_; + std::vector<IPC::Listener*> filters_; + DISALLOW_COPY_AND_ASSIGN(HostDispatcher); }; diff --git a/chromium/ppapi/proxy/interface_list.cc b/chromium/ppapi/proxy/interface_list.cc index 8b05f7ace99..7e5125d9e17 100644 --- a/chromium/ppapi/proxy/interface_list.cc +++ b/chromium/ppapi/proxy/interface_list.cc @@ -4,9 +4,9 @@ #include "ppapi/proxy/interface_list.h" +#include "base/hash.h" #include "base/lazy_instance.h" #include "base/memory/singleton.h" -#include "ppapi/c/dev/ppb_alarms_dev.h" #include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/dev/ppb_buffer_dev.h" #include "ppapi/c/dev/ppb_char_set_dev.h" @@ -15,27 +15,29 @@ #include "ppapi/c/dev/ppb_device_ref_dev.h" #include "ppapi/c/dev/ppb_font_dev.h" #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h" -#include "ppapi/c/dev/ppb_graphics_2d_dev.h" #include "ppapi/c/dev/ppb_ime_input_event_dev.h" -#include "ppapi/c/dev/ppb_keyboard_input_event_dev.h" #include "ppapi/c/dev/ppb_memory_dev.h" #include "ppapi/c/dev/ppb_opengles2ext_dev.h" #include "ppapi/c/dev/ppb_printing_dev.h" -#include "ppapi/c/dev/ppb_resource_array_dev.h" +#include "ppapi/c/dev/ppb_scrollbar_dev.h" #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" -#include "ppapi/c/dev/ppb_var_resource_dev.h" #include "ppapi/c/dev/ppb_video_capture_dev.h" #include "ppapi/c/dev/ppb_view_dev.h" -#include "ppapi/c/extensions/dev/ppb_ext_socket_dev.h" -#include "ppapi/c/ppb_audio_config.h" +#include "ppapi/c/dev/ppb_widget_dev.h" +#include "ppapi/c/dev/ppb_zoom_dev.h" #include "ppapi/c/ppb_audio.h" +#include "ppapi/c/ppb_audio_buffer.h" +#include "ppapi/c/ppb_audio_config.h" +#include "ppapi/c/ppb_compositor.h" +#include "ppapi/c/ppb_compositor_layer.h" #include "ppapi/c/ppb_console.h" #include "ppapi/c/ppb_core.h" #include "ppapi/c/ppb_file_io.h" +#include "ppapi/c/ppb_file_mapping.h" #include "ppapi/c/ppb_file_ref.h" #include "ppapi/c/ppb_file_system.h" #include "ppapi/c/ppb_fullscreen.h" @@ -44,6 +46,8 @@ #include "ppapi/c/ppb_image_data.h" #include "ppapi/c/ppb_input_event.h" #include "ppapi/c/ppb_instance.h" +#include "ppapi/c/ppb_media_stream_audio_track.h" +#include "ppapi/c/ppb_media_stream_video_track.h" #include "ppapi/c/ppb_message_loop.h" #include "ppapi/c/ppb_messaging.h" #include "ppapi/c/ppb_mouse_lock.h" @@ -62,6 +66,8 @@ #include "ppapi/c/ppb_var_array.h" #include "ppapi/c/ppb_var_array_buffer.h" #include "ppapi/c/ppb_var_dictionary.h" +#include "ppapi/c/ppb_video_decoder.h" +#include "ppapi/c/ppb_video_frame.h" #include "ppapi/c/ppb_view.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppp_instance.h" @@ -69,6 +75,7 @@ #include "ppapi/c/private/ppb_ext_crx_file_system_private.h" #include "ppapi/c/private/ppb_file_io_private.h" #include "ppapi/c/private/ppb_file_ref_private.h" +#include "ppapi/c/private/ppb_find_private.h" #include "ppapi/c/private/ppb_flash_clipboard.h" #include "ppapi/c/private/ppb_flash_file.h" #include "ppapi/c/private/ppb_flash_font_file.h" @@ -80,6 +87,7 @@ #include "ppapi/c/private/ppb_flash_message_loop.h" #include "ppapi/c/private/ppb_flash_print.h" #include "ppapi/c/private/ppb_host_resolver_private.h" +#include "ppapi/c/private/ppb_input_event_private.h" #include "ppapi/c/private/ppb_isolated_file_system_private.h" #include "ppapi/c/private/ppb_net_address_private.h" #include "ppapi/c/private/ppb_output_protection_private.h" @@ -90,6 +98,7 @@ #include "ppapi/c/private/ppb_tcp_socket_private.h" #include "ppapi/c/private/ppb_testing_private.h" #include "ppapi/c/private/ppb_udp_socket_private.h" +#include "ppapi/c/private/ppb_uma_private.h" #include "ppapi/c/private/ppb_video_destination_private.h" #include "ppapi/c/private/ppb_video_source_private.h" #include "ppapi/c/private/ppb_x509_certificate_private.h" @@ -100,6 +109,8 @@ #include "ppapi/c/trusted/ppb_file_chooser_trusted.h" #include "ppapi/c/trusted/ppb_url_loader_trusted.h" #include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/plugin_globals.h" +#include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppb_audio_proxy.h" #include "ppapi/proxy/ppb_broker_proxy.h" #include "ppapi/proxy/ppb_buffer_proxy.h" @@ -115,12 +126,14 @@ #include "ppapi/proxy/ppb_x509_certificate_private_proxy.h" #include "ppapi/proxy/ppp_class_proxy.h" #include "ppapi/proxy/ppp_content_decryptor_private_proxy.h" +#include "ppapi/proxy/ppp_find_proxy.h" #include "ppapi/proxy/ppp_graphics_3d_proxy.h" #include "ppapi/proxy/ppp_input_event_proxy.h" #include "ppapi/proxy/ppp_instance_private_proxy.h" #include "ppapi/proxy/ppp_instance_proxy.h" #include "ppapi/proxy/ppp_messaging_proxy.h" #include "ppapi/proxy/ppp_mouse_lock_proxy.h" +#include "ppapi/proxy/ppp_pdf_proxy.h" #include "ppapi/proxy/ppp_printing_proxy.h" #include "ppapi/proxy/ppp_text_input_proxy.h" #include "ppapi/proxy/ppp_video_decoder_proxy.h" @@ -148,24 +161,12 @@ namespace proxy { namespace { -// The interface list has interfaces with no ID listed as "NoAPIName" which -// means there's no corresponding _Proxy object. Our macros expand this to -// NoAPIName_Proxy, and then they look for kApiID inside it. -// -// This dummy class provides the correct definition for that interface ID, -// which is "NONE". -class NoAPIName_Proxy { - public: - static const ApiID kApiID = API_ID_NONE; -}; - template<typename ProxyClass> InterfaceProxy* ProxyFactory(Dispatcher* dispatcher) { return new ProxyClass(dispatcher); } base::LazyInstance<PpapiPermissions> g_process_global_permissions; -base::LazyInstance<bool> g_supports_dev_channel; } // namespace @@ -180,8 +181,8 @@ InterfaceList::InterfaceList() { // Register each proxied interface by calling AddPPB for each supported // interface. Set current_required_permission to the appropriate value for // the value you want expanded by this macro. - #define PROXIED_IFACE(api_name, iface_str, iface_struct) \ - AddPPB(iface_str, PROXY_API_ID(api_name), \ + #define PROXIED_IFACE(iface_str, iface_struct) \ + AddPPB(iface_str, \ INTERFACE_THUNK_NAME(iface_struct)(), \ current_required_permission); @@ -204,8 +205,10 @@ InterfaceList::InterfaceList() { #include "ppapi/thunk/interfaces_ppb_private_flash.h" #endif // !defined(OS_NACL) } - - // TODO(teravest): Add dev channel interfaces here. + { + Permission current_required_permission = PERMISSION_DEV_CHANNEL; + #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h" + } #undef PROXIED_API #undef PROXIED_IFACE @@ -216,34 +219,39 @@ InterfaceList::InterfaceList() { // proxy and the impl and there's no obvious message routing. AddProxy(API_ID_RESOURCE_CREATION, &ResourceCreationProxy::Create); AddProxy(API_ID_PPP_CLASS, &PPP_Class_Proxy::Create); - AddPPB(PPB_CORE_INTERFACE_1_0, API_ID_PPB_CORE, + AddPPB(PPB_CORE_INTERFACE_1_0, PPB_Core_Proxy::GetPPB_Core_Interface(), PERMISSION_NONE); - AddPPB(PPB_MESSAGELOOP_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_MESSAGELOOP_INTERFACE_1_0, PPB_MessageLoop_Proxy::GetInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_INSTANCEDARRAYS_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_INSTANCEDARRAYS_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetInstancedArraysInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_FRAMEBUFFERBLIT_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_FRAMEBUFFERBLIT_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetFramebufferBlitInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_FRAMEBUFFERMULTISAMPLE_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_FRAMEBUFFERMULTISAMPLE_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetFramebufferMultisampleInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_CHROMIUMENABLEFEATURE_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_CHROMIUMENABLEFEATURE_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetChromiumEnableFeatureInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_DEV_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_DEV_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE); - AddPPB(PPB_OPENGLES2_QUERY_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_QUERY_INTERFACE_1_0, PPB_OpenGLES2_Shared::GetQueryInterface(), PERMISSION_NONE); - AddPPB(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_OPENGLES2_DRAWBUFFERS_DEV_INTERFACE_1_0, + PPB_OpenGLES2_Shared::GetDrawBuffersInterface(), + PERMISSION_DEV); + AddPPB(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, PPB_Var_Shared::GetVarArrayBufferInterface1_0(), PERMISSION_NONE); - AddPPB(PPB_VAR_INTERFACE_1_1, API_ID_NONE, + AddPPB(PPB_VAR_INTERFACE_1_2, + PPB_Var_Shared::GetVarInterface1_2(), PERMISSION_NONE); + AddPPB(PPB_VAR_INTERFACE_1_1, PPB_Var_Shared::GetVarInterface1_1(), PERMISSION_NONE); - AddPPB(PPB_VAR_INTERFACE_1_0, API_ID_NONE, + AddPPB(PPB_VAR_INTERFACE_1_0, PPB_Var_Shared::GetVarInterface1_0(), PERMISSION_NONE); #if !defined(OS_NACL) @@ -251,12 +259,12 @@ InterfaceList::InterfaceList() { // Do not add more stuff here, they should be added to interface_list*.h // TODO(brettw) remove these. AddProxy(API_ID_PPB_INSTANCE_PRIVATE, &ProxyFactory<PPB_Instance_Proxy>); - AddPPB(PPB_INSTANCE_PRIVATE_INTERFACE_0_1, API_ID_PPB_INSTANCE_PRIVATE, + AddPPB(PPB_INSTANCE_PRIVATE_INTERFACE_0_1, thunk::GetPPB_Instance_Private_0_1_Thunk(), PERMISSION_PRIVATE); AddProxy(API_ID_PPB_VAR_DEPRECATED, &ProxyFactory<PPB_Var_Deprecated_Proxy>); - AddPPB(PPB_VAR_DEPRECATED_INTERFACE, API_ID_PPB_VAR_DEPRECATED, + AddPPB(PPB_VAR_DEPRECATED_INTERFACE, PPB_Var_Deprecated_Proxy::GetProxyInterface(), PERMISSION_DEV); // TODO(tomfinegan): Figure out where to put these once we refactor things @@ -264,37 +272,42 @@ InterfaceList::InterfaceList() { AddProxy(API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, &ProxyFactory<PPP_ContentDecryptor_Private_Proxy>); AddPPP(PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE, - API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, PPP_ContentDecryptor_Private_Proxy::GetProxyInterface()); #endif AddProxy(API_ID_PPB_TESTING, &ProxyFactory<PPB_Testing_Proxy>); - AddPPB(PPB_TESTING_PRIVATE_INTERFACE, API_ID_PPB_TESTING, + AddPPB(PPB_TESTING_PRIVATE_INTERFACE, PPB_Testing_Proxy::GetProxyInterface(), PERMISSION_TESTING); // PPP (plugin) interfaces. // TODO(brettw) move these to interface_list*.h + AddProxy(API_ID_PPP_GRAPHICS_3D, &ProxyFactory<PPP_Graphics3D_Proxy>); + AddPPP(PPP_GRAPHICS_3D_INTERFACE, PPP_Graphics3D_Proxy::GetProxyInterface()); + AddProxy(API_ID_PPP_INPUT_EVENT, &ProxyFactory<PPP_InputEvent_Proxy>); + AddPPP(PPP_INPUT_EVENT_INTERFACE, PPP_InputEvent_Proxy::GetProxyInterface()); AddProxy(API_ID_PPP_INSTANCE, &ProxyFactory<PPP_Instance_Proxy>); - #if !defined(OS_NACL) - AddPPP(PPP_INSTANCE_INTERFACE_1_1, API_ID_PPP_INSTANCE, +#if !defined(OS_NACL) + AddPPP(PPP_INSTANCE_INTERFACE_1_1, PPP_Instance_Proxy::GetInstanceInterface()); - #endif + AddProxy(API_ID_PPP_INSTANCE_PRIVATE, + &ProxyFactory<PPP_Instance_Private_Proxy>); + AddPPP(PPP_INSTANCE_PRIVATE_INTERFACE, + PPP_Instance_Private_Proxy::GetProxyInterface()); +#endif + AddProxy(API_ID_PPP_MESSAGING, &ProxyFactory<PPP_Messaging_Proxy>); + AddProxy(API_ID_PPP_MOUSE_LOCK, &ProxyFactory<PPP_MouseLock_Proxy>); + AddPPP(PPP_MOUSELOCK_INTERFACE, PPP_MouseLock_Proxy::GetProxyInterface()); AddProxy(API_ID_PPP_PRINTING, &ProxyFactory<PPP_Printing_Proxy>); - AddPPP(PPP_PRINTING_DEV_INTERFACE, API_ID_PPP_PRINTING, - PPP_Printing_Proxy::GetProxyInterface()); + AddPPP(PPP_PRINTING_DEV_INTERFACE, PPP_Printing_Proxy::GetProxyInterface()); AddProxy(API_ID_PPP_TEXT_INPUT, &ProxyFactory<PPP_TextInput_Proxy>); - AddPPP(PPP_TEXTINPUT_DEV_INTERFACE, API_ID_PPP_TEXT_INPUT, - PPP_TextInput_Proxy::GetProxyInterface()); - - // Old-style GetInfo PPP interfaces. - // Do not add more stuff here, they should be added to interface_list*.h - // TODO(brettw) remove these. - AddPPP(PPP_InputEvent_Proxy::GetInfo()); - AddPPP(PPP_Messaging_Proxy::GetInfo()); - AddPPP(PPP_MouseLock_Proxy::GetInfo()); - AddPPP(PPP_Graphics3D_Proxy::GetInfo()); + AddPPP(PPP_TEXTINPUT_DEV_INTERFACE, PPP_TextInput_Proxy::GetProxyInterface()); #if !defined(OS_NACL) - AddPPP(PPP_Instance_Private_Proxy::GetInfo()); - AddPPP(PPP_VideoDecoder_Proxy::GetInfo()); + AddProxy(API_ID_PPP_PDF, &ProxyFactory<PPP_Pdf_Proxy>); + AddPPP(PPP_PDF_INTERFACE, PPP_Pdf_Proxy::GetProxyInterface()); + AddProxy(API_ID_PPP_FIND_PRIVATE, &ProxyFactory<PPP_Find_Proxy>); + AddPPP(PPP_FIND_PRIVATE_INTERFACE, PPP_Find_Proxy::GetProxyInterface()); + AddProxy(API_ID_PPP_VIDEO_DECODER_DEV, &ProxyFactory<PPP_VideoDecoder_Proxy>); + AddPPP(PPP_VIDEODECODER_DEV_INTERFACE, + PPP_VideoDecoder_Proxy::GetProxyInterface()); #endif } @@ -312,28 +325,6 @@ void InterfaceList::SetProcessGlobalPermissions( g_process_global_permissions.Get() = permissions; } -// static -void InterfaceList::SetSupportsDevChannel( - bool supports_dev_channel) { - g_supports_dev_channel.Get() = supports_dev_channel; -} - -ApiID InterfaceList::GetIDForPPBInterface(const std::string& name) const { - NameToInterfaceInfoMap::const_iterator found = - name_to_browser_info_.find(name); - if (found == name_to_browser_info_.end()) - return API_ID_NONE; - return found->second.id; -} - -ApiID InterfaceList::GetIDForPPPInterface(const std::string& name) const { - NameToInterfaceInfoMap::const_iterator found = - name_to_plugin_info_.find(name); - if (found == name_to_plugin_info_.end()) - return API_ID_NONE; - return found->second.id; -} - InterfaceProxy::Factory InterfaceList::GetFactoryForID(ApiID id) const { int index = static_cast<int>(id); COMPILE_ASSERT(API_ID_NONE == 0, none_must_be_zero); @@ -342,17 +333,22 @@ InterfaceProxy::Factory InterfaceList::GetFactoryForID(ApiID id) const { return id_to_factory_[index]; } -const void* InterfaceList::GetInterfaceForPPB(const std::string& name) const { - NameToInterfaceInfoMap::const_iterator found = +const void* InterfaceList::GetInterfaceForPPB(const std::string& name) { + NameToInterfaceInfoMap::iterator found = name_to_browser_info_.find(name); if (found == name_to_browser_info_.end()) return NULL; - // Dev channel checking goes here. - if (g_process_global_permissions.Get().HasPermission( - found->second.required_permission)) + found->second.required_permission)) { + // Only log interface use once per plugin. + if (!found->second.interface_logged) { + PluginGlobals::Get()->GetBrowserSender()->Send( + new PpapiHostMsg_LogInterfaceUsage(HashInterfaceName(name))); + found->second.interface_logged = true; + } return found->second.iface; + } return NULL; } @@ -381,23 +377,24 @@ void InterfaceList::AddProxy(ApiID id, } void InterfaceList::AddPPB(const char* name, - ApiID id, const void* iface, Permission perm) { DCHECK(name_to_browser_info_.find(name) == name_to_browser_info_.end()); - name_to_browser_info_[name] = InterfaceInfo(id, iface, perm); + name_to_browser_info_[name] = InterfaceInfo(iface, perm); } void InterfaceList::AddPPP(const char* name, - ApiID id, const void* iface) { DCHECK(name_to_plugin_info_.find(name) == name_to_plugin_info_.end()); - name_to_plugin_info_[name] = InterfaceInfo(id, iface, PERMISSION_NONE); + name_to_plugin_info_[name] = InterfaceInfo(iface, PERMISSION_NONE); } -void InterfaceList::AddPPP(const InterfaceProxy::Info* info) { - AddProxy(info->id, info->create_proxy); - AddPPP(info->name, info->id, info->interface_ptr); +// static +int InterfaceList::HashInterfaceName(const std::string& name) { + uint32 data = base::Hash(name.c_str(), name.size()); + // Strip off the signed bit because UMA doesn't support negative values, + // but takes a signed int as input. + return static_cast<int>(data & 0x7fffffff); } } // namespace proxy diff --git a/chromium/ppapi/proxy/interface_list.h b/chromium/ppapi/proxy/interface_list.h index 78064170d1c..a2b4569c8f1 100644 --- a/chromium/ppapi/proxy/interface_list.h +++ b/chromium/ppapi/proxy/interface_list.h @@ -16,7 +16,7 @@ namespace ppapi { namespace proxy { -class InterfaceList { +class PPAPI_PROXY_EXPORT InterfaceList { public: InterfaceList(); ~InterfaceList(); @@ -33,15 +33,7 @@ class InterfaceList { // plugin process. A real security check is required for all IPC messages. // This check just allows us to return NULL for interfaces you "shouldn't" be // using to keep honest plugins honest. - static PPAPI_PROXY_EXPORT void SetProcessGlobalPermissions( - const PpapiPermissions& permissions); - static PPAPI_PROXY_EXPORT void SetSupportsDevChannel( - bool supports_dev_channel); - - // Looks up the ID for the given interface name. Returns API_ID_NONE if - // the interface string is not found. - ApiID GetIDForPPBInterface(const std::string& name) const; - ApiID GetIDForPPPInterface(const std::string& name) const; + static void SetProcessGlobalPermissions(const PpapiPermissions& permissions); // Looks up the factory function for the given ID. Returns NULL if not // supported. @@ -49,29 +41,33 @@ class InterfaceList { // Returns the interface pointer for the given browser or plugin interface, // or NULL if it's not supported. - const void* GetInterfaceForPPB(const std::string& name) const; + const void* GetInterfaceForPPB(const std::string& name); const void* GetInterfaceForPPP(const std::string& name) const; private: + friend class InterfaceListTest; + struct InterfaceInfo { InterfaceInfo() - : id(API_ID_NONE), - iface(NULL), - required_permission(PERMISSION_NONE) { + : iface(NULL), + required_permission(PERMISSION_NONE), + interface_logged(false) { } - InterfaceInfo(ApiID in_id, const void* in_interface, Permission in_perm) - : id(in_id), - iface(in_interface), - required_permission(in_perm) { + InterfaceInfo(const void* in_interface, Permission in_perm) + : iface(in_interface), + required_permission(in_perm), + interface_logged(false) { } - ApiID id; const void* iface; // Permission required to return non-null for this interface. This will // be checked with the value set via SetProcessGlobalPermissionBits when // an interface is requested. Permission required_permission; + + // Interface usage is logged just once per-interface-per-plugin-process. + bool interface_logged; }; typedef std::map<std::string, InterfaceInfo> NameToInterfaceInfoMap; @@ -81,13 +77,11 @@ class InterfaceList { // Permissions is the type of permission required to access the corresponding // interface. Currently this must be just one unique permission (rather than // a bitfield). - void AddPPB(const char* name, ApiID id, const void* iface, - Permission permission); - void AddPPP(const char* name, ApiID id, const void* iface); + void AddPPB(const char* name, const void* iface, Permission permission); + void AddPPP(const char* name, const void* iface); - // Old-style add functions. These should be removed when the rest of the - // proxies are converted over to using the new system. - void AddPPP(const InterfaceProxy::Info* info); + // Hash the interface name for UMA logging. + static int HashInterfaceName(const std::string& name); PpapiPermissions permissions_; diff --git a/chromium/ppapi/proxy/interface_list_unittest.cc b/chromium/ppapi/proxy/interface_list_unittest.cc new file mode 100644 index 00000000000..902a0a18a4a --- /dev/null +++ b/chromium/ppapi/proxy/interface_list_unittest.cc @@ -0,0 +1,80 @@ +// Copyright (c) 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 "base/hash.h" +#include "ppapi/c/ppb_core.h" +#include "ppapi/proxy/interface_list.h" +#include "ppapi/proxy/ppapi_proxy_test.h" + +namespace ppapi { +namespace proxy { + +class InterfaceListTest : public PluginProxyTest { + public: + // Wrapper function so we can use the private InterfaceList::AddPPB. + void AddPPB(InterfaceList* list, + const char* iface_name, void* iface_addr, Permission perm) { + list->AddPPB(iface_name, iface_addr, perm); + } + + // Wrapper function so we can use the private + // InterfaceList::HashInterfaceName. + int HashInterfaceName(const std::string& name) { + return InterfaceList::HashInterfaceName(name); + } +}; + +// Tests looking up a stable interface. +TEST_F(InterfaceListTest, Stable) { + InterfaceList list; + ASSERT_TRUE(list.GetInterfaceForPPB(PPB_CORE_INTERFACE_1_0) != NULL); + ASSERT_TRUE(list.GetInterfaceForPPB("FakeUnknownInterface") == NULL); +} + +// Tests that dev channel restrictions work properly. +TEST_F(InterfaceListTest, DevChannel) { + InterfaceList list; + // "Dev channel" interface. + static const char* dev_channel_iface_name = "TestDevChannelInterface"; + void* dev_channel_iface_addr = (void*)0xdeadbeef; + // "Dev" interface + static const char* dev_iface_name = "TestDevInterface"; + void* dev_iface_addr = (void*)0xcafefade; + + AddPPB(&list, dev_channel_iface_name, dev_channel_iface_addr, + PERMISSION_DEV_CHANNEL); + AddPPB(&list, dev_iface_name, dev_iface_addr, PERMISSION_DEV); + + InterfaceList::SetProcessGlobalPermissions( + PpapiPermissions(PERMISSION_NONE)); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_channel_iface_name) == NULL); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_iface_name) == NULL); + + InterfaceList::SetProcessGlobalPermissions( + PpapiPermissions(PERMISSION_DEV_CHANNEL)); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_channel_iface_name) == + dev_channel_iface_addr); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_iface_name) == NULL); + + InterfaceList::SetProcessGlobalPermissions( + PpapiPermissions(PERMISSION_DEV)); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_channel_iface_name) == NULL); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_iface_name) == dev_iface_addr); + + InterfaceList::SetProcessGlobalPermissions( + PpapiPermissions(PERMISSION_DEV | PERMISSION_DEV_CHANNEL)); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_channel_iface_name) == + dev_channel_iface_addr); + ASSERT_TRUE(list.GetInterfaceForPPB(dev_iface_name) == dev_iface_addr); +} + +// Test that the hash function provided by base::Hash is unchanged. This is so +// that we will generate correct values when logging interface use to UMA. +TEST_F(InterfaceListTest, InterfaceHash) { + EXPECT_EQ(612625164, HashInterfaceName("PPB_InputEvent;1.0")); + EXPECT_EQ(79708274, HashInterfaceName("PPB_TCPSocket;1.1")); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/interface_proxy.h b/chromium/ppapi/proxy/interface_proxy.h index dcab5473c9c..099d58b5fe7 100644 --- a/chromium/ppapi/proxy/interface_proxy.h +++ b/chromium/ppapi/proxy/interface_proxy.h @@ -24,24 +24,6 @@ class InterfaceProxy : public IPC::Listener, public IPC::Sender { // is transferred to the caller. typedef InterfaceProxy* (*Factory)(Dispatcher* dispatcher); - // DEPRECATED: New classes should be registered directly in the interface - // list. This is kept around until we convert all the existing code. - // - // Information about the interface. Each interface has a static function to - // return its info, which allows either construction on the target side, and - // getting the proxied interface on the source side (see dispatcher.h for - // terminology). - struct Info { - const void* interface_ptr; - - const char* name; - ApiID id; - - bool is_trusted; - - InterfaceProxy::Factory create_proxy; - }; - virtual ~InterfaceProxy(); Dispatcher* dispatcher() const { return dispatcher_; } diff --git a/chromium/ppapi/proxy/media_stream_audio_track_resource.cc b/chromium/ppapi/proxy/media_stream_audio_track_resource.cc new file mode 100644 index 00000000000..32fdd2846fe --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_audio_track_resource.cc @@ -0,0 +1,197 @@ +// 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. + +#include "ppapi/proxy/media_stream_audio_track_resource.h" + +#include "ppapi/proxy/audio_buffer_resource.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/media_stream_audio_track_shared.h" +#include "ppapi/shared_impl/media_stream_buffer.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +MediaStreamAudioTrackResource::MediaStreamAudioTrackResource( + Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id) + : MediaStreamTrackResourceBase( + connection, instance, pending_renderer_id, id), + get_buffer_output_(NULL) { +} + +MediaStreamAudioTrackResource::~MediaStreamAudioTrackResource() { + Close(); +} + +thunk::PPB_MediaStreamAudioTrack_API* +MediaStreamAudioTrackResource::AsPPB_MediaStreamAudioTrack_API() { + return this; +} + +PP_Var MediaStreamAudioTrackResource::GetId() { + return StringVar::StringToPPVar(id()); +} + +PP_Bool MediaStreamAudioTrackResource::HasEnded() { + return PP_FromBool(has_ended()); +} + +int32_t MediaStreamAudioTrackResource::Configure( + const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) { + if (has_ended()) + return PP_ERROR_FAILED; + + if (TrackedCallback::IsPending(configure_callback_) || + TrackedCallback::IsPending(get_buffer_callback_)) { + return PP_ERROR_INPROGRESS; + } + + // Do not support configure if audio buffers are held by plugin. + if (!buffers_.empty()) + return PP_ERROR_INPROGRESS; + + MediaStreamAudioTrackShared::Attributes attributes; + int i = 0; + for (; attrib_list[i] != PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE; i += 2) { + switch (attrib_list[i]) { + case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS: + attributes.buffers = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_RATE: + case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_SIZE: + case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_CHANNELS: + case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION: + return PP_ERROR_NOTSUPPORTED; + default: + return PP_ERROR_BADARGUMENT; + } + } + + if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes)) + return PP_ERROR_BADARGUMENT; + + configure_callback_ = callback; + Call<PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply>( + RENDERER, + PpapiHostMsg_MediaStreamAudioTrack_Configure(attributes), + base::Bind(&MediaStreamAudioTrackResource::OnPluginMsgConfigureReply, + base::Unretained(this)), + callback); + return PP_OK_COMPLETIONPENDING; +} + +int32_t MediaStreamAudioTrackResource::GetAttrib( + PP_MediaStreamAudioTrack_Attrib attrib, + int32_t* value) { + // TODO(penghuang): Implement this function. + return PP_ERROR_NOTSUPPORTED; +} + +int32_t MediaStreamAudioTrackResource::GetBuffer( + PP_Resource* buffer, + scoped_refptr<TrackedCallback> callback) { + if (has_ended()) + return PP_ERROR_FAILED; + + if (TrackedCallback::IsPending(configure_callback_) || + TrackedCallback::IsPending(get_buffer_callback_)) + return PP_ERROR_INPROGRESS; + + *buffer = GetAudioBuffer(); + if (*buffer) + return PP_OK; + + // TODO(penghuang): Use the callback as hints to determine which thread will + // use the resource, so we could deliver buffers to the target thread directly + // for better performance. + get_buffer_output_ = buffer; + get_buffer_callback_ = callback; + return PP_OK_COMPLETIONPENDING; +} + +int32_t MediaStreamAudioTrackResource::RecycleBuffer(PP_Resource buffer) { + BufferMap::iterator it = buffers_.find(buffer); + if (it == buffers_.end()) + return PP_ERROR_BADRESOURCE; + + scoped_refptr<AudioBufferResource> buffer_resource = it->second; + buffers_.erase(it); + + if (has_ended()) + return PP_OK; + + DCHECK_GE(buffer_resource->GetBufferIndex(), 0); + + SendEnqueueBufferMessageToHost(buffer_resource->GetBufferIndex()); + buffer_resource->Invalidate(); + return PP_OK; +} + +void MediaStreamAudioTrackResource::Close() { + if (has_ended()) + return; + + if (TrackedCallback::IsPending(get_buffer_callback_)) { + *get_buffer_output_ = 0; + get_buffer_callback_->PostAbort(); + get_buffer_callback_ = NULL; + get_buffer_output_ = 0; + } + + ReleaseBuffers(); + MediaStreamTrackResourceBase::CloseInternal(); +} + +void MediaStreamAudioTrackResource::OnNewBufferEnqueued() { + if (!TrackedCallback::IsPending(get_buffer_callback_)) + return; + + *get_buffer_output_ = GetAudioBuffer(); + int32_t result = *get_buffer_output_ ? PP_OK : PP_ERROR_FAILED; + get_buffer_output_ = NULL; + scoped_refptr<TrackedCallback> callback; + callback.swap(get_buffer_callback_); + callback->Run(result); +} + +PP_Resource MediaStreamAudioTrackResource::GetAudioBuffer() { + int32_t index = buffer_manager()->DequeueBuffer(); + if (index < 0) + return 0; + + MediaStreamBuffer* buffer = buffer_manager()->GetBufferPointer(index); + DCHECK(buffer); + scoped_refptr<AudioBufferResource> resource = + new AudioBufferResource(pp_instance(), index, buffer); + // Add |pp_resource()| and |resource| into |buffers_|. + // |buffers_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the + // resource alive. + buffers_.insert(BufferMap::value_type(resource->pp_resource(), resource)); + return resource->GetReference(); +} + +void MediaStreamAudioTrackResource::ReleaseBuffers() { + for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) { + // Just invalidate and release VideoBufferResorce, but keep PP_Resource. + // So plugin can still use |RecycleBuffer()|. + it->second->Invalidate(); + it->second = NULL; + } +} + +void MediaStreamAudioTrackResource::OnPluginMsgConfigureReply( + const ResourceMessageReplyParams& params) { + if (TrackedCallback::IsPending(configure_callback_)) { + scoped_refptr<TrackedCallback> callback; + callback.swap(configure_callback_); + callback->Run(params.result()); + } +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/media_stream_audio_track_resource.h b/chromium/ppapi/proxy/media_stream_audio_track_resource.h new file mode 100644 index 00000000000..6cc5d436f50 --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_audio_track_resource.h @@ -0,0 +1,76 @@ +// 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 PPAPI_PROXY_MEDIA_STREAM_AUDIO_TRACK_RESOURCE_H_ +#define PPAPI_PROXY_MEDIA_STREAM_AUDIO_TRACK_RESOURCE_H_ + +#include <map> +#include <string> + +#include "base/memory/ref_counted.h" +#include "ppapi/proxy/media_stream_track_resource_base.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/thunk/ppb_media_stream_audio_track_api.h" + +namespace ppapi { +namespace proxy { + +class AudioBufferResource; + +class PPAPI_PROXY_EXPORT MediaStreamAudioTrackResource + : public MediaStreamTrackResourceBase, + public thunk::PPB_MediaStreamAudioTrack_API { + public: + MediaStreamAudioTrackResource(Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id); + + virtual ~MediaStreamAudioTrackResource(); + + // Resource overrides: + virtual thunk::PPB_MediaStreamAudioTrack_API* + AsPPB_MediaStreamAudioTrack_API() OVERRIDE; + + // PPB_MediaStreamAudioTrack_API overrides: + virtual PP_Var GetId() OVERRIDE; + virtual PP_Bool HasEnded() OVERRIDE; + virtual int32_t Configure(const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t GetAttrib(PP_MediaStreamAudioTrack_Attrib attrib, + int32_t* value) OVERRIDE; + virtual int32_t GetBuffer( + PP_Resource* buffer, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t RecycleBuffer(PP_Resource buffer) OVERRIDE; + virtual void Close() OVERRIDE; + + // MediaStreamBufferManager::Delegate overrides: + virtual void OnNewBufferEnqueued() OVERRIDE; + + private: + PP_Resource GetAudioBuffer(); + + void ReleaseBuffers(); + + // IPC message handlers. + void OnPluginMsgConfigureReply(const ResourceMessageReplyParams& params); + + // Allocated buffer resources by |GetBuffer()|. + typedef std::map<PP_Resource, scoped_refptr<AudioBufferResource> > BufferMap; + BufferMap buffers_; + + PP_Resource* get_buffer_output_; + + scoped_refptr<TrackedCallback> configure_callback_; + + scoped_refptr<TrackedCallback> get_buffer_callback_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioTrackResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_MEDIA_STREAM_AUDIO_TRACK_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/media_stream_track_resource_base.cc b/chromium/ppapi/proxy/media_stream_track_resource_base.cc new file mode 100644 index 00000000000..12ebdb7c4f9 --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_track_resource_base.cc @@ -0,0 +1,93 @@ +// 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. + +#include "ppapi/proxy/media_stream_track_resource_base.h" + +#include "base/logging.h" +#include "ppapi/proxy/ppapi_messages.h" + +namespace ppapi { +namespace proxy { + +MediaStreamTrackResourceBase::MediaStreamTrackResourceBase( + Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id) + : PluginResource(connection, instance), + buffer_manager_(this), + id_(id), + has_ended_(false) { + AttachToPendingHost(RENDERER, pending_renderer_id); +} + +MediaStreamTrackResourceBase::MediaStreamTrackResourceBase( + Connection connection, + PP_Instance instance) + : PluginResource(connection, instance), + buffer_manager_(this), + has_ended_(false) { +} + +MediaStreamTrackResourceBase::~MediaStreamTrackResourceBase() { +} + +void MediaStreamTrackResourceBase::SendEnqueueBufferMessageToHost( + int32_t index) { + DCHECK_GE(index, 0); + DCHECK_LT(index, buffer_manager()->number_of_buffers()); + Post(RENDERER, PpapiHostMsg_MediaStreamTrack_EnqueueBuffer(index)); +} + +void MediaStreamTrackResourceBase::OnReplyReceived( + const ResourceMessageReplyParams& params, + const IPC::Message& msg) { + PPAPI_BEGIN_MESSAGE_MAP(MediaStreamTrackResourceBase, msg) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_MediaStreamTrack_InitBuffers, OnPluginMsgInitBuffers) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_MediaStreamTrack_EnqueueBuffer, OnPluginMsgEnqueueBuffer) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_MediaStreamTrack_EnqueueBuffers, + OnPluginMsgEnqueueBuffers) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( + PluginResource::OnReplyReceived(params, msg)) + PPAPI_END_MESSAGE_MAP() +} + +void MediaStreamTrackResourceBase::CloseInternal() { + if (!has_ended_) { + Post(RENDERER, PpapiHostMsg_MediaStreamTrack_Close()); + has_ended_ = true; + } +} + +void MediaStreamTrackResourceBase::OnPluginMsgInitBuffers( + const ResourceMessageReplyParams& params, + int32_t number_of_buffers, + int32_t buffer_size, + bool readonly) { + base::SharedMemoryHandle shm_handle = base::SharedMemory::NULLHandle(); + params.TakeSharedMemoryHandleAtIndex(0, &shm_handle); + buffer_manager_.SetBuffers(number_of_buffers, buffer_size, + scoped_ptr<base::SharedMemory>(new base::SharedMemory(shm_handle, + readonly)), + false); +} + +void MediaStreamTrackResourceBase::OnPluginMsgEnqueueBuffer( + const ResourceMessageReplyParams& params, + int32_t index) { + buffer_manager_.EnqueueBuffer(index); +} + +void MediaStreamTrackResourceBase::OnPluginMsgEnqueueBuffers( + const ResourceMessageReplyParams& params, + const std::vector<int32_t>& indices) { + for (size_t i = 0; i < indices.size(); ++i) + buffer_manager_.EnqueueBuffer(indices[i]); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/media_stream_track_resource_base.h b/chromium/ppapi/proxy/media_stream_track_resource_base.h new file mode 100644 index 00000000000..087d4a95c98 --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_track_resource_base.h @@ -0,0 +1,71 @@ +// 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 PPAPI_PROXY_MEDIA_STREAM_TRACK_RESOURCE_BASE_H_ +#define PPAPI_PROXY_MEDIA_STREAM_TRACK_RESOURCE_BASE_H_ + +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/media_stream_buffer_manager.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT MediaStreamTrackResourceBase + : public PluginResource, + public MediaStreamBufferManager::Delegate { + protected: + MediaStreamTrackResourceBase(Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id); + + MediaStreamTrackResourceBase(Connection connection, PP_Instance instance); + + virtual ~MediaStreamTrackResourceBase(); + + std::string id() const { return id_; } + + void set_id(const std::string& id) { id_ = id; } + + bool has_ended() const { return has_ended_; } + + MediaStreamBufferManager* buffer_manager() { return &buffer_manager_; } + + void CloseInternal(); + + // Sends a buffer index to the corresponding PepperMediaStreamTrackHostBase + // via an IPC message. The host adds the buffer index into its + // |buffer_manager_| for reading or writing. + // Also see |MediaStreamBufferManager|. + void SendEnqueueBufferMessageToHost(int32_t index); + + // PluginResource overrides: + virtual void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) OVERRIDE; + + private: + // Message handlers: + void OnPluginMsgInitBuffers(const ResourceMessageReplyParams& params, + int32_t number_of_buffers, + int32_t buffer_size, + bool readonly); + void OnPluginMsgEnqueueBuffer(const ResourceMessageReplyParams& params, + int32_t index); + void OnPluginMsgEnqueueBuffers(const ResourceMessageReplyParams& params, + const std::vector<int32_t>& indices); + + MediaStreamBufferManager buffer_manager_; + + std::string id_; + + bool has_ended_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamTrackResourceBase); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_MEDIA_STREAM_TRACK_RESOURCE_BASE_H_ diff --git a/chromium/ppapi/proxy/media_stream_video_track_resource.cc b/chromium/ppapi/proxy/media_stream_video_track_resource.cc new file mode 100644 index 00000000000..2942ff574fb --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_video_track_resource.cc @@ -0,0 +1,225 @@ +// 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. + +#include "ppapi/proxy/media_stream_video_track_resource.h" + +#include "base/logging.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/video_frame_resource.h" +#include "ppapi/shared_impl/media_stream_buffer.h" +#include "ppapi/shared_impl/media_stream_video_track_shared.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +MediaStreamVideoTrackResource::MediaStreamVideoTrackResource( + Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id) + : MediaStreamTrackResourceBase( + connection, instance, pending_renderer_id, id), + get_frame_output_(NULL) { +} + +MediaStreamVideoTrackResource::MediaStreamVideoTrackResource( + Connection connection, + PP_Instance instance) + : MediaStreamTrackResourceBase(connection, instance), + get_frame_output_(NULL) { + SendCreate(RENDERER, PpapiHostMsg_MediaStreamVideoTrack_Create()); +} + +MediaStreamVideoTrackResource::~MediaStreamVideoTrackResource() { + Close(); +} + +thunk::PPB_MediaStreamVideoTrack_API* +MediaStreamVideoTrackResource::AsPPB_MediaStreamVideoTrack_API() { + return this; +} + +PP_Var MediaStreamVideoTrackResource::GetId() { + return StringVar::StringToPPVar(id()); +} + +PP_Bool MediaStreamVideoTrackResource::HasEnded() { + return PP_FromBool(has_ended()); +} + +int32_t MediaStreamVideoTrackResource::Configure( + const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) { + if (has_ended()) + return PP_ERROR_FAILED; + + if (TrackedCallback::IsPending(configure_callback_) || + TrackedCallback::IsPending(get_frame_callback_)) { + return PP_ERROR_INPROGRESS; + } + + // Do not support configure, if frames are hold by plugin. + if (!frames_.empty()) + return PP_ERROR_INPROGRESS; + + MediaStreamVideoTrackShared::Attributes attributes; + int i = 0; + for (;attrib_list[i] != PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE; i += 2) { + switch (attrib_list[i]) { + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES: + attributes.buffers = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH: + attributes.width = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT: + attributes.height = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT: + attributes.format = static_cast<PP_VideoFrame_Format>(attrib_list[i + 1]); + break; + default: + return PP_ERROR_BADARGUMENT; + } + } + + if (!MediaStreamVideoTrackShared::VerifyAttributes(attributes)) + return PP_ERROR_BADARGUMENT; + + configure_callback_ = callback; + Call<PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply>( + RENDERER, + PpapiHostMsg_MediaStreamVideoTrack_Configure(attributes), + base::Bind(&MediaStreamVideoTrackResource::OnPluginMsgConfigureReply, + base::Unretained(this)), + callback); + return PP_OK_COMPLETIONPENDING; +} + +int32_t MediaStreamVideoTrackResource::GetAttrib( + PP_MediaStreamVideoTrack_Attrib attrib, + int32_t* value) { + // TODO(penghuang): implement this function. + return PP_ERROR_NOTSUPPORTED; +} + +int32_t MediaStreamVideoTrackResource::GetFrame( + PP_Resource* frame, + scoped_refptr<TrackedCallback> callback) { + if (has_ended()) + return PP_ERROR_FAILED; + + if (TrackedCallback::IsPending(configure_callback_) || + TrackedCallback::IsPending(get_frame_callback_)) { + return PP_ERROR_INPROGRESS; + } + + *frame = GetVideoFrame(); + if (*frame) + return PP_OK; + + get_frame_output_ = frame; + get_frame_callback_ = callback; + return PP_OK_COMPLETIONPENDING; +} + +int32_t MediaStreamVideoTrackResource::RecycleFrame(PP_Resource frame) { + FrameMap::iterator it = frames_.find(frame); + if (it == frames_.end()) + return PP_ERROR_BADRESOURCE; + + scoped_refptr<VideoFrameResource> frame_resource = it->second; + frames_.erase(it); + + if (has_ended()) + return PP_OK; + + DCHECK_GE(frame_resource->GetBufferIndex(), 0); + + SendEnqueueBufferMessageToHost(frame_resource->GetBufferIndex()); + frame_resource->Invalidate(); + return PP_OK; +} + +void MediaStreamVideoTrackResource::Close() { + if (has_ended()) + return; + + if (TrackedCallback::IsPending(get_frame_callback_)) { + *get_frame_output_ = 0; + get_frame_callback_->PostAbort(); + get_frame_callback_ = NULL; + get_frame_output_ = 0; + } + + ReleaseFrames(); + MediaStreamTrackResourceBase::CloseInternal(); +} + +int32_t MediaStreamVideoTrackResource::GetEmptyFrame( + PP_Resource* frame, scoped_refptr<TrackedCallback> callback) { + return GetFrame(frame, callback); +} + +int32_t MediaStreamVideoTrackResource::PutFrame(PP_Resource frame) { + // TODO(ronghuawu): Consider to rename RecycleFrame to PutFrame and use + // one set of GetFrame and PutFrame for both input and output. + return RecycleFrame(frame); +} + +void MediaStreamVideoTrackResource::OnNewBufferEnqueued() { + if (!TrackedCallback::IsPending(get_frame_callback_)) + return; + + *get_frame_output_ = GetVideoFrame(); + int32_t result = *get_frame_output_ ? PP_OK : PP_ERROR_FAILED; + get_frame_output_ = NULL; + scoped_refptr<TrackedCallback> callback; + callback.swap(get_frame_callback_); + callback->Run(result); +} + +PP_Resource MediaStreamVideoTrackResource::GetVideoFrame() { + int32_t index = buffer_manager()->DequeueBuffer(); + if (index < 0) + return 0; + + MediaStreamBuffer* buffer = buffer_manager()->GetBufferPointer(index); + DCHECK(buffer); + scoped_refptr<VideoFrameResource> resource = + new VideoFrameResource(pp_instance(), index, buffer); + // Add |pp_resource()| and |resource| into |frames_|. + // |frames_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the + // resource alive. + frames_.insert(FrameMap::value_type(resource->pp_resource(), resource)); + return resource->GetReference(); +} + +void MediaStreamVideoTrackResource::ReleaseFrames() { + for (FrameMap::iterator it = frames_.begin(); it != frames_.end(); ++it) { + // Just invalidate and release VideoFrameResorce, but keep PP_Resource. + // So plugin can still use |RecycleFrame()|. + it->second->Invalidate(); + it->second = NULL; + } +} + +void MediaStreamVideoTrackResource::OnPluginMsgConfigureReply( + const ResourceMessageReplyParams& params, + const std::string& track_id) { + if (id().empty()) { + set_id(track_id); + } else { + DCHECK_EQ(id(), track_id); + } + if (TrackedCallback::IsPending(configure_callback_)) { + scoped_refptr<TrackedCallback> callback; + callback.swap(configure_callback_); + callback->Run(params.result()); + } +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/media_stream_video_track_resource.h b/chromium/ppapi/proxy/media_stream_video_track_resource.h new file mode 100644 index 00000000000..1e9927f82fe --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_video_track_resource.h @@ -0,0 +1,79 @@ +// 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 PPAPI_PROXY_MEDIA_STREAM_VIDEO_TRACK_RESOURCE_H_ +#define PPAPI_PROXY_MEDIA_STREAM_VIDEO_TRACK_RESOURCE_H_ + +#include <map> + +#include "base/memory/ref_counted.h" +#include "ppapi/proxy/media_stream_track_resource_base.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/thunk/ppb_media_stream_video_track_api.h" + +namespace ppapi { +namespace proxy { + +class VideoFrameResource; + +class PPAPI_PROXY_EXPORT MediaStreamVideoTrackResource + : public MediaStreamTrackResourceBase, + public thunk::PPB_MediaStreamVideoTrack_API { + public: + MediaStreamVideoTrackResource(Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id); + + MediaStreamVideoTrackResource(Connection connection, PP_Instance instance); + + virtual ~MediaStreamVideoTrackResource(); + + // Resource overrides: + virtual thunk::PPB_MediaStreamVideoTrack_API* + AsPPB_MediaStreamVideoTrack_API() OVERRIDE; + + // PPB_MediaStreamVideoTrack_API overrides: + virtual PP_Var GetId() OVERRIDE; + virtual PP_Bool HasEnded() OVERRIDE; + virtual int32_t Configure(const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t GetAttrib(PP_MediaStreamVideoTrack_Attrib attrib, + int32_t* value) OVERRIDE; + virtual int32_t GetFrame(PP_Resource* frame, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t RecycleFrame(PP_Resource frame) OVERRIDE; + virtual void Close() OVERRIDE; + virtual int32_t GetEmptyFrame( + PP_Resource* frame, scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t PutFrame(PP_Resource frame) OVERRIDE; + + // MediaStreamBufferManager::Delegate overrides: + virtual void OnNewBufferEnqueued() OVERRIDE; + + private: + PP_Resource GetVideoFrame(); + + void ReleaseFrames(); + + // IPC message handlers. + void OnPluginMsgConfigureReply(const ResourceMessageReplyParams& params, + const std::string& track_id); + + // Allocated frame resources by |GetFrame()|. + typedef std::map<PP_Resource, scoped_refptr<VideoFrameResource> > FrameMap; + FrameMap frames_; + + PP_Resource* get_frame_output_; + scoped_refptr<TrackedCallback> get_frame_callback_; + + scoped_refptr<TrackedCallback> configure_callback_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoTrackResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_MEDIA_STREAM_VIDEO_TRACK_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/message_handler.cc b/chromium/ppapi/proxy/message_handler.cc new file mode 100644 index 00000000000..6e44d0e018e --- /dev/null +++ b/chromium/ppapi/proxy/message_handler.cc @@ -0,0 +1,134 @@ +// 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. + +#include "ppapi/proxy/message_handler.h" + +#include "ipc/ipc_message.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_message_loop_proxy.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/shared_impl/scoped_pp_var.h" +#include "ppapi/thunk/enter.h" + +namespace ppapi { +namespace proxy { +namespace { + +typedef void (*HandleMessageFunc)(PP_Instance, void*, PP_Var); +typedef PP_Var (*HandleBlockingMessageFunc)(PP_Instance, void*, PP_Var); + +void HandleMessageWrapper(HandleMessageFunc function, + PP_Instance instance, + void* user_data, + ScopedPPVar message_data) { + CallWhileUnlocked(function, instance, user_data, message_data.get()); +} + +void HandleBlockingMessageWrapper(HandleBlockingMessageFunc function, + PP_Instance instance, + void* user_data, + ScopedPPVar message_data, + scoped_ptr<IPC::Message> reply_msg) { + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); + if (!dispatcher) + return; + PP_Var return_value = CallWhileUnlocked(function, + instance, + user_data, + message_data.get()); + PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams( + reply_msg.get(), + SerializedVarReturnValue::Convert(dispatcher, return_value), + true /* was_handled */); + dispatcher->Send(reply_msg.release()); +} + +} // namespace + +// static +scoped_ptr<MessageHandler> MessageHandler::Create( + PP_Instance instance, + const PPP_MessageHandler_0_1* handler_if, + void* user_data, + PP_Resource message_loop, + int32_t* error) { + scoped_ptr<MessageHandler> result; + // The interface and all function pointers must be valid. + if (!handler_if || + !handler_if->HandleMessage || + !handler_if->HandleBlockingMessage || + !handler_if->Destroy) { + *error = PP_ERROR_BADARGUMENT; + return result.Pass(); + } + thunk::EnterResourceNoLock<thunk::PPB_MessageLoop_API> + enter_loop(message_loop, true); + if (enter_loop.failed()) { + *error = PP_ERROR_BADRESOURCE; + return result.Pass(); + } + scoped_refptr<MessageLoopResource> message_loop_resource( + static_cast<MessageLoopResource*>(enter_loop.object())); + if (message_loop_resource->is_main_thread_loop()) { + *error = PP_ERROR_WRONG_THREAD; + return result.Pass(); + } + + result.reset(new MessageHandler( + instance, handler_if, user_data, message_loop_resource)); + *error = PP_OK; + return result.Pass(); +} + +MessageHandler::~MessageHandler() { + // It's possible the message_loop_proxy is NULL if that loop has been quit. + // In that case, we unfortunately just can't call Destroy. + if (message_loop_->message_loop_proxy()) { + // The posted task won't have the proxy lock, but that's OK, it doesn't + // touch any internal state; it's a direct call on the plugin's function. + message_loop_->message_loop_proxy()->PostTask(FROM_HERE, + base::Bind(handler_if_->Destroy, + instance_, + user_data_)); + } +} + +bool MessageHandler::LoopIsValid() const { + return !!message_loop_->message_loop_proxy(); +} + +void MessageHandler::HandleMessage(ScopedPPVar var) { + message_loop_->message_loop_proxy()->PostTask(FROM_HERE, + RunWhileLocked(base::Bind(&HandleMessageWrapper, + handler_if_->HandleMessage, + instance_, + user_data_, + var))); +} + +void MessageHandler::HandleBlockingMessage(ScopedPPVar var, + scoped_ptr<IPC::Message> reply_msg) { + message_loop_->message_loop_proxy()->PostTask(FROM_HERE, + RunWhileLocked(base::Bind(&HandleBlockingMessageWrapper, + handler_if_->HandleBlockingMessage, + instance_, + user_data_, + var, + base::Passed(reply_msg.Pass())))); +} + +MessageHandler::MessageHandler( + PP_Instance instance, + const PPP_MessageHandler_0_1* handler_if, + void* user_data, + scoped_refptr<MessageLoopResource> message_loop) + : instance_(instance), + handler_if_(handler_if), + user_data_(user_data), + message_loop_(message_loop) { +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/message_handler.h b/chromium/ppapi/proxy/message_handler.h new file mode 100644 index 00000000000..61ee639f0b1 --- /dev/null +++ b/chromium/ppapi/proxy/message_handler.h @@ -0,0 +1,75 @@ +// 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 PPAPI_PROXY_MESSAGE_HANDLER_H_ +#define PPAPI_PROXY_MESSAGE_HANDLER_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/ppp_message_handler.h" +#include "ppapi/proxy/ppapi_proxy_export.h" + +namespace IPC { +class Message; +} + +namespace ppapi { + +class ScopedPPVar; + +namespace proxy { + +class MessageLoopResource; + +// MessageHandler wraps a PPP_MessageHandler to encapsulate calling methods +// on the right thread and calling the Destroy function when this +// MessageHandler is destroyed. +class PPAPI_PROXY_EXPORT MessageHandler { + public: + // Create a MessageHandler. If any parameters are invalid, it will return a + // null scoped_ptr and set |*error| appropriately. + // |handler_if| is the struct of function pointers we will invoke. All of + // the function pointers within must be valid, or we fail + // with PP_ERROR_BADARGUMENT. + // |user_data| is a pointer provided by the plugin that we pass back when we + // call functions in |handler_if|. + // |message_loop| is the message loop where we will invoke functions in + // |handler_if|. Must not be the main thread message loop, + // to try to force the plugin to not over-subscribe the main + // thread. If it's the main thread loop, |error| will be set + // to PP_ERROR_WRONGTHREAD. + // |error| is an out-param that will be set on failure. + static scoped_ptr<MessageHandler> Create( + PP_Instance instance, + const PPP_MessageHandler_0_1* handler_if, + void* user_data, + PP_Resource message_loop, + int32_t* error); + ~MessageHandler(); + + bool LoopIsValid() const; + + void HandleMessage(ScopedPPVar var); + void HandleBlockingMessage(ScopedPPVar var, + scoped_ptr<IPC::Message> reply_msg); + + private: + MessageHandler(PP_Instance instance, + const PPP_MessageHandler_0_1* handler_if, + void* user_data, + scoped_refptr<MessageLoopResource> message_loop); + + PP_Instance instance_; + const PPP_MessageHandler_0_1* handler_if_; + void* user_data_; + scoped_refptr<MessageLoopResource> message_loop_; + + DISALLOW_COPY_AND_ASSIGN(MessageHandler); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_MESSAGE_HANDLER_H_ diff --git a/chromium/ppapi/proxy/nacl_message_scanner.cc b/chromium/ppapi/proxy/nacl_message_scanner.cc index 027975eb66c..e3a965dbf33 100644 --- a/chromium/ppapi/proxy/nacl_message_scanner.cc +++ b/chromium/ppapi/proxy/nacl_message_scanner.cc @@ -19,12 +19,16 @@ namespace IPC { class Message; } +using ppapi::proxy::ResourceMessageReplyParams; +using ppapi::proxy::SerializedHandle; +using ppapi::proxy::SerializedVar; + namespace { -typedef std::vector<ppapi::proxy::SerializedHandle> Handles; +typedef std::vector<SerializedHandle> Handles; struct ScanningResults { - ScanningResults() : handle_index(0) {} + ScanningResults() : handle_index(0), pp_resource(0) {} // Vector to hold handles found in the message. Handles handles; @@ -36,12 +40,18 @@ struct ScanningResults { // may set this to NULL when it can determine that there are no parameters // that need conversion. (See the ResourceMessageReplyParams overload.) scoped_ptr<IPC::Message> new_msg; + // Resource id for resource messages. Save this when scanning resource replies + // so when we audit the nested message, we know which resource it is for. + PP_Resource pp_resource; + // Callback to receive the nested message in a resource message or reply. + base::Callback<void(PP_Resource, const IPC::Message&, SerializedHandle*)> + nested_msg_callback; }; void WriteHandle(int handle_index, - const ppapi::proxy::SerializedHandle& handle, + const SerializedHandle& handle, IPC::Message* msg) { - ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), msg); + SerializedHandle::WriteHeader(handle.header(), msg); // Now write the handle itself in POSIX style. msg->WriteBool(true); // valid == true @@ -52,8 +62,7 @@ void WriteHandle(int handle_index, // handling. See ScanTuple for how these get used. // Overload to match SerializedHandle. -void ScanParam(const ppapi::proxy::SerializedHandle& handle, - ScanningResults* results) { +void ScanParam(const SerializedHandle& handle, ScanningResults* results) { results->handles.push_back(handle); if (results->new_msg) WriteHandle(results->handle_index++, handle, results->new_msg.get()); @@ -61,14 +70,13 @@ void ScanParam(const ppapi::proxy::SerializedHandle& handle, void HandleWriter(int* handle_index, IPC::Message* m, - const ppapi::proxy::SerializedHandle& handle) { + const SerializedHandle& handle) { WriteHandle((*handle_index)++, handle, m); } // Overload to match SerializedVar, which can contain handles. -void ScanParam(const ppapi::proxy::SerializedVar& var, - ScanningResults* results) { - std::vector<ppapi::proxy::SerializedHandle*> var_handles = var.GetHandles(); +void ScanParam(const SerializedVar& var, ScanningResults* results) { + std::vector<SerializedHandle*> var_handles = var.GetHandles(); // Copy any handles and then rewrite the message. for (size_t i = 0; i < var_handles.size(); ++i) results->handles.push_back(*var_handles[i]); @@ -82,8 +90,9 @@ void ScanParam(const ppapi::proxy::SerializedVar& var, // NOTE: We only intercept handles from host->NaCl. The only kind of // ResourceMessageParams that travels this direction is // ResourceMessageReplyParams, so that's the only one we need to handle. -void ScanParam(const ppapi::proxy::ResourceMessageReplyParams& params, +void ScanParam(const ResourceMessageReplyParams& params, ScanningResults* results) { + results->pp_resource = params.pp_resource(); // If the resource reply params don't contain handles, NULL the new message // pointer to cancel further rewriting. // NOTE: This works because only handles currently need rewriting, and we @@ -112,8 +121,21 @@ void ScanParam(const ppapi::proxy::ResourceMessageReplyParams& params, params.ConsumeHandles(); } -// Overload to match all other types. If we need to rewrite the message, -// write the parameter. +// Overload to match nested messages. If we need to rewrite the message, write +// the parameter. +void ScanParam(const IPC::Message& param, ScanningResults* results) { + if (results->pp_resource && !results->nested_msg_callback.is_null()) { + SerializedHandle* handle = NULL; + if (results->handles.size() == 1) + handle = &results->handles[0]; + results->nested_msg_callback.Run(results->pp_resource, param, handle); + } + if (results->new_msg) + IPC::WriteParam(results->new_msg.get(), param); +} + +// Overload to match all other types. If we need to rewrite the message, write +// the parameter. template <class T> void ScanParam(const T& param, ScanningResults* results) { if (results->new_msg) @@ -211,18 +233,62 @@ namespace proxy { class SerializedHandle; +NaClMessageScanner::FileSystem::FileSystem() + : reserved_quota_(0) { +} + +NaClMessageScanner::FileSystem::~FileSystem() { +} + +bool NaClMessageScanner::FileSystem::UpdateReservedQuota(int64_t delta) { + base::AutoLock lock(lock_); + if (std::numeric_limits<int64_t>::max() - reserved_quota_ < delta) + return false; // reserved_quota_ + delta would overflow. + if (reserved_quota_ + delta < 0) + return false; + reserved_quota_ += delta; + return true; +} + +NaClMessageScanner::FileIO::FileIO(FileSystem* file_system, + int64_t max_written_offset) + : file_system_(file_system), + max_written_offset_(max_written_offset) { +} + +NaClMessageScanner::FileIO::~FileIO() { +} + +void NaClMessageScanner::FileIO::SetMaxWrittenOffset( + int64_t max_written_offset) { + base::AutoLock lock(lock_); + max_written_offset_ = max_written_offset; +} + +bool NaClMessageScanner::FileIO::Grow(int64_t amount) { + base::AutoLock lock(lock_); + DCHECK(amount > 0); + if (!file_system_->UpdateReservedQuota(-amount)) + return false; + max_written_offset_ += amount; + return true; +} + NaClMessageScanner::NaClMessageScanner() { } +NaClMessageScanner::~NaClMessageScanner() { + for (FileSystemMap::iterator it = file_systems_.begin(); + it != file_systems_.end(); ++it) + delete it->second; + for (FileIOMap::iterator it = files_.begin(); it != files_.end(); ++it) + delete it->second; +} + // Windows IPC differs from POSIX in that native handles are serialized in the // message body, rather than passed in a separate FileDescriptorSet. Therefore, // on Windows, any message containing handles must be rewritten in the POSIX // format before we can send it to the NaCl plugin. -// -// On POSIX and Windows we have to rewrite PpapiMsg_CreateNaClChannel messages. -// These contain a handle with an invalid (place holder) descriptor. We need to -// locate this handle so it can be replaced with a valid one when the channel is -// created. bool NaClMessageScanner::ScanMessage( const IPC::Message& msg, std::vector<SerializedHandle>* handles, @@ -236,17 +302,18 @@ bool NaClMessageScanner::ScanMessage( #if defined(OS_WIN) true; #else - (msg.type() == PpapiMsg_CreateNaClChannel::ID); + false; #endif - // We can't always tell from the message ID if rewriting is needed. Therefore, // scan any message types that might contain a handle. If we later determine // that there are no handles, we can cancel the rewriting by clearing the // results.new_msg pointer. ScanningResults results; + results.nested_msg_callback = + base::Bind(&NaClMessageScanner::AuditNestedMessage, + base::Unretained(this)); switch (msg.type()) { - CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel) CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage) CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) @@ -260,7 +327,7 @@ bool NaClMessageScanner::ScanMessage( uint32_t type = iter->second; pending_sync_msgs_.erase(iter); switch (type) { - CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer) + CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer) CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple) CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall) CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory) @@ -285,14 +352,192 @@ bool NaClMessageScanner::ScanMessage( return true; } -void NaClMessageScanner::RegisterSyncMessageForReply(const IPC::Message& msg) { - DCHECK(msg.is_sync()); +void NaClMessageScanner::ScanUntrustedMessage( + const IPC::Message& untrusted_msg, + scoped_ptr<IPC::Message>* new_msg_ptr) { + if (untrusted_msg.is_sync()) + RegisterSyncMessageForReply(untrusted_msg); + + // Audit FileIO and FileSystem messages to ensure that the plugin doesn't + // exceed its file quota. If we find the message is malformed, just pass it + // through - we only care about well formed messages to the host. + if (untrusted_msg.type() == PpapiHostMsg_ResourceCall::ID) { + ResourceMessageCallParams params; + IPC::Message nested_msg; + if (!UnpackMessage<PpapiHostMsg_ResourceCall>( + untrusted_msg, ¶ms, &nested_msg)) + return; + + switch (nested_msg.type()) { + case PpapiHostMsg_FileIO_Close::ID: { + FileIOMap::iterator it = files_.find(params.pp_resource()); + if (it == files_.end()) + return; + // Audit FileIO Close messages to make sure the plugin reports an + // accurate file size. + FileGrowth file_growth; + if (!UnpackMessage<PpapiHostMsg_FileIO_Close>( + nested_msg, &file_growth)) + return; + + int64_t trusted_max_written_offset = it->second->max_written_offset(); + delete it->second; + files_.erase(it); + // If the plugin is under-reporting, rewrite the message with the + // trusted value. + if (trusted_max_written_offset > file_growth.max_written_offset) { + new_msg_ptr->reset( + new PpapiHostMsg_ResourceCall( + params, + PpapiHostMsg_FileIO_Close( + FileGrowth(trusted_max_written_offset, 0)))); + } + break; + } + case PpapiHostMsg_FileIO_SetLength::ID: { + FileIOMap::iterator it = files_.find(params.pp_resource()); + if (it == files_.end()) + return; + // Audit FileIO SetLength messages to make sure the plugin is within + // the current quota reservation. In addition, deduct the file size + // increase from the quota reservation. + int64_t length = 0; + if (!UnpackMessage<PpapiHostMsg_FileIO_SetLength>( + nested_msg, &length)) + return; + + // Calculate file size increase, taking care to avoid overflows. + if (length < 0) + return; + int64_t trusted_max_written_offset = it->second->max_written_offset(); + int64_t increase = length - trusted_max_written_offset; + if (increase <= 0) + return; + if (!it->second->Grow(increase)) { + new_msg_ptr->reset( + new PpapiHostMsg_ResourceCall( + params, + PpapiHostMsg_FileIO_SetLength(-1))); + } + break; + } + case PpapiHostMsg_FileSystem_ReserveQuota::ID: { + // Audit FileSystem ReserveQuota messages to make sure the plugin + // reports accurate file sizes. + int64_t amount = 0; + FileGrowthMap file_growths; + if (!UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>( + nested_msg, &amount, &file_growths)) + return; + + bool audit_failed = false; + for (FileGrowthMap::iterator it = file_growths.begin(); + it != file_growths.end(); ++it) { + FileIOMap::iterator file_it = files_.find(it->first); + if (file_it == files_.end()) + continue; + int64_t trusted_max_written_offset = + file_it->second->max_written_offset(); + if (trusted_max_written_offset > it->second.max_written_offset) { + audit_failed = true; + it->second.max_written_offset = trusted_max_written_offset; + } + if (it->second.append_mode_write_amount < 0) { + audit_failed = true; + it->second.append_mode_write_amount = 0; + } + } + if (audit_failed) { + new_msg_ptr->reset( + new PpapiHostMsg_ResourceCall( + params, + PpapiHostMsg_FileSystem_ReserveQuota( + amount, file_growths))); + } + break; + } + case PpapiHostMsg_ResourceDestroyed::ID: { + // Audit resource destroyed messages to release FileSystems. + PP_Resource resource; + if (!UnpackMessage<PpapiHostMsg_ResourceDestroyed>( + nested_msg, &resource)) + return; + FileSystemMap::iterator fs_it = file_systems_.find(resource); + if (fs_it != file_systems_.end()) { + delete fs_it->second; + file_systems_.erase(fs_it); + } + break; + } + } + } +} +void NaClMessageScanner::RegisterSyncMessageForReply(const IPC::Message& msg) { int msg_id = IPC::SyncMessage::GetMessageId(msg); DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end()); pending_sync_msgs_[msg_id] = msg.type(); } +NaClMessageScanner::FileIO* NaClMessageScanner::GetFile( + PP_Resource file_io) { + FileIOMap::iterator it = files_.find(file_io); + DCHECK(it != files_.end()); + return it->second; +} + +void NaClMessageScanner::AuditNestedMessage(PP_Resource resource, + const IPC::Message& msg, + SerializedHandle* handle) { + switch (msg.type()) { + case PpapiPluginMsg_FileIO_OpenReply::ID: { + // A file that requires quota checking was opened. + PP_Resource quota_file_system; + int64_t max_written_offset = 0; + if (ppapi::UnpackMessage<PpapiPluginMsg_FileIO_OpenReply>( + msg, "a_file_system, &max_written_offset)) { + if (quota_file_system) { + // Look up the FileSystem by inserting a new one. If it was already + // present, get the existing one, otherwise construct it. + FileSystem* file_system = NULL; + std::pair<FileSystemMap::iterator, bool> insert_result = + file_systems_.insert(std::make_pair(quota_file_system, + file_system)); + if (insert_result.second) + insert_result.first->second = new FileSystem(); + file_system = insert_result.first->second; + // Create the FileIO. + DCHECK(files_.find(resource) == files_.end()); + files_.insert(std::make_pair( + resource, + new FileIO(file_system, max_written_offset))); + } + } + break; + } + case PpapiPluginMsg_FileSystem_ReserveQuotaReply::ID: { + // The amount of reserved quota for a FileSystem was refreshed. + int64_t amount = 0; + FileSizeMap file_sizes; + if (ppapi::UnpackMessage<PpapiPluginMsg_FileSystem_ReserveQuotaReply>( + msg, &amount, &file_sizes)) { + FileSystemMap::iterator it = file_systems_.find(resource); + DCHECK(it != file_systems_.end()); + it->second->UpdateReservedQuota(amount); + + FileSizeMap::const_iterator offset_it = file_sizes.begin(); + for (; offset_it != file_sizes.end(); ++offset_it) { + FileIOMap::iterator fio_it = files_.find(offset_it->first); + DCHECK(fio_it != files_.end()); + if (fio_it != files_.end()) + fio_it->second->SetMaxWrittenOffset(offset_it->second); + } + } + break; + } + } +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/nacl_message_scanner.h b/chromium/ppapi/proxy/nacl_message_scanner.h index cce821b7f0c..d1360b72519 100644 --- a/chromium/ppapi/proxy/nacl_message_scanner.h +++ b/chromium/ppapi/proxy/nacl_message_scanner.h @@ -10,6 +10,8 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "ppapi/c/pp_resource.h" #include "ppapi/proxy/ppapi_proxy_export.h" namespace IPC { @@ -24,6 +26,7 @@ class SerializedHandle; class PPAPI_PROXY_EXPORT NaClMessageScanner { public: NaClMessageScanner(); + ~NaClMessageScanner(); // Scans the message for items that require special handling. Copies any // SerializedHandles in the message into |handles| and if the message must be @@ -39,20 +42,83 @@ class PPAPI_PROXY_EXPORT NaClMessageScanner { std::vector<SerializedHandle>* handles, scoped_ptr<IPC::Message>* new_msg_ptr); - // This method informs NaClMessageScanner that a sync message is being sent - // so that it can associate reply messages with their type. - // - // Users of NaClMessageScanner must call this when they send a synchronous - // message, otherwise NaClMessageScanner won't scan replies. - void RegisterSyncMessageForReply(const IPC::Message& msg); + // Scans an untrusted message for items that require special handling. If the + // message had to be rewritten, sets |new_msg_ptr| to the new message. + void ScanUntrustedMessage(const IPC::Message& untrusted_msg, + scoped_ptr<IPC::Message>* new_msg_ptr); + + // FileSystem information for quota auditing. + class PPAPI_PROXY_EXPORT FileSystem { + public: + FileSystem(); + ~FileSystem(); + + int64_t reserved_quota() const { return reserved_quota_; } + + // Adds amount to reserved quota. Returns true if reserved quota >= 0. + bool UpdateReservedQuota(int64_t delta); + + private: + base::Lock lock_; + // This is the remaining amount of quota reserved for the file system. + // Acquire the lock to modify this field, since it may be used on multiple + // threads. + int64_t reserved_quota_; + + DISALLOW_COPY_AND_ASSIGN(FileSystem); + }; + + // FileIO information for quota auditing. + class PPAPI_PROXY_EXPORT FileIO { + public: + FileIO(FileSystem* file_system, int64_t max_written_offset); + ~FileIO(); + + int64_t max_written_offset() { return max_written_offset_; } + + void SetMaxWrittenOffset(int64_t max_written_offset); + + // Grows file by the given amount. Returns true on success. + bool Grow(int64_t amount); + + private: + base::Lock lock_; + + // The file system that contains this file. + FileSystem* file_system_; + + // The maximum written offset. This is initialized by NaClMessageScanner + // when the file is opened and modified by a NaClDescQuotaInterface when the + // plugin writes to greater maximum offsets. + int64_t max_written_offset_; + + DISALLOW_COPY_AND_ASSIGN(FileIO); + }; + + FileIO* GetFile(PP_Resource file_io); private: + friend class NaClMessageScannerTest; + + void RegisterSyncMessageForReply(const IPC::Message& msg); + void AuditNestedMessage(PP_Resource resource, + const IPC::Message& msg, + SerializedHandle* handle); + // When we send a synchronous message (from untrusted to trusted), we store // its type here, so that later we can associate the reply with its type // for scanning. typedef std::map<int, uint32> PendingSyncMsgMap; PendingSyncMsgMap pending_sync_msgs_; + // We intercept FileSystem and FileIO messages to maintain information about + // file systems and open files. This is used by NaClQuotaDescs to calculate + // quota consumption and check it against the reserved amount. + typedef std::map<int32_t, FileSystem*> FileSystemMap; + FileSystemMap file_systems_; + typedef std::map<int32_t, FileIO*> FileIOMap; + FileIOMap files_; + DISALLOW_COPY_AND_ASSIGN(NaClMessageScanner); }; diff --git a/chromium/ppapi/proxy/nacl_message_scanner_unittest.cc b/chromium/ppapi/proxy/nacl_message_scanner_unittest.cc new file mode 100644 index 00000000000..3e439559c71 --- /dev/null +++ b/chromium/ppapi/proxy/nacl_message_scanner_unittest.cc @@ -0,0 +1,295 @@ +// 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 "ipc/ipc_message.h" +#include "ppapi/proxy/nacl_message_scanner.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/proxy/serialized_handle.h" +#include "ppapi/shared_impl/host_resource.h" + +namespace ppapi { +namespace proxy { + +namespace { +const PP_Resource kInvalidResource = 0; +const PP_Resource kFileSystem = 1; +const PP_Resource kFileIO = 2; +const int64_t kQuotaReservationAmount = 100; +} + +class NaClMessageScannerTest : public PluginProxyTest { + public: + NaClMessageScannerTest() {} + + uint32 FindPendingSyncMessage( + const NaClMessageScanner& scanner, + const IPC::Message& msg) { + int msg_id = IPC::SyncMessage::GetMessageId(msg); + std::map<int, uint32>::const_iterator it = + scanner.pending_sync_msgs_.find(msg_id); + // O can signal that no message was found. + return (it != scanner.pending_sync_msgs_.end()) ? it->second : 0; + } + + NaClMessageScanner::FileSystem* FindFileSystem( + const NaClMessageScanner& scanner, + PP_Resource file_system) { + NaClMessageScanner::FileSystemMap::const_iterator it = + scanner.file_systems_.find(file_system); + return (it != scanner.file_systems_.end()) ? it->second : NULL; + } + + NaClMessageScanner::FileIO* FindFileIO( + const NaClMessageScanner& scanner, + PP_Resource file_io) { + NaClMessageScanner::FileIOMap::const_iterator it = + scanner.files_.find(file_io); + return (it != scanner.files_.end()) ? it->second : NULL; + } + + void OpenQuotaFile(NaClMessageScanner* scanner, + PP_Resource file_io, + PP_Resource file_system) { + std::vector<SerializedHandle> unused_handles; + ResourceMessageReplyParams fio_reply_params(file_io, 0); + scoped_ptr<IPC::Message> new_msg_ptr; + scanner->ScanMessage( + PpapiPluginMsg_ResourceReply( + fio_reply_params, + PpapiPluginMsg_FileIO_OpenReply(file_system, 0)), + &unused_handles, + &new_msg_ptr); + EXPECT_FALSE(new_msg_ptr); + } +}; + +TEST_F(NaClMessageScannerTest, SyncMessageAndReply) { + NaClMessageScanner test; + ppapi::proxy::SerializedHandle handle( + ppapi::proxy::SerializedHandle::SHARED_MEMORY); + int id = -1; + IPC::Message msg = + PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer( + ppapi::API_ID_PPB_GRAPHICS_3D, + HostResource(), + 4096, // size + &id, + &handle); + scoped_ptr<IPC::Message> new_msg_ptr; + EXPECT_NE(msg.type(), FindPendingSyncMessage(test, msg)); + test.ScanUntrustedMessage(msg, &new_msg_ptr); + EXPECT_FALSE(new_msg_ptr); + EXPECT_EQ(msg.type(), FindPendingSyncMessage(test, msg)); + + // TODO(bbudge) Figure out how to put together a sync reply message. +} + +TEST_F(NaClMessageScannerTest, FileOpenClose) { + NaClMessageScanner test; + std::vector<SerializedHandle> unused_handles; + ResourceMessageCallParams fio_call_params(kFileIO, 0); + ResourceMessageCallParams fs_call_params(kFileSystem, 0); + ResourceMessageReplyParams fio_reply_params(kFileIO, 0); + ResourceMessageReplyParams fs_reply_params(kFileSystem, 0); + scoped_ptr<IPC::Message> new_msg_ptr; + + EXPECT_EQ(NULL, FindFileSystem(test, kFileSystem)); + EXPECT_EQ(NULL, FindFileIO(test, kFileIO)); + + // Open a file, not in a quota file system. + test.ScanMessage( + PpapiPluginMsg_ResourceReply( + fio_reply_params, + PpapiPluginMsg_FileIO_OpenReply(kInvalidResource, 0)), + &unused_handles, + &new_msg_ptr); + EXPECT_FALSE(new_msg_ptr); + EXPECT_FALSE(FindFileSystem(test, kFileSystem)); + EXPECT_FALSE(FindFileIO(test, kFileIO)); + + // Open a file in a quota file system; info objects for it and its file system + // should be created. + OpenQuotaFile(&test, kFileIO, kFileSystem); + NaClMessageScanner::FileSystem* fs = FindFileSystem(test, kFileSystem); + NaClMessageScanner::FileIO* fio = FindFileIO(test, kFileIO); + EXPECT_TRUE(fs); + EXPECT_EQ(0, fs->reserved_quota()); + EXPECT_TRUE(fio); + EXPECT_EQ(0, fio->max_written_offset()); + + const int64_t kNewFileSize = 10; + fio->SetMaxWrittenOffset(kNewFileSize); + + // We should not be able to under-report max_written_offset when closing. + test.ScanUntrustedMessage( + PpapiHostMsg_ResourceCall( + fio_call_params, + PpapiHostMsg_FileIO_Close(FileGrowth(0, 0))), + &new_msg_ptr); + EXPECT_TRUE(new_msg_ptr); + ResourceMessageCallParams call_params; + IPC::Message nested_msg; + FileGrowth file_growth; + EXPECT_TRUE(UnpackMessage<PpapiHostMsg_ResourceCall>( + *new_msg_ptr, &call_params, &nested_msg) && + UnpackMessage<PpapiHostMsg_FileIO_Close>( + nested_msg, &file_growth)); + new_msg_ptr.reset(); + EXPECT_EQ(kNewFileSize, file_growth.max_written_offset); + EXPECT_FALSE(FindFileIO(test, kFileIO)); + + // Reopen the file. + OpenQuotaFile(&test, kFileIO, kFileSystem); + fio = FindFileIO(test, kFileIO); + fio->SetMaxWrittenOffset(kNewFileSize); + + // Close with correct max_written_offset. + test.ScanUntrustedMessage( + PpapiHostMsg_ResourceCall( + fio_call_params, + PpapiHostMsg_FileIO_Close(FileGrowth(kNewFileSize, 0))), + &new_msg_ptr); + EXPECT_FALSE(new_msg_ptr); + EXPECT_FALSE(FindFileIO(test, kFileIO)); + + // Destroy file system. + test.ScanUntrustedMessage( + PpapiHostMsg_ResourceCall( + fs_call_params, + PpapiHostMsg_ResourceDestroyed(kFileSystem)), + &new_msg_ptr); + EXPECT_FALSE(FindFileSystem(test, kFileSystem)); +} + +TEST_F(NaClMessageScannerTest, QuotaAuditing) { + NaClMessageScanner test; + std::vector<SerializedHandle> unused_handles; + ResourceMessageCallParams fio_call_params(kFileIO, 0); + ResourceMessageCallParams fs_call_params(kFileSystem, 0); + ResourceMessageReplyParams fio_reply_params(kFileIO, 0); + ResourceMessageReplyParams fs_reply_params(kFileSystem, 0); + scoped_ptr<IPC::Message> new_msg_ptr; + + OpenQuotaFile(&test, kFileIO, kFileSystem); + NaClMessageScanner::FileSystem* fs = FindFileSystem(test, kFileSystem); + NaClMessageScanner::FileIO* fio = FindFileIO(test, kFileIO); + EXPECT_TRUE(fs); + EXPECT_EQ(0, fs->reserved_quota()); + EXPECT_TRUE(fio); + EXPECT_EQ(0, fio->max_written_offset()); + + // Without reserving quota, we should not be able to grow the file. + EXPECT_FALSE(fio->Grow(1)); + EXPECT_EQ(0, fs->reserved_quota()); + EXPECT_EQ(0, fio->max_written_offset()); + + // Receive reserved quota, and updated file sizes. + const int64_t kNewFileSize = 10; + FileSizeMap file_sizes; + file_sizes[kFileIO] = kNewFileSize; + test.ScanMessage( + PpapiPluginMsg_ResourceReply( + fs_reply_params, + PpapiPluginMsg_FileSystem_ReserveQuotaReply( + kQuotaReservationAmount, + file_sizes)), + &unused_handles, + &new_msg_ptr); + EXPECT_FALSE(new_msg_ptr); + EXPECT_EQ(kQuotaReservationAmount, fs->reserved_quota()); + EXPECT_EQ(kNewFileSize, fio->max_written_offset()); + + // We should be able to grow the file within quota. + EXPECT_TRUE(fio->Grow(1)); + EXPECT_EQ(kQuotaReservationAmount - 1, fs->reserved_quota()); + EXPECT_EQ(kNewFileSize + 1, fio->max_written_offset()); + + // We should not be able to grow the file over quota. + EXPECT_FALSE(fio->Grow(kQuotaReservationAmount)); + EXPECT_EQ(kQuotaReservationAmount - 1, fs->reserved_quota()); + EXPECT_EQ(kNewFileSize + 1, fio->max_written_offset()); + + // Plugin should not under-report max written offsets when reserving quota. + file_sizes[kFileIO] = 0; // should be kNewFileSize + 1. + test.ScanUntrustedMessage( + PpapiHostMsg_ResourceCall( + fio_call_params, + PpapiHostMsg_FileSystem_ReserveQuota( + kQuotaReservationAmount, + FileSizeMapToFileGrowthMapForTesting(file_sizes))), + &new_msg_ptr); + EXPECT_TRUE(new_msg_ptr); + ResourceMessageCallParams call_params; + IPC::Message nested_msg; + int64_t amount = 0; + FileGrowthMap new_file_growths; + EXPECT_TRUE(UnpackMessage<PpapiHostMsg_ResourceCall>( + *new_msg_ptr, &call_params, &nested_msg) && + UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>( + nested_msg, &amount, &new_file_growths)); + new_msg_ptr.reset(); + EXPECT_EQ(kQuotaReservationAmount, amount); + EXPECT_EQ(kNewFileSize + 1, new_file_growths[kFileIO].max_written_offset); +} + +TEST_F(NaClMessageScannerTest, SetLength) { + NaClMessageScanner test; + std::vector<SerializedHandle> unused_handles; + ResourceMessageCallParams fio_call_params(kFileIO, 0); + ResourceMessageCallParams fs_call_params(kFileSystem, 0); + ResourceMessageReplyParams fio_reply_params(kFileIO, 0); + ResourceMessageReplyParams fs_reply_params(kFileSystem, 0); + scoped_ptr<IPC::Message> new_msg_ptr; + + OpenQuotaFile(&test, kFileIO, kFileSystem); + NaClMessageScanner::FileSystem* fs = FindFileSystem(test, kFileSystem); + NaClMessageScanner::FileIO* fio = FindFileIO(test, kFileIO); + + // Receive reserved quota, and updated file sizes. + const int64_t kNewFileSize = 10; + FileSizeMap file_sizes; + file_sizes[kFileIO] = 0; + test.ScanMessage( + PpapiPluginMsg_ResourceReply( + fs_reply_params, + PpapiPluginMsg_FileSystem_ReserveQuotaReply( + kQuotaReservationAmount, + file_sizes)), + &unused_handles, + &new_msg_ptr); + + // We should be able to SetLength within quota. + test.ScanUntrustedMessage( + PpapiHostMsg_ResourceCall( + fio_call_params, + PpapiHostMsg_FileIO_SetLength(kNewFileSize)), + &new_msg_ptr); + EXPECT_FALSE(new_msg_ptr); + EXPECT_EQ(kQuotaReservationAmount - kNewFileSize, fs->reserved_quota()); + EXPECT_EQ(kNewFileSize, fio->max_written_offset()); + + // We shouldn't be able to SetLength beyond quota. The message should be + // rewritten to fail with length == -1. + test.ScanUntrustedMessage( + PpapiHostMsg_ResourceCall( + fio_call_params, + PpapiHostMsg_FileIO_SetLength(kQuotaReservationAmount + 1)), + &new_msg_ptr); + EXPECT_TRUE(new_msg_ptr); + ResourceMessageCallParams call_params; + IPC::Message nested_msg; + int64_t length = 0; + EXPECT_TRUE(UnpackMessage<PpapiHostMsg_ResourceCall>( + *new_msg_ptr, &call_params, &nested_msg) && + UnpackMessage<PpapiHostMsg_FileIO_SetLength>( + nested_msg, &length)); + new_msg_ptr.reset(); + EXPECT_EQ(-1, length); + EXPECT_EQ(kQuotaReservationAmount - kNewFileSize, fs->reserved_quota()); + EXPECT_EQ(kNewFileSize, fio->max_written_offset()); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/network_monitor_resource.cc b/chromium/ppapi/proxy/network_monitor_resource.cc index 0dfb0b4b3eb..c76f1b8485f 100644 --- a/chromium/ppapi/proxy/network_monitor_resource.cc +++ b/chromium/ppapi/proxy/network_monitor_resource.cc @@ -31,14 +31,14 @@ NetworkMonitorResource::AsPPB_NetworkMonitor_API() { void NetworkMonitorResource::OnReplyReceived( const ResourceMessageReplyParams& params, const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(NetworkMonitorResource, msg) + PPAPI_BEGIN_MESSAGE_MAP(NetworkMonitorResource, msg) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_NetworkMonitor_NetworkList, OnPluginMsgNetworkList) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_0( PpapiPluginMsg_NetworkMonitor_Forbidden, OnPluginMsgForbidden) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( PluginResource::OnReplyReceived(params, msg)) - IPC_END_MESSAGE_MAP() + PPAPI_END_MESSAGE_MAP() } int32_t NetworkMonitorResource::UpdateNetworkList( diff --git a/chromium/ppapi/proxy/pdf_resource.cc b/chromium/ppapi/proxy/pdf_resource.cc index 80c4237a5e5..1398866e924 100644 --- a/chromium/ppapi/proxy/pdf_resource.cc +++ b/chromium/ppapi/proxy/pdf_resource.cc @@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/metrics/histogram.h" +#include "base/strings/utf_string_conversions.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/private/ppb_pdf.h" #include "ppapi/proxy/ppapi_messages.h" @@ -62,8 +63,10 @@ void PDFResource::SearchString(const unsigned short* input_string, PP_PrivateFindResult** results, int* count) { if (locale_.empty()) locale_ = GetLocale(); - const char16* string = reinterpret_cast<const char16*>(input_string); - const char16* term = reinterpret_cast<const char16*>(input_term); + const base::char16* string = + reinterpret_cast<const base::char16*>(input_string); + const base::char16* term = + reinterpret_cast<const base::char16*>(input_term); UErrorCode status = U_ZERO_ERROR; UStringSearch* searcher = usearch_open(term, -1, string, -1, locale_.c_str(), @@ -192,5 +195,14 @@ PP_Bool PDFResource::IsOutOfProcess() { return PP_TRUE; } +void PDFResource::SetSelectedText(const char* selected_text) { + Post(RENDERER, + PpapiHostMsg_PDF_SetSelectedText(base::UTF8ToUTF16(selected_text))); +} + +void PDFResource::SetLinkUnderCursor(const char* url) { + Post(RENDERER, PpapiHostMsg_PDF_SetLinkUnderCursor(url)); +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/pdf_resource.h b/chromium/ppapi/proxy/pdf_resource.h index 4ab30ba1ca7..46f7cbed0fc 100644 --- a/chromium/ppapi/proxy/pdf_resource.h +++ b/chromium/ppapi/proxy/pdf_resource.h @@ -55,6 +55,8 @@ class PPAPI_PROXY_EXPORT PDFResource float scale) OVERRIDE; virtual PP_Resource GetResourceImage(PP_ResourceImage image_id) OVERRIDE; virtual PP_Bool IsOutOfProcess() OVERRIDE; + virtual void SetSelectedText(const char* selected_text) OVERRIDE; + virtual void SetLinkUnderCursor(const char* url) OVERRIDE; private: std::string locale_; diff --git a/chromium/ppapi/proxy/pdf_resource_unittest.cc b/chromium/ppapi/proxy/pdf_resource_unittest.cc index 3ac60d6413b..62fcea877bc 100644 --- a/chromium/ppapi/proxy/pdf_resource_unittest.cc +++ b/chromium/ppapi/proxy/pdf_resource_unittest.cc @@ -65,10 +65,10 @@ TEST_F(PDFResourceTest, SearchString) { new PDFResource(Connection(&sink(), &sink()), pp_instance())); pdf_resource->SetLocaleForTest("en-US"); - string16 input; - string16 term; - UTF8ToUTF16("abcdefabcdef", 12, &input); - UTF8ToUTF16("bc", 2, &term); + base::string16 input; + base::string16 term; + base::UTF8ToUTF16("abcdefabcdef", 12, &input); + base::UTF8ToUTF16("bc", 2, &term); PP_PrivateFindResult* results; int count = 0; diff --git a/chromium/ppapi/proxy/plugin_dispatcher.cc b/chromium/ppapi/proxy/plugin_dispatcher.cc index 6cd0ab4151d..f6448d380c2 100644 --- a/chromium/ppapi/proxy/plugin_dispatcher.cc +++ b/chromium/ppapi/proxy/plugin_dispatcher.cc @@ -252,14 +252,11 @@ void PluginDispatcher::DidCreateInstance(PP_Instance instance) { if (!g_instance_to_dispatcher) g_instance_to_dispatcher = new InstanceToDispatcherMap; (*g_instance_to_dispatcher)[instance] = this; - - instance_map_[instance] = InstanceData(); + instance_map_.set(instance, scoped_ptr<InstanceData>(new InstanceData())); } void PluginDispatcher::DidDestroyInstance(PP_Instance instance) { - InstanceDataMap::iterator it = instance_map_.find(instance); - if (it != instance_map_.end()) - instance_map_.erase(it); + instance_map_.erase(instance); if (g_instance_to_dispatcher) { InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find( @@ -274,8 +271,7 @@ void PluginDispatcher::DidDestroyInstance(PP_Instance instance) { } InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) { - InstanceDataMap::iterator it = instance_map_.find(instance); - return (it == instance_map_.end()) ? NULL : &it->second; + return instance_map_.get(instance); } thunk::PPB_Instance_API* PluginDispatcher::GetInstanceAPI() { diff --git a/chromium/ppapi/proxy/plugin_dispatcher.h b/chromium/ppapi/proxy/plugin_dispatcher.h index 5176eba7c74..f8e22f6ebde 100644 --- a/chromium/ppapi/proxy/plugin_dispatcher.h +++ b/chromium/ppapi/proxy/plugin_dispatcher.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/containers/hash_tables.h" +#include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/process/process.h" @@ -19,6 +20,7 @@ #include "ppapi/c/pp_rect.h" #include "ppapi/c/ppb_console.h" #include "ppapi/proxy/dispatcher.h" +#include "ppapi/proxy/message_handler.h" #include "ppapi/shared_impl/ppapi_preferences.h" #include "ppapi/shared_impl/ppb_view_shared.h" #include "ppapi/shared_impl/singleton_resource_id.h" @@ -61,6 +63,10 @@ struct InstanceData { // calling when we shouldn't). bool is_request_surrounding_text_pending; bool should_do_request_surrounding_text; + + // The message handler which should handle JavaScript->Plugin messages, if + // one has been registered, otherwise NULL. + scoped_ptr<MessageHandler> message_handler; }; class PPAPI_PROXY_EXPORT PluginDispatcher @@ -183,7 +189,7 @@ class PPAPI_PROXY_EXPORT PluginDispatcher typedef base::hash_map<std::string, const void*> InterfaceMap; InterfaceMap plugin_interfaces_; - typedef base::hash_map<PP_Instance, InstanceData> InstanceDataMap; + typedef base::ScopedPtrHashMap<PP_Instance, InstanceData> InstanceDataMap; InstanceDataMap instance_map_; // The preferences sent from the host. We only want to set this once, which diff --git a/chromium/ppapi/proxy/plugin_globals.cc b/chromium/ppapi/proxy/plugin_globals.cc index 59b51919e1a..d361ae11919 100644 --- a/chromium/ppapi/proxy/plugin_globals.cc +++ b/chromium/ppapi/proxy/plugin_globals.cc @@ -10,8 +10,10 @@ #include "ipc/ipc_sender.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_proxy_delegate.h" +#include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppb_message_loop_proxy.h" #include "ppapi/proxy/resource_reply_thread_registrar.h" +#include "ppapi/shared_impl/ppapi_constants.h" #include "ppapi/shared_impl/proxy_lock.h" #include "ppapi/thunk/enter.h" @@ -54,7 +56,11 @@ PluginGlobals::PluginGlobals() plugin_proxy_delegate_(NULL), callback_tracker_(new CallbackTracker), resource_reply_thread_registrar_( - new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) { + new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())), + plugin_recently_active_(false), + keepalive_throttle_interval_milliseconds_( + ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds), + weak_factory_(this) { DCHECK(!plugin_globals_); plugin_globals_ = this; @@ -71,7 +77,11 @@ PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test) plugin_proxy_delegate_(NULL), callback_tracker_(new CallbackTracker), resource_reply_thread_registrar_( - new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) { + new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())), + plugin_recently_active_(false), + keepalive_throttle_interval_milliseconds_( + kKeepaliveThrottleIntervalDefaultMilliseconds), + weak_factory_(this) { DCHECK(!plugin_globals_); } @@ -165,6 +175,22 @@ base::TaskRunner* PluginGlobals::GetFileTaskRunner() { return file_thread_->message_loop_proxy(); } +void PluginGlobals::MarkPluginIsActive() { + if (!plugin_recently_active_) { + plugin_recently_active_ = true; + if (!GetBrowserSender() || !base::MessageLoop::current()) + return; + GetBrowserSender()->Send(new PpapiHostMsg_Keepalive()); + DCHECK(keepalive_throttle_interval_milliseconds_); + GetMainThreadMessageLoop()->PostDelayedTask( + FROM_HERE, + RunWhileLocked(base::Bind(&PluginGlobals::OnReleaseKeepaliveThrottle, + weak_factory_.GetWeakPtr())), + base::TimeDelta::FromMilliseconds( + keepalive_throttle_interval_milliseconds_)); + } +} + IPC::Sender* PluginGlobals::GetBrowserSender() { if (!browser_sender_.get()) { browser_sender_.reset( @@ -195,9 +221,18 @@ MessageLoopResource* PluginGlobals::loop_for_main_thread() { return loop_for_main_thread_.get(); } +void PluginGlobals::set_keepalive_throttle_interval_milliseconds(unsigned i) { + keepalive_throttle_interval_milliseconds_ = i; +} + bool PluginGlobals::IsPluginGlobals() const { return true; } +void PluginGlobals::OnReleaseKeepaliveThrottle() { + ppapi::ProxyLock::AssertAcquiredDebugOnly(); + plugin_recently_active_ = false; +} + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/plugin_globals.h b/chromium/ppapi/proxy/plugin_globals.h index 029e2d2e28e..5dc614d239b 100644 --- a/chromium/ppapi/proxy/plugin_globals.h +++ b/chromium/ppapi/proxy/plugin_globals.h @@ -74,6 +74,7 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals { const std::string& value) OVERRIDE; virtual MessageLoopShared* GetCurrentMessageLoop() OVERRIDE; base::TaskRunner* GetFileTaskRunner() OVERRIDE; + virtual void MarkPluginIsActive() OVERRIDE; // Returns the channel for sending to the browser. IPC::Sender* GetBrowserSender(); @@ -133,12 +134,20 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals { return resource_reply_thread_registrar_.get(); } + // Interval to limit how many IPC messages are sent indicating that the plugin + // is active and should be kept alive. The value must be smaller than any + // threshold used to kill inactive plugins by the embedder host. + void set_keepalive_throttle_interval_milliseconds(unsigned i); + private: class BrowserSender; // PpapiGlobals overrides. virtual bool IsPluginGlobals() const OVERRIDE; + // Locks the proxy lock and releases the throttle on keepalive IPC messages. + void OnReleaseKeepaliveThrottle(); + static PluginGlobals* plugin_globals_; PluginProxyDelegate* plugin_proxy_delegate_; @@ -167,6 +176,17 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals { scoped_refptr<ResourceReplyThreadRegistrar> resource_reply_thread_registrar_; + // Indicates activity by the plugin. Used to monitor when a plugin can be + // shutdown due to idleness. Current needs do not require differentiating + // between idle state between multiple instances, if any are active they are + // all considered active. + bool plugin_recently_active_; + + unsigned keepalive_throttle_interval_milliseconds_; + + // Member variables should appear before the WeakPtrFactory, see weak_ptr.h. + base::WeakPtrFactory<PluginGlobals> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(PluginGlobals); }; diff --git a/chromium/ppapi/proxy/plugin_main_nacl.cc b/chromium/ppapi/proxy/plugin_main_nacl.cc deleted file mode 100644 index 985deb7bd12..00000000000 --- a/chromium/ppapi/proxy/plugin_main_nacl.cc +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (c) 2012 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 <map> -#include <set> - -#include "build/build_config.h" -// Need to include this before most other files because it defines -// IPC_MESSAGE_LOG_ENABLED. We need to use it to define -// IPC_MESSAGE_MACROS_LOG_ENABLED so ppapi_messages.h will generate the -// ViewMsgLog et al. functions. - -#include "base/command_line.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "components/tracing/child_trace_message_filter.h" -#include "ipc/ipc_channel_handle.h" -#include "ipc/ipc_logging.h" -#include "ipc/ipc_message.h" -#include "native_client/src/shared/srpc/nacl_srpc.h" -#include "native_client/src/untrusted/irt/irt_ppapi.h" -#include "ppapi/c/ppp.h" -#include "ppapi/c/ppp_instance.h" -#include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h" -#include "ppapi/proxy/plugin_dispatcher.h" -#include "ppapi/proxy/plugin_globals.h" -#include "ppapi/proxy/plugin_message_filter.h" -#include "ppapi/proxy/plugin_proxy_delegate.h" -#include "ppapi/proxy/resource_reply_thread_registrar.h" -#include "ppapi/shared_impl/ppb_audio_shared.h" - -#if defined(IPC_MESSAGE_LOG_ENABLED) -#include "base/containers/hash_tables.h" - -LogFunctionMap g_log_function_mapping; - -#define IPC_MESSAGE_MACROS_LOG_ENABLED -#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \ - g_log_function_mapping[msg_id] = logger - -#endif -#include "ppapi/proxy/ppapi_messages.h" - -// This must match up with NACL_CHROME_INITIAL_IPC_DESC, -// defined in sel_main_chrome.h -#define NACL_IPC_FD 6 - -using ppapi::proxy::PluginDispatcher; -using ppapi::proxy::PluginGlobals; -using ppapi::proxy::PluginProxyDelegate; -using ppapi::proxy::ProxyChannel; -using ppapi::proxy::SerializedHandle; - -namespace { - -// This class manages communication between the plugin and the browser, and -// manages the PluginDispatcher instances for communication between the plugin -// and the renderer. -class PpapiDispatcher : public ProxyChannel, - public PluginDispatcher::PluginDelegate, - public PluginProxyDelegate { - public: - explicit PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop); - - // PluginDispatcher::PluginDelegate implementation. - virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE; - virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE; - virtual IPC::PlatformFileForTransit ShareHandleWithRemote( - base::PlatformFile handle, - base::ProcessId peer_pid, - bool should_close_source) OVERRIDE; - virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() OVERRIDE; - virtual uint32 Register(PluginDispatcher* plugin_dispatcher) OVERRIDE; - virtual void Unregister(uint32 plugin_dispatcher_id) OVERRIDE; - - // PluginProxyDelegate implementation. - virtual IPC::Sender* GetBrowserSender() OVERRIDE; - virtual std::string GetUILanguage() OVERRIDE; - virtual void PreCacheFont(const void* logfontw) OVERRIDE; - virtual void SetActiveURL(const std::string& url) OVERRIDE; - virtual PP_Resource CreateBrowserFont( - ppapi::proxy::Connection connection, - PP_Instance instance, - const PP_BrowserFont_Trusted_Description& desc, - const ppapi::Preferences& prefs) OVERRIDE; - - // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - private: - void OnMsgCreateNaClChannel(int renderer_id, - const ppapi::PpapiNaClChannelArgs& args, - SerializedHandle handle); - void OnPluginDispatcherMessageReceived(const IPC::Message& msg); - - std::set<PP_Instance> instances_; - std::map<uint32, PluginDispatcher*> plugin_dispatchers_; - uint32 next_plugin_dispatcher_id_; - scoped_refptr<base::MessageLoopProxy> message_loop_; - base::WaitableEvent shutdown_event_; -}; - -PpapiDispatcher::PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop) - : next_plugin_dispatcher_id_(0), - message_loop_(io_loop), - shutdown_event_(true, false) { - IPC::ChannelHandle channel_handle( - "NaCl IPC", base::FileDescriptor(NACL_IPC_FD, false)); - // We don't have/need a PID since handle sharing happens outside of the - // NaCl sandbox. - InitWithChannel(this, base::kNullProcessId, channel_handle, - false); // Channel is server. - channel()->AddFilter(new ppapi::proxy::PluginMessageFilter( - NULL, PluginGlobals::Get()->resource_reply_thread_registrar())); - channel()->AddFilter( - new tracing::ChildTraceMessageFilter(message_loop_.get())); -} - -base::MessageLoopProxy* PpapiDispatcher::GetIPCMessageLoop() { - return message_loop_.get(); -} - -base::WaitableEvent* PpapiDispatcher::GetShutdownEvent() { - return &shutdown_event_; -} - -IPC::PlatformFileForTransit PpapiDispatcher::ShareHandleWithRemote( - base::PlatformFile handle, - base::ProcessId peer_pid, - bool should_close_source) { - return IPC::InvalidPlatformFileForTransit(); -} - -std::set<PP_Instance>* PpapiDispatcher::GetGloballySeenInstanceIDSet() { - return &instances_; -} - -uint32 PpapiDispatcher::Register(PluginDispatcher* plugin_dispatcher) { - if (!plugin_dispatcher || - plugin_dispatchers_.size() >= std::numeric_limits<uint32>::max()) { - return 0; - } - - uint32 id = 0; - do { - // Although it is unlikely, make sure that we won't cause any trouble - // when the counter overflows. - id = next_plugin_dispatcher_id_++; - } while (id == 0 || - plugin_dispatchers_.find(id) != plugin_dispatchers_.end()); - plugin_dispatchers_[id] = plugin_dispatcher; - return id; -} - -void PpapiDispatcher::Unregister(uint32 plugin_dispatcher_id) { - plugin_dispatchers_.erase(plugin_dispatcher_id); -} - -IPC::Sender* PpapiDispatcher::GetBrowserSender() { - return this; -} - -std::string PpapiDispatcher::GetUILanguage() { - NOTIMPLEMENTED(); - return std::string(); -} - -void PpapiDispatcher::PreCacheFont(const void* logfontw) { - NOTIMPLEMENTED(); -} - -void PpapiDispatcher::SetActiveURL(const std::string& url) { - NOTIMPLEMENTED(); -} - -PP_Resource PpapiDispatcher::CreateBrowserFont( - ppapi::proxy::Connection connection, - PP_Instance instance, - const PP_BrowserFont_Trusted_Description& desc, - const ppapi::Preferences& prefs) { - NOTIMPLEMENTED(); - return 0; -} - -bool PpapiDispatcher::OnMessageReceived(const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(PpapiDispatcher, msg) - IPC_MESSAGE_HANDLER(PpapiMsg_CreateNaClChannel, OnMsgCreateNaClChannel) - // All other messages are simply forwarded to a PluginDispatcher. - IPC_MESSAGE_UNHANDLED(OnPluginDispatcherMessageReceived(msg)) - IPC_END_MESSAGE_MAP() - return true; -} - -void PpapiDispatcher::OnMsgCreateNaClChannel( - int renderer_id, - const ppapi::PpapiNaClChannelArgs& args, - SerializedHandle handle) { - static bool command_line_and_logging_initialized = false; - if (!command_line_and_logging_initialized) { - CommandLine::Init(0, NULL); - for (size_t i = 0; i < args.switch_names.size(); ++i) { - DCHECK(i < args.switch_values.size()); - CommandLine::ForCurrentProcess()->AppendSwitchASCII( - args.switch_names[i], args.switch_values[i]); - } - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - logging::InitLogging(settings); - command_line_and_logging_initialized = true; - } - // Tell the process-global GetInterface which interfaces it can return to the - // plugin. - ppapi::proxy::InterfaceList::SetProcessGlobalPermissions( - args.permissions); - ppapi::proxy::InterfaceList::SetSupportsDevChannel( - args.supports_dev_channel); - - int32_t error = ::PPP_InitializeModule( - 0 /* module */, - &ppapi::proxy::PluginDispatcher::GetBrowserInterface); - if (error) - ::exit(error); - - PluginDispatcher* dispatcher = - new PluginDispatcher(::PPP_GetInterface, args.permissions, - args.off_the_record); - // The channel handle's true name is not revealed here. - IPC::ChannelHandle channel_handle("nacl", handle.descriptor()); - if (!dispatcher->InitPluginWithChannel(this, base::kNullProcessId, - channel_handle, false)) { - delete dispatcher; - return; - } - // From here, the dispatcher will manage its own lifetime according to the - // lifetime of the attached channel. -} - -void PpapiDispatcher::OnPluginDispatcherMessageReceived( - const IPC::Message& msg) { - // The first parameter should be a plugin dispatcher ID. - PickleIterator iter(msg); - uint32 id = 0; - if (!msg.ReadUInt32(&iter, &id)) { - NOTREACHED(); - return; - } - std::map<uint32, ppapi::proxy::PluginDispatcher*>::iterator dispatcher = - plugin_dispatchers_.find(id); - if (dispatcher != plugin_dispatchers_.end()) - dispatcher->second->OnMessageReceived(msg); -} - -} // namespace - -void PpapiPluginRegisterThreadCreator( - const struct PP_ThreadFunctions* thread_functions) { - // Initialize all classes that need to create threads that call back into - // user code. - ppapi::PPB_Audio_Shared::SetThreadFunctions(thread_functions); -} - -int PpapiPluginMain() { - // Though it isn't referenced here, we must instantiate an AtExitManager. - base::AtExitManager exit_manager; - base::MessageLoop loop; - IPC::Logging::set_log_function_map(&g_log_function_mapping); - ppapi::proxy::PluginGlobals plugin_globals; - base::Thread io_thread("Chrome_NaClIOThread"); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - io_thread.StartWithOptions(options); - - // Start up the SRPC server on another thread. Otherwise, when it blocks - // on an RPC, the PPAPI proxy will hang. Do this before we initialize the - // module and start the PPAPI proxy so that the NaCl plugin can continue - // loading the app. - static struct NaClSrpcHandlerDesc srpc_methods[] = { { NULL, NULL } }; - if (!NaClSrpcAcceptClientOnThread(srpc_methods)) { - return 1; - } - - PpapiDispatcher ppapi_dispatcher(io_thread.message_loop_proxy()); - plugin_globals.set_plugin_proxy_delegate(&ppapi_dispatcher); - - loop.Run(); - - return 0; -} diff --git a/chromium/ppapi/proxy/plugin_message_filter.cc b/chromium/ppapi/proxy/plugin_message_filter.cc index 1a62d21454b..18469579b38 100644 --- a/chromium/ppapi/proxy/plugin_message_filter.cc +++ b/chromium/ppapi/proxy/plugin_message_filter.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/logging.h" +#include "ipc/ipc_channel.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/resource_message_params.h" #include "ppapi/proxy/resource_reply_thread_registrar.h" @@ -22,18 +23,18 @@ PluginMessageFilter::PluginMessageFilter( scoped_refptr<ResourceReplyThreadRegistrar> registrar) : seen_instance_ids_(seen_instance_ids), resource_reply_thread_registrar_(registrar), - channel_(NULL) { + sender_(NULL) { } PluginMessageFilter::~PluginMessageFilter() { } -void PluginMessageFilter::OnFilterAdded(IPC::Channel* channel) { - channel_ = channel; +void PluginMessageFilter::OnFilterAdded(IPC::Sender* sender) { + sender_ = sender; } void PluginMessageFilter::OnFilterRemoved() { - channel_ = NULL; + sender_ = NULL; } bool PluginMessageFilter::OnMessageReceived(const IPC::Message& message) { @@ -47,8 +48,8 @@ bool PluginMessageFilter::OnMessageReceived(const IPC::Message& message) { } bool PluginMessageFilter::Send(IPC::Message* msg) { - if (channel_) - return channel_->Send(msg); + if (sender_) + return sender_->Send(msg); delete msg; return false; } diff --git a/chromium/ppapi/proxy/plugin_message_filter.h b/chromium/ppapi/proxy/plugin_message_filter.h index 646900724a2..4018ffcc9e1 100644 --- a/chromium/ppapi/proxy/plugin_message_filter.h +++ b/chromium/ppapi/proxy/plugin_message_filter.h @@ -9,8 +9,8 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" -#include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_sender.h" +#include "ipc/message_filter.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/ppapi_proxy_export.h" @@ -25,9 +25,8 @@ class ResourceReplyThreadRegistrar; // // There is one instance of this class for each renderer channel (same as for // the PluginDispatchers). -class PPAPI_PROXY_EXPORT PluginMessageFilter - : public IPC::ChannelProxy::MessageFilter, - public IPC::Sender { +class PPAPI_PROXY_EXPORT PluginMessageFilter : public IPC::MessageFilter, + public IPC::Sender { public: // |seen_instance_ids| is a pointer to a set that will be used to uniquify // PP_Instances across all renderer channels. The same pointer should be @@ -42,7 +41,7 @@ class PPAPI_PROXY_EXPORT PluginMessageFilter virtual ~PluginMessageFilter(); // MessageFilter implementation. - virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; + virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE; virtual void OnFilterRemoved() OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; @@ -73,9 +72,9 @@ class PPAPI_PROXY_EXPORT PluginMessageFilter scoped_refptr<ResourceReplyThreadRegistrar> resource_reply_thread_registrar_; - // The IPC channel to the renderer. May be NULL if we're not currently + // The IPC sender to the renderer. May be NULL if we're not currently // attached as a filter. - IPC::Channel* channel_; + IPC::Sender* sender_; }; } // namespace proxy diff --git a/chromium/ppapi/proxy/plugin_var_tracker.cc b/chromium/ppapi/proxy/plugin_var_tracker.cc index a9cbd9c7a62..06db2249af3 100644 --- a/chromium/ppapi/proxy/plugin_var_tracker.cc +++ b/chromium/ppapi/proxy/plugin_var_tracker.cc @@ -10,6 +10,8 @@ #include "ppapi/c/dev/ppp_class_deprecated.h" #include "ppapi/c/ppb_var.h" #include "ppapi/proxy/file_system_resource.h" +#include "ppapi/proxy/media_stream_audio_track_resource.h" +#include "ppapi/proxy/media_stream_video_track_resource.h" #include "ppapi/proxy/plugin_array_buffer_var.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_globals.h" @@ -172,10 +174,10 @@ PP_Var PluginVarTracker::MakeResourcePPVarFromMessage( const IPC::Message& creation_message, int pending_renderer_id, int pending_browser_id) { - DCHECK(pending_renderer_id); - DCHECK(pending_browser_id); switch (creation_message.type()) { case PpapiPluginMsg_FileSystem_CreateFromPendingHost::ID: { + DCHECK(pending_renderer_id); + DCHECK(pending_browser_id); PP_FileSystemType file_system_type; if (!UnpackMessage<PpapiPluginMsg_FileSystem_CreateFromPendingHost>( creation_message, &file_system_type)) { @@ -194,6 +196,42 @@ PP_Var PluginVarTracker::MakeResourcePPVarFromMessage( file_system_type))->GetReference(); return MakeResourcePPVar(pp_resource); } + case PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost::ID: { + DCHECK(pending_renderer_id); + std::string track_id; + if (!UnpackMessage< + PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost>( + creation_message, &track_id)) { + NOTREACHED() << + "Invalid message of type " + "PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost"; + return PP_MakeNull(); + } + PP_Resource pp_resource = + (new MediaStreamAudioTrackResource(GetConnectionForInstance(instance), + instance, + pending_renderer_id, + track_id))->GetReference(); + return MakeResourcePPVar(pp_resource); + } + case PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost::ID: { + DCHECK(pending_renderer_id); + std::string track_id; + if (!UnpackMessage< + PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost>( + creation_message, &track_id)) { + NOTREACHED() << + "Invalid message of type " + "PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost"; + return PP_MakeNull(); + } + PP_Resource pp_resource = + (new MediaStreamVideoTrackResource(GetConnectionForInstance(instance), + instance, + pending_renderer_id, + track_id))->GetReference(); + return MakeResourcePPVar(pp_resource); + } default: { NOTREACHED() << "Creation message has unexpected type " << creation_message.type(); diff --git a/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc index a6da210795d..b9bd98fbb6d 100644 --- a/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc +++ b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc @@ -21,33 +21,14 @@ PpapiCommandBufferProxy::PpapiCommandBufferProxy( } PpapiCommandBufferProxy::~PpapiCommandBufferProxy() { - // Delete all the locally cached shared memory objects, closing the handle - // in this process. - for (TransferBufferMap::iterator it = transfer_buffers_.begin(); - it != transfer_buffers_.end(); ++it) { - delete it->second.shared_memory; - it->second.shared_memory = NULL; - } + // gpu::Buffers are no longer referenced, allowing shared memory objects to be + // deleted, closing the handle in this process. } bool PpapiCommandBufferProxy::Initialize() { return true; } -gpu::CommandBuffer::State PpapiCommandBufferProxy::GetState() { - // Send will flag state with lost context if IPC fails. - if (last_state_.error == gpu::error::kNoError) { - gpu::CommandBuffer::State state; - bool success = false; - if (Send(new PpapiHostMsg_PPBGraphics3D_GetState( - ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state, &success))) { - UpdateState(state, success); - } - } - - return last_state_; -} - gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() { ppapi::ProxyLock::AssertAcquiredDebugOnly(); return last_state_; @@ -72,130 +53,94 @@ void PpapiCommandBufferProxy::Flush(int32 put_offset) { Send(message); } -gpu::CommandBuffer::State PpapiCommandBufferProxy::FlushSync(int32 put_offset, - int32 last_known_get) { - if (last_known_get == last_state_.get_offset) { - // Send will flag state with lost context if IPC fails. - if (last_state_.error == gpu::error::kNoError) { - gpu::CommandBuffer::State state; - bool success = false; - if (Send(new PpapiHostMsg_PPBGraphics3D_Flush( - ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset, - last_known_get, &state, &success))) { - UpdateState(state, success); - } - } - } else { - Flush(put_offset); - } - return last_state_; -} - -void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) { - if (last_state_.error == gpu::error::kNoError) { - Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer( - ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id)); - } -} - -void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) { - // Not implemented in proxy. - NOTREACHED(); -} - -gpu::Buffer PpapiCommandBufferProxy::CreateTransferBuffer(size_t size, - int32* id) { - *id = -1; - +void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) { if (last_state_.error != gpu::error::kNoError) - return gpu::Buffer(); - - if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer( - ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id))) { - return gpu::Buffer(); - } - - if ((*id) <= 0) - return gpu::Buffer(); + return; - return GetTransferBuffer(*id); + bool success; + gpu::CommandBuffer::State state; + if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange( + ppapi::API_ID_PPB_GRAPHICS_3D, + resource_, + start, + end, + &state, + &success))) + UpdateState(state, success); } -void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) { +void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) { if (last_state_.error != gpu::error::kNoError) return; - // Remove the transfer buffer from the client side4 cache. - TransferBufferMap::iterator it = transfer_buffers_.find(id); - - if (it != transfer_buffers_.end()) { - // Delete the shared memory object, closing the handle in this process. - delete it->second.shared_memory; + bool success; + gpu::CommandBuffer::State state; + if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange( + ppapi::API_ID_PPB_GRAPHICS_3D, + resource_, + start, + end, + &state, + &success))) + UpdateState(state, success); +} - transfer_buffers_.erase(it); +void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) { + if (last_state_.error == gpu::error::kNoError) { + Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer( + ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id)); } - - Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer( - ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id)); } -void PpapiCommandBufferProxy::Echo(const base::Closure& callback) { - NOTREACHED(); -} +scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer( + size_t size, + int32* id) { + *id = -1; -gpu::Buffer PpapiCommandBufferProxy::GetTransferBuffer(int32 id) { if (last_state_.error != gpu::error::kNoError) - return gpu::Buffer(); - - // Check local cache to see if there is already a client side shared memory - // object for this id. - TransferBufferMap::iterator it = transfer_buffers_.find(id); - if (it != transfer_buffers_.end()) { - return it->second; - } + return NULL; // Assuming we are in the renderer process, the service is responsible for // duplicating the handle. This might not be true for NaCl. ppapi::proxy::SerializedHandle handle( ppapi::proxy::SerializedHandle::SHARED_MEMORY); - if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer( - ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) { - return gpu::Buffer(); + if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer( + ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id, &handle))) { + return NULL; } - if (!handle.is_shmem()) - return gpu::Buffer(); - // Cache the transfer buffer shared memory object client side. + if (*id <= 0 || !handle.is_shmem()) + return NULL; + scoped_ptr<base::SharedMemory> shared_memory( new base::SharedMemory(handle.shmem(), false)); // Map the shared memory on demand. if (!shared_memory->memory()) { if (!shared_memory->Map(handle.size())) { - return gpu::Buffer(); + *id = -1; + return NULL; } } - gpu::Buffer buffer; - buffer.ptr = shared_memory->memory(); - buffer.size = handle.size(); - buffer.shared_memory = shared_memory.release(); - transfer_buffers_[id] = buffer; - - return buffer; + return gpu::MakeBufferFromSharedMemory(shared_memory.Pass(), handle.size()); } -void PpapiCommandBufferProxy::SetToken(int32 token) { - NOTREACHED(); +void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) { + if (last_state_.error != gpu::error::kNoError) + return; + + Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer( + ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id)); } -void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) { +void PpapiCommandBufferProxy::Echo(const base::Closure& callback) { NOTREACHED(); } -void PpapiCommandBufferProxy::SetContextLostReason( - gpu::error::ContextLostReason reason) { +uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) { NOTREACHED(); + return 0; } uint32 PpapiCommandBufferProxy::InsertSyncPoint() { @@ -221,11 +166,6 @@ void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) { NOTREACHED(); } -void PpapiCommandBufferProxy::SendManagedMemoryStats( - const gpu::ManagedMemoryStats& stats) { - NOTREACHED(); -} - gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() { // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in // crbug.com/325391. @@ -236,6 +176,7 @@ gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer( size_t width, size_t height, unsigned internalformat, + unsigned usage, int32* id) { NOTREACHED(); return NULL; @@ -245,15 +186,6 @@ void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) { NOTREACHED(); } -bool PpapiCommandBufferProxy::GenerateMailboxNames( - unsigned num, std::vector<gpu::Mailbox>* names) { - // TODO(piman): implement this so we can expose mailboxes to pepper - // eventually. - NOTREACHED(); - return false; -} - - bool PpapiCommandBufferProxy::Send(IPC::Message* msg) { DCHECK(last_state_.error == gpu::error::kNoError); diff --git a/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h index 16809bdfea9..ad5cf62e814 100644 --- a/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h +++ b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h @@ -7,8 +7,8 @@ #include "base/callback.h" #include "base/containers/hash_tables.h" +#include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" -#include "gpu/command_buffer/common/gpu_control.h" #include "ppapi/proxy/ppapi_proxy_export.h" #include "ppapi/shared_impl/host_resource.h" @@ -30,48 +30,37 @@ class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public gpu::CommandBuffer, // gpu::CommandBuffer implementation: virtual bool Initialize() OVERRIDE; - virtual State GetState() OVERRIDE; virtual State GetLastState() OVERRIDE; virtual int32 GetLastToken() OVERRIDE; virtual void Flush(int32 put_offset) OVERRIDE; - virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE; + virtual void WaitForTokenInRange(int32 start, int32 end) OVERRIDE; + virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE; virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE; - virtual void SetGetOffset(int32 get_offset) OVERRIDE; - virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE; + virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size, + int32* id) OVERRIDE; virtual void DestroyTransferBuffer(int32 id) OVERRIDE; - virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE; - virtual void SetToken(int32 token) OVERRIDE; - virtual void SetParseError(gpu::error::Error error) OVERRIDE; - virtual void SetContextLostReason(gpu::error::ContextLostReason reason) - OVERRIDE; // gpu::GpuControl implementation: virtual gpu::Capabilities GetCapabilities() OVERRIDE; - virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( - size_t width, - size_t height, - unsigned internalformat, - int32* id) OVERRIDE; + virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer(size_t width, + size_t height, + unsigned internalformat, + unsigned usage, + int32* id) OVERRIDE; virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE; - virtual bool GenerateMailboxNames(unsigned num, - std::vector<gpu::Mailbox>* names) OVERRIDE; virtual uint32 InsertSyncPoint() OVERRIDE; virtual void SignalSyncPoint(uint32 sync_point, const base::Closure& callback) OVERRIDE; virtual void SignalQuery(uint32 query, const base::Closure& callback) OVERRIDE; virtual void SetSurfaceVisible(bool visible) OVERRIDE; - virtual void SendManagedMemoryStats(const gpu::ManagedMemoryStats& stats) - OVERRIDE; virtual void Echo(const base::Closure& callback) OVERRIDE; + virtual uint32 CreateStreamTexture(uint32 texture_id) OVERRIDE; private: bool Send(IPC::Message* msg); void UpdateState(const gpu::CommandBuffer::State& state, bool success); - typedef base::hash_map<int32, gpu::Buffer> TransferBufferMap; - TransferBufferMap transfer_buffers_; - State last_state_; HostResource resource_; diff --git a/chromium/ppapi/proxy/ppapi_messages.h b/chromium/ppapi/proxy/ppapi_messages.h index 4b4fed8aef4..03f15d71c83 100644 --- a/chromium/ppapi/proxy/ppapi_messages.h +++ b/chromium/ppapi/proxy/ppapi_messages.h @@ -3,6 +3,7 @@ // found in the LICENSE file. // Multiply-included message header, no traditional include guard. +#include <map> #include <string> #include <vector> @@ -12,8 +13,8 @@ #include "base/process/process.h" #include "base/strings/string16.h" #include "base/sync_socket.h" -#include "base/values.h" #include "gpu/command_buffer/common/command_buffer.h" +#include "gpu/command_buffer/common/mailbox.h" #include "gpu/ipc/gpu_command_buffer_traits.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" @@ -21,11 +22,11 @@ #include "ipc/ipc_platform_file.h" #include "ppapi/c/dev/pp_video_capture_dev.h" #include "ppapi/c/dev/pp_video_dev.h" -#include "ppapi/c/dev/ppb_graphics_2d_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppp_printing_dev.h" #include "ppapi/c/pp_bool.h" +#include "ppapi/c/pp_codecs.h" #include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_module.h" @@ -35,6 +36,7 @@ #include "ppapi/c/pp_size.h" #include "ppapi/c/pp_time.h" #include "ppapi/c/ppb_audio_config.h" +#include "ppapi/c/ppb_compositor_layer.h" #include "ppapi/c/ppb_image_data.h" #include "ppapi/c/ppb_tcp_socket.h" #include "ppapi/c/ppb_text_input_controller.h" @@ -57,10 +59,14 @@ #include "ppapi/proxy/serialized_handle.h" #include "ppapi/proxy/serialized_structs.h" #include "ppapi/proxy/serialized_var.h" +#include "ppapi/shared_impl/compositor_layer_data.h" #include "ppapi/shared_impl/dir_contents.h" +#include "ppapi/shared_impl/file_growth.h" #include "ppapi/shared_impl/file_path.h" #include "ppapi/shared_impl/file_ref_create_info.h" -#include "ppapi/shared_impl/ppapi_nacl_channel_args.h" +#include "ppapi/shared_impl/media_stream_audio_track_shared.h" +#include "ppapi/shared_impl/media_stream_video_track_shared.h" +#include "ppapi/shared_impl/ppapi_nacl_plugin_args.h" #include "ppapi/shared_impl/ppapi_preferences.h" #include "ppapi/shared_impl/ppb_device_ref_shared.h" #include "ppapi/shared_impl/ppb_input_event_shared.h" @@ -71,6 +77,7 @@ #include "ppapi/shared_impl/socket_option_data.h" #include "ppapi/shared_impl/url_request_info_data.h" #include "ppapi/shared_impl/url_response_info_data.h" +#include "ui/events/ipc/latency_info_param_traits.h" #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT PPAPI_PROXY_EXPORT @@ -80,15 +87,16 @@ IPC_ENUM_TRAITS_MAX_VALUE(ppapi::TCPSocketVersion, ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) IPC_ENUM_TRAITS(PP_AudioSampleRate) +IPC_ENUM_TRAITS_MAX_VALUE(PP_BlendMode, PP_BLENDMODE_LAST) IPC_ENUM_TRAITS(PP_DeviceType_Dev) IPC_ENUM_TRAITS(PP_DecryptorStreamType) +IPC_ENUM_TRAITS(PP_SessionType) +IPC_ENUM_TRAITS(PP_CdmExceptionCode) IPC_ENUM_TRAITS_MAX_VALUE(PP_FileSystemType, PP_FILESYSTEMTYPE_ISOLATED) IPC_ENUM_TRAITS_MAX_VALUE(PP_FileType, PP_FILETYPE_OTHER) IPC_ENUM_TRAITS(PP_Flash_BrowserOperations_Permission) IPC_ENUM_TRAITS(PP_Flash_BrowserOperations_SettingType) IPC_ENUM_TRAITS(PP_FlashSetting) -IPC_ENUM_TRAITS_MAX_VALUE(PP_Graphics2D_Dev_ResizeMode, - PP_GRAPHICS2D_DEV_RESIZEMODE_STRETCH) IPC_ENUM_TRAITS(PP_ImageDataFormat) IPC_ENUM_TRAITS(PP_InputEvent_MouseButton) IPC_ENUM_TRAITS(PP_InputEvent_Type) @@ -119,6 +127,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(PP_UDPSocket_Option, PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE) IPC_ENUM_TRAITS(PP_VideoDecodeError_Dev) IPC_ENUM_TRAITS(PP_VideoDecoder_Profile) +IPC_ENUM_TRAITS_MAX_VALUE(PP_VideoFrame_Format, PP_VIDEOFRAME_FORMAT_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(PP_VideoProfile, PP_VIDEOPROFILE_MAX) IPC_STRUCT_TRAITS_BEGIN(PP_Point) IPC_STRUCT_TRAITS_MEMBER(x) @@ -135,11 +145,21 @@ IPC_STRUCT_TRAITS_BEGIN(PP_Size) IPC_STRUCT_TRAITS_MEMBER(width) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(PP_FloatSize) + IPC_STRUCT_TRAITS_MEMBER(height) + IPC_STRUCT_TRAITS_MEMBER(width) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(PP_Rect) IPC_STRUCT_TRAITS_MEMBER(point) IPC_STRUCT_TRAITS_MEMBER(size) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(PP_FloatRect) + IPC_STRUCT_TRAITS_MEMBER(point) + IPC_STRUCT_TRAITS_MEMBER(size) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(PP_ImageDataDesc) IPC_STRUCT_TRAITS_MEMBER(format) IPC_STRUCT_TRAITS_MEMBER(size) @@ -209,6 +229,46 @@ IPC_STRUCT_TRAITS_BEGIN(PP_FileInfo) IPC_STRUCT_TRAITS_MEMBER(last_modified_time) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(ppapi::FileGrowth) + IPC_STRUCT_TRAITS_MEMBER(max_written_offset) + IPC_STRUCT_TRAITS_MEMBER(append_mode_write_amount) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData) + IPC_STRUCT_TRAITS_MEMBER(common) + IPC_STRUCT_TRAITS_MEMBER(color) + IPC_STRUCT_TRAITS_MEMBER(texture) + IPC_STRUCT_TRAITS_MEMBER(image) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::LayerCommon) + IPC_STRUCT_TRAITS_MEMBER(size) + IPC_STRUCT_TRAITS_MEMBER(clip_rect) + IPC_STRUCT_TRAITS_MEMBER(transform) + IPC_STRUCT_TRAITS_MEMBER(blend_mode) + IPC_STRUCT_TRAITS_MEMBER(opacity) + IPC_STRUCT_TRAITS_MEMBER(resource_id) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::ColorLayer) + IPC_STRUCT_TRAITS_MEMBER(red) + IPC_STRUCT_TRAITS_MEMBER(green) + IPC_STRUCT_TRAITS_MEMBER(blue) + IPC_STRUCT_TRAITS_MEMBER(alpha) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::ImageLayer) + IPC_STRUCT_TRAITS_MEMBER(resource) + IPC_STRUCT_TRAITS_MEMBER(source_rect) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::TextureLayer) + IPC_STRUCT_TRAITS_MEMBER(mailbox) + IPC_STRUCT_TRAITS_MEMBER(sync_point) + IPC_STRUCT_TRAITS_MEMBER(source_rect) + IPC_STRUCT_TRAITS_MEMBER(premult_alpha) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(ppapi::DeviceRefData) IPC_STRUCT_TRAITS_MEMBER(type) IPC_STRUCT_TRAITS_MEMBER(name) @@ -234,6 +294,17 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::FlashSiteSetting) IPC_STRUCT_TRAITS_MEMBER(permission) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(ppapi::MediaStreamAudioTrackShared::Attributes) + IPC_STRUCT_TRAITS_MEMBER(buffers) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(ppapi::MediaStreamVideoTrackShared::Attributes) + IPC_STRUCT_TRAITS_MEMBER(buffers) + IPC_STRUCT_TRAITS_MEMBER(width) + IPC_STRUCT_TRAITS_MEMBER(height) + IPC_STRUCT_TRAITS_MEMBER(format) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(ppapi::ViewData) IPC_STRUCT_TRAITS_MEMBER(rect) IPC_STRUCT_TRAITS_MEMBER(is_fullscreen) @@ -241,6 +312,7 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::ViewData) IPC_STRUCT_TRAITS_MEMBER(clip_rect) IPC_STRUCT_TRAITS_MEMBER(device_scale) IPC_STRUCT_TRAITS_MEMBER(css_scale) + IPC_STRUCT_TRAITS_MEMBER(scroll_offset) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(PP_TouchPoint) @@ -262,6 +334,7 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::Preferences) IPC_STRUCT_TRAITS_MEMBER(is_3d_supported) IPC_STRUCT_TRAITS_MEMBER(is_stage3d_supported) IPC_STRUCT_TRAITS_MEMBER(is_stage3d_baseline_supported) + IPC_STRUCT_TRAITS_MEMBER(is_accelerated_video_decode_enabled) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(ppapi::InputEventData) @@ -277,7 +350,6 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::InputEventData) IPC_STRUCT_TRAITS_MEMBER(wheel_ticks) IPC_STRUCT_TRAITS_MEMBER(wheel_scroll_by_page) IPC_STRUCT_TRAITS_MEMBER(key_code) - IPC_STRUCT_TRAITS_MEMBER(usb_key_code) IPC_STRUCT_TRAITS_MEMBER(code) IPC_STRUCT_TRAITS_MEMBER(character_text) IPC_STRUCT_TRAITS_MEMBER(composition_segment_offsets) @@ -287,6 +359,7 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::InputEventData) IPC_STRUCT_TRAITS_MEMBER(touches) IPC_STRUCT_TRAITS_MEMBER(changed_touches) IPC_STRUCT_TRAITS_MEMBER(target_touches) + IPC_STRUCT_TRAITS_MEMBER(latency_info) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(ppapi::HostPortPair) @@ -342,12 +415,13 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::proxy::SerializedNetworkInfo) IPC_STRUCT_TRAITS_MEMBER(mtu) IPC_STRUCT_TRAITS_END() -// Only whitelisted switches passed through NaClChannelArgs. +// Only whitelisted switches passed through PpapiNaClPluginArgs. // The list of switches can be found in: -// chrome/browser/nacl_host/nacl_process_host.cc -IPC_STRUCT_TRAITS_BEGIN(ppapi::PpapiNaClChannelArgs) +// components/nacl/browser/nacl_process_host.cc +IPC_STRUCT_TRAITS_BEGIN(ppapi::PpapiNaClPluginArgs) IPC_STRUCT_TRAITS_MEMBER(off_the_record) IPC_STRUCT_TRAITS_MEMBER(permissions) + IPC_STRUCT_TRAITS_MEMBER(keepalive_throttle_interval_milliseconds) IPC_STRUCT_TRAITS_MEMBER(switch_names) IPC_STRUCT_TRAITS_MEMBER(switch_values) IPC_STRUCT_TRAITS_END() @@ -364,10 +438,9 @@ IPC_STRUCT_TRAITS_END() // These are from the browser to the plugin. // Loads the given plugin. -IPC_MESSAGE_CONTROL3(PpapiMsg_LoadPlugin, +IPC_MESSAGE_CONTROL2(PpapiMsg_LoadPlugin, base::FilePath /* path */, - ppapi::PpapiPermissions /* permissions */, - bool /* supports_dev_channel */) + ppapi::PpapiPermissions /* permissions */) // Creates a channel to talk to a renderer. The plugin will respond with // PpapiHostMsg_ChannelCreated. @@ -376,13 +449,9 @@ IPC_MESSAGE_CONTROL3(PpapiMsg_CreateChannel, int /* renderer_child_id */, bool /* incognito */) -// Creates a channel to talk to a renderer. This message is only used by the -// NaCl IPC proxy. It is intercepted by NaClIPCAdapter, which creates the -// actual channel and rewrites the message for the untrusted side. -IPC_MESSAGE_CONTROL3(PpapiMsg_CreateNaClChannel, - int /* renderer_id */, - ppapi::PpapiNaClChannelArgs /* args */, - ppapi::proxy::SerializedHandle /* channel_handle */) +// Initializes the IPC dispatchers in the NaCl plugin. +IPC_MESSAGE_CONTROL1(PpapiMsg_InitializeNaClDispatcher, + ppapi::PpapiNaClPluginArgs /* args */) // Instructs the plugin process to crash. IPC_MESSAGE_CONTROL0(PpapiMsg_Crash) @@ -418,6 +487,9 @@ IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_SupportsInterface, std::string /* interface_name */, bool /* result */) +IPC_MESSAGE_CONTROL1(PpapiHostMsg_LogInterfaceUsage, + int /* interface_hash */) + #if !defined(OS_NACL) && !defined(NACL_WIN64) // Network state notification from the browser for implementing // PPP_NetworkState_Dev. @@ -605,15 +677,48 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_HandleDocumentLoad, int /* pending_loader_host_id */, ppapi::URLResponseInfoData /* response */) -// PPP_Messaging. +// PPP_Messaging and PPP_MessageHandler. IPC_MESSAGE_ROUTED2(PpapiMsg_PPPMessaging_HandleMessage, PP_Instance /* instance */, ppapi::proxy::SerializedVar /* message */) +IPC_SYNC_MESSAGE_ROUTED2_2(PpapiMsg_PPPMessageHandler_HandleBlockingMessage, + PP_Instance /* instance */, + ppapi::proxy::SerializedVar /* message */, + ppapi::proxy::SerializedVar /* result */, + bool /* was_handled */); // PPP_MouseLock. IPC_MESSAGE_ROUTED1(PpapiMsg_PPPMouseLock_MouseLockLost, PP_Instance /* instance */) +// PPP_Pdf +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPPdf_Rotate, + PP_Instance /* instance */, + bool /* clockwise */) + +// Find +IPC_MESSAGE_ROUTED2(PpapiPluginMsg_PPPFind_StartFind, + PP_Instance /* instance */, + std::string /* text */) +IPC_MESSAGE_ROUTED2(PpapiPluginMsg_PPPFind_SelectFindResult, + PP_Instance /* instance */, + PP_Bool /* forward */) +IPC_MESSAGE_ROUTED1(PpapiPluginMsg_PPPFind_StopFind, + PP_Instance /* instance */) + +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_SetPluginToHandleFindRequests, + PP_Instance /* instance */) +IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_NumberOfFindResultsChanged, + PP_Instance /* instance */, + int32_t /* total */, + PP_Bool /* final_result */) +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SelectFindResultChanged, + PP_Instance /* instance */, + int32_t /* index */) +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SetTickmarks, + PP_Instance /* instance */, + std::vector<PP_Rect> /* tickmarks */) + // PPP_Printing IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPPrinting_QuerySupportedFormats, PP_Instance /* instance */, @@ -649,18 +754,25 @@ IPC_MESSAGE_ROUTED3( IPC_MESSAGE_ROUTED2(PpapiMsg_PPPContentDecryptor_Initialize, PP_Instance /* instance */, ppapi::proxy::SerializedVar /* key_system, String */) -IPC_MESSAGE_ROUTED4(PpapiMsg_PPPContentDecryptor_CreateSession, +IPC_MESSAGE_ROUTED5(PpapiMsg_PPPContentDecryptor_CreateSession, PP_Instance /* instance */, - uint32_t /* session_id */, - ppapi::proxy::SerializedVar /* type, String */, - ppapi::proxy::SerializedVar /* init_data, ArrayBuffer */) -IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_UpdateSession, + uint32_t /* promise_id */, + ppapi::proxy::SerializedVar /* init_data_type, String */, + ppapi::proxy::SerializedVar /* init_data, ArrayBuffer */, + PP_SessionType /* session_type */) +IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_LoadSession, PP_Instance /* instance */, - uint32_t /* session_id */, + uint32_t /* promise_id */, + ppapi::proxy::SerializedVar /* web_session_id, String */) +IPC_MESSAGE_ROUTED4(PpapiMsg_PPPContentDecryptor_UpdateSession, + PP_Instance /* instance */, + uint32_t /* promise_id */, + ppapi::proxy::SerializedVar /* web_session_id, String */, ppapi::proxy::SerializedVar /* response, ArrayBuffer */) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPPContentDecryptor_ReleaseSession, +IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_ReleaseSession, PP_Instance /* instance */, - uint32_t /* session_id */) + uint32_t /* promise_id */, + ppapi::proxy::SerializedVar /* web_session_id, String */) IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_Decrypt, PP_Instance /* instance */, ppapi::proxy::PPPDecryptor_Buffer /* buffer */, @@ -688,44 +800,17 @@ IPC_MESSAGE_ROUTED4(PpapiMsg_PPPContentDecryptor_DecryptAndDecode, PP_DecryptorStreamType /* decoder_type */, ppapi::proxy::PPPDecryptor_Buffer /* buffer */, std::string /* serialized_block_info */) -#endif // !defined(OS_NACL) && !defined(NACL_WIN64) -#if !defined(OS_NACL) && !defined(NACL_WIN64) // PPP_Instance_Private. IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstancePrivate_GetInstanceObject, PP_Instance /* instance */, ppapi::proxy::SerializedVar /* result */) -// PPB_VideoDecoder_Dev. -// (Messages from renderer to plugin to notify it to run callbacks.) -IPC_MESSAGE_ROUTED3(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK, - ppapi::HostResource /* video_decoder */, - int32_t /* bitstream buffer id */, - int32_t /* PP_CompletionCallback result */) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_FlushACK, - ppapi::HostResource /* video_decoder */, - int32_t /* PP_CompletionCallback result */) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_ResetACK, - ppapi::HostResource /* video_decoder */, - int32_t /* PP_CompletionCallback result */) - -// PPP_VideoDecoder_Dev. -IPC_MESSAGE_ROUTED4(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers, - ppapi::HostResource /* video_decoder */, - uint32_t /* requested number of buffers */, - PP_Size /* dimensions of buffers */, - uint32_t /* texture_target */) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer, - ppapi::HostResource /* video_decoder */, - int32_t /* picture buffer id */) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_PictureReady, - ppapi::HostResource /* video_decoder */, - PP_Picture_Dev /* output picture */) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError, - ppapi::HostResource /* video_decoder */, - PP_VideoDecodeError_Dev /* error */) #endif // !defined(OS_NACL) && !defined(NACL_WIN64) +// Reports to the browser that a plugin has been active. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_Keepalive) + // ----------------------------------------------------------------------------- // These are from the plugin to the renderer. @@ -736,6 +821,14 @@ IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError, IPC_MESSAGE_CONTROL1(PpapiHostMsg_ChannelCreated, IPC::ChannelHandle /* handle */) +// Notify the renderer that the PPAPI channel gets ready in the plugin. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_StartupInitializationComplete); + +// Calls renderer to open a resource file for nacl_irt_open_resource(). +IPC_SYNC_MESSAGE_CONTROL1_1(PpapiHostMsg_OpenResource, + std::string /* key */, + ppapi::proxy::SerializedHandle /* fd */) + // Logs the given message to the console of all instances. IPC_MESSAGE_CONTROL4(PpapiHostMsg_LogWithSource, PP_Instance /* instance */, @@ -768,30 +861,29 @@ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics3D_Create, IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBGraphics3D_SetGetBuffer, ppapi::HostResource /* context */, int32 /* transfer_buffer_id */) -IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBGraphics3D_GetState, +IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange, ppapi::HostResource /* context */, + int32 /* start */, + int32 /* end */, gpu::CommandBuffer::State /* state */, bool /* success */) -IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBGraphics3D_Flush, +IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange, ppapi::HostResource /* context */, - int32 /* put_offset */, - int32 /* last_known_get */, + int32 /* start */, + int32 /* end */, gpu::CommandBuffer::State /* state */, bool /* success */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBGraphics3D_AsyncFlush, ppapi::HostResource /* context */, int32 /* put_offset */) -IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer, +IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer, ppapi::HostResource /* context */, uint32 /* size */, - int32 /* id */) + int32 /* id */, + ppapi::proxy::SerializedHandle /* transfer_buffer */) IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer, ppapi::HostResource /* context */, int32 /* id */) -IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer, - ppapi::HostResource /* context */, - int32 /* id */, - ppapi::proxy::SerializedHandle /* transfer_buffer */) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_SwapBuffers, ppapi::HostResource /* graphics_3d */) IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint, @@ -860,6 +952,8 @@ IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_RequestInputEvents, IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_ClearInputEvents, PP_Instance /* instance */, uint32_t /* event_classes */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_StartTrackingLatency, + PP_Instance /* instance */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_PostMessage, PP_Instance /* instance */, ppapi::proxy::SerializedVar /* message */) @@ -983,26 +1077,36 @@ IPC_SYNC_MESSAGE_ROUTED2_2( ppapi::proxy::SerializedHandle /* result_shm_handle */) // PPB_ContentDecryptor_Dev messages handled in PPB_Instance_Proxy. -IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_SessionCreated, +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_PromiseResolved, PP_Instance /* instance */, - uint32_t /* session_id */, + uint32_t /* promise_id */) +IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_PromiseResolvedWithSession, + PP_Instance /* instance */, + uint32_t /* promise_id */, ppapi::proxy::SerializedVar /* web_session_id, String */) +IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBInstance_PromiseRejected, + PP_Instance /* instance */, + uint32_t /* promise_id */, + PP_CdmExceptionCode /* exception_code */, + int32_t /* system_code */, + ppapi::proxy::SerializedVar /* error_description, String */) IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_SessionMessage, PP_Instance /* instance */, - uint32_t /* session_id */, + ppapi::proxy::SerializedVar /* web_session_id, String */, ppapi::proxy::SerializedVar /* message, ArrayBuffer */, ppapi::proxy::SerializedVar /* destination_url, String */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SessionReady, PP_Instance /* instance */, - uint32_t /* session_id */) + ppapi::proxy::SerializedVar /* web_session_id, String */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SessionClosed, PP_Instance /* instance */, - uint32_t /* session_id */) -IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_SessionError, + ppapi::proxy::SerializedVar /* web_session_id, String */) +IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBInstance_SessionError, PP_Instance /* instance */, - uint32_t /* session_id */, - int32_t /* media_error */, - int32_t /* system_code */) + ppapi::proxy::SerializedVar /* web_session_id, String */, + PP_CdmExceptionCode /* exception_code */, + int32_t /* system_code */, + ppapi::proxy::SerializedVar /* error_description, String */) IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_DeliverBlock, PP_Instance /* instance */, PP_Resource /* decrypted_block, PPB_Buffer_Dev */, @@ -1049,7 +1153,8 @@ IPC_SYNC_MESSAGE_ROUTED1_0( #if !defined(OS_NACL) && !defined(NACL_WIN64) -// PPB_VideoDecoder. +// PPB_VideoDecoder_Dev. +// (Messages from plugin to renderer.) IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVideoDecoder_Create, PP_Instance /* instance */, ppapi::HostResource /* context */, @@ -1073,15 +1178,34 @@ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVideoDecoder_Reset, IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBVideoDecoder_Destroy, ppapi::HostResource /* video_decoder */) -// PPB_Flash_MessageLoop. -IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Create, - PP_Instance /* instance */, - ppapi::HostResource /* result */) -IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Run, - ppapi::HostResource /* flash_message_loop */, - int32_t /* result */) -IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlashMessageLoop_Quit, - ppapi::HostResource /* flash_message_loop */) +// PPB_VideoDecoder_Dev. +// (Messages from renderer to plugin to notify it to run callbacks.) +IPC_MESSAGE_ROUTED3(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK, + ppapi::HostResource /* video_decoder */, + int32_t /* bitstream buffer id */, + int32_t /* PP_CompletionCallback result */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_FlushACK, + ppapi::HostResource /* video_decoder */, + int32_t /* PP_CompletionCallback result */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_ResetACK, + ppapi::HostResource /* video_decoder */, + int32_t /* PP_CompletionCallback result */) + +// PPP_VideoDecoder_Dev. +IPC_MESSAGE_ROUTED4(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers, + ppapi::HostResource /* video_decoder */, + uint32_t /* requested number of buffers */, + PP_Size /* dimensions of buffers */, + uint32_t /* texture_target */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer, + ppapi::HostResource /* video_decoder */, + int32_t /* picture buffer id */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_PictureReady, + ppapi::HostResource /* video_decoder */, + PP_Picture_Dev /* output picture */) +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError, + ppapi::HostResource /* video_decoder */, + PP_VideoDecodeError_Dev /* error */) #endif // !defined(OS_NACL) && !defined(NACL_WIN64) // PPB_X509Certificate_Private @@ -1188,24 +1312,37 @@ IPC_MESSAGE_CONTROL0(PpapiHostMsg_Broker_Create) // ResourceMessageReplyParams in the reply message. IPC_MESSAGE_CONTROL0(PpapiHostMsg_Broker_IsAllowed) -// Extensions common ----------------------------------------------------------- -IPC_MESSAGE_CONTROL0(PpapiHostMsg_ExtensionsCommon_Create) - -// Starts an extension API request which doesn't expect a response. -// |request_name| is an API function name. |args| is a list of input arguments. -IPC_MESSAGE_CONTROL2(PpapiHostMsg_ExtensionsCommon_Post, - std::string /* request_name */, - base::ListValue /* args */) - -// Starts an extension API request which expects a response sent back using a -// PpapiPluginMsg_ExtensionsCommon_CallReply message. -// |request_name| is an API function name. |args| is a list of input arguments. -// |output| is a list of output results. -IPC_MESSAGE_CONTROL2(PpapiHostMsg_ExtensionsCommon_Call, - std::string /* request_name */, - base::ListValue /* args */) -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_ExtensionsCommon_CallReply, - base::ListValue /* output */) +// UMA +IPC_MESSAGE_CONTROL0(PpapiHostMsg_UMA_Create) +IPC_MESSAGE_CONTROL5(PpapiHostMsg_UMA_HistogramCustomTimes, + std::string /* name */, + int64_t /* sample */, + int64_t /* min */, + int64_t /* max */, + uint32_t /* bucket_count */) +IPC_MESSAGE_CONTROL5(PpapiHostMsg_UMA_HistogramCustomCounts, + std::string /* name */, + int32_t /* sample */, + int32_t /* min */, + int32_t /* max */, + uint32_t /* bucket_count */) +IPC_MESSAGE_CONTROL3(PpapiHostMsg_UMA_HistogramEnumeration, + std::string /* name */, + int32_t /* sample */, + int32_t /* boundary_value */) +IPC_MESSAGE_CONTROL0(PpapiHostMsg_UMA_IsCrashReportingEnabled); +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_UMA_IsCrashReportingEnabledReply); + +// Compositor +IPC_MESSAGE_CONTROL0(PpapiHostMsg_Compositor_Create) +IPC_MESSAGE_CONTROL2(PpapiHostMsg_Compositor_CommitLayers, + std::vector<ppapi::CompositorLayerData> /* layers */, + bool /* reset */) +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Compositor_CommitLayersReply) +IPC_MESSAGE_CONTROL3(PpapiPluginMsg_Compositor_ReleaseResource, + int32_t /* id */, + uint32_t /* sync_point */, + bool /* is_lost */) // File chooser. IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileChooser_Create) @@ -1222,14 +1359,14 @@ IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Create) IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Open, PP_Resource /* file_ref_resource */, int32_t /* open_flags */) -IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_OpenReply) -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Close) +IPC_MESSAGE_CONTROL2(PpapiPluginMsg_FileIO_OpenReply, + PP_Resource /* quota_file_system */, + int64_t /* file_size */) +IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileIO_Close, + ppapi::FileGrowth /* file_growth */) IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Touch, PP_Time /* last_access_time */, PP_Time /* last_modified_time */) -IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Write, - int64_t /* offset */, - std::string /* data */) IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileIO_SetLength, int64_t /* length */) IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Flush) @@ -1240,19 +1377,19 @@ IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_GeneralReply) // FileRef // Creates a FileRef to a path on an external file system. This message may // only be sent from the renderer. -IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileRef_CreateExternal, +IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileRef_CreateForRawFS, base::FilePath /* external_path */) -// Creates a FileRef to a path on an internal file system. This message may -// be sent from the renderer or the plugin. -IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileRef_CreateInternal, +// Creates a FileRef to a path on a file system that uses fileapi. +// This message may be sent from the renderer or the plugin. +IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileRef_CreateForFileAPI, PP_Resource /* file_system */, std::string /* internal_path */) // Requests that the browser create a directory at the location indicated by // the FileRef. IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileRef_MakeDirectory, - bool /* make_ancestors */) + int32_t /* make_directory_flags */) IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileRef_MakeDirectoryReply) // Requests that the browser update the last accessed and last modified times @@ -1315,38 +1452,12 @@ IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileSystem_CreateFromRenderer, // linked to the existing resource host given in the ResourceVar. IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileSystem_CreateFromPendingHost, PP_FileSystemType /* file_system_type */) - -// Flash DRM ------------------------------------------------------------------ -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_Create) - -// Requests the device ID. -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetDeviceID) -// Reply for GetDeviceID which includes the device ID as a string. -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetDeviceIDReply, - std::string /* id */) - -// Requests the HMONITOR corresponding to the monitor on which the instance is -// displayed. -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetHmonitor) -// Reply message for GetHmonitor which contains the HMONITOR as an int64_t. -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetHmonitorReply, - int64_t /* hmonitor */) - -// Requests the voucher file which is used to verify the integrity of the Flash -// module. A PPB_FileRef resource will be created. -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetVoucherFile) -// Reply message for GetVoucherFile which contains the CreateInfo for a -// PPB_FileRef which points to the voucher file. -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetVoucherFileReply, - ppapi::FileRefCreateInfo /* file_info */) - -// Requests a value indicating whether the monitor on which the instance is -// displayed is external. -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_MonitorIsExternal) -// Reply message for MonitorIsExternal which contains the value indicating if -// the monitor is external. -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_MonitorIsExternalReply, - PP_Bool /* is_external */) +IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileSystem_ReserveQuota, + int64_t /* amount */, + ppapi::FileGrowthMap /* file_growths */) +IPC_MESSAGE_CONTROL2(PpapiPluginMsg_FileSystem_ReserveQuotaReply, + int64_t /* amount */, + ppapi::FileSizeMap /* file_sizes */) // Gamepad. IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create) @@ -1375,16 +1486,12 @@ IPC_MESSAGE_CONTROL3(PpapiHostMsg_Graphics2D_Scroll, PP_Point /* amount */) IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_ReplaceContents, ppapi::HostResource /* image_data */) -IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_Dev_SetScale, +IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_SetScale, float /* scale */) -IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_SetOffset, - PP_Point /* offset */) -IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_SetResizeMode, - PP_Graphics2D_Dev_ResizeMode /* resize_mode */) // Graphics2D, plugin -> host -> plugin IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_Flush, - ppapi::ViewData /* view_data */) + std::vector<ui::LatencyInfo> /* latency_info */) IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Graphics2D_FlushAck) IPC_MESSAGE_CONTROL2(PpapiHostMsg_Graphics2D_ReadImageData, @@ -1399,6 +1506,36 @@ IPC_MESSAGE_CONTROL1(PpapiHostMsg_IsolatedFileSystem_BrowserOpen, IPC_MESSAGE_CONTROL1(PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply, std::string /* fsid */) +// MediaStream ----------------------------------------------------------------- +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost, + std::string /* track_id */) +IPC_MESSAGE_CONTROL1( + PpapiHostMsg_MediaStreamAudioTrack_Configure, + ppapi::MediaStreamAudioTrackShared::Attributes /* attributes */) +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost, + std::string /* track_id */) +IPC_MESSAGE_CONTROL0(PpapiHostMsg_MediaStreamVideoTrack_Create) +IPC_MESSAGE_CONTROL1( + PpapiHostMsg_MediaStreamVideoTrack_Configure, + ppapi::MediaStreamVideoTrackShared::Attributes /* attributes */) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply, + std::string /* track_id */) + +// Message for init buffers. It also takes a shared memory handle which is put +// in the outer ResourceReplyMessage. +IPC_MESSAGE_CONTROL3(PpapiPluginMsg_MediaStreamTrack_InitBuffers, + int32_t /* number_of_buffers */, + int32_t /* buffer_size */, + bool /* readonly */) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamTrack_EnqueueBuffer, + int32_t /* index */); +IPC_MESSAGE_CONTROL1(PpapiHostMsg_MediaStreamTrack_EnqueueBuffer, + int32_t /* index */); +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamTrack_EnqueueBuffers, + std::vector<int32_t> /* indices */); +IPC_MESSAGE_CONTROL0(PpapiHostMsg_MediaStreamTrack_Close) + // NetworkMonitor. IPC_MESSAGE_CONTROL0(PpapiHostMsg_NetworkMonitor_Create) IPC_MESSAGE_CONTROL1(PpapiPluginMsg_NetworkMonitor_NetworkList, @@ -1749,6 +1886,48 @@ IPC_MESSAGE_CONTROL2(PpapiPluginMsg_OutputProtection_QueryStatusReply, uint32_t /* link_mask */, uint32_t /* protection_mask */) +// VideoDecoder ------------------------------------------------------ + +IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoDecoder_Create) +IPC_MESSAGE_CONTROL3(PpapiHostMsg_VideoDecoder_Initialize, + ppapi::HostResource /* graphics_context */, + PP_VideoProfile /* profile */, + bool /* allow_software_fallback */) +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_VideoDecoder_InitializeReply) +IPC_MESSAGE_CONTROL2(PpapiHostMsg_VideoDecoder_GetShm, + uint32_t /* shm_id */, + uint32_t /* shm_size */) +// On success, a shm handle is passed in the ReplyParams struct. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoDecoder_GetShmReply, + uint32_t /* shm_size */) +IPC_MESSAGE_CONTROL3(PpapiHostMsg_VideoDecoder_Decode, + uint32_t /* shm_id */, + uint32_t /* size */, + int32_t /* decode_id */) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoDecoder_DecodeReply, + uint32_t /* shm_id */) +IPC_MESSAGE_CONTROL4(PpapiPluginMsg_VideoDecoder_RequestTextures, + uint32_t /* num_textures */, + PP_Size /* size */, + uint32_t /* texture_target */, + std::vector<gpu::Mailbox> /* mailboxes*/) +IPC_MESSAGE_CONTROL2(PpapiHostMsg_VideoDecoder_AssignTextures, + PP_Size /* size */, + std::vector<uint32_t> /* texture_ids */) +IPC_MESSAGE_CONTROL2(PpapiPluginMsg_VideoDecoder_PictureReady, + int32_t /* decode_id */, + uint32_t /* texture_id */) +IPC_MESSAGE_CONTROL1(PpapiHostMsg_VideoDecoder_RecyclePicture, + uint32_t /* texture_id */) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoDecoder_DismissPicture, + uint32_t /* texture_id */) +IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoDecoder_Flush) +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_VideoDecoder_FlushReply) +IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoDecoder_Reset) +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_VideoDecoder_ResetReply) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoDecoder_NotifyError, + int32_t /* error */) + #if !defined(OS_NACL) && !defined(NACL_WIN64) // Audio input. @@ -1865,6 +2044,42 @@ IPC_MESSAGE_CONTROL3(PpapiHostMsg_FlashClipboard_WriteData, uint32_t /* clipboard_type */, std::vector<uint32_t> /* formats */, std::vector<std::string> /* data */) +IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashClipboard_GetSequenceNumber, + uint32_t /* clipboard_type */) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashClipboard_GetSequenceNumberReply, + uint64_t /* sequence_number */) + +// Flash DRM. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_Create) + +// Requests the device ID. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetDeviceID) +// Reply for GetDeviceID which includes the device ID as a string. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetDeviceIDReply, + std::string /* id */) + +// Requests the HMONITOR corresponding to the monitor on which the instance is +// displayed. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetHmonitor) +// Reply message for GetHmonitor which contains the HMONITOR as an int64_t. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetHmonitorReply, + int64_t /* hmonitor */) + +// Requests the voucher file which is used to verify the integrity of the Flash +// module. A PPB_FileRef resource will be created. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetVoucherFile) +// Reply message for GetVoucherFile which contains the CreateInfo for a +// PPB_FileRef which points to the voucher file. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetVoucherFileReply, + ppapi::FileRefCreateInfo /* file_info */) + +// Requests a value indicating whether the monitor on which the instance is +// displayed is external. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_MonitorIsExternal) +// Reply message for MonitorIsExternal which contains the value indicating if +// the monitor is external. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_MonitorIsExternalReply, + PP_Bool /* is_external */) // Flash file. IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFile_Create) @@ -1882,7 +2097,7 @@ IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_CreateDir, IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_QueryFile, ppapi::PepperFilePath /* path */) IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFile_QueryFileReply, - base::PlatformFileInfo /* file_info */) + base::File::Info /* file_info */) IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_GetDirContents, ppapi::PepperFilePath /* path */) IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFile_GetDirContentsReply, @@ -1903,7 +2118,7 @@ IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFullscreen_Create) IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFullscreen_SetFullscreen, bool /* fullscreen */) -// FlashMenu ------------------------------------------------------------------ +// FlashMenu. // Creates the flash menu with the given data. IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashMenu_Create, @@ -1918,6 +2133,16 @@ IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashMenu_Show, IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashMenu_ShowReply, int32_t /* selected_id */) +// PPB_Flash_MessageLoop. +IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Create, + PP_Instance /* instance */, + ppapi::HostResource /* result */) +IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Run, + ppapi::HostResource /* flash_message_loop */, + int32_t /* result */) +IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlashMessageLoop_Quit, + ppapi::HostResource /* flash_message_loop */) + // PDF ------------------------------------------------------------------------ // Creates the PDF resource. @@ -1966,6 +2191,14 @@ IPC_MESSAGE_CONTROL2(PpapiPluginMsg_PDF_GetResourceImageReply, ppapi::HostResource /* resource_id */, PP_ImageDataDesc /* image_data_desc */) +// Called by the plugin when its selection changes. +IPC_MESSAGE_CONTROL1(PpapiHostMsg_PDF_SetSelectedText, + base::string16 /* selected_text */) + +// Called by the plugin to set the link under the cursor. +IPC_MESSAGE_CONTROL1(PpapiHostMsg_PDF_SetLinkUnderCursor, + std::string /* url */) + // VideoCapture_Dev, plugin -> host IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoCapture_Create) IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoCapture_StartCapture) diff --git a/chromium/ppapi/proxy/ppapi_param_traits.cc b/chromium/ppapi/proxy/ppapi_param_traits.cc index 5ee0a34397a..1623395924e 100644 --- a/chromium/ppapi/proxy/ppapi_param_traits.cc +++ b/chromium/ppapi/proxy/ppapi_param_traits.cc @@ -235,7 +235,6 @@ void ParamTraits<ppapi::proxy::SerializedHandle>::Write(Message* m, ParamTraits<base::SharedMemoryHandle>::Write(m, p.shmem()); break; case ppapi::proxy::SerializedHandle::SOCKET: - case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: case ppapi::proxy::SerializedHandle::FILE: ParamTraits<IPC::PlatformFileForTransit>::Write(m, p.descriptor()); break; @@ -269,18 +268,10 @@ bool ParamTraits<ppapi::proxy::SerializedHandle>::Read(const Message* m, } break; } - case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: { - IPC::PlatformFileForTransit desc; - if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) { - r->set_channel_handle(desc); - return true; - } - break; - } case ppapi::proxy::SerializedHandle::FILE: { IPC::PlatformFileForTransit desc; if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) { - r->set_file_handle(desc, header.open_flag); + r->set_file_handle(desc, header.open_flags, header.file_io); return true; } break; @@ -642,4 +633,31 @@ void ParamTraits<ppapi::SocketOptionData>::Log(const param_type& p, std::string* l) { } +// ppapi::CompositorLayerData -------------------------------------------------- + +// static +void ParamTraits<ppapi::CompositorLayerData::Transform>::Write( + Message* m, + const param_type& p) { + for (size_t i = 0; i < arraysize(p.matrix); i++) + ParamTraits<float>::Write(m, p.matrix[i]); +} + +// static +bool ParamTraits<ppapi::CompositorLayerData::Transform>::Read( + const Message* m, + PickleIterator* iter, + param_type* r) { + for (size_t i = 0; i < arraysize(r->matrix);i++) { + if (!ParamTraits<float>::Read(m, iter, &r->matrix[i])) + return false; + } + return true; +} + +void ParamTraits<ppapi::CompositorLayerData::Transform>::Log( + const param_type& p, + std::string* l) { +} + } // namespace IPC diff --git a/chromium/ppapi/proxy/ppapi_param_traits.h b/chromium/ppapi/proxy/ppapi_param_traits.h index 3bf5fb6b696..76dd10df6f8 100644 --- a/chromium/ppapi/proxy/ppapi_param_traits.h +++ b/chromium/ppapi/proxy/ppapi_param_traits.h @@ -14,8 +14,10 @@ #include "ppapi/c/pp_rect.h" #include "ppapi/c/pp_var.h" #include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/compositor_layer_data.h" #include "ppapi/shared_impl/file_path.h" #include "ppapi/shared_impl/file_ref_create_info.h" +#include "ppapi/shared_impl/media_stream_video_track_shared.h" #include "ppapi/shared_impl/ppapi_permissions.h" #include "ppapi/shared_impl/socket_option_data.h" @@ -176,6 +178,14 @@ struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::SocketOptionData> { static void Log(const param_type& p, std::string* l); }; +template<> +struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::CompositorLayerData::Transform> { + typedef ppapi::CompositorLayerData::Transform param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, PickleIterator* iter, param_type* r); + static void Log(const param_type& p, std::string* l); +}; + } // namespace IPC #endif // PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_ diff --git a/chromium/ppapi/proxy/ppb_audio_proxy.cc b/chromium/ppapi/proxy/ppb_audio_proxy.cc index 58f5abc0d41..d84c3cb6995 100644 --- a/chromium/ppapi/proxy/ppb_audio_proxy.cc +++ b/chromium/ppapi/proxy/ppb_audio_proxy.cc @@ -95,6 +95,8 @@ PP_Resource Audio::GetCurrentConfig() { PP_Bool Audio::StartPlayback() { if (playing()) return PP_TRUE; + if (!PPB_Audio_Shared::IsThreadFunctionReady()) + return PP_FALSE; SetStartPlaybackState(); PluginDispatcher::GetForResource(this)->Send( new PpapiHostMsg_PPBAudio_StartOrStop( diff --git a/chromium/ppapi/proxy/ppb_broker_proxy.cc b/chromium/ppapi/proxy/ppb_broker_proxy.cc index 19cd978608f..5463cf3a9ab 100644 --- a/chromium/ppapi/proxy/ppb_broker_proxy.cc +++ b/chromium/ppapi/proxy/ppb_broker_proxy.cc @@ -57,11 +57,11 @@ class Broker : public PPB_Broker_API, public Resource { Broker::Broker(const HostResource& resource) : Resource(OBJECT_IS_PROXY, resource), called_connect_(false), - socket_handle_(base::kInvalidPlatformFileValue) { + socket_handle_(base::SyncSocket::kInvalidHandle) { } Broker::~Broker() { - socket_handle_ = base::kInvalidPlatformFileValue; + socket_handle_ = base::SyncSocket::kInvalidHandle; } PPB_Broker_API* Broker::AsPPB_Broker_API() { @@ -84,7 +84,7 @@ int32_t Broker::Connect(scoped_refptr<TrackedCallback> connect_callback) { } int32_t Broker::GetHandle(int32_t* handle) { - if (socket_handle_ == base::kInvalidPlatformFileValue) + if (socket_handle_ == base::SyncSocket::kInvalidHandle) return PP_ERROR_FAILED; *handle = PlatformFileToInt(socket_handle_); return PP_OK; @@ -93,7 +93,7 @@ int32_t Broker::GetHandle(int32_t* handle) { void Broker::ConnectComplete(IPC::PlatformFileForTransit socket_handle, int32_t result) { if (result == PP_OK) { - DCHECK(socket_handle_ == base::kInvalidPlatformFileValue); + DCHECK(socket_handle_ == base::SyncSocket::kInvalidHandle); socket_handle_ = IPC::PlatformFileForTransitToPlatformFile(socket_handle); } else { // The caller may still have given us a handle in the failure case. @@ -197,12 +197,13 @@ void PPB_Broker_Proxy::ConnectCompleteInHost(int32_t result, IPC::PlatformFileForTransit foreign_socket_handle = IPC::InvalidPlatformFileForTransit(); if (result == PP_OK) { - int32_t socket_handle = PlatformFileToInt(base::kInvalidPlatformFileValue); + int32_t socket_handle = PlatformFileToInt(base::SyncSocket::kInvalidHandle); EnterHostFromHostResource<PPB_Broker_API> enter(broker); if (enter.succeeded()) result = enter.object()->GetHandle(&socket_handle); DCHECK(result == PP_OK || - socket_handle == PlatformFileToInt(base::kInvalidPlatformFileValue)); + socket_handle == + PlatformFileToInt(base::SyncSocket::kInvalidHandle)); if (result == PP_OK) { foreign_socket_handle = diff --git a/chromium/ppapi/proxy/ppb_core_proxy.cc b/chromium/ppapi/proxy/ppb_core_proxy.cc index 65845aed7be..52f965c1245 100644 --- a/chromium/ppapi/proxy/ppb_core_proxy.cc +++ b/chromium/ppapi/proxy/ppb_core_proxy.cc @@ -103,18 +103,20 @@ const PPB_Core* PPB_Core_Proxy::GetPPB_Core_Interface() { } bool PPB_Core_Proxy::OnMessageReceived(const IPC::Message& msg) { +#if defined(OS_NACL) + return false; +#else bool handled = true; IPC_BEGIN_MESSAGE_MAP(PPB_Core_Proxy, msg) -#if !defined(OS_NACL) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_AddRefResource, OnMsgAddRefResource) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_ReleaseResource, OnMsgReleaseResource) -#endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() // TODO(brettw) handle bad messages! return handled; +#endif } #if !defined(OS_NACL) diff --git a/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc index 02e06f76b8f..ba0e505bd46 100644 --- a/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc +++ b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc @@ -28,18 +28,10 @@ namespace { const int32 kCommandBufferSize = 1024 * 1024; const int32 kTransferBufferSize = 1024 * 1024; -base::SharedMemoryHandle TransportSHMHandleFromInt(Dispatcher* dispatcher, - int shm_handle) { - // TODO(piman): Change trusted interface to return a PP_FileHandle, those - // casts are ugly. +base::SharedMemoryHandle TransportSHMHandle(Dispatcher* dispatcher, + base::SharedMemory* shm) { base::PlatformFile source = -#if defined(OS_WIN) - reinterpret_cast<HANDLE>(static_cast<intptr_t>(shm_handle)); -#elif defined(OS_POSIX) - shm_handle; -#else - #error Not implemented. -#endif + IPC::PlatformFileForTransitToPlatformFile(shm->handle()); // Don't close the handle, it doesn't belong to us. return dispatcher->ShareHandleWithRemote(source, false); } @@ -76,34 +68,28 @@ PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) { return PP_FALSE; } -gpu::CommandBuffer::State Graphics3D::GetState() { - return GetErrorState(); -} - PP_Bool Graphics3D::Flush(int32_t put_offset) { return PP_FALSE; } -gpu::CommandBuffer::State Graphics3D::FlushSync(int32_t put_offset) { - return GetErrorState(); -} - -int32_t Graphics3D::CreateTransferBuffer(uint32_t size) { - return PP_FALSE; +scoped_refptr<gpu::Buffer> Graphics3D::CreateTransferBuffer( + uint32_t size, + int32_t* id) { + *id = -1; + return NULL; } PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) { return PP_FALSE; } -PP_Bool Graphics3D::GetTransferBuffer(int32_t id, - int* shm_handle, - uint32_t* shm_size) { - return PP_FALSE; +gpu::CommandBuffer::State Graphics3D::WaitForTokenInRange(int32_t start, + int32_t end) { + return GetErrorState(); } -gpu::CommandBuffer::State Graphics3D::FlushSyncFast(int32_t put_offset, - int32_t last_known_get) { +gpu::CommandBuffer::State Graphics3D::WaitForGetOffsetInRange(int32_t start, + int32_t end) { return GetErrorState(); } @@ -191,18 +177,15 @@ bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) { OnMsgCreate) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer, OnMsgSetGetBuffer) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetState, - OnMsgGetState) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Flush, - OnMsgFlush) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, - OnMsgAsyncFlush) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange, + OnMsgWaitForTokenInRange) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange, + OnMsgWaitForGetOffsetInRange) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, OnMsgAsyncFlush) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer, OnMsgCreateTransferBuffer) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer, OnMsgDestroyTransferBuffer) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer, - OnMsgGetTransferBuffer) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers, OnMsgSwapBuffers) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint, @@ -247,29 +230,33 @@ void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer( enter.object()->SetGetBuffer(transfer_buffer_id); } -void PPB_Graphics3D_Proxy::OnMsgGetState(const HostResource& context, - gpu::CommandBuffer::State* state, - bool* success) { +void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange( + const HostResource& context, + int32 start, + int32 end, + gpu::CommandBuffer::State* state, + bool* success) { EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); if (enter.failed()) { *success = false; return; } - *state = enter.object()->GetState(); + *state = enter.object()->WaitForTokenInRange(start, end); *success = true; } -void PPB_Graphics3D_Proxy::OnMsgFlush(const HostResource& context, - int32 put_offset, - int32 last_known_get, - gpu::CommandBuffer::State* state, - bool* success) { +void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange( + const HostResource& context, + int32 start, + int32 end, + gpu::CommandBuffer::State* state, + bool* success) { EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); if (enter.failed()) { *success = false; return; } - *state = enter.object()->FlushSyncFast(put_offset, last_known_get); + *state = enter.object()->WaitForGetOffsetInRange(start, end); *success = true; } @@ -283,12 +270,24 @@ void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context, void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer( const HostResource& context, uint32 size, - int32* id) { + int32* id, + ppapi::proxy::SerializedHandle* transfer_buffer) { + transfer_buffer->set_null_shmem(); EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); - if (enter.succeeded()) - *id = enter.object()->CreateTransferBuffer(size); - else + if (enter.succeeded()) { + scoped_refptr<gpu::Buffer> buffer = + enter.object()->CreateTransferBuffer(size, id); + if (!buffer) + return; + gpu::SharedMemoryBufferBacking* backing = + static_cast<gpu::SharedMemoryBufferBacking*>(buffer->backing()); + DCHECK(backing && backing->shared_memory()); + transfer_buffer->set_shmem( + TransportSHMHandle(dispatcher(), backing->shared_memory()), + buffer->size()); + } else { *id = -1; + } } void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer( @@ -299,23 +298,6 @@ void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer( enter.object()->DestroyTransferBuffer(id); } -void PPB_Graphics3D_Proxy::OnMsgGetTransferBuffer( - const HostResource& context, - int32 id, - ppapi::proxy::SerializedHandle* transfer_buffer) { - transfer_buffer->set_null_shmem(); - - EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); - int shm_handle = 0; - uint32_t shm_size = 0; - if (enter.succeeded() && - enter.object()->GetTransferBuffer(id, &shm_handle, &shm_size)) { - transfer_buffer->set_shmem( - TransportSHMHandleFromInt(dispatcher(), shm_handle), - shm_size); - } -} - void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) { EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter( context, callback_factory_, diff --git a/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h index 18ba9dd5e3c..e66405cc99b 100644 --- a/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h @@ -12,6 +12,7 @@ #include "ppapi/c/pp_graphics_3d.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" +#include "ppapi/proxy/ppapi_proxy_export.h" #include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/ppb_graphics_3d_shared.h" #include "ppapi/shared_impl/resource.h" @@ -26,7 +27,7 @@ namespace proxy { class SerializedHandle; class PpapiCommandBufferProxy; -class Graphics3D : public PPB_Graphics3D_Shared { +class PPAPI_PROXY_EXPORT Graphics3D : public PPB_Graphics3D_Shared { public: explicit Graphics3D(const HostResource& resource); virtual ~Graphics3D(); @@ -35,17 +36,15 @@ class Graphics3D : public PPB_Graphics3D_Shared { // Graphics3DTrusted API. These are not implemented in the proxy. virtual PP_Bool SetGetBuffer(int32_t shm_id) OVERRIDE; - virtual gpu::CommandBuffer::State GetState() OVERRIDE; virtual PP_Bool Flush(int32_t put_offset) OVERRIDE; - virtual gpu::CommandBuffer::State FlushSync(int32_t put_offset) OVERRIDE; - virtual int32_t CreateTransferBuffer(uint32_t size) OVERRIDE; + virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(uint32_t size, + int32* id) OVERRIDE; virtual PP_Bool DestroyTransferBuffer(int32_t id) OVERRIDE; - virtual PP_Bool GetTransferBuffer(int32_t id, - int* shm_handle, - uint32_t* shm_size) OVERRIDE; - virtual gpu::CommandBuffer::State FlushSyncFast( - int32_t put_offset, - int32_t last_known_get) OVERRIDE; + virtual gpu::CommandBuffer::State WaitForTokenInRange(int32_t start, + int32_t end) OVERRIDE; + virtual gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start, + int32_t end) + OVERRIDE; virtual uint32_t InsertSyncPoint() OVERRIDE; private: @@ -81,24 +80,24 @@ class PPB_Graphics3D_Proxy : public InterfaceProxy { HostResource* result); void OnMsgSetGetBuffer(const HostResource& context, int32 id); - void OnMsgGetState(const HostResource& context, - gpu::CommandBuffer::State* state, - bool* success); - void OnMsgFlush(const HostResource& context, - int32 put_offset, - int32 last_known_get, - gpu::CommandBuffer::State* state, - bool* success); - void OnMsgAsyncFlush(const HostResource& context, - int32 put_offset); - void OnMsgCreateTransferBuffer(const HostResource& context, - uint32 size, - int32* id); + void OnMsgWaitForTokenInRange(const HostResource& context, + int32 start, + int32 end, + gpu::CommandBuffer::State* state, + bool* success); + void OnMsgWaitForGetOffsetInRange(const HostResource& context, + int32 start, + int32 end, + gpu::CommandBuffer::State* state, + bool* success); + void OnMsgAsyncFlush(const HostResource& context, int32 put_offset); + void OnMsgCreateTransferBuffer( + const HostResource& context, + uint32 size, + int32* id, + ppapi::proxy::SerializedHandle* transfer_buffer); void OnMsgDestroyTransferBuffer(const HostResource& context, int32 id); - void OnMsgGetTransferBuffer(const HostResource& context, - int32 id, - ppapi::proxy::SerializedHandle* transfer_buffer); void OnMsgSwapBuffers(const HostResource& context); void OnMsgInsertSyncPoint(const HostResource& context, uint32* sync_point); // Renderer->plugin message handlers. diff --git a/chromium/ppapi/proxy/ppb_image_data_proxy.cc b/chromium/ppapi/proxy/ppb_image_data_proxy.cc index c9d61f9feae..4ed4442ceb4 100644 --- a/chromium/ppapi/proxy/ppb_image_data_proxy.cc +++ b/chromium/ppapi/proxy/ppb_image_data_proxy.cc @@ -416,8 +416,6 @@ SkCanvas* PlatformImageData::GetCanvas() { ImageHandle PlatformImageData::NullHandle() { #if defined(OS_WIN) return NULL; -#elif defined(TOOLKIT_GTK) - return 0; #else return ImageHandle(); #endif @@ -426,8 +424,6 @@ ImageHandle PlatformImageData::NullHandle() { ImageHandle PlatformImageData::HandleFromInt(int32_t i) { #if defined(OS_WIN) return reinterpret_cast<ImageHandle>(i); -#elif defined(TOOLKIT_GTK) - return static_cast<ImageHandle>(i); #else return ImageHandle(i, false); #endif @@ -607,14 +603,6 @@ PP_Resource PPB_ImageData_Proxy::CreateImageData( #if defined(OS_WIN) *image_handle = dispatcher->ShareHandleWithRemote( reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false); -#elif defined(TOOLKIT_GTK) - // On X Windows, a PlatformImageData is backed by a SysV shared memory key, - // so embed that in a fake PlatformFileForTransit and don't share it across - // processes. - if (type == PPB_ImageData_Shared::PLATFORM) - *image_handle = IPC::PlatformFileForTransit(local_fd, false); - else - *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false); #elif defined(OS_POSIX) *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false); #else @@ -632,6 +620,9 @@ void PPB_ImageData_Proxy::OnHostMsgCreatePlatform( HostResource* result, PP_ImageDataDesc* desc, ImageHandle* result_image_handle) { + // Clear |desc| so we don't send unitialized memory to the plugin. + // https://crbug.com/391023. + *desc = PP_ImageDataDesc(); IPC::PlatformFileForTransit image_handle; uint32_t byte_count; PP_Resource resource = @@ -643,12 +634,7 @@ void PPB_ImageData_Proxy::OnHostMsgCreatePlatform( desc, &image_handle, &byte_count); result->SetHostResource(instance, resource); if (resource) { -#if defined(TOOLKIT_GTK) - // On X Windows ImageHandle is a SysV shared memory key. - *result_image_handle = image_handle.fd; -#else *result_image_handle = image_handle; -#endif } else { *result_image_handle = PlatformImageData::NullHandle(); } @@ -662,6 +648,9 @@ void PPB_ImageData_Proxy::OnHostMsgCreateSimple( HostResource* result, PP_ImageDataDesc* desc, ppapi::proxy::SerializedHandle* result_image_handle) { + // Clear |desc| so we don't send unitialized memory to the plugin. + // https://crbug.com/391023. + *desc = PP_ImageDataDesc(); IPC::PlatformFileForTransit image_handle; uint32_t byte_count; PP_Resource resource = diff --git a/chromium/ppapi/proxy/ppb_instance_proxy.cc b/chromium/ppapi/proxy/ppb_instance_proxy.cc index 5d0e7ed3eb0..4f64e917af4 100644 --- a/chromium/ppapi/proxy/ppb_instance_proxy.cc +++ b/chromium/ppapi/proxy/ppb_instance_proxy.cc @@ -18,7 +18,7 @@ #include "ppapi/proxy/browser_font_singleton_resource.h" #include "ppapi/proxy/content_decryptor_private_serializer.h" #include "ppapi/proxy/enter_proxy.h" -#include "ppapi/proxy/extensions_common_resource.h" +#include "ppapi/proxy/file_mapping_resource.h" #include "ppapi/proxy/flash_clipboard_resource.h" #include "ppapi/proxy/flash_file_resource.h" #include "ppapi/proxy/flash_fullscreen_resource.h" @@ -26,17 +26,20 @@ #include "ppapi/proxy/gamepad_resource.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/isolated_file_system_private_resource.h" +#include "ppapi/proxy/message_handler.h" #include "ppapi/proxy/network_proxy_resource.h" #include "ppapi/proxy/pdf_resource.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_var.h" #include "ppapi/proxy/truetype_font_singleton_resource.h" +#include "ppapi/proxy/uma_private_resource.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppb_url_util_shared.h" #include "ppapi/shared_impl/ppb_view_shared.h" #include "ppapi/shared_impl/var.h" #include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_compositor_api.h" #include "ppapi/thunk/ppb_graphics_2d_api.h" #include "ppapi/thunk/ppb_graphics_3d_api.h" #include "ppapi/thunk/thunk.h" @@ -48,6 +51,7 @@ using ppapi::thunk::EnterInstanceNoLock; using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_Compositor_API; using ppapi::thunk::PPB_Graphics2D_API; using ppapi::thunk::PPB_Graphics3D_API; using ppapi::thunk::PPB_Instance_API; @@ -57,13 +61,11 @@ namespace proxy { namespace { +#if !defined(OS_NACL) const char kSerializationError[] = "Failed to convert a PostMessage " "argument from a PP_Var to a Javascript value. It may have cycles or be of " "an unsupported type."; - -InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher) { - return new PPB_Instance_Proxy(dispatcher); -} +#endif void RequestSurroundingText(PP_Instance instance) { PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); @@ -96,18 +98,6 @@ PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher) PPB_Instance_Proxy::~PPB_Instance_Proxy() { } -// static -const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfoPrivate() { - static const Info info = { - ppapi::thunk::GetPPB_Instance_Private_0_1_Thunk(), - PPB_INSTANCE_PRIVATE_INTERFACE_0_1, - API_ID_NONE, // 1_0 is the canonical one. - false, - &CreateInstanceProxy, - }; - return &info; -} - bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { // Prevent the dispatcher from going away during a call to ExecuteScript. // This must happen OUTSIDE of ExecuteScript since the SerializedVars use @@ -139,6 +129,14 @@ bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { OnHostMsgExecuteScript) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDefaultCharSet, OnHostMsgGetDefaultCharSet) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetPluginToHandleFindRequests, + OnHostMsgSetPluginToHandleFindRequests); + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_NumberOfFindResultsChanged, + OnHostMsgNumberOfFindResultsChanged) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SelectFindResultChanged, + OnHostMsgSelectFindResultChanged) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetTickmarks, + OnHostMsgSetTickmarks) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage, OnHostMsgPostMessage) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen, @@ -149,6 +147,8 @@ bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { OnHostMsgRequestInputEvents) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ClearInputEvents, OnHostMsgClearInputEvents) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_StartTrackingLatency, + OnHostMsgStartTrackingLatency) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_LockMouse, OnHostMsgLockMouse) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UnlockMouse, @@ -175,8 +175,12 @@ bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { OnHostMsgGetPluginInstanceURL) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginReferrerURL, OnHostMsgGetPluginReferrerURL) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionCreated, - OnHostMsgSessionCreated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PromiseResolved, + OnHostMsgPromiseResolved) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PromiseResolvedWithSession, + OnHostMsgPromiseResolvedWithSession) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PromiseRejected, + OnHostMsgPromiseRejected) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionMessage, OnHostMsgSessionMessage) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionReady, @@ -230,9 +234,10 @@ PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance, // We need to pass different resource to Graphics 2D and 3D right now. Once // 3D is migrated to the new design, we should be able to unify this. + EnterResourceNoLock<PPB_Compositor_API> enter_compositor(device, false); EnterResourceNoLock<PPB_Graphics2D_API> enter_2d(device, false); EnterResourceNoLock<PPB_Graphics3D_API> enter_3d(device, false); - if (enter_2d.succeeded()) { + if (enter_compositor.succeeded() || enter_2d.succeeded()) { dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics( API_ID_PPB_INSTANCE, instance, pp_resource)); return PP_TRUE; @@ -323,15 +328,30 @@ PP_Var PPB_Instance_Proxy::GetDefaultCharSet(PP_Instance instance) { return result.Return(dispatcher); } +void PPB_Instance_Proxy::SetPluginToHandleFindRequests(PP_Instance instance) { + dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetPluginToHandleFindRequests( + API_ID_PPB_INSTANCE, instance)); +} + void PPB_Instance_Proxy::NumberOfFindResultsChanged(PP_Instance instance, int32_t total, PP_Bool final_result) { - NOTIMPLEMENTED(); // Not proxied yet. + dispatcher()->Send(new PpapiHostMsg_PPBInstance_NumberOfFindResultsChanged( + API_ID_PPB_INSTANCE, instance, total, final_result)); } void PPB_Instance_Proxy::SelectedFindResultChanged(PP_Instance instance, int32_t index) { - NOTIMPLEMENTED(); // Not proxied yet. + dispatcher()->Send(new PpapiHostMsg_PPBInstance_SelectFindResultChanged( + API_ID_PPB_INSTANCE, instance, index)); +} + +void PPB_Instance_Proxy::SetTickmarks(PP_Instance instance, + const PP_Rect* tickmarks, + uint32_t count) { + dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetTickmarks( + API_ID_PPB_INSTANCE, instance, + std::vector<PP_Rect>(tickmarks, tickmarks + count))); } PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) { @@ -375,8 +395,8 @@ Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance, case BROKER_SINGLETON_ID: new_singleton = new BrokerResource(connection, instance); break; - case EXTENSIONS_COMMON_SINGLETON_ID: - new_singleton = new ExtensionsCommonResource(connection, instance); + case FILE_MAPPING_SINGLETON_ID: + new_singleton = new FileMappingResource(connection, instance); break; case GAMEPAD_SINGLETON_ID: new_singleton = new GamepadResource(connection, instance); @@ -391,6 +411,9 @@ Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance, case TRUETYPE_FONT_SINGLETON_ID: new_singleton = new TrueTypeFontSingletonResource(connection, instance); break; + case UMA_SINGLETON_ID: + new_singleton = new UMAPrivateResource(connection, instance); + break; // Flash/trusted resources aren't needed for NaCl. #if !defined(OS_NACL) && !defined(NACL_WIN64) case BROWSER_FONT_SINGLETON_ID: @@ -463,6 +486,11 @@ void PPB_Instance_Proxy::ClearInputEventRequest(PP_Instance instance, API_ID_PPB_INSTANCE, instance, event_classes)); } +void PPB_Instance_Proxy::StartTrackingLatency(PP_Instance instance) { + dispatcher()->Send(new PpapiHostMsg_PPBInstance_StartTrackingLatency( + API_ID_PPB_INSTANCE, instance)); +} + void PPB_Instance_Proxy::ZoomChanged(PP_Instance instance, double factor) { // Not proxied yet. @@ -542,46 +570,76 @@ PP_Var PPB_Instance_Proxy::GetPluginReferrerURL( components); } -void PPB_Instance_Proxy::SessionCreated(PP_Instance instance, - uint32_t session_id, - PP_Var web_session_id) { - dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionCreated( +void PPB_Instance_Proxy::PromiseResolved(PP_Instance instance, + uint32 promise_id) { + dispatcher()->Send(new PpapiHostMsg_PPBInstance_PromiseResolved( + API_ID_PPB_INSTANCE, instance, promise_id)); +} + +void PPB_Instance_Proxy::PromiseResolvedWithSession(PP_Instance instance, + uint32 promise_id, + PP_Var web_session_id_var) { + dispatcher()->Send(new PpapiHostMsg_PPBInstance_PromiseResolvedWithSession( API_ID_PPB_INSTANCE, instance, - session_id, - SerializedVarSendInput(dispatcher(), web_session_id))); + promise_id, + SerializedVarSendInput(dispatcher(), web_session_id_var))); +} + +void PPB_Instance_Proxy::PromiseRejected(PP_Instance instance, + uint32 promise_id, + PP_CdmExceptionCode exception_code, + uint32 system_code, + PP_Var error_description_var) { + dispatcher()->Send(new PpapiHostMsg_PPBInstance_PromiseRejected( + API_ID_PPB_INSTANCE, + instance, + promise_id, + exception_code, + system_code, + SerializedVarSendInput(dispatcher(), error_description_var))); } void PPB_Instance_Proxy::SessionMessage(PP_Instance instance, - uint32_t session_id, - PP_Var message, - PP_Var destination_url) { + PP_Var web_session_id_var, + PP_Var message_var, + PP_Var destination_url_var) { dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionMessage( API_ID_PPB_INSTANCE, instance, - session_id, - SerializedVarSendInput(dispatcher(), message), - SerializedVarSendInput(dispatcher(), destination_url))); + SerializedVarSendInput(dispatcher(), web_session_id_var), + SerializedVarSendInput(dispatcher(), message_var), + SerializedVarSendInput(dispatcher(), destination_url_var))); } void PPB_Instance_Proxy::SessionReady(PP_Instance instance, - uint32_t session_id) { + PP_Var web_session_id_var) { dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionReady( - API_ID_PPB_INSTANCE, instance, session_id)); + API_ID_PPB_INSTANCE, + instance, + SerializedVarSendInput(dispatcher(), web_session_id_var))); } void PPB_Instance_Proxy::SessionClosed(PP_Instance instance, - uint32_t session_id) { + PP_Var web_session_id_var) { dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionClosed( - API_ID_PPB_INSTANCE, instance, session_id)); + API_ID_PPB_INSTANCE, + instance, + SerializedVarSendInput(dispatcher(), web_session_id_var))); } void PPB_Instance_Proxy::SessionError(PP_Instance instance, - uint32_t session_id, - int32_t media_error, - int32_t system_code) { + PP_Var web_session_id_var, + PP_CdmExceptionCode exception_code, + uint32 system_code, + PP_Var error_description_var) { dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionError( - API_ID_PPB_INSTANCE, instance, session_id, media_error, system_code)); + API_ID_PPB_INSTANCE, + instance, + SerializedVarSendInput(dispatcher(), web_session_id_var), + exception_code, + system_code, + SerializedVarSendInput(dispatcher(), error_description_var))); } void PPB_Instance_Proxy::DeliverBlock(PP_Instance instance, @@ -717,6 +775,32 @@ void PPB_Instance_Proxy::PostMessage(PP_Instance instance, instance))); } +int32_t PPB_Instance_Proxy::RegisterMessageHandler( + PP_Instance instance, + void* user_data, + const PPP_MessageHandler_0_1* handler, + PP_Resource message_loop) { + InstanceData* data = + static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance); + if (!data) + return PP_ERROR_BADARGUMENT; + + int32_t result = PP_ERROR_FAILED; + scoped_ptr<MessageHandler> message_handler = MessageHandler::Create( + instance, handler, user_data, message_loop, &result); + if (message_handler) + data->message_handler = message_handler.Pass(); + return result; +} + +void PPB_Instance_Proxy::UnregisterMessageHandler(PP_Instance instance) { + InstanceData* data = + static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance); + if (!data) + return; + data->message_handler.reset(); +} + PP_Bool PPB_Instance_Proxy::SetCursor(PP_Instance instance, PP_MouseCursor_Type type, PP_Resource image, @@ -905,6 +989,52 @@ void PPB_Instance_Proxy::OnHostMsgGetDefaultCharSet( result.Return(dispatcher(), enter.functions()->GetDefaultCharSet(instance)); } +void PPB_Instance_Proxy::OnHostMsgSetPluginToHandleFindRequests( + PP_Instance instance) { + if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) + return; + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) + enter.functions()->SetPluginToHandleFindRequests(instance); +} + +void PPB_Instance_Proxy::OnHostMsgNumberOfFindResultsChanged( + PP_Instance instance, + int32_t total, + PP_Bool final_result) { + if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) + return; + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + enter.functions()->NumberOfFindResultsChanged( + instance, total, final_result); + } +} + +void PPB_Instance_Proxy::OnHostMsgSelectFindResultChanged( + PP_Instance instance, + int32_t index) { + if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) + return; + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) + enter.functions()->SelectedFindResultChanged(instance, index); +} + +void PPB_Instance_Proxy::OnHostMsgSetTickmarks( + PP_Instance instance, + const std::vector<PP_Rect>& tickmarks) { + if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) + return; + const PP_Rect* array = tickmarks.empty() ? NULL : &tickmarks[0]; + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + enter.functions()->SetTickmarks(instance, + array, + static_cast<uint32_t>(tickmarks.size())); + } +} + void PPB_Instance_Proxy::OnHostMsgSetFullscreen(PP_Instance instance, PP_Bool fullscreen, PP_Bool* result) { @@ -941,6 +1071,12 @@ void PPB_Instance_Proxy::OnHostMsgClearInputEvents(PP_Instance instance, enter.functions()->ClearInputEventRequest(instance, event_classes); } +void PPB_Instance_Proxy::OnHostMsgStartTrackingLatency(PP_Instance instance) { + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) + enter.functions()->StartTrackingLatency(instance); +} + void PPB_Instance_Proxy::OnHostMsgPostMessage( PP_Instance instance, SerializedVarReceiveInput message) { @@ -1048,22 +1184,50 @@ void PPB_Instance_Proxy::OnHostMsgGetPluginReferrerURL( } } -void PPB_Instance_Proxy::OnHostMsgSessionCreated( +void PPB_Instance_Proxy::OnHostMsgPromiseResolved(PP_Instance instance, + uint32_t promise_id) { + if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) + return; + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + enter.functions()->PromiseResolved(instance, promise_id); + } +} + +void PPB_Instance_Proxy::OnHostMsgPromiseResolvedWithSession( PP_Instance instance, - uint32_t session_id, + uint32_t promise_id, SerializedVarReceiveInput web_session_id) { if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) { - enter.functions()->SessionCreated( - instance, session_id, web_session_id.Get(dispatcher())); + enter.functions()->PromiseResolvedWithSession( + instance, promise_id, web_session_id.Get(dispatcher())); + } +} + +void PPB_Instance_Proxy::OnHostMsgPromiseRejected( + PP_Instance instance, + uint32_t promise_id, + PP_CdmExceptionCode exception_code, + uint32_t system_code, + SerializedVarReceiveInput error_description) { + if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) + return; + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + enter.functions()->PromiseRejected(instance, + promise_id, + exception_code, + system_code, + error_description.Get(dispatcher())); } } void PPB_Instance_Proxy::OnHostMsgSessionMessage( PP_Instance instance, - uint32_t session_id, + SerializedVarReceiveInput web_session_id, SerializedVarReceiveInput message, SerializedVarReceiveInput destination_url) { if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) @@ -1071,42 +1235,50 @@ void PPB_Instance_Proxy::OnHostMsgSessionMessage( EnterInstanceNoLock enter(instance); if (enter.succeeded()) { enter.functions()->SessionMessage(instance, - session_id, + web_session_id.Get(dispatcher()), message.Get(dispatcher()), destination_url.Get(dispatcher())); } } -void PPB_Instance_Proxy::OnHostMsgSessionReady(PP_Instance instance, - uint32_t session_id) { +void PPB_Instance_Proxy::OnHostMsgSessionReady( + PP_Instance instance, + SerializedVarReceiveInput web_session_id) { if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) { - enter.functions()->SessionReady(instance, session_id); + enter.functions()->SessionReady(instance, web_session_id.Get(dispatcher())); } } -void PPB_Instance_Proxy::OnHostMsgSessionClosed(PP_Instance instance, - uint32_t session_id) { +void PPB_Instance_Proxy::OnHostMsgSessionClosed( + PP_Instance instance, + SerializedVarReceiveInput web_session_id) { if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) { - enter.functions()->SessionClosed(instance, session_id); + enter.functions()->SessionClosed(instance, + web_session_id.Get(dispatcher())); } } -void PPB_Instance_Proxy::OnHostMsgSessionError(PP_Instance instance, - uint32_t session_id, - int32_t media_error, - int32_t system_error) { +void PPB_Instance_Proxy::OnHostMsgSessionError( + PP_Instance instance, + SerializedVarReceiveInput web_session_id, + PP_CdmExceptionCode exception_code, + uint32_t system_code, + SerializedVarReceiveInput error_description) { if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE)) return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) { - enter.functions()->SessionError( - instance, session_id, media_error, system_error); + enter.functions()->SessionError(instance, + web_session_id.Get(dispatcher()), + exception_code, + system_code, + error_description.Get(dispatcher())); } } @@ -1211,8 +1383,6 @@ void PPB_Instance_Proxy::OnHostMsgSetCursor( void PPB_Instance_Proxy::OnHostMsgSetTextInputType(PP_Instance instance, PP_TextInput_Type type) { - if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV)) - return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) enter.functions()->SetTextInputType(instance, type); @@ -1222,8 +1392,6 @@ void PPB_Instance_Proxy::OnHostMsgUpdateCaretPosition( PP_Instance instance, const PP_Rect& caret, const PP_Rect& bounding_box) { - if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV)) - return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) enter.functions()->UpdateCaretPosition(instance, caret, bounding_box); @@ -1231,8 +1399,6 @@ void PPB_Instance_Proxy::OnHostMsgUpdateCaretPosition( void PPB_Instance_Proxy::OnHostMsgCancelCompositionText(PP_Instance instance) { EnterInstanceNoLock enter(instance); - if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV)) - return; if (enter.succeeded()) enter.functions()->CancelCompositionText(instance); } @@ -1242,8 +1408,6 @@ void PPB_Instance_Proxy::OnHostMsgUpdateSurroundingText( const std::string& text, uint32_t caret, uint32_t anchor) { - if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV)) - return; EnterInstanceNoLock enter(instance); if (enter.succeeded()) { enter.functions()->UpdateSurroundingText(instance, text.c_str(), caret, diff --git a/chromium/ppapi/proxy/ppb_instance_proxy.h b/chromium/ppapi/proxy/ppb_instance_proxy.h index 12e56b938e5..24086741d54 100644 --- a/chromium/ppapi/proxy/ppb_instance_proxy.h +++ b/chromium/ppapi/proxy/ppb_instance_proxy.h @@ -39,8 +39,6 @@ class PPB_Instance_Proxy : public InterfaceProxy, PPB_Instance_Proxy(Dispatcher* dispatcher); virtual ~PPB_Instance_Proxy(); - static const Info* GetInfoPrivate(); - // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg); @@ -60,11 +58,15 @@ class PPB_Instance_Proxy : public InterfaceProxy, virtual uint32_t GetAudioHardwareOutputBufferSize(PP_Instance instance) OVERRIDE; virtual PP_Var GetDefaultCharSet(PP_Instance instance) OVERRIDE; + virtual void SetPluginToHandleFindRequests(PP_Instance instance) OVERRIDE; virtual void NumberOfFindResultsChanged(PP_Instance instance, int32_t total, PP_Bool final_result) OVERRIDE; virtual void SelectedFindResultChanged(PP_Instance instance, int32_t index) OVERRIDE; + virtual void SetTickmarks(PP_Instance instance, + const PP_Rect* tickmarks, + uint32_t count) OVERRIDE; virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE; virtual PP_Bool SetFullscreen(PP_Instance instance, PP_Bool fullscreen) OVERRIDE; @@ -76,6 +78,7 @@ class PPB_Instance_Proxy : public InterfaceProxy, uint32_t event_classes) OVERRIDE; virtual int32_t RequestFilteringInputEvents(PP_Instance instance, uint32_t event_classes) OVERRIDE; + virtual void StartTrackingLatency(PP_Instance instance) OVERRIDE; virtual void ClearInputEventRequest(PP_Instance instance, uint32_t event_classes) OVERRIDE; virtual void ZoomChanged(PP_Instance instance, double factor) OVERRIDE; @@ -83,6 +86,11 @@ class PPB_Instance_Proxy : public InterfaceProxy, double minimum_factor, double maximium_factor) OVERRIDE; virtual void PostMessage(PP_Instance instance, PP_Var message) OVERRIDE; + virtual int32_t RegisterMessageHandler(PP_Instance instance, + void* user_data, + const PPP_MessageHandler_0_1* handler, + PP_Resource message_loop) OVERRIDE; + virtual void UnregisterMessageHandler(PP_Instance instance) OVERRIDE; virtual PP_Bool SetCursor(PP_Instance instance, PP_MouseCursor_Type type, PP_Resource image, @@ -117,20 +125,29 @@ class PPB_Instance_Proxy : public InterfaceProxy, virtual PP_Var GetPluginReferrerURL( PP_Instance instance, PP_URLComponents_Dev* components) OVERRIDE; - virtual void SessionCreated(PP_Instance instance, - uint32_t session_id, - PP_Var web_session_id) OVERRIDE; + virtual void PromiseResolved(PP_Instance instance, + uint32 promise_id) OVERRIDE; + virtual void PromiseResolvedWithSession(PP_Instance instance, + uint32 promise_id, + PP_Var web_session_id_var) OVERRIDE; + virtual void PromiseRejected(PP_Instance instance, + uint32 promise_id, + PP_CdmExceptionCode exception_code, + uint32 system_code, + PP_Var error_description_var) OVERRIDE; virtual void SessionMessage(PP_Instance instance, - uint32_t session_id, - PP_Var message, - PP_Var destination_url) OVERRIDE; - virtual void SessionReady(PP_Instance instance, uint32_t session_id) OVERRIDE; + PP_Var web_session_id_var, + PP_Var message_var, + PP_Var destination_url_var) OVERRIDE; + virtual void SessionReady(PP_Instance instance, + PP_Var web_session_id_var) OVERRIDE; virtual void SessionClosed(PP_Instance instance, - uint32_t session_id) OVERRIDE; + PP_Var web_session_id_var) OVERRIDE; virtual void SessionError(PP_Instance instance, - uint32_t session_id, - int32_t media_error, - int32_t system_code) OVERRIDE; + PP_Var web_session_id_var, + PP_CdmExceptionCode exception_code, + uint32 system_code, + PP_Var error_description_var) OVERRIDE; virtual void DeliverBlock(PP_Instance instance, PP_Resource decrypted_block, const PP_DecryptedBlockInfo* block_info) OVERRIDE; @@ -174,6 +191,14 @@ class PPB_Instance_Proxy : public InterfaceProxy, uint32_t *result); void OnHostMsgGetDefaultCharSet(PP_Instance instance, SerializedVarReturnValue result); + void OnHostMsgSetPluginToHandleFindRequests(PP_Instance instance); + void OnHostMsgNumberOfFindResultsChanged(PP_Instance instance, + int32_t total, + PP_Bool final_result); + void OnHostMsgSelectFindResultChanged(PP_Instance instance, + int32_t index); + void OnHostMsgSetTickmarks(PP_Instance instance, + const std::vector<PP_Rect>& tickmarks); void OnHostMsgSetFullscreen(PP_Instance instance, PP_Bool fullscreen, PP_Bool* result); @@ -183,6 +208,7 @@ class PPB_Instance_Proxy : public InterfaceProxy, void OnHostMsgRequestInputEvents(PP_Instance instance, bool is_filtering, uint32_t event_classes); + void OnHostMsgStartTrackingLatency(PP_Instance instance); void OnHostMsgClearInputEvents(PP_Instance instance, uint32_t event_classes); void OnHostMsgPostMessage(PP_Instance instance, @@ -221,22 +247,34 @@ class PPB_Instance_Proxy : public InterfaceProxy, SerializedVarReturnValue result); void OnHostMsgGetPluginReferrerURL(PP_Instance instance, SerializedVarReturnValue result); - virtual void OnHostMsgSessionCreated( + + virtual void OnHostMsgPromiseResolved(PP_Instance instance, + uint32_t promise_id); + virtual void OnHostMsgPromiseResolvedWithSession( PP_Instance instance, - uint32_t session_id, + uint32_t promise_id, SerializedVarReceiveInput web_session_id); + virtual void OnHostMsgPromiseRejected( + PP_Instance instance, + uint32_t promise_id, + PP_CdmExceptionCode exception_code, + uint32_t system_code, + SerializedVarReceiveInput error_description); virtual void OnHostMsgSessionMessage( PP_Instance instance, - uint32_t session_id, + SerializedVarReceiveInput web_session_id, SerializedVarReceiveInput message, SerializedVarReceiveInput destination_url); - virtual void OnHostMsgSessionReady(PP_Instance instance, uint32_t session_id); + virtual void OnHostMsgSessionReady(PP_Instance instance, + SerializedVarReceiveInput web_session_id); virtual void OnHostMsgSessionClosed(PP_Instance instance, - uint32_t session_id); - virtual void OnHostMsgSessionError(PP_Instance instance, - uint32_t session_id, - int32_t media_error, - int32_t system_code); + SerializedVarReceiveInput web_session_id); + virtual void OnHostMsgSessionError( + PP_Instance instance, + SerializedVarReceiveInput web_session_id, + PP_CdmExceptionCode exception_code, + uint32_t system_code, + SerializedVarReceiveInput error_description); virtual void OnHostMsgDecoderInitializeDone( PP_Instance instance, PP_DecryptorStreamType decoder_type, diff --git a/chromium/ppapi/proxy/ppb_message_loop_proxy.cc b/chromium/ppapi/proxy/ppb_message_loop_proxy.cc index 582ddcbeb73..2bc9694ab5d 100644 --- a/chromium/ppapi/proxy/ppb_message_loop_proxy.cc +++ b/chromium/ppapi/proxy/ppb_message_loop_proxy.cc @@ -86,7 +86,7 @@ int32_t MessageLoopResource::AttachToCurrentThread() { AddRef(); slot->Set(this); - loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT)); + loop_.reset(new base::MessageLoop); loop_proxy_ = base::MessageLoopProxy::current(); // Post all pending work to the message loop. diff --git a/chromium/ppapi/proxy/ppb_message_loop_proxy.h b/chromium/ppapi/proxy/ppb_message_loop_proxy.h index d8bfc4c644d..f6cc25227bc 100644 --- a/chromium/ppapi/proxy/ppb_message_loop_proxy.h +++ b/chromium/ppapi/proxy/ppb_message_loop_proxy.h @@ -44,6 +44,10 @@ class PPAPI_PROXY_EXPORT MessageLoopResource : public MessageLoopShared { return is_main_thread_loop_; } + const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy() { + return loop_proxy_; + } + private: struct TaskInfo { tracked_objects::Location from_here; diff --git a/chromium/ppapi/proxy/ppb_var_unittest.cc b/chromium/ppapi/proxy/ppb_var_unittest.cc index 7315d00b72a..5e25379eeb0 100644 --- a/chromium/ppapi/proxy/ppb_var_unittest.cc +++ b/chromium/ppapi/proxy/ppb_var_unittest.cc @@ -30,7 +30,7 @@ class PPB_VarTest : public PluginProxyTest { public: PPB_VarTest() : test_strings_(kNumStrings), vars_(kNumStrings), - ppb_var_(ppapi::PPB_Var_Shared::GetVarInterface1_1()) { + ppb_var_(ppapi::PPB_Var_Shared::GetVarInterface1_2()) { // Set the value of test_strings_[i] to "i". for (size_t i = 0; i < kNumStrings; ++i) test_strings_[i] = base::IntToString(i); @@ -102,7 +102,7 @@ class CreateVarThreadDelegate : public base::PlatformThread::Delegate { } virtual ~CreateVarThreadDelegate() {} virtual void ThreadMain() { - const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1(); + const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_2(); for (size_t i = 0; i < size_; ++i) { vars_out_[i] = ppb_var->VarFromUtf8(strings_in_[i].c_str(), strings_in_[i].length()); @@ -125,7 +125,7 @@ class ChangeRefVarThreadDelegate : public base::PlatformThread::Delegate { } virtual ~ChangeRefVarThreadDelegate() {} virtual void ThreadMain() { - const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1(); + const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_2(); // Increment and decrement the reference count for each var kRefsToAdd // times. Note that we always AddRef once before doing the matching Release, // to ensure that we never accidentally release the last reference. @@ -153,7 +153,7 @@ class RemoveRefVarThreadDelegate : public base::PlatformThread::Delegate { } virtual ~RemoveRefVarThreadDelegate() {} virtual void ThreadMain() { - const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1(); + const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_2(); for (size_t i = 0; i < kNumStrings; ++i) { ppb_var->Release(vars_[i]); } diff --git a/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc b/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc index 2a00674f416..4eae1f22654 100644 --- a/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc +++ b/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc @@ -18,7 +18,7 @@ using ppapi::thunk::EnterResourceNoLock; using ppapi::thunk::PPB_Buffer_API; using ppapi::thunk::PPB_Graphics3D_API; -using ppapi::thunk::PPB_VideoDecoder_API; +using ppapi::thunk::PPB_VideoDecoder_Dev_API; namespace ppapi { namespace proxy { @@ -33,7 +33,7 @@ class VideoDecoder : public PPB_VideoDecoder_Shared { PP_Resource graphics_context, PP_VideoDecoder_Profile profile); - // PPB_VideoDecoder_API implementation. + // PPB_VideoDecoder_Dev_API implementation. virtual int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual void AssignPictureBuffers( @@ -192,6 +192,9 @@ PP_Resource PPB_VideoDecoder_Proxy::CreateProxyResource( if (!dispatcher) return 0; + if (!dispatcher->preferences().is_accelerated_video_decode_enabled) + return 0; + EnterResourceNoLock<PPB_Graphics3D_API> enter_context(graphics_context, true); if (enter_context.failed()) @@ -222,14 +225,14 @@ void PPB_VideoDecoder_Proxy::OnMsgCreate( // Make the resource and get the API pointer to its interface. result->SetHostResource( - instance, resource_creation.functions()->CreateVideoDecoder( + instance, resource_creation.functions()->CreateVideoDecoderDev( instance, graphics_context.host_resource(), profile)); } void PPB_VideoDecoder_Proxy::OnMsgDecode( const HostResource& decoder, const HostResource& buffer, int32 id, uint32 size) { - EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_API> enter( + EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter( decoder, callback_factory_, &PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin, decoder, id); if (enter.failed()) @@ -241,7 +244,7 @@ void PPB_VideoDecoder_Proxy::OnMsgDecode( void PPB_VideoDecoder_Proxy::OnMsgAssignPictureBuffers( const HostResource& decoder, const std::vector<PP_PictureBuffer_Dev>& buffers) { - EnterHostFromHostResource<PPB_VideoDecoder_API> enter(decoder); + EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); if (enter.succeeded() && !buffers.empty()) { const PP_PictureBuffer_Dev* buffer_array = &buffers.front(); enter.object()->AssignPictureBuffers(buffers.size(), buffer_array); @@ -250,13 +253,13 @@ void PPB_VideoDecoder_Proxy::OnMsgAssignPictureBuffers( void PPB_VideoDecoder_Proxy::OnMsgReusePictureBuffer( const HostResource& decoder, int32 picture_buffer_id) { - EnterHostFromHostResource<PPB_VideoDecoder_API> enter(decoder); + EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); if (enter.succeeded()) enter.object()->ReusePictureBuffer(picture_buffer_id); } void PPB_VideoDecoder_Proxy::OnMsgFlush(const HostResource& decoder) { - EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_API> enter( + EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter( decoder, callback_factory_, &PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin, decoder); if (enter.succeeded()) @@ -264,7 +267,7 @@ void PPB_VideoDecoder_Proxy::OnMsgFlush(const HostResource& decoder) { } void PPB_VideoDecoder_Proxy::OnMsgReset(const HostResource& decoder) { - EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_API> enter( + EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_Dev_API> enter( decoder, callback_factory_, &PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin, decoder); if (enter.succeeded()) @@ -272,7 +275,7 @@ void PPB_VideoDecoder_Proxy::OnMsgReset(const HostResource& decoder) { } void PPB_VideoDecoder_Proxy::OnMsgDestroy(const HostResource& decoder) { - EnterHostFromHostResource<PPB_VideoDecoder_API> enter(decoder); + EnterHostFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); if (enter.succeeded()) enter.object()->Destroy(); } @@ -297,21 +300,21 @@ void PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin( void PPB_VideoDecoder_Proxy::OnMsgEndOfBitstreamACK( const HostResource& decoder, int32_t id, int32_t result) { - EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder); + EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); if (enter.succeeded()) static_cast<VideoDecoder*>(enter.object())->EndOfBitstreamACK(id, result); } void PPB_VideoDecoder_Proxy::OnMsgFlushACK( const HostResource& decoder, int32_t result) { - EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder); + EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); if (enter.succeeded()) static_cast<VideoDecoder*>(enter.object())->FlushACK(result); } void PPB_VideoDecoder_Proxy::OnMsgResetACK( const HostResource& decoder, int32_t result) { - EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder); + EnterPluginFromHostResource<PPB_VideoDecoder_Dev_API> enter(decoder); if (enter.succeeded()) static_cast<VideoDecoder*>(enter.object())->ResetACK(result); } diff --git a/chromium/ppapi/proxy/ppb_video_decoder_proxy.h b/chromium/ppapi/proxy/ppb_video_decoder_proxy.h index e9127a7e63a..dbc030e47cc 100644 --- a/chromium/ppapi/proxy/ppb_video_decoder_proxy.h +++ b/chromium/ppapi/proxy/ppb_video_decoder_proxy.h @@ -9,7 +9,7 @@ #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/ppb_video_decoder_shared.h" -#include "ppapi/thunk/ppb_video_decoder_api.h" +#include "ppapi/thunk/ppb_video_decoder_dev_api.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc index 167e4764d38..eee3871b509 100644 --- a/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc +++ b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc @@ -4,7 +4,7 @@ #include "ppapi/proxy/ppp_content_decryptor_private_proxy.h" -#include "base/platform_file.h" +#include "base/files/file.h" #include "ppapi/c/pp_bool.h" #include "ppapi/c/ppb_core.h" #include "ppapi/proxy/content_decryptor_private_serializer.h" @@ -125,9 +125,10 @@ void Initialize(PP_Instance instance, } void CreateSession(PP_Instance instance, - uint32_t session_id, - PP_Var type, - PP_Var init_data) { + uint32_t promise_id, + PP_Var init_data_type, + PP_Var init_data, + PP_SessionType session_type) { HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); if (!dispatcher) { NOTREACHED(); @@ -137,12 +138,32 @@ void CreateSession(PP_Instance instance, dispatcher->Send(new PpapiMsg_PPPContentDecryptor_CreateSession( API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, instance, - session_id, - SerializedVarSendInput(dispatcher, type), - SerializedVarSendInput(dispatcher, init_data))); + promise_id, + SerializedVarSendInput(dispatcher, init_data_type), + SerializedVarSendInput(dispatcher, init_data), + session_type)); } -void UpdateSession(PP_Instance instance, uint32_t session_id, PP_Var response) { +void LoadSession(PP_Instance instance, + uint32_t promise_id, + PP_Var web_session_id) { + HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); + if (!dispatcher) { + NOTREACHED(); + return; + } + + dispatcher->Send(new PpapiMsg_PPPContentDecryptor_LoadSession( + API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, + instance, + promise_id, + SerializedVarSendInput(dispatcher, web_session_id))); +} + +void UpdateSession(PP_Instance instance, + uint32_t promise_id, + PP_Var web_session_id, + PP_Var response) { HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); if (!dispatcher) { NOTREACHED(); @@ -152,11 +173,14 @@ void UpdateSession(PP_Instance instance, uint32_t session_id, PP_Var response) { dispatcher->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession( API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, instance, - session_id, + promise_id, + SerializedVarSendInput(dispatcher, web_session_id), SerializedVarSendInput(dispatcher, response))); } -void ReleaseSession(PP_Instance instance, uint32_t session_id) { +void ReleaseSession(PP_Instance instance, + uint32_t promise_id, + PP_Var web_session_id) { HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); if (!dispatcher) { NOTREACHED(); @@ -164,7 +188,10 @@ void ReleaseSession(PP_Instance instance, uint32_t session_id) { } dispatcher->Send(new PpapiMsg_PPPContentDecryptor_ReleaseSession( - API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, instance, session_id)); + API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE, + instance, + promise_id, + SerializedVarSendInput(dispatcher, web_session_id))); } void Decrypt(PP_Instance instance, @@ -357,6 +384,7 @@ void DecryptAndDecode(PP_Instance instance, static const PPP_ContentDecryptor_Private content_decryptor_interface = { &Initialize, &CreateSession, + &LoadSession, &UpdateSession, &ReleaseSession, &Decrypt, @@ -401,6 +429,8 @@ bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived( OnMsgInitialize) IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CreateSession, OnMsgCreateSession) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession, + OnMsgLoadSession) IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession, OnMsgUpdateSession) IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ReleaseSession, @@ -436,37 +466,59 @@ void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize( void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSession( PP_Instance instance, - uint32_t session_id, - SerializedVarReceiveInput type, - SerializedVarReceiveInput init_data) { + uint32_t promise_id, + SerializedVarReceiveInput init_data_type, + SerializedVarReceiveInput init_data, + PP_SessionType session_type) { if (ppp_decryptor_impl_) { - CallWhileUnlocked(ppp_decryptor_impl_->CreateSession, - instance, - session_id, - ExtractReceivedVarAndAddRef(dispatcher(), &type), - ExtractReceivedVarAndAddRef(dispatcher(), &init_data)); + CallWhileUnlocked( + ppp_decryptor_impl_->CreateSession, + instance, + promise_id, + ExtractReceivedVarAndAddRef(dispatcher(), &init_data_type), + ExtractReceivedVarAndAddRef(dispatcher(), &init_data), + session_type); + } +} + +void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession( + PP_Instance instance, + uint32_t promise_id, + SerializedVarReceiveInput web_session_id) { + if (ppp_decryptor_impl_) { + CallWhileUnlocked( + ppp_decryptor_impl_->LoadSession, + instance, + promise_id, + ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id)); } } void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession( PP_Instance instance, - uint32_t session_id, + uint32_t promise_id, + SerializedVarReceiveInput web_session_id, SerializedVarReceiveInput response) { if (ppp_decryptor_impl_) { - CallWhileUnlocked(ppp_decryptor_impl_->UpdateSession, - instance, - session_id, - ExtractReceivedVarAndAddRef(dispatcher(), &response)); + CallWhileUnlocked( + ppp_decryptor_impl_->UpdateSession, + instance, + promise_id, + ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id), + ExtractReceivedVarAndAddRef(dispatcher(), &response)); } } void PPP_ContentDecryptor_Private_Proxy::OnMsgReleaseSession( PP_Instance instance, - uint32_t session_id) { + uint32_t promise_id, + SerializedVarReceiveInput web_session_id) { if (ppp_decryptor_impl_) { - CallWhileUnlocked(ppp_decryptor_impl_->ReleaseSession, - instance, - session_id); + CallWhileUnlocked( + ppp_decryptor_impl_->ReleaseSession, + instance, + promise_id, + ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id)); } } diff --git a/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h index dfbcf4f5d42..f7c78baa6db 100644 --- a/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h +++ b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h @@ -33,13 +33,20 @@ class PPP_ContentDecryptor_Private_Proxy : public InterfaceProxy { void OnMsgInitialize(PP_Instance instance, SerializedVarReceiveInput key_system); void OnMsgCreateSession(PP_Instance instance, - uint32_t session_id, - SerializedVarReceiveInput type, - SerializedVarReceiveInput init_data); + uint32_t promise_id, + SerializedVarReceiveInput init_data_type, + SerializedVarReceiveInput init_data, + PP_SessionType session_type); + void OnMsgLoadSession(PP_Instance instance, + uint32_t promise_id, + SerializedVarReceiveInput web_session_id); void OnMsgUpdateSession(PP_Instance instance, - uint32_t session_id, + uint32_t promise_id, + SerializedVarReceiveInput web_session_id, SerializedVarReceiveInput response); - void OnMsgReleaseSession(PP_Instance instance, uint32_t session_id); + void OnMsgReleaseSession(PP_Instance instance, + uint32_t promise_id, + SerializedVarReceiveInput web_session_id); void OnMsgDecrypt(PP_Instance instance, const PPPDecryptor_Buffer& encrypted_buffer, const std::string& serialized_encrypted_block_info); diff --git a/chromium/ppapi/proxy/ppp_find_proxy.cc b/chromium/ppapi/proxy/ppp_find_proxy.cc new file mode 100644 index 00000000000..abd5663ba7e --- /dev/null +++ b/chromium/ppapi/proxy/ppp_find_proxy.cc @@ -0,0 +1,103 @@ +// 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. + +#include "ppapi/proxy/ppp_find_proxy.h" + +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/api_id.h" +#include "ppapi/shared_impl/proxy_lock.h" + +namespace ppapi { +namespace proxy { + +namespace { + +#if !defined(OS_NACL) +PP_Bool StartFind(PP_Instance instance, + const char* text, + PP_Bool case_sensitive) { + DCHECK(case_sensitive == PP_FALSE); + HostDispatcher::GetForInstance(instance)->Send( + new PpapiPluginMsg_PPPFind_StartFind(API_ID_PPP_FIND_PRIVATE, + instance, + text)); + return PP_TRUE; +} + +void SelectFindResult(PP_Instance instance, + PP_Bool forward) { + HostDispatcher::GetForInstance(instance)->Send( + new PpapiPluginMsg_PPPFind_SelectFindResult(API_ID_PPP_FIND_PRIVATE, + instance, forward)); +} + +void StopFind(PP_Instance instance) { + HostDispatcher::GetForInstance(instance)->Send( + new PpapiPluginMsg_PPPFind_StopFind(API_ID_PPP_FIND_PRIVATE, instance)); +} + +const PPP_Find_Private ppp_find_interface = { + &StartFind, + &SelectFindResult, + &StopFind +}; +#else +// The NaCl plugin doesn't need the host side interface - stub it out. +const PPP_Find_Private ppp_find_interface = {}; +#endif + +} // namespace + +PPP_Find_Proxy::PPP_Find_Proxy(Dispatcher* dispatcher) + : InterfaceProxy(dispatcher), + ppp_find_(NULL) { + if (dispatcher->IsPlugin()) { + ppp_find_ = static_cast<const PPP_Find_Private*>( + dispatcher->local_get_interface()(PPP_FIND_PRIVATE_INTERFACE)); + } +} + +PPP_Find_Proxy::~PPP_Find_Proxy() { +} + +// static +const PPP_Find_Private* PPP_Find_Proxy::GetProxyInterface() { + return &ppp_find_interface; +} + +bool PPP_Find_Proxy::OnMessageReceived(const IPC::Message& msg) { + if (!dispatcher()->IsPlugin()) + return false; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPP_Find_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiPluginMsg_PPPFind_StartFind, OnPluginMsgStartFind) + IPC_MESSAGE_HANDLER(PpapiPluginMsg_PPPFind_SelectFindResult, + OnPluginMsgSelectFindResult) + IPC_MESSAGE_HANDLER(PpapiPluginMsg_PPPFind_StopFind, OnPluginMsgStopFind) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void PPP_Find_Proxy::OnPluginMsgStartFind(PP_Instance instance, + const std::string& text) { + if (ppp_find_) + CallWhileUnlocked(ppp_find_->StartFind, instance, text.c_str(), PP_FALSE); +} + +void PPP_Find_Proxy::OnPluginMsgSelectFindResult(PP_Instance instance, + PP_Bool forward) { + if (ppp_find_) + CallWhileUnlocked(ppp_find_->SelectFindResult, instance, forward); +} + +void PPP_Find_Proxy::OnPluginMsgStopFind(PP_Instance instance) { + if (ppp_find_) + CallWhileUnlocked(ppp_find_->StopFind, instance); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/ppp_find_proxy.h b/chromium/ppapi/proxy/ppp_find_proxy.h new file mode 100644 index 00000000000..6d2230424d8 --- /dev/null +++ b/chromium/ppapi/proxy/ppp_find_proxy.h @@ -0,0 +1,46 @@ +// 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 PPAPI_PROXY_PPP_FIND_PROXY_H_ +#define PPAPI_PROXY_PPP_FIND_PROXY_H_ + +#include <string> + +#include "ppapi/c/private/ppp_find_private.h" +#include "ppapi/proxy/interface_proxy.h" + +namespace ppapi { + +namespace proxy { + +class PPP_Find_Proxy : public InterfaceProxy { + public: + explicit PPP_Find_Proxy(Dispatcher* dispatcher); + virtual ~PPP_Find_Proxy(); + + static const PPP_Find_Private* GetProxyInterface(); + + // InterfaceProxy implementation. + virtual bool OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnPluginMsgStartFind(PP_Instance instance, + const std::string& text); + void OnPluginMsgSelectFindResult(PP_Instance instance, + PP_Bool forward); + void OnPluginMsgStopFind(PP_Instance instance); + + // When this proxy is in the plugin side, this value caches the interface + // pointer so we don't have to retrieve it from the dispatcher each time. + // In the host, this value is always NULL. + const PPP_Find_Private* ppp_find_; + + DISALLOW_COPY_AND_ASSIGN(PPP_Find_Proxy); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_PPP_FIND_PROXY_H_ diff --git a/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc index ee00a925ed0..b5f0ac1df85 100644 --- a/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc +++ b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc @@ -29,10 +29,6 @@ static const PPP_Graphics3D graphics_3d_interface = { static const PPP_Graphics3D graphics_3d_interface = {}; #endif // !defined(OS_NACL) -InterfaceProxy* CreateGraphics3DProxy(Dispatcher* dispatcher) { - return new PPP_Graphics3D_Proxy(dispatcher); -} - } // namespace PPP_Graphics3D_Proxy::PPP_Graphics3D_Proxy(Dispatcher* dispatcher) @@ -48,15 +44,8 @@ PPP_Graphics3D_Proxy::~PPP_Graphics3D_Proxy() { } // static -const InterfaceProxy::Info* PPP_Graphics3D_Proxy::GetInfo() { - static const Info info = { - &graphics_3d_interface, - PPP_GRAPHICS_3D_INTERFACE, - API_ID_PPP_GRAPHICS_3D, - false, - &CreateGraphics3DProxy, - }; - return &info; +const PPP_Graphics3D* PPP_Graphics3D_Proxy::GetProxyInterface() { + return &graphics_3d_interface; } bool PPP_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) { diff --git a/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h index 9b4d7a0fe67..a6f7eb63b1e 100644 --- a/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h +++ b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h @@ -18,7 +18,7 @@ class PPP_Graphics3D_Proxy : public InterfaceProxy { PPP_Graphics3D_Proxy(Dispatcher* dispatcher); virtual ~PPP_Graphics3D_Proxy(); - static const Info* GetInfo(); + static const PPP_Graphics3D* GetProxyInterface(); // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg); diff --git a/chromium/ppapi/proxy/ppp_input_event_proxy.cc b/chromium/ppapi/proxy/ppp_input_event_proxy.cc index 8302dfd12db..cbf6a63ad2a 100644 --- a/chromium/ppapi/proxy/ppp_input_event_proxy.cc +++ b/chromium/ppapi/proxy/ppp_input_event_proxy.cc @@ -54,10 +54,6 @@ static const PPP_InputEvent input_event_interface = { static const PPP_InputEvent input_event_interface = {}; #endif // !defined(OS_NACL) -InterfaceProxy* CreateInputEventProxy(Dispatcher* dispatcher) { - return new PPP_InputEvent_Proxy(dispatcher); -} - } // namespace PPP_InputEvent_Proxy::PPP_InputEvent_Proxy(Dispatcher* dispatcher) @@ -73,15 +69,8 @@ PPP_InputEvent_Proxy::~PPP_InputEvent_Proxy() { } // static -const InterfaceProxy::Info* PPP_InputEvent_Proxy::GetInfo() { - static const Info info = { - &input_event_interface, - PPP_INPUT_EVENT_INTERFACE, - API_ID_PPP_INPUT_EVENT, - false, - &CreateInputEventProxy, - }; - return &info; +const PPP_InputEvent* PPP_InputEvent_Proxy::GetProxyInterface() { + return &input_event_interface; } bool PPP_InputEvent_Proxy::OnMessageReceived(const IPC::Message& msg) { diff --git a/chromium/ppapi/proxy/ppp_input_event_proxy.h b/chromium/ppapi/proxy/ppp_input_event_proxy.h index a7cc05455c9..9fbc418b687 100644 --- a/chromium/ppapi/proxy/ppp_input_event_proxy.h +++ b/chromium/ppapi/proxy/ppp_input_event_proxy.h @@ -20,7 +20,7 @@ class PPP_InputEvent_Proxy : public InterfaceProxy { PPP_InputEvent_Proxy(Dispatcher* dispatcher); virtual ~PPP_InputEvent_Proxy(); - static const Info* GetInfo(); + static const PPP_InputEvent* GetProxyInterface(); // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg); diff --git a/chromium/ppapi/proxy/ppp_instance_private_proxy.cc b/chromium/ppapi/proxy/ppp_instance_private_proxy.cc index 1d8b8d753ca..8df9c4f28f1 100644 --- a/chromium/ppapi/proxy/ppp_instance_private_proxy.cc +++ b/chromium/ppapi/proxy/ppp_instance_private_proxy.cc @@ -34,10 +34,6 @@ static const PPP_Instance_Private instance_private_interface = { &GetInstanceObject }; -InterfaceProxy* CreateInstancePrivateProxy(Dispatcher* dispatcher) { - return new PPP_Instance_Private_Proxy(dispatcher); -} - } // namespace PPP_Instance_Private_Proxy::PPP_Instance_Private_Proxy(Dispatcher* dispatcher) @@ -53,15 +49,8 @@ PPP_Instance_Private_Proxy::~PPP_Instance_Private_Proxy() { } // static -const InterfaceProxy::Info* PPP_Instance_Private_Proxy::GetInfo() { - static const Info info = { - &instance_private_interface, - PPP_INSTANCE_PRIVATE_INTERFACE, - API_ID_PPP_INSTANCE_PRIVATE, - false, - &CreateInstancePrivateProxy, - }; - return &info; +const PPP_Instance_Private* PPP_Instance_Private_Proxy::GetProxyInterface() { + return &instance_private_interface; } bool PPP_Instance_Private_Proxy::OnMessageReceived(const IPC::Message& msg) { diff --git a/chromium/ppapi/proxy/ppp_instance_private_proxy.h b/chromium/ppapi/proxy/ppp_instance_private_proxy.h index 60d5ea9f1f3..4fc3a3a068a 100644 --- a/chromium/ppapi/proxy/ppp_instance_private_proxy.h +++ b/chromium/ppapi/proxy/ppp_instance_private_proxy.h @@ -22,7 +22,7 @@ class PPP_Instance_Private_Proxy : public InterfaceProxy { PPP_Instance_Private_Proxy(Dispatcher* dispatcher); virtual ~PPP_Instance_Private_Proxy(); - static const Info* GetInfo(); + static const PPP_Instance_Private* GetProxyInterface(); private: // InterfaceProxy implementation. diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy.cc b/chromium/ppapi/proxy/ppp_messaging_proxy.cc index 5a12419f78a..75614ae08b2 100644 --- a/chromium/ppapi/proxy/ppp_messaging_proxy.cc +++ b/chromium/ppapi/proxy/ppp_messaging_proxy.cc @@ -8,12 +8,15 @@ #include "ppapi/c/ppp_messaging.h" #include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/message_handler.h" +#include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/plugin_var_tracker.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_var.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/shared_impl/scoped_pp_var.h" #include "ppapi/shared_impl/var_tracker.h" namespace ppapi { @@ -21,32 +24,33 @@ namespace proxy { namespace { -#if !defined(OS_NACL) -void HandleMessage(PP_Instance instance, PP_Var message_data) { - HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); - if (!dispatcher || (message_data.type == PP_VARTYPE_OBJECT)) { - // The dispatcher should always be valid, and the browser should never send - // an 'object' var over PPP_Messaging. +MessageHandler* GetMessageHandler(Dispatcher* dispatcher, + PP_Instance instance) { + if (!dispatcher || !dispatcher->IsPlugin()) { NOTREACHED(); - return; + return NULL; } + PluginDispatcher* plugin_dispatcher = + static_cast<PluginDispatcher*>(dispatcher); + InstanceData* instance_data = plugin_dispatcher->GetInstanceData(instance); + if (!instance_data) + return NULL; - dispatcher->Send(new PpapiMsg_PPPMessaging_HandleMessage( - API_ID_PPP_MESSAGING, - instance, - SerializedVarSendInputShmem(dispatcher, message_data, instance))); + return instance_data->message_handler.get(); } -static const PPP_Messaging messaging_interface = { - &HandleMessage -}; -#else -// The NaCl plugin doesn't need the host side interface - stub it out. -static const PPP_Messaging messaging_interface = {}; -#endif // !defined(OS_NACL) +void ResetMessageHandler(Dispatcher* dispatcher, PP_Instance instance) { + if (!dispatcher || !dispatcher->IsPlugin()) { + NOTREACHED(); + return; + } + PluginDispatcher* plugin_dispatcher = + static_cast<PluginDispatcher*>(dispatcher); + InstanceData* instance_data = plugin_dispatcher->GetInstanceData(instance); + if (!instance_data) + return; -InterfaceProxy* CreateMessagingProxy(Dispatcher* dispatcher) { - return new PPP_Messaging_Proxy(dispatcher); + instance_data->message_handler.reset(); } } // namespace @@ -63,18 +67,6 @@ PPP_Messaging_Proxy::PPP_Messaging_Proxy(Dispatcher* dispatcher) PPP_Messaging_Proxy::~PPP_Messaging_Proxy() { } -// static -const InterfaceProxy::Info* PPP_Messaging_Proxy::GetInfo() { - static const Info info = { - &messaging_interface, - PPP_MESSAGING_INTERFACE, - API_ID_PPP_MESSAGING, - false, - &CreateMessagingProxy, - }; - return &info; -} - bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) { if (!dispatcher()->IsPlugin()) return false; @@ -83,6 +75,9 @@ bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(PPP_Messaging_Proxy, msg) IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage, OnMsgHandleMessage) + IPC_MESSAGE_HANDLER_DELAY_REPLY( + PpapiMsg_PPPMessageHandler_HandleBlockingMessage, + OnMsgHandleBlockingMessage) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -91,13 +86,57 @@ bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) { void PPP_Messaging_Proxy::OnMsgHandleMessage( PP_Instance instance, SerializedVarReceiveInput message_data) { PP_Var received_var(message_data.GetForInstance(dispatcher(), instance)); + MessageHandler* message_handler = GetMessageHandler(dispatcher(), instance); + if (message_handler) { + if (message_handler->LoopIsValid()) { + message_handler->HandleMessage(ScopedPPVar(received_var)); + return; + } else { + // If the MessageHandler's loop has been quit, then we should treat it as + // though it has been unregistered and start sending messages to the + // default handler. This might mean the plugin has lost messages, but + // there's not really anything sane we can do about it. They should have + // used UnregisterMessageHandler. + ResetMessageHandler(dispatcher(), instance); + } + } + // If we reach this point, then there's no message handler registered, so + // we send to the default PPP_Messaging one for the instance. + // SerializedVarReceiveInput will decrement the reference count, but we want - // to give the recipient a reference. + // to give the recipient a reference in the legacy API. PpapiGlobals::Get()->GetVarTracker()->AddRefVar(received_var); CallWhileUnlocked(ppp_messaging_impl_->HandleMessage, instance, received_var); } +void PPP_Messaging_Proxy::OnMsgHandleBlockingMessage( + PP_Instance instance, + SerializedVarReceiveInput message_data, + IPC::Message* reply_msg) { + ScopedPPVar received_var(message_data.GetForInstance(dispatcher(), instance)); + MessageHandler* message_handler = GetMessageHandler(dispatcher(), instance); + if (message_handler) { + if (message_handler->LoopIsValid()) { + message_handler->HandleBlockingMessage( + received_var, scoped_ptr<IPC::Message>(reply_msg)); + return; + } else { + // If the MessageHandler's loop has been quit, then we should treat it as + // though it has been unregistered. Also see the note for PostMessage. + ResetMessageHandler(dispatcher(), instance); + } + } + // We have no handler, but we still need to respond to unblock the renderer + // and inform the JavaScript caller. + PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams( + reply_msg, + SerializedVarReturnValue::Convert(dispatcher(), PP_MakeUndefined()), + false /* was_handled */); + dispatcher()->Send(reply_msg); +} + + } // namespace proxy } // namespace ppapi diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy.h b/chromium/ppapi/proxy/ppp_messaging_proxy.h index 4b66f92c4f7..d9dde3cb2e5 100644 --- a/chromium/ppapi/proxy/ppp_messaging_proxy.h +++ b/chromium/ppapi/proxy/ppp_messaging_proxy.h @@ -20,8 +20,6 @@ class PPP_Messaging_Proxy : public InterfaceProxy { PPP_Messaging_Proxy(Dispatcher* dispatcher); virtual ~PPP_Messaging_Proxy(); - static const Info* GetInfo(); - // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; @@ -29,6 +27,9 @@ class PPP_Messaging_Proxy : public InterfaceProxy { // Message handlers. void OnMsgHandleMessage(PP_Instance instance, SerializedVarReceiveInput data); + void OnMsgHandleBlockingMessage(PP_Instance instance, + SerializedVarReceiveInput data, + IPC::Message* reply); // When this proxy is in the plugin side, this value caches the interface // pointer so we don't have to retrieve it from the dispatcher each time. diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc b/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc index 1fe0ef71806..d1fa9b60fde 100644 --- a/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc +++ b/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc @@ -8,7 +8,10 @@ #include "ppapi/c/pp_var.h" #include "ppapi/c/ppb_var.h" #include "ppapi/c/ppp_messaging.h" +#include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/proxy/serialized_var.h" +#include "ppapi/shared_impl/api_id.h" #include "ppapi/shared_impl/proxy_lock.h" #include "ppapi/shared_impl/var.h" @@ -42,6 +45,17 @@ PPP_Messaging ppp_messaging_mock = { &HandleMessage }; +// CallHandleMessage does the host-side work to cause HandleMessage to be called +// in the plugin side. +void CallHandleMessage(Dispatcher* dispatcher, + PP_Instance instance, + PP_Var message) { + dispatcher->Send(new PpapiMsg_PPPMessaging_HandleMessage( + API_ID_PPP_MESSAGING, + instance, + SerializedVarSendInputShmem(dispatcher, message, instance))); +} + class PPP_Messaging_ProxyTest : public TwoWayTest { public: PPP_Messaging_ProxyTest() @@ -68,29 +82,25 @@ void CompareAndReleaseStringVar(PluginProxyTestHarness* plugin_harness, } // namespace TEST_F(PPP_Messaging_ProxyTest, SendMessages) { - // Grab the host-side proxy of ppp_messaging. - const PPP_Messaging* ppp_messaging = static_cast<const PPP_Messaging*>( - host().host_dispatcher()->GetProxiedInterface( - PPP_MESSAGING_INTERFACE)); - PP_Instance expected_instance = pp_instance(); PP_Var expected_var = PP_MakeUndefined(); ResetReceived(); - ppp_messaging->HandleMessage(expected_instance, expected_var); + Dispatcher* host_dispatcher = host().GetDispatcher(); + CallHandleMessage(host_dispatcher, expected_instance, expected_var); handle_message_called.Wait(); EXPECT_EQ(expected_instance, received_instance); EXPECT_EQ(expected_var.type, received_var.type); expected_var = PP_MakeNull(); ResetReceived(); - ppp_messaging->HandleMessage(expected_instance, expected_var); + CallHandleMessage(host_dispatcher, expected_instance, expected_var); handle_message_called.Wait(); EXPECT_EQ(expected_instance, received_instance); EXPECT_EQ(expected_var.type, received_var.type); expected_var = PP_MakeBool(PP_TRUE); ResetReceived(); - ppp_messaging->HandleMessage(expected_instance, expected_var); + CallHandleMessage(host_dispatcher, expected_instance, expected_var); handle_message_called.Wait(); EXPECT_EQ(expected_instance, received_instance); EXPECT_EQ(expected_var.type, received_var.type); @@ -98,7 +108,7 @@ TEST_F(PPP_Messaging_ProxyTest, SendMessages) { expected_var = PP_MakeInt32(12345); ResetReceived(); - ppp_messaging->HandleMessage(expected_instance, expected_var); + CallHandleMessage(host_dispatcher, expected_instance, expected_var); handle_message_called.Wait(); EXPECT_EQ(expected_instance, received_instance); EXPECT_EQ(expected_var.type, received_var.type); @@ -106,7 +116,7 @@ TEST_F(PPP_Messaging_ProxyTest, SendMessages) { expected_var = PP_MakeDouble(3.1415); ResetReceived(); - ppp_messaging->HandleMessage(expected_instance, expected_var); + CallHandleMessage(host_dispatcher, expected_instance, expected_var); handle_message_called.Wait(); EXPECT_EQ(expected_instance, received_instance); EXPECT_EQ(expected_var.type, received_var.type); @@ -115,7 +125,7 @@ TEST_F(PPP_Messaging_ProxyTest, SendMessages) { const std::string kTestString("Hello world!"); expected_var = StringVar::StringToPPVar(kTestString); ResetReceived(); - ppp_messaging->HandleMessage(expected_instance, expected_var); + CallHandleMessage(host_dispatcher, expected_instance, expected_var); // Now release the var, and the string should go away (because the ref // count should be one). host().var_tracker().ReleaseVar(expected_var); diff --git a/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc index 6fd746dc01f..66dc1304c51 100644 --- a/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc +++ b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc @@ -35,10 +35,6 @@ static const PPP_MouseLock mouse_lock_interface = { static const PPP_MouseLock mouse_lock_interface = {}; #endif // !defined(OS_NACL) -InterfaceProxy* CreateMouseLockProxy(Dispatcher* dispatcher) { - return new PPP_MouseLock_Proxy(dispatcher); -} - } // namespace PPP_MouseLock_Proxy::PPP_MouseLock_Proxy(Dispatcher* dispatcher) @@ -54,15 +50,8 @@ PPP_MouseLock_Proxy::~PPP_MouseLock_Proxy() { } // static -const InterfaceProxy::Info* PPP_MouseLock_Proxy::GetInfo() { - static const Info info = { - &mouse_lock_interface, - PPP_MOUSELOCK_INTERFACE, - API_ID_PPP_MOUSE_LOCK, - false, - &CreateMouseLockProxy, - }; - return &info; +const PPP_MouseLock* PPP_MouseLock_Proxy::GetProxyInterface() { + return &mouse_lock_interface; } bool PPP_MouseLock_Proxy::OnMessageReceived(const IPC::Message& msg) { diff --git a/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h index 64f1b7a05d7..3945bdfad0e 100644 --- a/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h +++ b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h @@ -18,7 +18,7 @@ class PPP_MouseLock_Proxy : public InterfaceProxy { PPP_MouseLock_Proxy(Dispatcher* dispatcher); virtual ~PPP_MouseLock_Proxy(); - static const Info* GetInfo(); + static const PPP_MouseLock* GetProxyInterface(); // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; diff --git a/chromium/ppapi/proxy/ppp_pdf_proxy.cc b/chromium/ppapi/proxy/ppp_pdf_proxy.cc new file mode 100644 index 00000000000..356b42f0ebd --- /dev/null +++ b/chromium/ppapi/proxy/ppp_pdf_proxy.cc @@ -0,0 +1,77 @@ +// 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. + +#include "ppapi/proxy/ppp_pdf_proxy.h" + +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/proxy_lock.h" + +namespace ppapi { +namespace proxy { + +namespace { + +#if !defined(OS_NACL) +PP_Var GetLinkAtPosition(PP_Instance instance, PP_Point point) { + // This isn't implemented in the out of process case. + return PP_MakeUndefined(); +} + +void Transform(PP_Instance instance, PP_PrivatePageTransformType type) { + bool clockwise = type == PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CW; + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPPdf_Rotate(API_ID_PPP_PDF, instance, clockwise)); +} + +const PPP_Pdf ppp_pdf_interface = { + &GetLinkAtPosition, + &Transform, +}; +#else +// The NaCl plugin doesn't need the host side interface - stub it out. +const PPP_Pdf ppp_pdf_interface = {}; +#endif + +} // namespace + +PPP_Pdf_Proxy::PPP_Pdf_Proxy(Dispatcher* dispatcher) + : InterfaceProxy(dispatcher), + ppp_pdf_(NULL) { + if (dispatcher->IsPlugin()) { + ppp_pdf_ = static_cast<const PPP_Pdf*>( + dispatcher->local_get_interface()(PPP_PDF_INTERFACE)); + } +} + +PPP_Pdf_Proxy::~PPP_Pdf_Proxy() { +} + +// static +const PPP_Pdf* PPP_Pdf_Proxy::GetProxyInterface() { + return &ppp_pdf_interface; +} + +bool PPP_Pdf_Proxy::OnMessageReceived(const IPC::Message& msg) { + if (!dispatcher()->IsPlugin()) + return false; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPP_Pdf_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPPdf_Rotate, OnPluginMsgRotate) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void PPP_Pdf_Proxy::OnPluginMsgRotate(PP_Instance instance, bool clockwise) { + PP_PrivatePageTransformType type = clockwise ? + PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CW : + PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CCW; + if (ppp_pdf_) + CallWhileUnlocked(ppp_pdf_->Transform, instance, type); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/ppp_pdf_proxy.h b/chromium/ppapi/proxy/ppp_pdf_proxy.h new file mode 100644 index 00000000000..992b2248811 --- /dev/null +++ b/chromium/ppapi/proxy/ppp_pdf_proxy.h @@ -0,0 +1,40 @@ +// 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 PPAPI_PROXY_PPP_PDF_PROXY_H_ +#define PPAPI_PROXY_PPP_PDF_PROXY_H_ + +#include "ppapi/c/private/ppp_pdf.h" +#include "ppapi/proxy/interface_proxy.h" + +namespace ppapi { + +namespace proxy { + +class PPP_Pdf_Proxy : public InterfaceProxy { + public: + PPP_Pdf_Proxy(Dispatcher* dispatcher); + virtual ~PPP_Pdf_Proxy(); + + static const PPP_Pdf* GetProxyInterface(); + + // InterfaceProxy implementation. + virtual bool OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnPluginMsgRotate(PP_Instance instance, bool clockwise); + + // When this proxy is in the plugin side, this value caches the interface + // pointer so we don't have to retrieve it from the dispatcher each time. + // In the host, this value is always NULL. + const PPP_Pdf* ppp_pdf_; + + DISALLOW_COPY_AND_ASSIGN(PPP_Pdf_Proxy); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_PPP_PDF_PROXY_H_ diff --git a/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc b/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc index f1a67212791..19803187d17 100644 --- a/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc +++ b/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc @@ -10,11 +10,9 @@ #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppb_video_decoder_proxy.h" #include "ppapi/thunk/enter.h" -#include "ppapi/thunk/ppb_video_decoder_api.h" +#include "ppapi/thunk/ppb_video_decoder_dev_api.h" #include "ppapi/thunk/thunk.h" -using ppapi::thunk::PPB_VideoDecoder_API; - namespace ppapi { namespace proxy { @@ -77,10 +75,6 @@ static const PPP_VideoDecoder_Dev video_decoder_interface = { &NotifyError }; -InterfaceProxy* CreateVideoDecoderPPPProxy(Dispatcher* dispatcher) { - return new PPP_VideoDecoder_Proxy(dispatcher); -} - } // namespace PPP_VideoDecoder_Proxy::PPP_VideoDecoder_Proxy(Dispatcher* dispatcher) @@ -96,15 +90,8 @@ PPP_VideoDecoder_Proxy::~PPP_VideoDecoder_Proxy() { } // static -const InterfaceProxy::Info* PPP_VideoDecoder_Proxy::GetInfo() { - static const Info info = { - &video_decoder_interface, - PPP_VIDEODECODER_DEV_INTERFACE, - API_ID_PPP_VIDEO_DECODER_DEV, - false, - &CreateVideoDecoderPPPProxy, - }; - return &info; +const PPP_VideoDecoder_Dev* PPP_VideoDecoder_Proxy::GetProxyInterface() { + return &video_decoder_interface; } bool PPP_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) { diff --git a/chromium/ppapi/proxy/ppp_video_decoder_proxy.h b/chromium/ppapi/proxy/ppp_video_decoder_proxy.h index 84d83a56b1a..54beac12796 100644 --- a/chromium/ppapi/proxy/ppp_video_decoder_proxy.h +++ b/chromium/ppapi/proxy/ppp_video_decoder_proxy.h @@ -21,7 +21,7 @@ class PPP_VideoDecoder_Proxy : public InterfaceProxy { PPP_VideoDecoder_Proxy(Dispatcher* dispatcher); virtual ~PPP_VideoDecoder_Proxy(); - static const Info* GetInfo(); + static const PPP_VideoDecoder_Dev* GetProxyInterface(); // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg); diff --git a/chromium/ppapi/proxy/proxy_channel.cc b/chromium/ppapi/proxy/proxy_channel.cc index b7f8a826ce3..7a7dfaa469e 100644 --- a/chromium/ppapi/proxy/proxy_channel.cc +++ b/chromium/ppapi/proxy/proxy_channel.cc @@ -31,11 +31,12 @@ bool ProxyChannel::InitWithChannel(Delegate* delegate, bool is_client) { delegate_ = delegate; peer_pid_ = peer_pid; - IPC::Channel::Mode mode = is_client ? IPC::Channel::MODE_CLIENT - : IPC::Channel::MODE_SERVER; - channel_.reset(new IPC::SyncChannel(channel_handle, mode, this, + IPC::Channel::Mode mode = is_client + ? IPC::Channel::MODE_CLIENT + : IPC::Channel::MODE_SERVER; + channel_ = IPC::SyncChannel::Create(channel_handle, mode, this, delegate->GetIPCMessageLoop(), true, - delegate->GetShutdownEvent())); + delegate->GetShutdownEvent()); return true; } @@ -64,11 +65,7 @@ IPC::PlatformFileForTransit ProxyChannel::ShareHandleWithRemote( // Channel could be closed if the plugin crashes. if (!channel_.get()) { if (should_close_source) { -#if !defined(OS_NACL) - base::ClosePlatformFile(handle); -#else - close(handle); -#endif + base::File file_closer(handle); } return IPC::InvalidPlatformFileForTransit(); } diff --git a/chromium/ppapi/proxy/raw_var_data.cc b/chromium/ppapi/proxy/raw_var_data.cc index 49ee8c261dd..97a6d944ae5 100644 --- a/chromium/ppapi/proxy/raw_var_data.cc +++ b/chromium/ppapi/proxy/raw_var_data.cc @@ -319,7 +319,7 @@ bool BasicRawVarData::Read(PP_VarType type, case PP_VARTYPE_UNDEFINED: case PP_VARTYPE_NULL: // These don't have any data associated with them other than the type we - // just serialized. + // just deserialized. break; case PP_VARTYPE_BOOL: { bool bool_value; diff --git a/chromium/ppapi/proxy/raw_var_data_unittest.cc b/chromium/ppapi/proxy/raw_var_data_unittest.cc index 03408923322..e1c56a3358d 100644 --- a/chromium/ppapi/proxy/raw_var_data_unittest.cc +++ b/chromium/ppapi/proxy/raw_var_data_unittest.cc @@ -72,7 +72,7 @@ bool WriteReadAndCompare(const PP_Var& var) { if (!success) return false; ScopedPPVar actual(ScopedPPVar::PassRef(), result); - return TestEqual(expected.get(), actual.get()); + return TestEqual(expected.get(), actual.get(), true); } } // namespace diff --git a/chromium/ppapi/proxy/resource_creation_proxy.cc b/chromium/ppapi/proxy/resource_creation_proxy.cc index 231142a937d..8b65dbd30cc 100644 --- a/chromium/ppapi/proxy/resource_creation_proxy.cc +++ b/chromium/ppapi/proxy/resource_creation_proxy.cc @@ -7,6 +7,7 @@ #include "ppapi/c/pp_errors.h" #include "ppapi/c/pp_size.h" #include "ppapi/proxy/audio_input_resource.h" +#include "ppapi/proxy/compositor_resource.h" #include "ppapi/proxy/connection.h" #include "ppapi/proxy/file_chooser_resource.h" #include "ppapi/proxy/file_io_resource.h" @@ -18,6 +19,7 @@ #include "ppapi/proxy/graphics_2d_resource.h" #include "ppapi/proxy/host_resolver_private_resource.h" #include "ppapi/proxy/host_resolver_resource.h" +#include "ppapi/proxy/media_stream_video_track_resource.h" #include "ppapi/proxy/net_address_resource.h" #include "ppapi/proxy/network_monitor_resource.h" #include "ppapi/proxy/output_protection_resource.h" @@ -46,6 +48,7 @@ #include "ppapi/proxy/url_request_info_resource.h" #include "ppapi/proxy/url_response_info_resource.h" #include "ppapi/proxy/video_capture_resource.h" +#include "ppapi/proxy/video_decoder_resource.h" #include "ppapi/proxy/video_destination_resource.h" #include "ppapi/proxy/video_source_resource.h" #include "ppapi/proxy/websocket_resource.h" @@ -54,7 +57,6 @@ #include "ppapi/shared_impl/ppb_audio_config_shared.h" #include "ppapi/shared_impl/ppb_audio_shared.h" #include "ppapi/shared_impl/ppb_input_event_shared.h" -#include "ppapi/shared_impl/ppb_resource_array_shared.h" #include "ppapi/shared_impl/var.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_image_data_api.h" @@ -108,16 +110,30 @@ PP_Resource ResourceCreationProxy::CreateIMEInputEvent( segment_offsets, target_segment, selection_start, selection_end); } -PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent( +PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent_1_0( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, uint32_t key_code, struct PP_Var character_text) { + PP_Var code = StringVar::StringToPPVar(""); return PPB_InputEvent_Shared::CreateKeyboardInputEvent( OBJECT_IS_PROXY, instance, type, time_stamp, modifiers, key_code, - character_text); + character_text, code); +} + +PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent_1_2( + PP_Instance instance, + PP_InputEvent_Type type, + PP_TimeTicks time_stamp, + uint32_t modifiers, + uint32_t key_code, + struct PP_Var character_text, + struct PP_Var code) { + return PPB_InputEvent_Shared::CreateKeyboardInputEvent( + OBJECT_IS_PROXY, instance, type, time_stamp, modifiers, key_code, + character_text, code); } PP_Resource ResourceCreationProxy::CreateMouseInputEvent( @@ -143,15 +159,6 @@ PP_Resource ResourceCreationProxy::CreateTouchInputEvent( OBJECT_IS_PROXY, instance, type, time_stamp, modifiers); } -PP_Resource ResourceCreationProxy::CreateResourceArray( - PP_Instance instance, - const PP_Resource elements[], - uint32_t size) { - PPB_ResourceArray_Shared* object = new PPB_ResourceArray_Shared( - OBJECT_IS_PROXY, instance, elements, size); - return object->GetReference(); -} - PP_Resource ResourceCreationProxy::CreateTrueTypeFont( PP_Instance instance, const PP_TrueTypeFontDesc_Dev* desc) { @@ -213,6 +220,10 @@ PP_Resource ResourceCreationProxy::CreateAudioConfig( OBJECT_IS_PROXY, instance, sample_rate, sample_frame_count); } +PP_Resource ResourceCreationProxy::CreateCompositor(PP_Instance instance) { + return (new CompositorResource(GetConnection(), instance))->GetReference(); +} + PP_Resource ResourceCreationProxy::CreateFileChooser( PP_Instance instance, PP_FileChooserMode_Dev mode, @@ -286,6 +297,12 @@ PP_Resource ResourceCreationProxy::CreateImageDataSimple( format, *size, init_to_zero); } +PP_Resource ResourceCreationProxy::CreateMediaStreamVideoTrack( + PP_Instance instance) { + return (new MediaStreamVideoTrackResource(GetConnection(), + instance))->GetReference(); +} + PP_Resource ResourceCreationProxy::CreateNetAddressFromIPv4Address( PP_Instance instance, const PP_NetAddress_IPv4* ipv4_addr) { @@ -358,6 +375,10 @@ PP_Resource ResourceCreationProxy::CreateUDPSocketPrivate( GetConnection(), instance))->GetReference(); } +PP_Resource ResourceCreationProxy::CreateVideoDecoder(PP_Instance instance) { + return (new VideoDecoderResource(GetConnection(), instance))->GetReference(); +} + PP_Resource ResourceCreationProxy::CreateVideoDestination( PP_Instance instance) { return (new VideoDestinationResource(GetConnection(), @@ -454,7 +475,7 @@ PP_Resource ResourceCreationProxy::CreateVideoCapture(PP_Instance instance) { ->GetReference(); } -PP_Resource ResourceCreationProxy::CreateVideoDecoder( +PP_Resource ResourceCreationProxy::CreateVideoDecoderDev( PP_Instance instance, PP_Resource context3d_id, PP_VideoDecoder_Profile profile) { diff --git a/chromium/ppapi/proxy/resource_creation_proxy.h b/chromium/ppapi/proxy/resource_creation_proxy.h index df564da7ca3..48b8aaa8255 100644 --- a/chromium/ppapi/proxy/resource_creation_proxy.h +++ b/chromium/ppapi/proxy/resource_creation_proxy.h @@ -52,13 +52,21 @@ class ResourceCreationProxy : public InterfaceProxy, int32_t target_segment, uint32_t selection_start, uint32_t selection_end) OVERRIDE; - virtual PP_Resource CreateKeyboardInputEvent( + virtual PP_Resource CreateKeyboardInputEvent_1_0( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, uint32_t key_code, PP_Var character_text) OVERRIDE; + virtual PP_Resource CreateKeyboardInputEvent_1_2( + PP_Instance instance, + PP_InputEvent_Type type, + PP_TimeTicks time_stamp, + uint32_t modifiers, + uint32_t key_code, + PP_Var character_text, + PP_Var code) OVERRIDE; virtual PP_Resource CreateMouseInputEvent( PP_Instance instance, PP_InputEvent_Type type, @@ -73,9 +81,6 @@ class ResourceCreationProxy : public InterfaceProxy, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers) OVERRIDE; - virtual PP_Resource CreateResourceArray(PP_Instance instance, - const PP_Resource elements[], - uint32_t size) OVERRIDE; virtual PP_Resource CreateTrueTypeFont( PP_Instance instance, const PP_TrueTypeFontDesc_Dev* desc) OVERRIDE; @@ -101,6 +106,7 @@ class ResourceCreationProxy : public InterfaceProxy, virtual PP_Resource CreateAudioConfig(PP_Instance instance, PP_AudioSampleRate sample_rate, uint32_t sample_frame_count) OVERRIDE; + virtual PP_Resource CreateCompositor(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateFileChooser(PP_Instance instance, PP_FileChooserMode_Dev mode, const PP_Var& accept_types) OVERRIDE; @@ -124,6 +130,8 @@ class ResourceCreationProxy : public InterfaceProxy, PP_ImageDataFormat format, const PP_Size* size, PP_Bool init_to_zero) OVERRIDE; + virtual PP_Resource CreateMediaStreamVideoTrack( + PP_Instance instance) OVERRIDE; virtual PP_Resource CreateNetAddressFromIPv4Address( PP_Instance instance, const PP_NetAddress_IPv4* ipv4_addr) OVERRIDE; @@ -144,6 +152,7 @@ class ResourceCreationProxy : public InterfaceProxy, virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateVideoDecoder(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoDestination(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoSource(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateWebSocket(PP_Instance instance) OVERRIDE; @@ -171,7 +180,7 @@ class ResourceCreationProxy : public InterfaceProxy, PP_Bool vertical) OVERRIDE; virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoCapture(PP_Instance instance) OVERRIDE; - virtual PP_Resource CreateVideoDecoder( + virtual PP_Resource CreateVideoDecoderDev( PP_Instance instance, PP_Resource context3d_id, PP_VideoDecoder_Profile profile) OVERRIDE; diff --git a/chromium/ppapi/proxy/resource_message_test_sink.cc b/chromium/ppapi/proxy/resource_message_test_sink.cc index e76e32ac88e..2c237b0670a 100644 --- a/chromium/ppapi/proxy/resource_message_test_sink.cc +++ b/chromium/ppapi/proxy/resource_message_test_sink.cc @@ -13,26 +13,25 @@ namespace proxy { namespace { -// Backend for GetFirstResource[Call|Reply]Matching. +// Backend for GetAllResource[Calls|Replies]Matching. template<class WrapperMessage, class Params> -bool GetFirstResourceMessageMatching(const ResourceMessageTestSink& sink, - uint32 id, - Params* params, - IPC::Message* nested_msg) { +std::vector<std::pair<Params, IPC::Message> > +GetAllResourceMessagesMatching(const ResourceMessageTestSink& sink, + uint32 id) { + std::vector<std::pair<Params, IPC::Message> > result; for (size_t i = 0; i < sink.message_count(); i++) { const IPC::Message* msg = sink.GetMessageAt(i); if (msg->type() == WrapperMessage::ID) { - Params cur_params; - IPC::Message cur_msg; - WrapperMessage::Read(msg, &cur_params, &cur_msg); + typename WrapperMessage::Param params; + WrapperMessage::Read(msg, ¶ms); + Params cur_params = params.a; + IPC::Message cur_msg = params.b; if (cur_msg.type() == id) { - *params = cur_params; - *nested_msg = cur_msg; - return true; + result.push_back(std::make_pair(cur_params, cur_msg)); } } } - return false; + return result; } } // namespace @@ -71,18 +70,42 @@ bool ResourceMessageTestSink::GetFirstResourceCallMatching( uint32 id, ResourceMessageCallParams* params, IPC::Message* nested_msg) const { - return GetFirstResourceMessageMatching<PpapiHostMsg_ResourceCall, - ResourceMessageCallParams>( - *this, id, params, nested_msg); + ResourceCallVector matching_messages = + GetAllResourceMessagesMatching<PpapiHostMsg_ResourceCall, + ResourceMessageCallParams>(*this, id); + if (matching_messages.empty()) + return false; + + *params = matching_messages[0].first; + *nested_msg = matching_messages[0].second; + return true; } bool ResourceMessageTestSink::GetFirstResourceReplyMatching( uint32 id, ResourceMessageReplyParams* params, IPC::Message* nested_msg) { - return GetFirstResourceMessageMatching<PpapiPluginMsg_ResourceReply, - ResourceMessageReplyParams>( - *this, id, params, nested_msg); + ResourceReplyVector matching_messages = + GetAllResourceMessagesMatching<PpapiPluginMsg_ResourceReply, + ResourceMessageReplyParams>(*this, id); + if (matching_messages.empty()) + return false; + + *params = matching_messages[0].first; + *nested_msg = matching_messages[0].second; + return true; +} + +ResourceMessageTestSink::ResourceCallVector +ResourceMessageTestSink::GetAllResourceCallsMatching(uint32 id) { + return GetAllResourceMessagesMatching<PpapiHostMsg_ResourceCall, + ResourceMessageCallParams>(*this, id); +} + +ResourceMessageTestSink::ResourceReplyVector +ResourceMessageTestSink::GetAllResourceRepliesMatching(uint32 id) { + return GetAllResourceMessagesMatching<PpapiPluginMsg_ResourceReply, + ResourceMessageReplyParams>(*this, id); } ResourceSyncCallHandler::ResourceSyncCallHandler( diff --git a/chromium/ppapi/proxy/resource_message_test_sink.h b/chromium/ppapi/proxy/resource_message_test_sink.h index cbbece3134d..2593aaae221 100644 --- a/chromium/ppapi/proxy/resource_message_test_sink.h +++ b/chromium/ppapi/proxy/resource_message_test_sink.h @@ -33,7 +33,7 @@ class ResourceMessageTestSink : public IPC::TestSink { // Searches the queue for the first resource call message with a nested // message matching the given ID. On success, returns true and populates the - // givem params and nested message. + // given params and nested message. bool GetFirstResourceCallMatching( uint32 id, ResourceMessageCallParams* params, @@ -45,6 +45,17 @@ class ResourceMessageTestSink : public IPC::TestSink { ResourceMessageReplyParams* params, IPC::Message* nested_msg); + // Searches the queue for all resource call messages with a nested message + // matching the given ID. + typedef std::pair<ResourceMessageCallParams, IPC::Message> ResourceCall; + typedef std::vector<ResourceCall> ResourceCallVector; + ResourceCallVector GetAllResourceCallsMatching(uint32 id); + + // Like GetAllResourceCallsMatching except for replies. + typedef std::pair<ResourceMessageReplyParams, IPC::Message> ResourceReply; + typedef std::vector<ResourceReply> ResourceReplyVector; + ResourceReplyVector GetAllResourceRepliesMatching(uint32 id); + private: scoped_ptr<IPC::Message> sync_reply_msg_; }; diff --git a/chromium/ppapi/proxy/serialized_handle.cc b/chromium/ppapi/proxy/serialized_handle.cc index c9ce13b41a9..7d06c763b31 100644 --- a/chromium/ppapi/proxy/serialized_handle.cc +++ b/chromium/ppapi/proxy/serialized_handle.cc @@ -4,9 +4,9 @@ #include "ppapi/proxy/serialized_handle.h" +#include "base/files/file.h" #include "base/memory/shared_memory.h" #include "base/pickle.h" -#include "base/platform_file.h" #include "build/build_config.h" #include "ipc/ipc_platform_file.h" @@ -21,14 +21,18 @@ SerializedHandle::SerializedHandle() : type_(INVALID), shm_handle_(base::SharedMemory::NULLHandle()), size_(0), - descriptor_(IPC::InvalidPlatformFileForTransit()) { + descriptor_(IPC::InvalidPlatformFileForTransit()), + open_flags_(0), + file_io_(0) { } SerializedHandle::SerializedHandle(Type type_param) : type_(type_param), shm_handle_(base::SharedMemory::NULLHandle()), size_(0), - descriptor_(IPC::InvalidPlatformFileForTransit()) { + descriptor_(IPC::InvalidPlatformFileForTransit()), + open_flags_(0), + file_io_(0) { } SerializedHandle::SerializedHandle(const base::SharedMemoryHandle& handle, @@ -36,7 +40,9 @@ SerializedHandle::SerializedHandle(const base::SharedMemoryHandle& handle, : type_(SHARED_MEMORY), shm_handle_(handle), size_(size), - descriptor_(IPC::InvalidPlatformFileForTransit()) { + descriptor_(IPC::InvalidPlatformFileForTransit()), + open_flags_(0), + file_io_(0) { } SerializedHandle::SerializedHandle( @@ -45,7 +51,9 @@ SerializedHandle::SerializedHandle( : type_(type), shm_handle_(base::SharedMemory::NULLHandle()), size_(0), - descriptor_(socket_descriptor) { + descriptor_(socket_descriptor), + open_flags_(0), + file_io_(0) { } bool SerializedHandle::IsHandleValid() const { @@ -53,7 +61,6 @@ bool SerializedHandle::IsHandleValid() const { case SHARED_MEMORY: return base::SharedMemory::IsHandleValid(shm_handle_); case SOCKET: - case CHANNEL_HANDLE: case FILE: return !(IPC::InvalidPlatformFileForTransit() == descriptor_); case INVALID: @@ -73,15 +80,8 @@ void SerializedHandle::Close() { base::SharedMemory::CloseHandle(shm_handle_); break; case SOCKET: - case CHANNEL_HANDLE: case FILE: - base::PlatformFile file = - IPC::PlatformFileForTransitToPlatformFile(descriptor_); -#if !defined(OS_NACL) - base::ClosePlatformFile(file); -#else - close(file); -#endif + base::File file_closer = IPC::PlatformFileForTransitToFile(descriptor_); break; // No default so the compiler will warn us if a new type is added. } @@ -98,7 +98,7 @@ bool SerializedHandle::WriteHeader(const Header& hdr, Pickle* pickle) { return false; } if (hdr.type == FILE) { - if (!pickle->WriteInt(hdr.open_flag)) + if (!pickle->WriteInt(hdr.open_flags) || !pickle->WriteInt(hdr.file_io)) return false; } return true; @@ -106,7 +106,7 @@ bool SerializedHandle::WriteHeader(const Header& hdr, Pickle* pickle) { // static bool SerializedHandle::ReadHeader(PickleIterator* iter, Header* hdr) { - *hdr = Header(INVALID, 0, 0); + *hdr = Header(INVALID, 0, 0, 0); int type = 0; if (!iter->ReadInt(&type)) return false; @@ -121,14 +121,15 @@ bool SerializedHandle::ReadHeader(PickleIterator* iter, Header* hdr) { break; } case FILE: { - int open_flag = 0; - if (!iter->ReadInt(&open_flag)) + int open_flags = 0; + PP_Resource file_io = 0; + if (!iter->ReadInt(&open_flags) || !iter->ReadInt(&file_io)) return false; - hdr->open_flag = open_flag; + hdr->open_flags = open_flags; + hdr->file_io = file_io; valid_type = true; } case SOCKET: - case CHANNEL_HANDLE: case INVALID: valid_type = true; break; diff --git a/chromium/ppapi/proxy/serialized_handle.h b/chromium/ppapi/proxy/serialized_handle.h index 91efa075b5d..252ffcb9f3c 100644 --- a/chromium/ppapi/proxy/serialized_handle.h +++ b/chromium/ppapi/proxy/serialized_handle.h @@ -8,11 +8,14 @@ #include <string> #include <vector> +#include "base/atomicops.h" #include "base/basictypes.h" #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" #include "build/build_config.h" #include "ipc/ipc_platform_file.h" +#include "ppapi/c/pp_resource.h" #include "ppapi/proxy/ppapi_proxy_export.h" class Pickle; @@ -26,15 +29,25 @@ namespace proxy { // NaClIPCAdapter for use in NaCl. class PPAPI_PROXY_EXPORT SerializedHandle { public: - enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE, FILE }; + enum Type { INVALID, SHARED_MEMORY, SOCKET, FILE }; + // Header contains the fields that we send in IPC messages, apart from the + // actual handle. See comments on the SerializedHandle fields below. struct Header { - Header() : type(INVALID), size(0), open_flag(0) {} - Header(Type type_arg, uint32 size_arg, int32 open_flag_arg) - : type(type_arg), size(size_arg), open_flag(open_flag_arg) { + Header() : type(INVALID), size(0), open_flags(0) {} + Header(Type type_arg, + uint32 size_arg, + int32 open_flags_arg, + PP_Resource file_io_arg) + : type(type_arg), + size(size_arg), + open_flags(open_flags_arg), + file_io(file_io_arg) { } + Type type; uint32 size; - int32 open_flag; + int32 open_flags; + PP_Resource file_io; }; SerializedHandle(); @@ -44,14 +57,13 @@ class PPAPI_PROXY_EXPORT SerializedHandle { // Create a shared memory handle. SerializedHandle(const base::SharedMemoryHandle& handle, uint32 size); - // Create a socket, channel or file handle. + // Create a socket or file handle. SerializedHandle(const Type type, const IPC::PlatformFileForTransit& descriptor); Type type() const { return type_; } bool is_shmem() const { return type_ == SHARED_MEMORY; } bool is_socket() const { return type_ == SOCKET; } - bool is_channel_handle() const { return type_ == CHANNEL_HANDLE; } bool is_file() const { return type_ == FILE; } const base::SharedMemoryHandle& shmem() const { DCHECK(is_shmem()); @@ -62,11 +74,14 @@ class PPAPI_PROXY_EXPORT SerializedHandle { return size_; } const IPC::PlatformFileForTransit& descriptor() const { - DCHECK(is_socket() || is_channel_handle() || is_file()); + DCHECK(is_socket() || is_file()); return descriptor_; } - int32 open_flag() const { - return open_flag_; + int32 open_flags() const { + return open_flags_; + } + PP_Resource file_io() const { + return file_io_; } void set_shmem(const base::SharedMemoryHandle& handle, uint32 size) { type_ = SHARED_MEMORY; @@ -82,21 +97,16 @@ class PPAPI_PROXY_EXPORT SerializedHandle { shm_handle_ = base::SharedMemory::NULLHandle(); size_ = 0; } - void set_channel_handle(const IPC::PlatformFileForTransit& descriptor) { - type_ = CHANNEL_HANDLE; - - descriptor_ = descriptor; - shm_handle_ = base::SharedMemory::NULLHandle(); - size_ = 0; - } void set_file_handle(const IPC::PlatformFileForTransit& descriptor, - int32 open_flag) { + int32 open_flags, + PP_Resource file_io) { type_ = FILE; descriptor_ = descriptor; shm_handle_ = base::SharedMemory::NULLHandle(); size_ = 0; - open_flag_ = open_flag; + open_flags_ = open_flags; + file_io_ = file_io; } void set_null_shmem() { set_shmem(base::SharedMemory::NULLHandle(), 0); @@ -104,16 +114,13 @@ class PPAPI_PROXY_EXPORT SerializedHandle { void set_null_socket() { set_socket(IPC::InvalidPlatformFileForTransit()); } - void set_null_channel_handle() { - set_channel_handle(IPC::InvalidPlatformFileForTransit()); - } void set_null_file_handle() { - set_file_handle(IPC::InvalidPlatformFileForTransit(), 0); + set_file_handle(IPC::InvalidPlatformFileForTransit(), 0, 0); } bool IsHandleValid() const; Header header() const { - return Header(type_, size_, open_flag_); + return Header(type_, size_, open_flags_, file_io_); } // Closes the handle and sets it to invalid. @@ -137,11 +144,13 @@ class PPAPI_PROXY_EXPORT SerializedHandle { base::SharedMemoryHandle shm_handle_; uint32 size_; - // This is valid if type == SOCKET || type == CHANNEL_HANDLE || type == FILE. + // This is valid if type == SOCKET || type == FILE. IPC::PlatformFileForTransit descriptor_; - // This is valid if type == FILE. - int32 open_flag_; + // The following fields are valid if type == FILE. + int32 open_flags_; + // This is non-zero if file writes require quota checking. + PP_Resource file_io_; }; } // namespace proxy diff --git a/chromium/ppapi/proxy/serialized_structs.h b/chromium/ppapi/proxy/serialized_structs.h index fb93dd16d03..f3e114c09fa 100644 --- a/chromium/ppapi/proxy/serialized_structs.h +++ b/chromium/ppapi/proxy/serialized_structs.h @@ -135,9 +135,6 @@ struct PPPDecryptor_Buffer { // TODO(raymes): Make ImageHandle compatible with SerializedHandle. #if defined(OS_WIN) typedef HANDLE ImageHandle; -#elif defined(TOOLKIT_GTK) -// On legacy X Windows this is a SysV shared memory key. -typedef int ImageHandle; #else typedef base::SharedMemoryHandle ImageHandle; #endif diff --git a/chromium/ppapi/proxy/serialized_var.cc b/chromium/ppapi/proxy/serialized_var.cc index 72e7cc8ecbb..d00a7d39aab 100644 --- a/chromium/ppapi/proxy/serialized_var.cc +++ b/chromium/ppapi/proxy/serialized_var.cc @@ -68,14 +68,14 @@ PP_Var SerializedVar::Inner::GetVar() { #if defined(NACL_WIN64) NOTREACHED(); return PP_MakeUndefined(); -#endif - +#else if (raw_var_data_.get()) { var_ = raw_var_data_->CreatePPVar(instance_); raw_var_data_.reset(NULL); } return var_; +#endif } void SerializedVar::Inner::SetVar(PP_Var var) { diff --git a/chromium/ppapi/proxy/talk_resource.cc b/chromium/ppapi/proxy/talk_resource.cc index 2e60abfd331..b076064df6e 100644 --- a/chromium/ppapi/proxy/talk_resource.cc +++ b/chromium/ppapi/proxy/talk_resource.cc @@ -78,13 +78,13 @@ int32_t TalkResource::StopRemoting(scoped_refptr<TrackedCallback> callback) { void TalkResource::OnReplyReceived(const ResourceMessageReplyParams& params, const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(TalkResource, msg) + PPAPI_BEGIN_MESSAGE_MAP(TalkResource, msg) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_Talk_NotifyEvent, OnNotifyEvent) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( PluginResource::OnReplyReceived(params, msg)) - IPC_END_MESSAGE_MAP() + PPAPI_END_MESSAGE_MAP() } void TalkResource::OnNotifyEvent(const ResourceMessageReplyParams& params, diff --git a/chromium/ppapi/proxy/tcp_socket_resource_base.cc b/chromium/ppapi/proxy/tcp_socket_resource_base.cc index fff2da3cf8a..39c9fa311d6 100644 --- a/chromium/ppapi/proxy/tcp_socket_resource_base.cc +++ b/chromium/ppapi/proxy/tcp_socket_resource_base.cc @@ -189,32 +189,13 @@ PP_Resource TCPSocketResourceBase::GetServerCertificateImpl() { PP_Bool TCPSocketResourceBase::AddChainBuildingCertificateImpl( PP_Resource certificate, PP_Bool trusted) { - // TODO(raymes): The plumbing for this functionality is implemented but the - // certificates aren't yet used for the connection, so just return false for - // now. + // TODO(raymes): This is exposed in the private PPB_TCPSocket_Private + // interface for Flash but isn't currently implemented due to security + // implications. It is exposed so that it can be hooked up on the Flash side + // and if we decide to implement it we can do so without modifying the Flash + // codebase. + NOTIMPLEMENTED(); return PP_FALSE; - - thunk::EnterResourceNoLock<thunk::PPB_X509Certificate_Private_API> - enter_cert(certificate, true); - if (enter_cert.failed()) - return PP_FALSE; - - PP_Var der_var = enter_cert.object()->GetField( - PP_X509CERTIFICATE_PRIVATE_RAW); - ArrayBufferVar* der_array_buffer = ArrayBufferVar::FromPPVar(der_var); - PP_Bool success = PP_FALSE; - if (der_array_buffer) { - const char* der_bytes = static_cast<const char*>(der_array_buffer->Map()); - uint32_t der_length = der_array_buffer->ByteLength(); - std::vector<char> der(der_bytes, der_bytes + der_length); - if (PP_ToBool(trusted)) - trusted_certificates_.push_back(der); - else - untrusted_certificates_.push_back(der); - success = PP_TRUE; - } - PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(der_var); - return success; } int32_t TCPSocketResourceBase::ReadImpl( diff --git a/chromium/ppapi/proxy/uma_private_resource.cc b/chromium/ppapi/proxy/uma_private_resource.cc new file mode 100644 index 00000000000..2932e6cbe26 --- /dev/null +++ b/chromium/ppapi/proxy/uma_private_resource.cc @@ -0,0 +1,110 @@ +// 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. + +#include "ppapi/proxy/uma_private_resource.h" + +#include "base/bind.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/resource_message_params.h" +#include "ppapi/shared_impl/var.h" + +namespace { + +std::string StringFromPPVar(const PP_Var& var) { + scoped_refptr<ppapi::StringVar> name_stringvar = + ppapi::StringVar::FromPPVar(var); + if (!name_stringvar.get()) + return std::string(); + return name_stringvar->value(); +} + +} + +namespace ppapi { +namespace proxy { + +UMAPrivateResource::UMAPrivateResource( + Connection connection, PP_Instance instance) + : PluginResource(connection, instance) { + SendCreate(RENDERER, PpapiHostMsg_UMA_Create()); +} + +UMAPrivateResource::~UMAPrivateResource() { +} + +thunk::PPB_UMA_Singleton_API* UMAPrivateResource::AsPPB_UMA_Singleton_API() { + return this; +} + +void UMAPrivateResource::HistogramCustomTimes( + PP_Instance instance, + struct PP_Var name, + int64_t sample, + int64_t min, + int64_t max, + uint32_t bucket_count) { + if (name.type != PP_VARTYPE_STRING) + return; + + Post(RENDERER, PpapiHostMsg_UMA_HistogramCustomTimes(StringFromPPVar(name), + sample, + min, + max, + bucket_count)); +} + +void UMAPrivateResource::HistogramCustomCounts( + PP_Instance instance, + struct PP_Var name, + int32_t sample, + int32_t min, + int32_t max, + uint32_t bucket_count) { + if (name.type != PP_VARTYPE_STRING) + return; + + Post(RENDERER, PpapiHostMsg_UMA_HistogramCustomCounts(StringFromPPVar(name), + sample, + min, + max, + bucket_count)); +} + +void UMAPrivateResource::HistogramEnumeration( + PP_Instance instance, + struct PP_Var name, + int32_t sample, + int32_t boundary_value) { + if (name.type != PP_VARTYPE_STRING) + return; + + Post(RENDERER, PpapiHostMsg_UMA_HistogramEnumeration(StringFromPPVar(name), + sample, + boundary_value)); +} + +int32_t UMAPrivateResource::IsCrashReportingEnabled( + PP_Instance instance, + scoped_refptr<TrackedCallback> callback) { + if (pending_callback_ != NULL) + return PP_ERROR_INPROGRESS; + pending_callback_ = callback; + Call<PpapiPluginMsg_UMA_IsCrashReportingEnabledReply>( + RENDERER, + PpapiHostMsg_UMA_IsCrashReportingEnabled(), + base::Bind(&UMAPrivateResource::OnPluginMsgIsCrashReportingEnabled, + this)); + return PP_OK_COMPLETIONPENDING; +} + +void UMAPrivateResource::OnPluginMsgIsCrashReportingEnabled( + const ResourceMessageReplyParams& params) { + if (TrackedCallback::IsPending(pending_callback_)) + pending_callback_->Run(params.result()); + pending_callback_ = NULL; +} + +} // namespace proxy +} // namespace ppapi + diff --git a/chromium/ppapi/proxy/uma_private_resource.h b/chromium/ppapi/proxy/uma_private_resource.h new file mode 100644 index 00000000000..93328e8ec84 --- /dev/null +++ b/chromium/ppapi/proxy/uma_private_resource.h @@ -0,0 +1,62 @@ +// 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 PPAPI_PROXY_UMA_PRIVATE_RESOURCE_H_ +#define PPAPI_PROXY_UMA_PRIVATE_RESOURCE_H_ + +#include "ppapi/proxy/connection.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/thunk/ppb_uma_singleton_api.h" + +namespace ppapi { + +namespace proxy { + +class PPAPI_PROXY_EXPORT UMAPrivateResource + : public PluginResource, + public thunk::PPB_UMA_Singleton_API { + public: + UMAPrivateResource(Connection connection, PP_Instance instance); + virtual ~UMAPrivateResource(); + + // Resource overrides. + virtual thunk::PPB_UMA_Singleton_API* AsPPB_UMA_Singleton_API() OVERRIDE; + + // PPB_UMA_Singleton_API implementation. + virtual void HistogramCustomTimes(PP_Instance instance, + struct PP_Var name, + int64_t sample, + int64_t min, + int64_t max, + uint32_t bucket_count) OVERRIDE; + + virtual void HistogramCustomCounts(PP_Instance instance, + struct PP_Var name, + int32_t sample, + int32_t min, + int32_t max, + uint32_t bucket_count) OVERRIDE; + + virtual void HistogramEnumeration(PP_Instance instance, + struct PP_Var name, + int32_t sample, + int32_t boundary_value) OVERRIDE; + + virtual int32_t IsCrashReportingEnabled( + PP_Instance instance, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + + private: + void OnPluginMsgIsCrashReportingEnabled( + const ResourceMessageReplyParams& params); + scoped_refptr<TrackedCallback> pending_callback_; + + DISALLOW_COPY_AND_ASSIGN(UMAPrivateResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_UMA_PRIVATE_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/url_loader_resource.cc b/chromium/ppapi/proxy/url_loader_resource.cc index 1ff0a5e1a98..73bdb2342f4 100644 --- a/chromium/ppapi/proxy/url_loader_resource.cc +++ b/chromium/ppapi/proxy/url_loader_resource.cc @@ -235,7 +235,7 @@ void URLLoaderResource::RegisterStatusCallback( void URLLoaderResource::OnReplyReceived( const ResourceMessageReplyParams& params, const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(URLLoaderResource, msg) + PPAPI_BEGIN_MESSAGE_MAP(URLLoaderResource, msg) case PpapiPluginMsg_URLLoader_SendData::ID: // Special message, manually dispatch since we don't want the automatic // unpickling. @@ -251,7 +251,7 @@ void URLLoaderResource::OnReplyReceived( PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_URLLoader_UpdateProgress, OnPluginMsgUpdateProgress) - IPC_END_MESSAGE_MAP() + PPAPI_END_MESSAGE_MAP() } void URLLoaderResource::OnPluginMsgReceivedResponse( diff --git a/chromium/ppapi/proxy/video_capture_resource.cc b/chromium/ppapi/proxy/video_capture_resource.cc index 6ea8bd50015..8931b8fa378 100644 --- a/chromium/ppapi/proxy/video_capture_resource.cc +++ b/chromium/ppapi/proxy/video_capture_resource.cc @@ -45,7 +45,7 @@ void VideoCaptureResource::OnReplyReceived( return; } - IPC_BEGIN_MESSAGE_MAP(VideoCaptureResource, msg) + PPAPI_BEGIN_MESSAGE_MAP(VideoCaptureResource, msg) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_VideoCapture_OnDeviceInfo, OnPluginMsgOnDeviceInfo) @@ -59,13 +59,7 @@ void VideoCaptureResource::OnReplyReceived( PpapiPluginMsg_VideoCapture_OnBufferReady, OnPluginMsgOnBufferReady) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED()) - IPC_END_MESSAGE_MAP() -} - -int32_t VideoCaptureResource::EnumerateDevices0_2( - PP_Resource* devices, - scoped_refptr<TrackedCallback> callback) { - return enumeration_helper_.EnumerateDevices0_2(devices, callback); + PPAPI_END_MESSAGE_MAP() } int32_t VideoCaptureResource::EnumerateDevices( diff --git a/chromium/ppapi/proxy/video_capture_resource.h b/chromium/ppapi/proxy/video_capture_resource.h index e533ef095fb..44e415e2d41 100644 --- a/chromium/ppapi/proxy/video_capture_resource.h +++ b/chromium/ppapi/proxy/video_capture_resource.h @@ -29,9 +29,6 @@ class VideoCaptureResource } // PPB_VideoCapture_API implementation. - virtual int32_t EnumerateDevices0_2( - PP_Resource* devices, - scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t EnumerateDevices( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) OVERRIDE; diff --git a/chromium/ppapi/proxy/video_decoder_constants.h b/chromium/ppapi/proxy/video_decoder_constants.h new file mode 100644 index 00000000000..666ad46044d --- /dev/null +++ b/chromium/ppapi/proxy/video_decoder_constants.h @@ -0,0 +1,28 @@ +// Copyright (c) 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 PPAPI_PROXY_VIDEO_DECODER_CONSTANTS_H_ +#define PPAPI_PROXY_VIDEO_DECODER_CONSTANTS_H_ + +namespace ppapi { +namespace proxy { + +// These constants are shared by the video decoder resource and host. +enum { + // Maximum number of concurrent decodes which can be pending. + kMaximumPendingDecodes = 8, + + // Minimum size of shared-memory buffers (100 KB). Make them large since we + // try to reuse them. + kMinimumBitstreamBufferSize = 100 << 10, + + // Maximum size of shared-memory buffers (4 MB). This should be enough even + // for 4K video at reasonable compression levels. + kMaximumBitstreamBufferSize = 4 << 20 +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_VIDEO_DECODER_CONSTANTS_H_ diff --git a/chromium/ppapi/proxy/video_decoder_resource.cc b/chromium/ppapi/proxy/video_decoder_resource.cc new file mode 100644 index 00000000000..54ccfe78254 --- /dev/null +++ b/chromium/ppapi/proxy/video_decoder_resource.cc @@ -0,0 +1,518 @@ +// Copyright (c) 2012 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 "ppapi/proxy/video_decoder_resource.h" + +#include "base/bind.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/common/mailbox.h" +#include "ipc/ipc_message.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppb_opengles2.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_graphics_3d_proxy.h" +#include "ppapi/proxy/serialized_handle.h" +#include "ppapi/proxy/video_decoder_constants.h" +#include "ppapi/shared_impl/ppapi_globals.h" +#include "ppapi/shared_impl/ppb_graphics_3d_shared.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/shared_impl/resource_tracker.h" +#include "ppapi/thunk/enter.h" + +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_Graphics3D_API; +using ppapi::thunk::PPB_VideoDecoder_API; + +namespace ppapi { +namespace proxy { + +VideoDecoderResource::ShmBuffer::ShmBuffer( + scoped_ptr<base::SharedMemory> shm_ptr, + uint32_t size, + uint32_t shm_id) + : shm(shm_ptr.Pass()), addr(NULL), shm_id(shm_id) { + if (shm->Map(size)) + addr = shm->memory(); +} + +VideoDecoderResource::ShmBuffer::~ShmBuffer() { +} + +VideoDecoderResource::Texture::Texture(uint32_t texture_target, + const PP_Size& size) + : texture_target(texture_target), size(size) { +} + +VideoDecoderResource::Texture::~Texture() { +} + +VideoDecoderResource::Picture::Picture(int32_t decode_id, uint32_t texture_id) + : decode_id(decode_id), texture_id(texture_id) { +} + +VideoDecoderResource::Picture::~Picture() { +} + +VideoDecoderResource::VideoDecoderResource(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance), + num_decodes_(0), + get_picture_(NULL), + gles2_impl_(NULL), + initialized_(false), + testing_(false), + // Set |decoder_last_error_| to PP_OK after successful initialization. + // This makes error checking a little more concise, since we can check + // that the decoder has been initialized and hasn't returned an error by + // just testing |decoder_last_error_|. + decoder_last_error_(PP_ERROR_FAILED) { + // Clear the decode_ids_ array. + memset(decode_ids_, 0, arraysize(decode_ids_)); + SendCreate(RENDERER, PpapiHostMsg_VideoDecoder_Create()); +} + +VideoDecoderResource::~VideoDecoderResource() { + // Destroy any textures which haven't been dismissed. + TextureMap::iterator it = textures_.begin(); + for (; it != textures_.end(); ++it) + DeleteGLTexture(it->first); +} + +PPB_VideoDecoder_API* VideoDecoderResource::AsPPB_VideoDecoder_API() { + return this; +} + +int32_t VideoDecoderResource::Initialize( + PP_Resource graphics_context, + PP_VideoProfile profile, + PP_Bool allow_software_fallback, + scoped_refptr<TrackedCallback> callback) { + if (initialized_) + return PP_ERROR_FAILED; + if (profile < 0 || profile > PP_VIDEOPROFILE_MAX) + return PP_ERROR_BADARGUMENT; + if (initialize_callback_) + return PP_ERROR_INPROGRESS; + if (!graphics_context) + return PP_ERROR_BADRESOURCE; + + HostResource host_resource; + if (!testing_) { + // Create a new Graphics3D resource that can create texture resources to + // share with the plugin. We can't use the plugin's Graphics3D, since we + // create textures on a proxy thread, and would interfere with the plugin. + thunk::EnterResourceCreationNoLock enter_create(pp_instance()); + if (enter_create.failed()) + return PP_ERROR_FAILED; + int32_t attrib_list[] = {PP_GRAPHICS3DATTRIB_NONE}; + graphics3d_ = + ScopedPPResource(ScopedPPResource::PassRef(), + enter_create.functions()->CreateGraphics3D( + pp_instance(), graphics_context, attrib_list)); + EnterResourceNoLock<PPB_Graphics3D_API> enter_graphics(graphics3d_.get(), + false); + if (enter_graphics.failed()) + return PP_ERROR_BADRESOURCE; + + PPB_Graphics3D_Shared* ppb_graphics3d_shared = + static_cast<PPB_Graphics3D_Shared*>(enter_graphics.object()); + gles2_impl_ = ppb_graphics3d_shared->gles2_impl(); + host_resource = ppb_graphics3d_shared->host_resource(); + } + + initialize_callback_ = callback; + + Call<PpapiPluginMsg_VideoDecoder_InitializeReply>( + RENDERER, + PpapiHostMsg_VideoDecoder_Initialize( + host_resource, profile, PP_ToBool(allow_software_fallback)), + base::Bind(&VideoDecoderResource::OnPluginMsgInitializeComplete, this)); + + return PP_OK_COMPLETIONPENDING; +} + +int32_t VideoDecoderResource::Decode(uint32_t decode_id, + uint32_t size, + const void* buffer, + scoped_refptr<TrackedCallback> callback) { + if (decoder_last_error_) + return decoder_last_error_; + if (flush_callback_ || reset_callback_) + return PP_ERROR_FAILED; + if (decode_callback_) + return PP_ERROR_INPROGRESS; + if (size > kMaximumBitstreamBufferSize) + return PP_ERROR_NOMEMORY; + + // If we allow the plugin to call Decode again, we must have somewhere to + // copy their buffer. + DCHECK(!available_shm_buffers_.empty() || + shm_buffers_.size() < kMaximumPendingDecodes); + + // Count up, wrapping back to 0 before overflowing. + int32_t uid = ++num_decodes_; + if (uid == std::numeric_limits<int32_t>::max()) + num_decodes_ = 0; + + // Save decode_id in a ring buffer. The ring buffer is sized to store + // decode_id for the maximum picture delay. + decode_ids_[uid % kMaximumPictureDelay] = decode_id; + + if (available_shm_buffers_.empty() || + available_shm_buffers_.back()->shm->mapped_size() < size) { + uint32_t shm_id; + if (shm_buffers_.size() < kMaximumPendingDecodes) { + // Signal the host to create a new shm buffer by passing an index outside + // the legal range. + shm_id = static_cast<uint32_t>(shm_buffers_.size()); + } else { + // Signal the host to grow a buffer by passing a legal index. Choose the + // last available shm buffer for simplicity. + shm_id = available_shm_buffers_.back()->shm_id; + available_shm_buffers_.pop_back(); + } + + // Synchronously get shared memory. Use GenericSyncCall so we can get the + // reply params, which contain the handle. + uint32_t shm_size = 0; + IPC::Message reply; + ResourceMessageReplyParams reply_params; + int32_t result = + GenericSyncCall(RENDERER, + PpapiHostMsg_VideoDecoder_GetShm(shm_id, size), + &reply, + &reply_params); + if (result != PP_OK) + return PP_ERROR_FAILED; + if (!UnpackMessage<PpapiPluginMsg_VideoDecoder_GetShmReply>(reply, + &shm_size)) + return PP_ERROR_FAILED; + base::SharedMemoryHandle shm_handle = base::SharedMemory::NULLHandle(); + if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &shm_handle)) + return PP_ERROR_NOMEMORY; + scoped_ptr<base::SharedMemory> shm( + new base::SharedMemory(shm_handle, false /* read_only */)); + scoped_ptr<ShmBuffer> shm_buffer( + new ShmBuffer(shm.Pass(), shm_size, shm_id)); + if (!shm_buffer->addr) + return PP_ERROR_NOMEMORY; + + available_shm_buffers_.push_back(shm_buffer.get()); + if (shm_buffers_.size() < kMaximumPendingDecodes) { + shm_buffers_.push_back(shm_buffer.release()); + } else { + // Delete manually since ScopedVector won't delete the existing element if + // we just assign it. + delete shm_buffers_[shm_id]; + shm_buffers_[shm_id] = shm_buffer.release(); + } + } + + // At this point we should have shared memory to hold the plugin's buffer. + DCHECK(!available_shm_buffers_.empty() && + available_shm_buffers_.back()->shm->mapped_size() >= size); + + ShmBuffer* shm_buffer = available_shm_buffers_.back(); + available_shm_buffers_.pop_back(); + memcpy(shm_buffer->addr, buffer, size); + + Call<PpapiPluginMsg_VideoDecoder_DecodeReply>( + RENDERER, + PpapiHostMsg_VideoDecoder_Decode(shm_buffer->shm_id, size, uid), + base::Bind(&VideoDecoderResource::OnPluginMsgDecodeComplete, this)); + + // If we have another free buffer, or we can still create new buffers, let + // the plugin call Decode again. + if (!available_shm_buffers_.empty() || + shm_buffers_.size() < kMaximumPendingDecodes) + return PP_OK; + + // All buffers are busy and we can't create more. Delay completion until a + // buffer is available. + decode_callback_ = callback; + return PP_OK_COMPLETIONPENDING; +} + +int32_t VideoDecoderResource::GetPicture( + PP_VideoPicture* picture, + scoped_refptr<TrackedCallback> callback) { + if (decoder_last_error_) + return decoder_last_error_; + if (reset_callback_) + return PP_ERROR_FAILED; + if (get_picture_callback_) + return PP_ERROR_INPROGRESS; + + // If the next picture is ready, return it synchronously. + if (!received_pictures_.empty()) { + WriteNextPicture(picture); + return PP_OK; + } + + get_picture_callback_ = callback; + get_picture_ = picture; + return PP_OK_COMPLETIONPENDING; +} + +void VideoDecoderResource::RecyclePicture(const PP_VideoPicture* picture) { + if (decoder_last_error_) + return; + + Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture(picture->texture_id)); +} + +int32_t VideoDecoderResource::Flush(scoped_refptr<TrackedCallback> callback) { + if (decoder_last_error_) + return decoder_last_error_; + if (reset_callback_) + return PP_ERROR_FAILED; + if (flush_callback_) + return PP_ERROR_INPROGRESS; + flush_callback_ = callback; + + Call<PpapiPluginMsg_VideoDecoder_FlushReply>( + RENDERER, + PpapiHostMsg_VideoDecoder_Flush(), + base::Bind(&VideoDecoderResource::OnPluginMsgFlushComplete, this)); + + return PP_OK_COMPLETIONPENDING; +} + +int32_t VideoDecoderResource::Reset(scoped_refptr<TrackedCallback> callback) { + if (decoder_last_error_) + return decoder_last_error_; + if (flush_callback_) + return PP_ERROR_FAILED; + if (reset_callback_) + return PP_ERROR_INPROGRESS; + reset_callback_ = callback; + + // Cause any pending Decode or GetPicture callbacks to abort after we return, + // to avoid reentering the plugin. + if (TrackedCallback::IsPending(decode_callback_)) + decode_callback_->PostAbort(); + decode_callback_ = NULL; + if (TrackedCallback::IsPending(get_picture_callback_)) + get_picture_callback_->PostAbort(); + get_picture_callback_ = NULL; + Call<PpapiPluginMsg_VideoDecoder_ResetReply>( + RENDERER, + PpapiHostMsg_VideoDecoder_Reset(), + base::Bind(&VideoDecoderResource::OnPluginMsgResetComplete, this)); + + return PP_OK_COMPLETIONPENDING; +} + +void VideoDecoderResource::OnReplyReceived( + const ResourceMessageReplyParams& params, + const IPC::Message& msg) { + PPAPI_BEGIN_MESSAGE_MAP(VideoDecoderResource, msg) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_VideoDecoder_RequestTextures, OnPluginMsgRequestTextures) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_VideoDecoder_PictureReady, OnPluginMsgPictureReady) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_VideoDecoder_DismissPicture, OnPluginMsgDismissPicture) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_VideoDecoder_NotifyError, OnPluginMsgNotifyError) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( + PluginResource::OnReplyReceived(params, msg)) + PPAPI_END_MESSAGE_MAP() +} + +void VideoDecoderResource::SetForTest() { + testing_ = true; +} + +void VideoDecoderResource::OnPluginMsgRequestTextures( + const ResourceMessageReplyParams& params, + uint32_t num_textures, + const PP_Size& size, + uint32_t texture_target, + const std::vector<gpu::Mailbox>& mailboxes) { + DCHECK(num_textures); + DCHECK(mailboxes.empty() || mailboxes.size() == num_textures); + std::vector<uint32_t> texture_ids(num_textures); + if (gles2_impl_) { + gles2_impl_->GenTextures(num_textures, &texture_ids.front()); + for (uint32_t i = 0; i < num_textures; ++i) { + gles2_impl_->ActiveTexture(GL_TEXTURE0); + gles2_impl_->BindTexture(texture_target, texture_ids[i]); + gles2_impl_->TexParameteri( + texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gles2_impl_->TexParameteri( + texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gles2_impl_->TexParameterf( + texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gles2_impl_->TexParameterf( + texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + if (texture_target == GL_TEXTURE_2D) { + gles2_impl_->TexImage2D(texture_target, + 0, + GL_RGBA, + size.width, + size.height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + NULL); + } + if (!mailboxes.empty()) { + gles2_impl_->ProduceTextureCHROMIUM( + GL_TEXTURE_2D, reinterpret_cast<const GLbyte*>(mailboxes[i].name)); + } + + textures_.insert( + std::make_pair(texture_ids[i], Texture(texture_target, size))); + } + gles2_impl_->Flush(); + } else { + DCHECK(testing_); + // Create some fake texture ids so we can test picture handling. + for (uint32_t i = 0; i < num_textures; ++i) { + texture_ids[i] = i + 1; + textures_.insert( + std::make_pair(texture_ids[i], Texture(texture_target, size))); + } + } + + Post(RENDERER, PpapiHostMsg_VideoDecoder_AssignTextures(size, texture_ids)); +} + +void VideoDecoderResource::OnPluginMsgPictureReady( + const ResourceMessageReplyParams& params, + int32_t decode_id, + uint32_t texture_id) { + received_pictures_.push(Picture(decode_id, texture_id)); + + if (TrackedCallback::IsPending(get_picture_callback_)) { + // The plugin may call GetPicture in its callback. + scoped_refptr<TrackedCallback> callback; + callback.swap(get_picture_callback_); + PP_VideoPicture* picture = get_picture_; + get_picture_ = NULL; + WriteNextPicture(picture); + callback->Run(PP_OK); + } +} + +void VideoDecoderResource::OnPluginMsgDismissPicture( + const ResourceMessageReplyParams& params, + uint32_t texture_id) { + DeleteGLTexture(texture_id); + textures_.erase(texture_id); +} + +void VideoDecoderResource::OnPluginMsgNotifyError( + const ResourceMessageReplyParams& params, + int32_t error) { + decoder_last_error_ = error; + // Cause any pending callbacks to run immediately. Reentrancy isn't a problem, + // since the plugin wasn't calling us. + RunCallbackWithError(&initialize_callback_); + RunCallbackWithError(&decode_callback_); + RunCallbackWithError(&get_picture_callback_); + RunCallbackWithError(&flush_callback_); + RunCallbackWithError(&reset_callback_); +} + +void VideoDecoderResource::OnPluginMsgInitializeComplete( + const ResourceMessageReplyParams& params) { + decoder_last_error_ = params.result(); + if (decoder_last_error_ == PP_OK) + initialized_ = true; + + // Let the plugin call Initialize again from its callback in case of failure. + scoped_refptr<TrackedCallback> callback; + callback.swap(initialize_callback_); + callback->Run(decoder_last_error_); +} + +void VideoDecoderResource::OnPluginMsgDecodeComplete( + const ResourceMessageReplyParams& params, + uint32_t shm_id) { + if (shm_id >= shm_buffers_.size()) { + NOTREACHED(); + return; + } + // Make the shm buffer available. + available_shm_buffers_.push_back(shm_buffers_[shm_id]); + // If the plugin is waiting, let it call Decode again. + if (decode_callback_) { + scoped_refptr<TrackedCallback> callback; + callback.swap(decode_callback_); + callback->Run(PP_OK); + } +} + +void VideoDecoderResource::OnPluginMsgFlushComplete( + const ResourceMessageReplyParams& params) { + // All shm buffers should have been made available by now. + DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size()); + + if (get_picture_callback_) { + scoped_refptr<TrackedCallback> callback; + callback.swap(get_picture_callback_); + callback->Abort(); + } + + scoped_refptr<TrackedCallback> callback; + callback.swap(flush_callback_); + callback->Run(params.result()); +} + +void VideoDecoderResource::OnPluginMsgResetComplete( + const ResourceMessageReplyParams& params) { + // All shm buffers should have been made available by now. + DCHECK_EQ(shm_buffers_.size(), available_shm_buffers_.size()); + // Recycle any pictures which haven't been passed to the plugin. + while (!received_pictures_.empty()) { + Post(RENDERER, PpapiHostMsg_VideoDecoder_RecyclePicture( + received_pictures_.front().texture_id)); + received_pictures_.pop(); + } + + scoped_refptr<TrackedCallback> callback; + callback.swap(reset_callback_); + callback->Run(params.result()); +} + +void VideoDecoderResource::RunCallbackWithError( + scoped_refptr<TrackedCallback>* callback) { + if (TrackedCallback::IsPending(*callback)) { + scoped_refptr<TrackedCallback> temp; + callback->swap(temp); + temp->Run(decoder_last_error_); + } +} + +void VideoDecoderResource::DeleteGLTexture(uint32_t id) { + if (gles2_impl_) { + gles2_impl_->DeleteTextures(1, &id); + gles2_impl_->Flush(); + } +} + +void VideoDecoderResource::WriteNextPicture(PP_VideoPicture* pp_picture) { + DCHECK(!received_pictures_.empty()); + Picture& picture = received_pictures_.front(); + // Internally, we identify decodes by a unique id, which the host returns + // to us in the picture. Use this to get the plugin's decode_id. + pp_picture->decode_id = decode_ids_[picture.decode_id % kMaximumPictureDelay]; + pp_picture->texture_id = picture.texture_id; + TextureMap::iterator it = textures_.find(picture.texture_id); + if (it != textures_.end()) { + pp_picture->texture_target = it->second.texture_target; + pp_picture->texture_size = it->second.size; + } else { + NOTREACHED(); + } + received_pictures_.pop(); +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/video_decoder_resource.h b/chromium/ppapi/proxy/video_decoder_resource.h new file mode 100644 index 00000000000..a466eb2774f --- /dev/null +++ b/chromium/ppapi/proxy/video_decoder_resource.h @@ -0,0 +1,181 @@ +// Copyright (c) 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 PPAPI_PROXY_VIDEO_DECODER_RESOURCE_H_ +#define PPAPI_PROXY_VIDEO_DECODER_RESOURCE_H_ + +#include <queue> + +#include "base/containers/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "ppapi/proxy/connection.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/shared_impl/scoped_pp_resource.h" +#include "ppapi/thunk/ppb_video_decoder_api.h" + +namespace gpu { +struct Mailbox; +namespace gles2 { +class GLES2Implementation; +} +} + +namespace ppapi { + +class PPB_Graphics3D_Shared; +class TrackedCallback; + +namespace proxy { + +class PPAPI_PROXY_EXPORT VideoDecoderResource + : public PluginResource, + public thunk::PPB_VideoDecoder_API { + public: + VideoDecoderResource(Connection connection, PP_Instance instance); + virtual ~VideoDecoderResource(); + + // Resource overrides. + virtual thunk::PPB_VideoDecoder_API* AsPPB_VideoDecoder_API() OVERRIDE; + + // PPB_VideoDecoder_API implementation. + virtual int32_t Initialize(PP_Resource graphics_context, + PP_VideoProfile profile, + PP_Bool allow_software_fallback, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t Decode(uint32_t decode_id, + uint32_t size, + const void* buffer, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t GetPicture(PP_VideoPicture* picture, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual void RecyclePicture(const PP_VideoPicture* picture) OVERRIDE; + virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t Reset(scoped_refptr<TrackedCallback> callback) OVERRIDE; + + // PluginResource implementation. + virtual void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) OVERRIDE; + + // Called only by unit tests. This bypasses Graphics3D setup, which doesn't + // work in ppapi::proxy::PluginProxyTest. + void SetForTest(); + + private: + // Struct to hold a shared memory buffer. + struct ShmBuffer { + ShmBuffer(scoped_ptr<base::SharedMemory> shm, + uint32_t size, + uint32_t shm_id); + ~ShmBuffer(); + + const scoped_ptr<base::SharedMemory> shm; + void* addr; + // Index into shm_buffers_ vector, used as an id. This should map 1:1 to + // the index on the host side of the proxy. + const uint32_t shm_id; + }; + + // Struct to hold texture information. + struct Texture { + Texture(uint32_t texture_target, const PP_Size& size); + ~Texture(); + + const uint32_t texture_target; + const PP_Size size; + }; + + // Struct to hold a picture received from the decoder. + struct Picture { + Picture(int32_t decode_id, uint32_t texture_id); + ~Picture(); + + int32_t decode_id; + uint32_t texture_id; + }; + + int32_t InitializeInternal(PP_Resource graphics_context, + PP_VideoProfile profile, + PP_Bool allow_software_fallback, + scoped_refptr<TrackedCallback> callback, + bool testing); + + // Unsolicited reply message handlers. + void OnPluginMsgRequestTextures(const ResourceMessageReplyParams& params, + uint32_t num_textures, + const PP_Size& size, + uint32_t texture_target, + const std::vector<gpu::Mailbox>& mailboxes); + void OnPluginMsgPictureReady(const ResourceMessageReplyParams& params, + int32_t decode_id, + uint32_t texture_id); + void OnPluginMsgDismissPicture(const ResourceMessageReplyParams& params, + uint32_t texture_id); + void OnPluginMsgNotifyError(const ResourceMessageReplyParams& params, + int32_t error); + + // Reply message handlers for operations that are done in the host. + void OnPluginMsgInitializeComplete(const ResourceMessageReplyParams& params); + void OnPluginMsgDecodeComplete(const ResourceMessageReplyParams& params, + uint32_t shm_id); + void OnPluginMsgFlushComplete(const ResourceMessageReplyParams& params); + void OnPluginMsgResetComplete(const ResourceMessageReplyParams& params); + + void RunCallbackWithError(scoped_refptr<TrackedCallback>* callback); + void DeleteGLTexture(uint32_t texture_id); + void WriteNextPicture(PP_VideoPicture* picture); + + // ScopedVector to own the shared memory buffers. + ScopedVector<ShmBuffer> shm_buffers_; + + // List of available shared memory buffers. + typedef std::vector<ShmBuffer*> ShmBufferList; + ShmBufferList available_shm_buffers_; + + // Map of GL texture id to texture info. + typedef base::hash_map<uint32_t, Texture> TextureMap; + TextureMap textures_; + + // Queue of received pictures. + typedef std::queue<Picture> PictureQueue; + PictureQueue received_pictures_; + + // Pending callbacks. + scoped_refptr<TrackedCallback> initialize_callback_; + scoped_refptr<TrackedCallback> decode_callback_; + scoped_refptr<TrackedCallback> get_picture_callback_; + scoped_refptr<TrackedCallback> flush_callback_; + scoped_refptr<TrackedCallback> reset_callback_; + + // Number of Decode calls made, mod 2^31, to serve as a uid for each decode. + int32_t num_decodes_; + // The maximum delay (in Decode calls) before we receive a picture. If we + // haven't received a picture from a Decode call after this many successive + // calls to Decode, then we will never receive a picture from the call. + // Note that this isn't guaranteed by H264 or other codecs. In practice, this + // number is less than 16. Make it much larger just to be safe. + // NOTE: because we count decodes mod 2^31, this value must be a power of 2. + static const int kMaximumPictureDelay = 128; + uint32_t decode_ids_[kMaximumPictureDelay]; + + // State for pending get_picture_callback_. + PP_VideoPicture* get_picture_; + + ScopedPPResource graphics3d_; + gpu::gles2::GLES2Implementation* gles2_impl_; + + bool initialized_; + bool testing_; + int32_t decoder_last_error_; + + DISALLOW_COPY_AND_ASSIGN(VideoDecoderResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_VIDEO_DECODER_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/video_decoder_resource_unittest.cc b/chromium/ppapi/proxy/video_decoder_resource_unittest.cc new file mode 100644 index 00000000000..b9f0e7918d4 --- /dev/null +++ b/chromium/ppapi/proxy/video_decoder_resource_unittest.cc @@ -0,0 +1,583 @@ +// 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. + +#include <GLES2/gl2.h> + +#include "base/memory/shared_memory.h" +#include "base/message_loop/message_loop.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppb_video_decoder.h" +#include "ppapi/proxy/locking_resource_releaser.h" +#include "ppapi/proxy/plugin_message_filter.h" +#include "ppapi/proxy/ppapi_message_utils.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/proxy/ppb_graphics_3d_proxy.h" +#include "ppapi/proxy/video_decoder_constants.h" +#include "ppapi/proxy/video_decoder_resource.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/thunk/thunk.h" + +using ppapi::proxy::ResourceMessageTestSink; + +namespace ppapi { +namespace proxy { + +namespace { + +const PP_Bool kAllowSoftwareFallback = PP_TRUE; +const PP_Resource kGraphics3D = 7; +const uint32_t kShmSize = 256; +const size_t kDecodeBufferSize = 16; +const uint32_t kDecodeId = 5; +const uint32_t kTextureId1 = 1; +const uint32_t kTextureId2 = 2; +const uint32_t kNumRequestedTextures = 2; + +class MockCompletionCallback { + public: + MockCompletionCallback() : called_(false) {} + + bool called() { return called_; } + int32_t result() { return result_; } + + void Reset() { called_ = false; } + + static void Callback(void* user_data, int32_t result) { + MockCompletionCallback* that = + reinterpret_cast<MockCompletionCallback*>(user_data); + that->called_ = true; + that->result_ = result; + } + + private: + bool called_; + int32_t result_; +}; + +class VideoDecoderResourceTest : public PluginProxyTest { + public: + VideoDecoderResourceTest() + : decoder_iface_(thunk::GetPPB_VideoDecoder_0_1_Thunk()) {} + + const PPB_VideoDecoder_0_1* decoder_iface() const { return decoder_iface_; } + + void SendReply(const ResourceMessageCallParams& params, + int32_t result, + const IPC::Message& nested_message) { + ResourceMessageReplyParams reply_params(params.pp_resource(), + params.sequence()); + reply_params.set_result(result); + PluginMessageFilter::DispatchResourceReplyForTest(reply_params, + nested_message); + } + + void SendReplyWithHandle(const ResourceMessageCallParams& params, + int32_t result, + const IPC::Message& nested_message, + const SerializedHandle& handle) { + ResourceMessageReplyParams reply_params(params.pp_resource(), + params.sequence()); + reply_params.set_result(result); + reply_params.AppendHandle(handle); + PluginMessageFilter::DispatchResourceReplyForTest(reply_params, + nested_message); + } + + PP_Resource CreateDecoder() { + PP_Resource result = decoder_iface()->Create(pp_instance()); + if (result) { + ProxyAutoLock lock; + ppapi::Resource* resource = + GetGlobals()->GetResourceTracker()->GetResource(result); + proxy::VideoDecoderResource* decoder = + static_cast<proxy::VideoDecoderResource*>(resource); + decoder->SetForTest(); + } + + return result; + } + + PP_Resource CreateGraphics3d() { + ProxyAutoLock lock; + + HostResource host_resource; + host_resource.SetHostResource(pp_instance(), kGraphics3D); + scoped_refptr<ppapi::proxy::Graphics3D> graphics_3d( + new ppapi::proxy::Graphics3D(host_resource)); + return graphics_3d->GetReference(); + } + + PP_Resource CreateAndInitializeDecoder() { + PP_Resource decoder = CreateDecoder(); + LockingResourceReleaser graphics3d(CreateGraphics3d()); + MockCompletionCallback cb; + int32_t result = decoder_iface()->Initialize( + decoder, + graphics3d.get(), + PP_VIDEOPROFILE_H264MAIN, + PP_TRUE /* allow_software_fallback */, + PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, + &cb)); + if (result != PP_OK_COMPLETIONPENDING) + return 0; + ResourceMessageCallParams params; + IPC::Message msg; + if (!sink().GetFirstResourceCallMatching( + PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)) + return 0; + sink().ClearMessages(); + SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); + return decoder; + } + + int32_t CallDecode(PP_Resource pp_decoder, + MockCompletionCallback* cb, + const PpapiHostMsg_VideoDecoder_GetShm* expected_shm_msg) { + // Set up a handler in case the resource sends a sync message to create + // shared memory. + PpapiPluginMsg_VideoDecoder_GetShmReply shm_msg_reply(kShmSize); + ResourceSyncCallHandler shm_msg_handler( + &sink(), PpapiHostMsg_VideoDecoder_GetShm::ID, PP_OK, shm_msg_reply); + sink().AddFilter(&shm_msg_handler); + + base::SharedMemory shm; + if (expected_shm_msg) { + shm.CreateAnonymous(kShmSize); + base::SharedMemoryHandle shm_handle; + shm.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle); + SerializedHandle serialized_handle(shm_handle, kShmSize); + shm_msg_handler.set_serialized_handle(&serialized_handle); + } + + memset(decode_buffer_, 0x55, kDecodeBufferSize); + int32_t result = + decoder_iface()->Decode(pp_decoder, + kDecodeId, + kDecodeBufferSize, + decode_buffer_, + PP_MakeOptionalCompletionCallback( + &MockCompletionCallback::Callback, cb)); + + if (expected_shm_msg) { + uint32_t shm_id, shm_size, expected_shm_id, expected_shm_size; + UnpackMessage<PpapiHostMsg_VideoDecoder_GetShm>( + *expected_shm_msg, &expected_shm_id, &expected_shm_size); + if (shm_msg_handler.last_handled_msg().type() == 0 || + !UnpackMessage<PpapiHostMsg_VideoDecoder_GetShm>( + shm_msg_handler.last_handled_msg(), &shm_id, &shm_size) || + shm_id != expected_shm_id || + shm_size != expected_shm_size) { + // Signal that the expected shm message wasn't sent by failing. + result = PP_ERROR_FAILED; + } + } + + sink().RemoveFilter(&shm_msg_handler); + return result; + } + + int32_t CallGetPicture(PP_Resource pp_decoder, + PP_VideoPicture* picture, + MockCompletionCallback* cb) { + int32_t result = + decoder_iface()->GetPicture(pp_decoder, + picture, + PP_MakeOptionalCompletionCallback( + &MockCompletionCallback::Callback, cb)); + return result; + } + + void CallRecyclePicture(PP_Resource pp_decoder, + const PP_VideoPicture& picture) { + decoder_iface()->RecyclePicture(pp_decoder, &picture); + } + + int32_t CallFlush(PP_Resource pp_decoder, MockCompletionCallback* cb) { + int32_t result = + decoder_iface()->Flush(pp_decoder, + PP_MakeOptionalCompletionCallback( + &MockCompletionCallback::Callback, cb)); + return result; + } + + int32_t CallReset(PP_Resource pp_decoder, MockCompletionCallback* cb) { + int32_t result = + decoder_iface()->Reset(pp_decoder, + PP_MakeOptionalCompletionCallback( + &MockCompletionCallback::Callback, cb)); + return result; + } + + void SendDecodeReply(const ResourceMessageCallParams& params, + uint32_t shm_id) { + SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id)); + } + + void SendPictureReady(const ResourceMessageCallParams& params, + uint32_t decode_count, + uint32_t texture_id) { + SendReply( + params, + PP_OK, + PpapiPluginMsg_VideoDecoder_PictureReady(decode_count, texture_id)); + } + + void SendFlushReply(const ResourceMessageCallParams& params) { + SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_FlushReply()); + } + + void SendResetReply(const ResourceMessageCallParams& params) { + SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_ResetReply()); + } + + void SendRequestTextures(const ResourceMessageCallParams& params) { + SendReply(params, + PP_OK, + PpapiPluginMsg_VideoDecoder_RequestTextures( + kNumRequestedTextures, + PP_MakeSize(320, 240), + GL_TEXTURE_2D, + std::vector<gpu::Mailbox>())); + } + + void SendNotifyError(const ResourceMessageCallParams& params, int32_t error) { + SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_NotifyError(error)); + } + + bool CheckDecodeMsg(ResourceMessageCallParams* params, + uint32_t* shm_id, + uint32_t* size, + int32_t* decode_id) { + IPC::Message msg; + if (!sink().GetFirstResourceCallMatching( + PpapiHostMsg_VideoDecoder_Decode::ID, params, &msg)) + return false; + sink().ClearMessages(); + return UnpackMessage<PpapiHostMsg_VideoDecoder_Decode>( + msg, shm_id, size, decode_id); + } + + bool CheckRecyclePictureMsg(ResourceMessageCallParams* params, + uint32_t* texture_id) { + IPC::Message msg; + if (!sink().GetFirstResourceCallMatching( + PpapiHostMsg_VideoDecoder_RecyclePicture::ID, params, &msg)) + return false; + sink().ClearMessages(); + return UnpackMessage<PpapiHostMsg_VideoDecoder_RecyclePicture>(msg, + texture_id); + } + + bool CheckFlushMsg(ResourceMessageCallParams* params) { + return CheckMsg(params, PpapiHostMsg_VideoDecoder_Flush::ID); + } + + bool CheckResetMsg(ResourceMessageCallParams* params) { + return CheckMsg(params, PpapiHostMsg_VideoDecoder_Reset::ID); + } + + void ClearCallbacks(PP_Resource pp_decoder) { + ResourceMessageCallParams params; + MockCompletionCallback cb; + + // Reset to abort Decode and GetPicture callbacks. + CallReset(pp_decoder, &cb); + // Initialize params so we can reply to the Reset. + CheckResetMsg(¶ms); + // Run the Reset callback. + SendResetReply(params); + } + + private: + bool CheckMsg(ResourceMessageCallParams* params, int id) { + IPC::Message msg; + if (!sink().GetFirstResourceCallMatching(id, params, &msg)) + return false; + sink().ClearMessages(); + return true; + } + + const PPB_VideoDecoder_0_1* decoder_iface_; + + char decode_buffer_[kDecodeBufferSize]; +}; + +} // namespace + +TEST_F(VideoDecoderResourceTest, Initialize) { + // Initialize with 0 graphics3d_context should fail. + { + LockingResourceReleaser decoder(CreateDecoder()); + MockCompletionCallback cb; + int32_t result = decoder_iface()->Initialize( + decoder.get(), + 0 /* invalid 3d graphics */, + PP_VIDEOPROFILE_H264MAIN, + kAllowSoftwareFallback, + PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, + &cb)); + ASSERT_EQ(PP_ERROR_BADRESOURCE, result); + } + // Initialize with bad profile value should fail. + { + LockingResourceReleaser decoder(CreateDecoder()); + MockCompletionCallback cb; + int32_t result = decoder_iface()->Initialize( + decoder.get(), + 1 /* non-zero resource */, + static_cast<PP_VideoProfile>(-1), + kAllowSoftwareFallback, + PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, + &cb)); + ASSERT_EQ(PP_ERROR_BADARGUMENT, result); + } + // Initialize with valid graphics3d_context and profile should succeed. + { + LockingResourceReleaser decoder(CreateDecoder()); + LockingResourceReleaser graphics3d(CreateGraphics3d()); + MockCompletionCallback cb; + int32_t result = decoder_iface()->Initialize( + decoder.get(), + graphics3d.get(), + PP_VIDEOPROFILE_H264MAIN, + kAllowSoftwareFallback, + PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, + &cb)); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); + ASSERT_TRUE(decoder_iface()->IsVideoDecoder(decoder.get())); + + // Another attempt while pending should fail. + result = decoder_iface()->Initialize( + decoder.get(), + graphics3d.get(), + PP_VIDEOPROFILE_H264MAIN, + kAllowSoftwareFallback, + PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, + &cb)); + ASSERT_EQ(PP_ERROR_INPROGRESS, result); + + // Check for host message and send a reply to complete initialization. + ResourceMessageCallParams params; + IPC::Message msg; + ASSERT_TRUE(sink().GetFirstResourceCallMatching( + PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)); + sink().ClearMessages(); + SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); + ASSERT_TRUE(cb.called()); + ASSERT_EQ(PP_OK, cb.result()); + } +} + +TEST_F(VideoDecoderResourceTest, Uninitialized) { + // Operations on uninitialized decoders should fail. + LockingResourceReleaser decoder(CreateDecoder()); + MockCompletionCallback uncalled_cb; + + ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb, NULL)); + ASSERT_FALSE(uncalled_cb.called()); + + ASSERT_EQ(PP_ERROR_FAILED, CallGetPicture(decoder.get(), NULL, &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + + ASSERT_EQ(PP_ERROR_FAILED, CallFlush(decoder.get(), &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + + ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); +} + +// TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply +// message for GetShm isn't received, causing Decode to fail. +// http://crbug.com/379260 +#if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) +TEST_F(VideoDecoderResourceTest, DecodeAndGetPicture) { + LockingResourceReleaser decoder(CreateAndInitializeDecoder()); + ResourceMessageCallParams params, params2; + MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; + + uint32_t shm_id; + uint32_t decode_size; + int32_t decode_id; + // Call Decode until we have the maximum pending, minus one. + for (uint32_t i = 0; i < kMaximumPendingDecodes - 1; i++) { + PpapiHostMsg_VideoDecoder_GetShm shm_msg(i, kDecodeBufferSize); + ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &uncalled_cb, &shm_msg)); + ASSERT_FALSE(uncalled_cb.called()); + CheckDecodeMsg(¶ms, &shm_id, &decode_size, &decode_id); + ASSERT_EQ(i, shm_id); + ASSERT_EQ(kDecodeBufferSize, decode_size); + // The resource generates uids internally, starting at 1. + int32_t uid = i + 1; + ASSERT_EQ(uid, decode_id); + } + // Once we've allocated the maximum number of buffers, we must wait. + PpapiHostMsg_VideoDecoder_GetShm shm_msg(7U, kDecodeBufferSize); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, + CallDecode(decoder.get(), &decode_cb, &shm_msg)); + CheckDecodeMsg(¶ms, &shm_id, &decode_size, &decode_id); + ASSERT_EQ(7U, shm_id); + ASSERT_EQ(kDecodeBufferSize, decode_size); + + // Calling Decode when another Decode is pending should fail. + ASSERT_EQ(PP_ERROR_INPROGRESS, CallDecode(decoder.get(), &uncalled_cb, NULL)); + ASSERT_FALSE(uncalled_cb.called()); + // Free up the first decode buffer. + SendDecodeReply(params, 0U); + // The decoder should run the pending callback. + ASSERT_TRUE(decode_cb.called()); + ASSERT_EQ(PP_OK, decode_cb.result()); + decode_cb.Reset(); + + // Now try to get a picture. No picture ready message has been received yet. + PP_VideoPicture picture; + ASSERT_EQ(PP_OK_COMPLETIONPENDING, + CallGetPicture(decoder.get(), &picture, &get_picture_cb)); + ASSERT_FALSE(get_picture_cb.called()); + // Calling GetPicture when another GetPicture is pending should fail. + ASSERT_EQ(PP_ERROR_INPROGRESS, + CallGetPicture(decoder.get(), &picture, &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + // Send 'request textures' message to initialize textures. + SendRequestTextures(params); + // Send a picture ready message for Decode call 1. The GetPicture callback + // should complete. + SendPictureReady(params, 1U, kTextureId1); + ASSERT_TRUE(get_picture_cb.called()); + ASSERT_EQ(PP_OK, get_picture_cb.result()); + ASSERT_EQ(kDecodeId, picture.decode_id); + get_picture_cb.Reset(); + + // Send a picture ready message for Decode call 2. Since there is no pending + // GetPicture call, the picture should be queued. + SendPictureReady(params, 2U, kTextureId2); + // The next GetPicture should return synchronously. + ASSERT_EQ(PP_OK, CallGetPicture(decoder.get(), &picture, &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + ASSERT_EQ(kDecodeId, picture.decode_id); +} +#endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) + +// TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply +// message for GetShm isn't received, causing Decode to fail. +// http://crbug.com/379260 +#if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) +TEST_F(VideoDecoderResourceTest, RecyclePicture) { + LockingResourceReleaser decoder(CreateAndInitializeDecoder()); + ResourceMessageCallParams params; + MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; + + // Get to a state where we have a picture to recycle. + PpapiHostMsg_VideoDecoder_GetShm shm_msg(0U, kDecodeBufferSize); + ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &decode_cb, &shm_msg)); + uint32_t shm_id; + uint32_t decode_size; + int32_t decode_id; + CheckDecodeMsg(¶ms, &shm_id, &decode_size, &decode_id); + SendDecodeReply(params, 0U); + // Send 'request textures' message to initialize textures. + SendRequestTextures(params); + // Call GetPicture and send 'picture ready' message to get a picture to + // recycle. + PP_VideoPicture picture; + ASSERT_EQ(PP_OK_COMPLETIONPENDING, + CallGetPicture(decoder.get(), &picture, &get_picture_cb)); + SendPictureReady(params, 0U, kTextureId1); + ASSERT_EQ(kTextureId1, picture.texture_id); + + CallRecyclePicture(decoder.get(), picture); + uint32_t texture_id; + ASSERT_TRUE(CheckRecyclePictureMsg(¶ms, &texture_id)); + ASSERT_EQ(kTextureId1, texture_id); + + ClearCallbacks(decoder.get()); +} +#endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) + +TEST_F(VideoDecoderResourceTest, Flush) { + LockingResourceReleaser decoder(CreateAndInitializeDecoder()); + ResourceMessageCallParams params, params2; + MockCompletionCallback flush_cb, get_picture_cb, uncalled_cb; + + ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallFlush(decoder.get(), &flush_cb)); + ASSERT_FALSE(flush_cb.called()); + ASSERT_TRUE(CheckFlushMsg(¶ms)); + + ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb, NULL)); + ASSERT_FALSE(uncalled_cb.called()); + + // Plugin can call GetPicture while Flush is pending. + ASSERT_EQ(PP_OK_COMPLETIONPENDING, + CallGetPicture(decoder.get(), NULL, &get_picture_cb)); + ASSERT_FALSE(get_picture_cb.called()); + + ASSERT_EQ(PP_ERROR_INPROGRESS, CallFlush(decoder.get(), &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + + ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + + // Plugin can call RecyclePicture while Flush is pending. + PP_VideoPicture picture; + picture.texture_id = kTextureId1; + CallRecyclePicture(decoder.get(), picture); + uint32_t texture_id; + ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2, &texture_id)); + + SendFlushReply(params); + // Any pending GetPicture call is aborted. + ASSERT_TRUE(get_picture_cb.called()); + ASSERT_EQ(PP_ERROR_ABORTED, get_picture_cb.result()); + ASSERT_TRUE(flush_cb.called()); + ASSERT_EQ(PP_OK, flush_cb.result()); +} + +// TODO(bbudge) Test Reset when we can run the message loop to get aborted +// callbacks to run. + +// TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply +// message for GetShm isn't received, causing Decode to fail. +// http://crbug.com/379260 +#if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) +TEST_F(VideoDecoderResourceTest, NotifyError) { + LockingResourceReleaser decoder(CreateAndInitializeDecoder()); + ResourceMessageCallParams params; + MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; + + // Call Decode and GetPicture to have some pending requests. + PpapiHostMsg_VideoDecoder_GetShm shm_msg(0U, kDecodeBufferSize); + ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &decode_cb, &shm_msg)); + ASSERT_FALSE(decode_cb.called()); + ASSERT_EQ(PP_OK_COMPLETIONPENDING, + CallGetPicture(decoder.get(), NULL, &get_picture_cb)); + ASSERT_FALSE(get_picture_cb.called()); + + // Send the decoder resource an unsolicited notify error message. We first + // need to initialize 'params' so the message is routed to the decoder. + uint32_t shm_id; + uint32_t decode_size; + int32_t decode_id; + CheckDecodeMsg(¶ms, &shm_id, &decode_size, &decode_id); + SendNotifyError(params, PP_ERROR_RESOURCE_FAILED); + + // Any pending message should be run with the reported error. + ASSERT_TRUE(get_picture_cb.called()); + ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, get_picture_cb.result()); + + // All further calls return the reported error. + ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, + CallDecode(decoder.get(), &uncalled_cb, NULL)); + ASSERT_FALSE(uncalled_cb.called()); + ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, + CallGetPicture(decoder.get(), NULL, &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallFlush(decoder.get(), &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); + ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallReset(decoder.get(), &uncalled_cb)); + ASSERT_FALSE(uncalled_cb.called()); +} +#endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/video_frame_resource.cc b/chromium/ppapi/proxy/video_frame_resource.cc new file mode 100644 index 00000000000..941471256ee --- /dev/null +++ b/chromium/ppapi/proxy/video_frame_resource.cc @@ -0,0 +1,96 @@ +// 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. + +#include "ppapi/proxy/video_frame_resource.h" + +#include "base/logging.h" +#include "ppapi/c/pp_bool.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +VideoFrameResource::VideoFrameResource(PP_Instance instance, + int32_t index, + MediaStreamBuffer* buffer) + : Resource(OBJECT_IS_PROXY, instance), + index_(index), + buffer_(buffer) { + DCHECK_EQ(buffer_->header.type, MediaStreamBuffer::TYPE_VIDEO); +} + +VideoFrameResource::~VideoFrameResource() { + CHECK(!buffer_) << "An unused (or unrecycled) frame is destroyed."; +} + +thunk::PPB_VideoFrame_API* VideoFrameResource::AsPPB_VideoFrame_API() { + return this; +} + +PP_TimeDelta VideoFrameResource::GetTimestamp() { + if (!buffer_) { + VLOG(1) << "Frame is invalid"; + return 0.0; + } + return buffer_->video.timestamp; +} + +void VideoFrameResource::SetTimestamp(PP_TimeDelta timestamp) { + if (!buffer_) { + VLOG(1) << "Frame is invalid"; + return; + } + buffer_->video.timestamp = timestamp; +} + +PP_VideoFrame_Format VideoFrameResource::GetFormat() { + if (!buffer_) { + VLOG(1) << "Frame is invalid"; + return PP_VIDEOFRAME_FORMAT_UNKNOWN; + } + return buffer_->video.format; +} + +PP_Bool VideoFrameResource::GetSize(PP_Size* size) { + if (!buffer_) { + VLOG(1) << "Frame is invalid"; + return PP_FALSE; + } + *size = buffer_->video.size; + return PP_TRUE; +} + +void* VideoFrameResource::GetDataBuffer() { + if (!buffer_) { + VLOG(1) << "Frame is invalid"; + return NULL; + } + return buffer_->video.data; +} + +uint32_t VideoFrameResource::GetDataBufferSize() { + if (!buffer_) { + VLOG(1) << "Frame is invalid"; + return 0; + } + return buffer_->video.data_size; +} + +MediaStreamBuffer* VideoFrameResource::GetBuffer() { + return buffer_; +} + +int32_t VideoFrameResource::GetBufferIndex() { + return index_; +} + +void VideoFrameResource::Invalidate() { + DCHECK(buffer_); + DCHECK_GE(index_, 0); + buffer_ = NULL; + index_ = -1; +} + +} // namespace proxy +} // namespace ppapi diff --git a/chromium/ppapi/proxy/video_frame_resource.h b/chromium/ppapi/proxy/video_frame_resource.h new file mode 100644 index 00000000000..92ac08e0c9d --- /dev/null +++ b/chromium/ppapi/proxy/video_frame_resource.h @@ -0,0 +1,52 @@ +// 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 PPAPI_PROXY_VIDEO_FRAME_RESOURCE_H_ +#define PPAPI_PROXY_VIDEO_FRAME_RESOURCE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/media_stream_buffer.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_video_frame_api.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT VideoFrameResource : public Resource, + public thunk::PPB_VideoFrame_API { + public: + VideoFrameResource(PP_Instance instance, + int32_t index, + MediaStreamBuffer* buffer); + + virtual ~VideoFrameResource(); + + // PluginResource overrides: + virtual thunk::PPB_VideoFrame_API* AsPPB_VideoFrame_API() OVERRIDE; + + // PPB_VideoFrame_API overrides: + virtual PP_TimeDelta GetTimestamp() OVERRIDE; + virtual void SetTimestamp(PP_TimeDelta timestamp) OVERRIDE; + virtual PP_VideoFrame_Format GetFormat() OVERRIDE; + virtual PP_Bool GetSize(PP_Size* size) OVERRIDE; + virtual void* GetDataBuffer() OVERRIDE; + virtual uint32_t GetDataBufferSize() OVERRIDE; + virtual MediaStreamBuffer* GetBuffer() OVERRIDE; + virtual int32_t GetBufferIndex() OVERRIDE; + virtual void Invalidate() OVERRIDE; + + // Frame index + int32_t index_; + + MediaStreamBuffer* buffer_; + + DISALLOW_COPY_AND_ASSIGN(VideoFrameResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_VIDEO_FRAME_RESOURCE_H_ diff --git a/chromium/ppapi/proxy/websocket_resource.cc b/chromium/ppapi/proxy/websocket_resource.cc index c998cd94b72..d03121a870f 100644 --- a/chromium/ppapi/proxy/websocket_resource.cc +++ b/chromium/ppapi/proxy/websocket_resource.cc @@ -15,7 +15,6 @@ #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/var.h" #include "ppapi/shared_impl/var_tracker.h" -#include "third_party/WebKit/public/web/WebSocket.h" namespace { @@ -137,17 +136,10 @@ int32_t WebSocketResource::Close(uint16_t code, // Validate |code| and |reason|. scoped_refptr<StringVar> reason_string_var; std::string reason_string; - blink::WebSocket::CloseEventCode event_code = - static_cast<blink::WebSocket::CloseEventCode>(code); - if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) { - // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are - // assigned to different values. A conversion is needed if - // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified. - event_code = blink::WebSocket::CloseEventCodeNotSpecified; - } else { - if (!(code == PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE || - (PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN <= code && - code <= PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX))) + if (code != PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) { + if (code != PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE && + (code < PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN || + code > PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX)) // RFC 6455 limits applications to use reserved connection close code in // section 7.4.2.. The WebSocket API (http://www.w3.org/TR/websockets/) // defines this out of range error as InvalidAccessError in JavaScript. @@ -195,7 +187,7 @@ int32_t WebSocketResource::Close(uint16_t code, // Close connection. state_ = PP_WEBSOCKETREADYSTATE_CLOSING; - PpapiHostMsg_WebSocket_Close msg(static_cast<int32_t>(event_code), + PpapiHostMsg_WebSocket_Close msg(static_cast<int32_t>(code), reason_string); Call<PpapiPluginMsg_WebSocket_CloseReply>(RENDERER, msg, base::Bind(&WebSocketResource::OnPluginMsgCloseReply, this)); @@ -336,7 +328,7 @@ void WebSocketResource::OnReplyReceived( return; } - IPC_BEGIN_MESSAGE_MAP(WebSocketResource, msg) + PPAPI_BEGIN_MESSAGE_MAP(WebSocketResource, msg) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_WebSocket_ReceiveTextReply, OnPluginMsgReceiveTextReply) @@ -356,7 +348,7 @@ void WebSocketResource::OnReplyReceived( PpapiPluginMsg_WebSocket_ClosedReply, OnPluginMsgClosedReply) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED()) - IPC_END_MESSAGE_MAP() + PPAPI_END_MESSAGE_MAP() } void WebSocketResource::OnPluginMsgConnectReply( diff --git a/chromium/ppapi/proxy/websocket_resource_unittest.cc b/chromium/ppapi/proxy/websocket_resource_unittest.cc index 5cfc71a88e3..eac6d8f8320 100644 --- a/chromium/ppapi/proxy/websocket_resource_unittest.cc +++ b/chromium/ppapi/proxy/websocket_resource_unittest.cc @@ -46,7 +46,7 @@ PP_CompletionCallback MakeCallback() { PP_Var MakeStringVar(const std::string& string) { if (!ppb_var_) - ppb_var_ = ppapi::PPB_Var_Shared::GetVarInterface1_1(); + ppb_var_ = ppapi::PPB_Var_Shared::GetVarInterface1_2(); return ppb_var_->VarFromUtf8(string.c_str(), string.length()); } |