diff options
Diffstat (limited to 'content')
14 files changed, 648 insertions, 28 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 0dc741e..570e48c 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -145,12 +145,17 @@ 'renderer/notification_provider.h', 'renderer/paint_aggregator.cc', 'renderer/paint_aggregator.h', + 'renderer/pepper/pepper_instance_state_accessor.h', + 'renderer/pepper/pepper_instance_state_accessor_impl.cc', + 'renderer/pepper/pepper_instance_state_accessor_impl.h', 'renderer/pepper/content_renderer_pepper_host_factory.cc', 'renderer/pepper/content_renderer_pepper_host_factory.h', 'renderer/pepper/pepper_broker_impl.cc', 'renderer/pepper/pepper_broker_impl.h', 'renderer/pepper/pepper_device_enumeration_event_handler.cc', 'renderer/pepper/pepper_device_enumeration_event_handler.h', + 'renderer/pepper/pepper_file_chooser_host.cc', + 'renderer/pepper/pepper_file_chooser_host.h', 'renderer/pepper/pepper_hung_plugin_filter.cc', 'renderer/pepper/pepper_hung_plugin_filter.h', 'renderer/pepper/pepper_in_process_resource_creation.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 520031b..0320e1f 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -521,7 +521,12 @@ 'content_shell_lib', 'test_support_content', '../base/base.gyp:test_support_base', + '../ipc/ipc.gyp:test_support_ipc', '../net/net.gyp:net_test_support', + '../ppapi/ppapi_internal.gyp:ppapi_host', + '../ppapi/ppapi_internal.gyp:ppapi_proxy', + '../ppapi/ppapi_internal.gyp:ppapi_shared', + '../ppapi/ppapi_internal.gyp:ppapi_unittest_shared', '../skia/skia.gyp:skia', '../testing/gtest.gyp:gtest', '../ui/ui.gyp:ui', @@ -537,6 +542,7 @@ 'test/content_browser_test.h', 'test/content_browser_test.cc', 'test/content_test_launcher.cc', + 'renderer/pepper/pepper_file_chooser_host_browsertest.cc', ], 'conditions': [ ['OS=="win"', { diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc index de7cf75..ec7e7ca 100644 --- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc +++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc @@ -4,6 +4,8 @@ #include "content/renderer/pepper/content_renderer_pepper_host_factory.h" +#include "content/renderer/pepper/pepper_instance_state_accessor.h" +#include "content/renderer/pepper/pepper_file_chooser_host.h" #include "ppapi/host/resource_host.h" #include "ppapi/proxy/ppapi_messages.h" @@ -12,8 +14,12 @@ using ppapi::host::ResourceHost; namespace content { ContentRendererPepperHostFactory::ContentRendererPepperHostFactory( - RenderViewImpl* render_view) - : render_view_(render_view) { + RenderViewImpl* render_view, + const ppapi::PpapiPermissions& permissions, + PepperInstanceStateAccessor* state) + : render_view_(render_view), + permissions_(permissions), + instance_state_(state) { } ContentRendererPepperHostFactory::~ContentRendererPepperHostFactory() { @@ -24,7 +30,21 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost( const ppapi::proxy::ResourceMessageCallParams& params, PP_Instance instance, const IPC::Message& message) { - // TODO(brettw) host creation goes here. + // Make sure the plugin is giving us a valid instance for this resource. + if (!instance_state_->IsValidInstance(instance)) + return scoped_ptr<ResourceHost>(); + + // Resources for dev interfaces. + // TODO(brettw) when we support any public or private interfaces, put them in + // a separate switch above. + if (permissions_.HasPermission(ppapi::PERMISSION_DEV)) { + switch (message.type()) { + case PpapiHostMsg_FileChooser_Create::ID: + return scoped_ptr<ResourceHost>(new PepperFileChooserHost( + host, instance, params.pp_resource(), render_view_, + instance_state_)); + } + } return scoped_ptr<ResourceHost>(); } diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.h b/content/renderer/pepper/content_renderer_pepper_host_factory.h index dbb36af..ad92f5b 100644 --- a/content/renderer/pepper/content_renderer_pepper_host_factory.h +++ b/content/renderer/pepper/content_renderer_pepper_host_factory.h @@ -7,14 +7,20 @@ #include "base/compiler_specific.h" #include "ppapi/host/host_factory.h" +#include "ppapi/shared_impl/ppapi_permissions.h" class RenderViewImpl; namespace content { +class PepperInstanceStateAccessor; + class ContentRendererPepperHostFactory : public ppapi::host::HostFactory { public: - explicit ContentRendererPepperHostFactory(RenderViewImpl* render_view); + explicit ContentRendererPepperHostFactory( + RenderViewImpl* render_view, + const ppapi::PpapiPermissions& permissions, + PepperInstanceStateAccessor* state); virtual ~ContentRendererPepperHostFactory(); virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost( @@ -24,7 +30,9 @@ class ContentRendererPepperHostFactory : public ppapi::host::HostFactory { const IPC::Message& message) OVERRIDE; private: - RenderViewImpl* render_view_; + RenderViewImpl* render_view_; // Non-owning. + ppapi::PpapiPermissions permissions_; + PepperInstanceStateAccessor* instance_state_; // Non-owning. DISALLOW_COPY_AND_ASSIGN(ContentRendererPepperHostFactory); }; diff --git a/content/renderer/pepper/pepper_file_chooser_host.cc b/content/renderer/pepper/pepper_file_chooser_host.cc new file mode 100644 index 0000000..79c825f --- /dev/null +++ b/content/renderer/pepper/pepper_file_chooser_host.cc @@ -0,0 +1,176 @@ +// 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 "content/renderer/pepper/pepper_file_chooser_host.h" + +#include "base/file_path.h" +#include "base/utf_string_conversions.h" +#include "content/renderer/pepper/pepper_instance_state_accessor.h" +#include "content/renderer/render_view_impl.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/host/dispatch_host_message.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_file_ref_proxy.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserCompletion.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" +#include "webkit/plugins/ppapi/ppb_file_ref_impl.h" + +namespace content { + +class PepperFileChooserHost::CompletionHandler + : public WebKit::WebFileChooserCompletion { + public: + CompletionHandler(const base::WeakPtr<PepperFileChooserHost>& host) + : host_(host) { + } + + virtual ~CompletionHandler() {} + + virtual void didChooseFile( + const WebKit::WebVector<WebKit::WebString>& file_names) { + if (host_) { + std::vector<PepperFileChooserHost::ChosenFileInfo> files; + for (size_t i = 0; i < file_names.size(); i++) { + files.push_back(PepperFileChooserHost::ChosenFileInfo( + file_names[i].utf8(), std::string())); + } + host_->StoreChosenFiles(files); + } + + // It is the responsibility of this method to delete the instance. + delete this; + } + virtual void didChooseFile( + const WebKit::WebVector<SelectedFileInfo>& file_names) { + if (host_) { + std::vector<PepperFileChooserHost::ChosenFileInfo> files; + for (size_t i = 0; i < file_names.size(); i++) { + files.push_back(PepperFileChooserHost::ChosenFileInfo( + file_names[i].path.utf8(), + file_names[i].displayName.utf8())); + } + host_->StoreChosenFiles(files); + } + + // It is the responsibility of this method to delete the instance. + delete this; + } + + private: + base::WeakPtr<PepperFileChooserHost> host_; + + DISALLOW_COPY_AND_ASSIGN(CompletionHandler); +}; + +PepperFileChooserHost::ChosenFileInfo::ChosenFileInfo( + const std::string& path, + const std::string& display_name) + : path(path), + display_name(display_name) { +} + + +PepperFileChooserHost::PepperFileChooserHost( + ppapi::host::PpapiHost* host, + PP_Instance instance, + PP_Resource resource, + RenderViewImpl* render_view, + PepperInstanceStateAccessor* state) + : ResourceHost(host, instance, resource), + render_view_(render_view), + instance_state_(state), + handler_(NULL) { +} + +PepperFileChooserHost::~PepperFileChooserHost() { +} + +int32_t PepperFileChooserHost::OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) { + IPC_BEGIN_MESSAGE_MAP(PepperFileChooserHost, msg) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileChooser_Show, + OnMsgShow) + IPC_END_MESSAGE_MAP() + return PP_ERROR_FAILED; +} + +void PepperFileChooserHost::StoreChosenFiles( + const std::vector<ChosenFileInfo>& files) { + std::vector<ppapi::PPB_FileRef_CreateInfo> chosen_files; + for (size_t i = 0; i < files.size(); i++) { +#if defined(OS_WIN) + FilePath file_path(UTF8ToWide(files[i].path)); +#else + FilePath file_path(files[i].path); +#endif + + webkit::ppapi::PPB_FileRef_Impl* ref = + webkit::ppapi::PPB_FileRef_Impl::CreateExternal( + pp_instance(), file_path, files[i].display_name); + ppapi::PPB_FileRef_CreateInfo create_info; + ppapi::proxy::PPB_FileRef_Proxy::SerializeFileRef(ref->GetReference(), + &create_info); + chosen_files.push_back(create_info); + } + + reply_params_.set_result((chosen_files.size() > 0) ? PP_OK + : PP_ERROR_USERCANCEL); + host()->SendReply(reply_params_, + PpapiPluginMsg_FileChooser_ShowReply(chosen_files)); + + reply_params_ = ppapi::proxy::ResourceMessageReplyParams(); + handler_ = NULL; // Handler deletes itself. +} + +int32_t PepperFileChooserHost::OnMsgShow( + ppapi::host::HostMessageContext* context, + bool save_as, + bool open_multiple, + const std::string& suggested_file_name, + const std::vector<std::string>& accept_mime_types) { + if (handler_) + return PP_ERROR_INPROGRESS; // Already pending. + + if (!host()->permissions().HasPermission( + ppapi::PERMISSION_BYPASS_USER_GESTURE) && + !instance_state_->HasUserGesture(pp_instance())) { + return PP_ERROR_NO_USER_GESTURE; + } + + WebKit::WebFileChooserParams params; + if (save_as) { + params.saveAs = true; + params.initialValue = WebKit::WebString::fromUTF8( + suggested_file_name.data(), suggested_file_name.size()); + } else { + params.multiSelect = open_multiple; + } + std::vector<WebKit::WebString> mine_types(accept_mime_types.size()); + for (size_t i = 0; i < accept_mime_types.size(); i++) { + mine_types[i] = WebKit::WebString::fromUTF8( + accept_mime_types[i].data(), accept_mime_types[i].size()); + } + params.acceptTypes = mine_types; + params.directory = false; + + handler_ = new CompletionHandler(AsWeakPtr()); + if (!render_view_->runFileChooser(params, handler_)) { + delete handler_; + handler_ = NULL; + return PP_ERROR_NOACCESS; + } + + reply_params_ = ppapi::proxy::ResourceMessageReplyParams( + context->params.pp_resource(), + context->params.sequence()); + return PP_OK_COMPLETIONPENDING; +} + +} // namespace content diff --git a/content/renderer/pepper/pepper_file_chooser_host.h b/content/renderer/pepper/pepper_file_chooser_host.h new file mode 100644 index 0000000..8dbc4e3 --- /dev/null +++ b/content/renderer/pepper/pepper_file_chooser_host.h @@ -0,0 +1,68 @@ +// 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. + +#ifndef CONTENT_RENDERER_PEPPER_PEPPER_FILE_CHOOSER_HOST_H_ +#define CONTENT_RENDERER_PEPPER_PEPPER_FILE_CHOOSER_HOST_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/proxy/resource_message_params.h" + +class RenderViewImpl; + +namespace content { + +class PepperInstanceStateAccessor; + +class CONTENT_EXPORT PepperFileChooserHost + : public ppapi::host::ResourceHost, + public base::SupportsWeakPtr<PepperFileChooserHost> { + public: + // Structure to store the information about chosen files. + struct ChosenFileInfo { + ChosenFileInfo(const std::string& path, const std::string& display_name); + std::string path; + std::string display_name; // May be empty. + }; + + PepperFileChooserHost(ppapi::host::PpapiHost* host, + PP_Instance instance, + PP_Resource resource, + RenderViewImpl* render_view, + PepperInstanceStateAccessor* state); + virtual ~PepperFileChooserHost(); + + virtual int32_t OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) OVERRIDE; + + void StoreChosenFiles(const std::vector<ChosenFileInfo>& files); + + private: + class CompletionHandler; + + int32_t OnMsgShow(ppapi::host::HostMessageContext* context, + bool save_as, + bool open_multiple, + const std::string& suggested_file_name, + const std::vector<std::string>& accept_mime_types); + + // Non-owning pointers. + RenderViewImpl* render_view_; + PepperInstanceStateAccessor* instance_state_; + + ppapi::proxy::ResourceMessageReplyParams reply_params_; + CompletionHandler* handler_; + + DISALLOW_COPY_AND_ASSIGN(PepperFileChooserHost); +}; + +} // namespace ppapi + +#endif // CONTENT_RENDERER_PEPPER_PEPPER_FILE_CHOOSER_HOST_H_ diff --git a/content/renderer/pepper/pepper_file_chooser_host_browsertest.cc b/content/renderer/pepper/pepper_file_chooser_host_browsertest.cc new file mode 100644 index 0000000..6a482d3 --- /dev/null +++ b/content/renderer/pepper/pepper_file_chooser_host_browsertest.cc @@ -0,0 +1,175 @@ +// 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 "base/file_path.h" +#include "base/utf_string_conversions.h" +#include "content/public/test/render_view_test.h" +#include "content/common/view_messages.h" +#include "content/public/common/file_chooser_params.h" +#include "content/renderer/pepper/pepper_file_chooser_host.h" +#include "content/renderer/pepper/pepper_instance_state_accessor.h" +#include "content/renderer/render_view_impl.h" +#include "content/test/test_content_client.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/resource_message_params.h" +#include "ppapi/proxy/resource_message_test_sink.h" +#include "ppapi/shared_impl/ppapi_permissions.h" +#include "ppapi/shared_impl/ppb_file_ref_shared.h" +#include "ppapi/shared_impl/resource_tracker.h" +#include "ppapi/shared_impl/test_globals.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/dialogs/selected_file_info.h" + +namespace content { + +namespace { + +class PepperFileChooserHostTest : public RenderViewTest { + public: + PepperFileChooserHostTest() : pp_instance_(123456) {} + + virtual void SetUp() { + SetContentClient(&client_); + RenderViewTest::SetUp(); + + globals_.GetResourceTracker()->DidCreateInstance(pp_instance_); + } + virtual void TearDown() { + globals_.GetResourceTracker()->DidDeleteInstance(pp_instance_); + + RenderViewTest::TearDown(); + SetContentClient(NULL); + } + + PP_Instance pp_instance() const { return pp_instance_; } + + private: + PP_Instance pp_instance_; + + ppapi::TestGlobals globals_; + TestContentClient client_; +}; + +// For testing to convert our hardcoded file paths to 8-bit. +std::string FilePathToUTF8(const FilePath::StringType& path) { +#if defined(OS_WIN) + return UTF16ToUTF8(path); +#else + return path; +#endif +} + +class MockInstanceState : public PepperInstanceStateAccessor { + public: + MockInstanceState() : has_user_gesture_(true) {} + virtual ~MockInstanceState() {} + + void set_has_user_gesture(bool has) { has_user_gesture_ = has; } + + // PepperInstanceStateAccessor. + virtual bool IsValidInstance(PP_Instance instance) OVERRIDE { + return true; + } + virtual bool HasUserGesture(PP_Instance instance) OVERRIDE { + return has_user_gesture_; + } + + private: + bool has_user_gesture_; +}; + +} // namespace + +TEST_F(PepperFileChooserHostTest, Show) { + PP_Resource pp_resource = 123; + + MockInstanceState state; + ppapi::proxy::ResourceMessageTestSink sink; + ppapi::host::PpapiHost host(&sink, NULL, ppapi::PpapiPermissions()); + RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_); + PepperFileChooserHost chooser(&host, pp_instance(), pp_resource, view_impl, + &state); + + std::vector<std::string> accept; + accept.push_back("text/plain"); + PpapiHostMsg_FileChooser_Show show_msg(false, false, std::string(), accept); + + ppapi::proxy::ResourceMessageCallParams call_params(pp_resource, 0); + ppapi::host::HostMessageContext context(call_params); + int32 result = chooser.OnResourceMessageReceived(show_msg, &context); + EXPECT_EQ(PP_OK_COMPLETIONPENDING, result); + + // The render view should have sent a chooser request to the browser + // (caught by the render thread's test message sink). + const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching( + ViewHostMsg_RunFileChooser::ID); + ASSERT_TRUE(msg); + ViewHostMsg_RunFileChooser::Schema::Param call_msg_param; + ASSERT_TRUE(ViewHostMsg_RunFileChooser::Read(msg, &call_msg_param)); + const FileChooserParams& chooser_params = call_msg_param.a; + + // Basic validation of request. + EXPECT_EQ(FileChooserParams::Open, chooser_params.mode); + ASSERT_EQ(1u, chooser_params.accept_types.size()); + EXPECT_EQ(accept[0], UTF16ToUTF8(chooser_params.accept_types[0])); + + // Send a chooser reply to the render view. Note our reply path has to have a + // path separator so we include both a Unix and a Windows one. + ui::SelectedFileInfo selected_info; + selected_info.display_name = FILE_PATH_LITERAL("Hello, world"); + selected_info.path = FilePath(FILE_PATH_LITERAL("myp\\ath/foo")); + std::vector<ui::SelectedFileInfo> selected_info_vector; + selected_info_vector.push_back(selected_info); + ViewMsg_RunFileChooserResponse response(view_impl->routing_id(), + selected_info_vector); + EXPECT_TRUE(view_impl->OnMessageReceived(response)); + + // This should have sent the Pepper reply to our test sink. + ppapi::proxy::ResourceMessageReplyParams reply_params; + IPC::Message reply_msg; + ASSERT_TRUE(sink.GetFirstResourceReplyMatching( + PpapiPluginMsg_FileChooser_ShowReply::ID, &reply_params, &reply_msg)); + + // Basic validation of reply. + EXPECT_EQ(call_params.sequence(), reply_params.sequence()); + EXPECT_EQ(PP_OK, reply_params.result()); + PpapiPluginMsg_FileChooser_ShowReply::Schema::Param reply_msg_param; + ASSERT_TRUE(PpapiPluginMsg_FileChooser_ShowReply::Read(&reply_msg, + &reply_msg_param)); + const std::vector<ppapi::PPB_FileRef_CreateInfo>& chooser_results = + reply_msg_param.a; + ASSERT_EQ(1u, chooser_results.size()); + // Note path is empty because this is an external filesystem. + EXPECT_EQ(std::string(), chooser_results[0].path); + EXPECT_EQ(FilePathToUTF8(selected_info.display_name), + chooser_results[0].name); +} + +TEST_F(PepperFileChooserHostTest, NoUserGesture) { + PP_Resource pp_resource = 123; + + MockInstanceState state; + ppapi::proxy::ResourceMessageTestSink sink; + ppapi::host::PpapiHost host(&sink, NULL, ppapi::PpapiPermissions()); + RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_); + PepperFileChooserHost chooser(&host, pp_instance(), pp_resource, view_impl, + &state); + + // Say there's no user gesture. + state.set_has_user_gesture(false); + + std::vector<std::string> accept; + accept.push_back("text/plain"); + PpapiHostMsg_FileChooser_Show show_msg(false, false, std::string(), accept); + + ppapi::proxy::ResourceMessageCallParams call_params(pp_resource, 0); + ppapi::host::HostMessageContext context(call_params); + int32 result = chooser.OnResourceMessageReceived(show_msg, &context); + EXPECT_EQ(PP_ERROR_NO_USER_GESTURE, result); +} + +} // namespace content diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.cc b/content/renderer/pepper/pepper_in_process_resource_creation.cc index 3371f75..af3e0e7 100644 --- a/content/renderer/pepper/pepper_in_process_resource_creation.cc +++ b/content/renderer/pepper/pepper_in_process_resource_creation.cc @@ -11,10 +11,12 @@ #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" #include "ppapi/host/ppapi_host.h" +#include "ppapi/proxy/file_chooser_resource.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppapi_permissions.h" #include "ppapi/shared_impl/resource_tracker.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" // Note that the code in the creation functions in this file should generally // be the same as that in ppapi/proxy/resource_creation_proxy.cc. See @@ -26,6 +28,7 @@ class PepperInProcessResourceCreation::PluginToHostRouter : public IPC::Sender { public: PluginToHostRouter(RenderViewImpl* render_view, + PepperInstanceStateAccessor* state, IPC::Sender* host_to_plugin_sender, const ppapi::PpapiPermissions& perms); virtual ~PluginToHostRouter() {} @@ -46,10 +49,11 @@ class PepperInProcessResourceCreation::PluginToHostRouter PepperInProcessResourceCreation::PluginToHostRouter::PluginToHostRouter( RenderViewImpl* render_view, + PepperInstanceStateAccessor* state, IPC::Sender* host_to_plugin_sender, const ppapi::PpapiPermissions& perms) : weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), - factory_(render_view), + factory_(render_view, perms, state), host_(host_to_plugin_sender, &factory_, perms) { } @@ -136,13 +140,24 @@ PepperInProcessResourceCreation::PepperInProcessResourceCreation( webkit::ppapi::PluginInstance* instance, const ppapi::PpapiPermissions& perms) : ResourceCreationImpl(instance), + instance_state_(instance->module()), host_to_plugin_router_(new HostToPluginRouter), plugin_to_host_router_( - new PluginToHostRouter(render_view, host_to_plugin_router_.get(), + new PluginToHostRouter(render_view, &instance_state_, + host_to_plugin_router_.get(), perms)) { } PepperInProcessResourceCreation::~PepperInProcessResourceCreation() { } +PP_Resource PepperInProcessResourceCreation::CreateFileChooser( + PP_Instance instance, + PP_FileChooserMode_Dev mode, + const char* accept_types) { + return (new ppapi::proxy::FileChooserResource( + plugin_to_host_router_.get(), + instance, mode, accept_types))->GetReference(); +} + } // namespace content diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.h b/content/renderer/pepper/pepper_in_process_resource_creation.h index 0f01b81..78216b2 100644 --- a/content/renderer/pepper/pepper_in_process_resource_creation.h +++ b/content/renderer/pepper/pepper_in_process_resource_creation.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "content/renderer/pepper/pepper_instance_state_accessor_impl.h" #include "webkit/plugins/ppapi/resource_creation_impl.h" class RenderViewImpl; @@ -42,7 +43,15 @@ class PepperInProcessResourceCreation const ppapi::PpapiPermissions& perms); virtual ~PepperInProcessResourceCreation(); + // ResourceCreation_API implementation. + virtual PP_Resource CreateFileChooser( + PP_Instance instance, + PP_FileChooserMode_Dev mode, + const char* accept_types) OVERRIDE; + private: + PepperInstanceStateAccessorImpl instance_state_; + class HostToPluginRouter; scoped_ptr<HostToPluginRouter> host_to_plugin_router_; diff --git a/content/renderer/pepper/pepper_instance_state_accessor.h b/content/renderer/pepper/pepper_instance_state_accessor.h new file mode 100644 index 0000000..120640c --- /dev/null +++ b/content/renderer/pepper/pepper_instance_state_accessor.h @@ -0,0 +1,33 @@ +// 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.
+
+#ifndef CONTENT_RENDERER_PEPPER_PEPPER_INSTANCE_STATE_ACCESSOR_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_INSTANCE_STATE_ACCESSOR_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+
+namespace content {
+
+// This interface provides functions for querying instance state for resource
+// host implementations. It allows us to mock out some of these interactions
+// for testing, as well as limit the dependencies on the webkit layer.
+class PepperInstanceStateAccessor {
+ public:
+ virtual ~PepperInstanceStateAccessor() {}
+
+ // Returns true if the given instance is valid for the host.
+ virtual bool IsValidInstance(PP_Instance instance) = 0;
+
+ // Returns true if the given instance is considered to be currently
+ // processing a user gesture or the plugin module has the "override user
+ // gesture" flag set (in which case it can always do things normally
+ // restricted by user gestures). Returns false if the instance is invalid or
+ // if there is no current user gesture.
+ virtual bool HasUserGesture(PP_Instance instance) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PEPPER_INSTANCE_STATE_ACCESSOR_H_
diff --git a/content/renderer/pepper/pepper_instance_state_accessor_impl.cc b/content/renderer/pepper/pepper_instance_state_accessor_impl.cc new file mode 100644 index 0000000..376d3aa --- /dev/null +++ b/content/renderer/pepper/pepper_instance_state_accessor_impl.cc @@ -0,0 +1,50 @@ +// 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 "content/renderer/pepper/pepper_instance_state_accessor_impl.h"
+
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "webkit/plugins/ppapi/host_globals.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+using webkit::ppapi::HostGlobals;
+using webkit::ppapi::PluginInstance;
+
+namespace content {
+
+PepperInstanceStateAccessorImpl::PepperInstanceStateAccessorImpl(
+ webkit::ppapi::PluginModule* module)
+ : module_(module) {
+}
+
+PepperInstanceStateAccessorImpl::~PepperInstanceStateAccessorImpl() {
+}
+
+bool PepperInstanceStateAccessorImpl::IsValidInstance(PP_Instance instance) {
+ return !!GetAndValidateInstance(instance);
+}
+
+bool PepperInstanceStateAccessorImpl::HasUserGesture(PP_Instance pp_instance) {
+ PluginInstance* instance = GetAndValidateInstance(pp_instance);
+ if (!instance)
+ return false;
+
+ if (instance->module()->permissions().HasPermission(
+ ppapi::PERMISSION_BYPASS_USER_GESTURE))
+ return true;
+ return instance->IsProcessingUserGesture();
+}
+
+PluginInstance* PepperInstanceStateAccessorImpl::GetAndValidateInstance(
+ PP_Instance pp_instance) {
+ PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance);
+ if (!instance)
+ return NULL;
+ if (instance->module() != module_)
+ return NULL;
+ return instance;
+}
+
+} // namespace content
diff --git a/content/renderer/pepper/pepper_instance_state_accessor_impl.h b/content/renderer/pepper/pepper_instance_state_accessor_impl.h new file mode 100644 index 0000000..108686e --- /dev/null +++ b/content/renderer/pepper/pepper_instance_state_accessor_impl.h @@ -0,0 +1,45 @@ +// 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.
+
+#ifndef CONTENT_RENDERER_PEPPER_PEPPER_INSTANCE_STATE_ACCESSOR_IMPL_H
+#define CONTENT_RENDERER_PEPPER_PEPPER_INSTANCE_STATE_ACCESSOR_IMPL_H
+
+#include "base/compiler_specific.h"
+#include "content/renderer/pepper/pepper_instance_state_accessor.h"
+
+namespace webkit {
+namespace ppapi {
+class PluginInstance;
+class PluginModule;
+}
+}
+
+namespace content {
+
+class PepperInstanceStateAccessorImpl : public PepperInstanceStateAccessor {
+ public:
+ PepperInstanceStateAccessorImpl(webkit::ppapi::PluginModule* module);
+ virtual ~PepperInstanceStateAccessorImpl();
+
+ // PepperInstanceStateAccessor implmentation.
+ virtual bool IsValidInstance(PP_Instance instance) OVERRIDE;
+ virtual bool HasUserGesture(PP_Instance pp_instance) OVERRIDE;
+
+ private:
+ // Retrieves the plugin instance object associated with the given PP_Instance
+ // and validates that it is one of the instances associated with our module.
+ // Returns NULL on failure.
+ //
+ // We use this to security check the PP_Instance values sent from a plugin to
+ // make sure it's not trying to spoof another instance.
+ webkit::ppapi::PluginInstance* GetAndValidateInstance(PP_Instance instance);
+
+ webkit::ppapi::PluginModule* module_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperInstanceStateAccessorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PEPPER_INSTANCE_STATE_ACCESSOR_IMPL_H
diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc index ec8057d..f66b4b3 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc @@ -41,10 +41,12 @@ #include "content/renderer/media/pepper_platform_video_decoder_impl.h" #include "content/renderer/p2p/p2p_transport_impl.h" #include "content/renderer/p2p/socket_dispatcher.h" +#include "content/renderer/pepper/content_renderer_pepper_host_factory.h" #include "content/renderer/pepper/pepper_broker_impl.h" #include "content/renderer/pepper/pepper_device_enumeration_event_handler.h" #include "content/renderer/pepper/pepper_hung_plugin_filter.h" #include "content/renderer/pepper/pepper_in_process_resource_creation.h" +#include "content/renderer/pepper/pepper_instance_state_accessor.h" #include "content/renderer/pepper/pepper_platform_audio_input_impl.h" #include "content/renderer/pepper/pepper_platform_audio_output_impl.h" #include "content/renderer/pepper/pepper_platform_context_3d_impl.h" @@ -63,6 +65,7 @@ #include "ppapi/c/dev/pp_video_dev.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/private/ppb_flash.h" +#include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/pepper_file_messages.h" #include "ppapi/proxy/ppapi_messages.h" @@ -75,8 +78,6 @@ #include "ppapi/thunk/ppb_tcp_server_socket_private_api.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserCompletion.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" @@ -105,13 +106,19 @@ namespace { class HostDispatcherWrapper : public webkit::ppapi::PluginDelegate::OutOfProcessProxy { public: - HostDispatcherWrapper() {} + HostDispatcherWrapper(RenderViewImpl* rv, + webkit::ppapi::PluginModule* module, + const ppapi::PpapiPermissions& perms) + : module_(module), + instance_state_(module), + host_factory_(rv, perms, &instance_state_) { + } virtual ~HostDispatcherWrapper() {} bool Init(const IPC::ChannelHandle& channel_handle, - PP_Module pp_module, PP_GetInterface_Func local_get_interface, const ppapi::Preferences& preferences, + const ppapi::PpapiPermissions& permissions, PepperHungPluginFilter* filter) { if (channel_handle.name.empty()) return false; @@ -124,7 +131,11 @@ class HostDispatcherWrapper dispatcher_delegate_.reset(new PepperProxyChannelDelegateImpl); dispatcher_.reset(new ppapi::proxy::HostDispatcher( - pp_module, local_get_interface, filter)); + module_->pp_module(), local_get_interface, filter)); + + host_.reset(new ppapi::host::PpapiHost(dispatcher_.get(), &host_factory_, + permissions)); + dispatcher_->AddFilter(host_.get()); if (!dispatcher_->InitHostWithChannel(dispatcher_delegate_.get(), channel_handle, @@ -151,6 +162,12 @@ class HostDispatcherWrapper } private: + webkit::ppapi::PluginModule* module_; + PepperInstanceStateAccessorImpl instance_state_; + ContentRendererPepperHostFactory host_factory_; + + scoped_ptr<ppapi::host::PpapiHost> host_; + scoped_ptr<ppapi::proxy::HostDispatcher> dispatcher_; scoped_ptr<ppapi::proxy::ProxyChannel::Delegate> dispatcher_delegate_; }; @@ -325,12 +342,13 @@ PepperPluginDelegateImpl::CreatePepperPluginModule( PepperPluginRegistry::GetInstance(), permissions); PepperPluginRegistry::GetInstance()->AddLiveModule(path, module); - scoped_ptr<HostDispatcherWrapper> dispatcher(new HostDispatcherWrapper); + scoped_ptr<HostDispatcherWrapper> dispatcher( + new HostDispatcherWrapper(render_view_, module, permissions)); if (!dispatcher->Init( channel_handle, - module->pp_module(), webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(), GetPreferences(), + permissions, hung_filter.get())) return scoped_refptr<webkit::ppapi::PluginModule>(); module->InitAsProxied(dispatcher.release()); @@ -348,6 +366,8 @@ scoped_refptr<webkit::ppapi::PluginModule> if (module) return module; + ppapi::PpapiPermissions permissions; + FilePath path(kBrowserPluginPath); scoped_refptr<PepperHungPluginFilter> hung_filter( new PepperHungPluginFilter(path, @@ -358,15 +378,16 @@ scoped_refptr<webkit::ppapi::PluginModule> module = new webkit::ppapi::PluginModule(kBrowserPluginName, path, registry, - ppapi::PpapiPermissions()); + permissions); RenderThreadImpl::current()->browser_plugin_registry()->AddModule( guest_process_id, module); - scoped_ptr<HostDispatcherWrapper> dispatcher(new HostDispatcherWrapper); + scoped_ptr<HostDispatcherWrapper> dispatcher( + new HostDispatcherWrapper(render_view_, module, permissions)); if (!dispatcher->Init( channel_handle, - module->pp_module(), webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(), GetPreferences(), + permissions, hung_filter.get())) return scoped_refptr<webkit::ppapi::PluginModule>(); module->InitAsProxied(dispatcher.release()); @@ -786,12 +807,6 @@ PepperPluginDelegateImpl::ConnectToBroker( return broker; } -bool PepperPluginDelegateImpl::RunFileChooser( - const WebKit::WebFileChooserParams& params, - WebKit::WebFileChooserCompletion* chooser_completion) { - return render_view_->runFileChooser(params, chooser_completion); -} - bool PepperPluginDelegateImpl::AsyncOpenFile( const FilePath& path, int flags, diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.h b/content/renderer/pepper/pepper_plugin_delegate_impl.h index d7d367b..984ae12 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h @@ -58,11 +58,9 @@ class PluginModule; } namespace WebKit { -class WebFileChooserCompletion; class WebGamepads; class WebMouseEvent; struct WebCompositionUnderline; -struct WebFileChooserParams; } namespace content { @@ -209,9 +207,6 @@ class PepperPluginDelegateImpl int total, bool final_result) OVERRIDE; virtual void SelectedFindResultChanged(int identifier, int index) OVERRIDE; - virtual bool RunFileChooser( - const WebKit::WebFileChooserParams& params, - WebKit::WebFileChooserCompletion* chooser_completion) OVERRIDE; virtual bool AsyncOpenFile(const FilePath& path, int flags, const AsyncOpenFileCallback& callback) OVERRIDE; |