summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/content_renderer.gypi5
-rw-r--r--content/content_tests.gypi6
-rw-r--r--content/renderer/pepper/content_renderer_pepper_host_factory.cc26
-rw-r--r--content/renderer/pepper/content_renderer_pepper_host_factory.h12
-rw-r--r--content/renderer/pepper/pepper_file_chooser_host.cc176
-rw-r--r--content/renderer/pepper/pepper_file_chooser_host.h68
-rw-r--r--content/renderer/pepper/pepper_file_chooser_host_browsertest.cc175
-rw-r--r--content/renderer/pepper/pepper_in_process_resource_creation.cc19
-rw-r--r--content/renderer/pepper/pepper_in_process_resource_creation.h9
-rw-r--r--content/renderer/pepper/pepper_instance_state_accessor.h33
-rw-r--r--content/renderer/pepper/pepper_instance_state_accessor_impl.cc50
-rw-r--r--content/renderer/pepper/pepper_instance_state_accessor_impl.h45
-rw-r--r--content/renderer/pepper/pepper_plugin_delegate_impl.cc47
-rw-r--r--content/renderer/pepper/pepper_plugin_delegate_impl.h5
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;