summaryrefslogtreecommitdiffstats
path: root/webkit/plugins
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-16 18:15:52 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-16 18:15:52 +0000
commit0bd753681a82634f322d4867b19148474c25566b (patch)
tree2f96cb4494c075ddee5a3e42e6b41c096a5357a9 /webkit/plugins
parentd1d0afe664ff43825a4585f88ee8ce412eab0194 (diff)
downloadchromium_src-0bd753681a82634f322d4867b19148474c25566b.zip
chromium_src-0bd753681a82634f322d4867b19148474c25566b.tar.gz
chromium_src-0bd753681a82634f322d4867b19148474c25566b.tar.bz2
Move the Pepper implementation from webkit/glue/plugins/pepper_* to
webkit/plugins/ppapi/*. This renamed the files and interface implementation classes from foo.cc/Foo to ppb_foo_impl/PPB_Foo_Impl to match the proxy ppb_foo_proxy/PPB_Foo_Proxy. This moves plugin_switches.* from webkit/glue/plugins to webkit/plugins. Review URL: http://codereview.chromium.org/5828003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69424 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/plugins')
-rw-r--r--webkit/plugins/plugin_switches.cc15
-rw-r--r--webkit/plugins/plugin_switches.h15
-rw-r--r--webkit/plugins/ppapi/DEPS8
-rw-r--r--webkit/plugins/ppapi/common.h26
-rw-r--r--webkit/plugins/ppapi/dir_contents.h25
-rw-r--r--webkit/plugins/ppapi/error_util.cc36
-rw-r--r--webkit/plugins/ppapi/error_util.h18
-rw-r--r--webkit/plugins/ppapi/event_conversion.cc302
-rw-r--r--webkit/plugins/ppapi/event_conversion.h32
-rw-r--r--webkit/plugins/ppapi/file_callbacks.cc103
-rw-r--r--webkit/plugins/ppapi/file_callbacks.h59
-rw-r--r--webkit/plugins/ppapi/fullscreen_container.h38
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.cc190
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.h100
-rw-r--r--webkit/plugins/ppapi/mock_resource.h27
-rw-r--r--webkit/plugins/ppapi/npapi_glue.cc199
-rw-r--r--webkit/plugins/ppapi/npapi_glue.h188
-rw-r--r--webkit/plugins/ppapi/plugin_delegate.h314
-rw-r--r--webkit/plugins/ppapi/plugin_module.cc498
-rw-r--r--webkit/plugins/ppapi/plugin_module.h182
-rw-r--r--webkit/plugins/ppapi/plugin_object.cc333
-rw-r--r--webkit/plugins/ppapi/plugin_object.h91
-rw-r--r--webkit/plugins/ppapi/ppapi_plugin_instance.cc1186
-rw-r--r--webkit/plugins/ppapi/ppapi_plugin_instance.h320
-rw-r--r--webkit/plugins/ppapi/ppapi_unittest.cc113
-rw-r--r--webkit/plugins/ppapi/ppapi_unittest.h48
-rw-r--r--webkit/plugins/ppapi/ppapi_webplugin_impl.cc229
-rw-r--r--webkit/plugins/ppapi/ppapi_webplugin_impl.h97
-rw-r--r--webkit/plugins/ppapi/ppb_audio_impl.cc365
-rw-r--r--webkit/plugins/ppapi/ppb_audio_impl.h116
-rw-r--r--webkit/plugins/ppapi/ppb_buffer_impl.cc121
-rw-r--r--webkit/plugins/ppapi/ppb_buffer_impl.h55
-rw-r--r--webkit/plugins/ppapi/ppb_char_set_impl.cc169
-rw-r--r--webkit/plugins/ppapi/ppb_char_set_impl.h23
-rw-r--r--webkit/plugins/ppapi/ppb_cursor_control_impl.cc94
-rw-r--r--webkit/plugins/ppapi/ppb_cursor_control_impl.h21
-rw-r--r--webkit/plugins/ppapi/ppb_directory_reader_impl.cc167
-rw-r--r--webkit/plugins/ppapi/ppb_directory_reader_impl.h53
-rw-r--r--webkit/plugins/ppapi/ppb_file_chooser_impl.cc169
-rw-r--r--webkit/plugins/ppapi/ppb_file_chooser_impl.h55
-rw-r--r--webkit/plugins/ppapi/ppb_file_io_impl.cc443
-rw-r--r--webkit/plugins/ppapi/ppb_file_io_impl.h100
-rw-r--r--webkit/plugins/ppapi/ppb_file_ref_impl.cc359
-rw-r--r--webkit/plugins/ppapi/ppb_file_ref_impl.h66
-rw-r--r--webkit/plugins/ppapi/ppb_file_system_impl.cc94
-rw-r--r--webkit/plugins/ppapi/ppb_file_system_impl.h48
-rw-r--r--webkit/plugins/ppapi/ppb_flash.h117
-rw-r--r--webkit/plugins/ppapi/ppb_flash_impl.cc246
-rw-r--r--webkit/plugins/ppapi/ppb_flash_impl.h48
-rw-r--r--webkit/plugins/ppapi/ppb_flash_impl_linux.cc112
-rw-r--r--webkit/plugins/ppapi/ppb_font_impl.cc302
-rw-r--r--webkit/plugins/ppapi/ppb_font_impl.h58
-rw-r--r--webkit/plugins/ppapi/ppb_graphics_2d_impl.cc652
-rw-r--r--webkit/plugins/ppapi/ppb_graphics_2d_impl.h182
-rw-r--r--webkit/plugins/ppapi/ppb_graphics_3d_impl.cc263
-rw-r--r--webkit/plugins/ppapi/ppb_graphics_3d_impl.h93
-rw-r--r--webkit/plugins/ppapi/ppb_image_data_impl.cc226
-rw-r--r--webkit/plugins/ppapi/ppb_image_data_impl.h134
-rw-r--r--webkit/plugins/ppapi/ppb_open_gl_es_impl.cc673
-rw-r--r--webkit/plugins/ppapi/ppb_pdf.h135
-rw-r--r--webkit/plugins/ppapi/ppb_pdf_impl.cc302
-rw-r--r--webkit/plugins/ppapi/ppb_pdf_impl.h25
-rw-r--r--webkit/plugins/ppapi/ppb_scrollbar_impl.cc256
-rw-r--r--webkit/plugins/ppapi/ppb_scrollbar_impl.h67
-rw-r--r--webkit/plugins/ppapi/ppb_transport_impl.cc145
-rw-r--r--webkit/plugins/ppapi/ppb_transport_impl.h38
-rw-r--r--webkit/plugins/ppapi/ppb_url_loader_impl.cc559
-rw-r--r--webkit/plugins/ppapi/ppb_url_loader_impl.h145
-rw-r--r--webkit/plugins/ppapi/ppb_url_request_info_impl.cc287
-rw-r--r--webkit/plugins/ppapi/ppb_url_request_info_impl.h74
-rw-r--r--webkit/plugins/ppapi/ppb_url_response_info_impl.cc146
-rw-r--r--webkit/plugins/ppapi/ppb_url_response_info_impl.h58
-rw-r--r--webkit/plugins/ppapi/ppb_url_util_impl.cc180
-rw-r--r--webkit/plugins/ppapi/ppb_url_util_impl.h21
-rw-r--r--webkit/plugins/ppapi/ppb_video_decoder_impl.cc152
-rw-r--r--webkit/plugins/ppapi/ppb_video_decoder_impl.h55
-rw-r--r--webkit/plugins/ppapi/ppb_widget_impl.cc109
-rw-r--r--webkit/plugins/ppapi/ppb_widget_impl.h58
-rw-r--r--webkit/plugins/ppapi/ppp_pdf.h20
-rw-r--r--webkit/plugins/ppapi/resource.cc45
-rw-r--r--webkit/plugins/ppapi/resource.h141
-rw-r--r--webkit/plugins/ppapi/resource_tracker.cc196
-rw-r--r--webkit/plugins/ppapi/resource_tracker.h149
-rw-r--r--webkit/plugins/ppapi/resource_tracker_unittest.cc119
-rw-r--r--webkit/plugins/ppapi/string.cc16
-rw-r--r--webkit/plugins/ppapi/string.h32
-rw-r--r--webkit/plugins/ppapi/var.cc872
-rw-r--r--webkit/plugins/ppapi/var.h253
-rw-r--r--webkit/plugins/ppapi/var_object_class.cc286
-rw-r--r--webkit/plugins/ppapi/var_object_class.h75
90 files changed, 15432 insertions, 0 deletions
diff --git a/webkit/plugins/plugin_switches.cc b/webkit/plugins/plugin_switches.cc
new file mode 100644
index 0000000..be3342c
--- /dev/null
+++ b/webkit/plugins/plugin_switches.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 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 "webkit/plugins/plugin_switches.h"
+
+namespace switches {
+
+// Enables the testing interface for PPAPI.
+const char kEnablePepperTesting[] = "enable-pepper-testing";
+
+// Dumps extra logging about plugin loading to the log file.
+const char kDebugPluginLoading[] = "debug-plugin-loading";
+
+} // namespace switches
diff --git a/webkit/plugins/plugin_switches.h b/webkit/plugins/plugin_switches.h
new file mode 100644
index 0000000..7497ec1
--- /dev/null
+++ b/webkit/plugins/plugin_switches.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
+#define WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
+
+namespace switches {
+
+extern const char kDebugPluginLoading[];
+extern const char kEnablePepperTesting[];
+
+} // namespace switches
+
+#endif // WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
diff --git a/webkit/plugins/ppapi/DEPS b/webkit/plugins/ppapi/DEPS
new file mode 100644
index 0000000..884f203
--- /dev/null
+++ b/webkit/plugins/ppapi/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ "+app",
+ "+gpu/command_buffer",
+ "+ppapi/c",
+ "+ppapi/shared_impl",
+ "+printing",
+ "+skia",
+]
diff --git a/webkit/plugins/ppapi/common.h b/webkit/plugins/ppapi/common.h
new file mode 100644
index 0000000..542bad9
--- /dev/null
+++ b/webkit/plugins/ppapi/common.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_COMMON_H_
+#define WEBKIT_PLUGINS_PPAPI_COMMON_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_var.h"
+
+namespace webkit {
+namespace ppapi {
+
+inline PP_Bool BoolToPPBool(bool value) {
+ return value ? PP_TRUE : PP_FALSE;
+}
+
+inline bool PPBoolToBool(PP_Bool value) {
+ return (PP_TRUE == value);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_COMMON_H_
+
diff --git a/webkit/plugins/ppapi/dir_contents.h b/webkit/plugins/ppapi/dir_contents.h
new file mode 100644
index 0000000..f9a6c45
--- /dev/null
+++ b/webkit/plugins/ppapi/dir_contents.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_DIR_CONTENTS_H_
+#define WEBKIT_PLUGINS_PPAPI_DIR_CONTENTS_H_
+
+#include <vector>
+
+#include "base/file_path.h"
+
+namespace webkit {
+namespace ppapi {
+
+struct DirEntry {
+ FilePath name;
+ bool is_dir;
+};
+
+typedef std::vector<DirEntry> DirContents;
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_DIR_CONTENTS_H_
diff --git a/webkit/plugins/ppapi/error_util.cc b/webkit/plugins/ppapi/error_util.cc
new file mode 100644
index 0000000..0ff127d
--- /dev/null
+++ b/webkit/plugins/ppapi/error_util.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/error_util.h"
+
+#include "ppapi/c/pp_errors.h"
+
+namespace webkit {
+namespace ppapi {
+
+int PlatformFileErrorToPepperError(base::PlatformFileError error_code) {
+ switch (error_code) {
+ case base::PLATFORM_FILE_OK:
+ return PP_OK;
+ case base::PLATFORM_FILE_ERROR_EXISTS:
+ return PP_ERROR_FILEEXISTS;
+ case base::PLATFORM_FILE_ERROR_NOT_FOUND:
+ return PP_ERROR_FILENOTFOUND;
+ case base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
+ case base::PLATFORM_FILE_ERROR_SECURITY:
+ return PP_ERROR_NOACCESS;
+ case base::PLATFORM_FILE_ERROR_NO_MEMORY:
+ return PP_ERROR_NOMEMORY;
+ case base::PLATFORM_FILE_ERROR_NO_SPACE:
+ return PP_ERROR_NOSPACE;
+ case base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
+ return PP_ERROR_FAILED;
+ default:
+ return PP_ERROR_FAILED;
+ }
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/error_util.h b/webkit/plugins/ppapi/error_util.h
new file mode 100644
index 0000000..660f7d2
--- /dev/null
+++ b/webkit/plugins/ppapi/error_util.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_ERROR_UTIL_H_
+#define WEBKIT_PLUGINS_PPAPI_ERROR_UTIL_H_
+
+#include "base/platform_file.h"
+
+namespace webkit {
+namespace ppapi {
+
+int PlatformFileErrorToPepperError(base::PlatformFileError error_code);
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_ERROR_UTIL_H_
diff --git a/webkit/plugins/ppapi/event_conversion.cc b/webkit/plugins/ppapi/event_conversion.cc
new file mode 100644
index 0000000..c5e8fac
--- /dev/null
+++ b/webkit/plugins/ppapi/event_conversion.cc
@@ -0,0 +1,302 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/event_conversion.h"
+
+#include "base/i18n/char_iterator.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/utf_string_conversion_utils.h"
+#include "ppapi/c/pp_input_event.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "webkit/plugins/ppapi/common.h"
+
+using WebKit::WebInputEvent;
+using WebKit::WebKeyboardEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_InputEvent_Type ConvertEventTypes(WebInputEvent::Type wetype) {
+ switch (wetype) {
+ case WebInputEvent::MouseDown:
+ return PP_INPUTEVENT_TYPE_MOUSEDOWN;
+ case WebInputEvent::MouseUp:
+ return PP_INPUTEVENT_TYPE_MOUSEUP;
+ case WebInputEvent::MouseMove:
+ return PP_INPUTEVENT_TYPE_MOUSEMOVE;
+ case WebInputEvent::MouseEnter:
+ return PP_INPUTEVENT_TYPE_MOUSEENTER;
+ case WebInputEvent::MouseLeave:
+ return PP_INPUTEVENT_TYPE_MOUSELEAVE;
+ case WebInputEvent::MouseWheel:
+ return PP_INPUTEVENT_TYPE_MOUSEWHEEL;
+ case WebInputEvent::RawKeyDown:
+ return PP_INPUTEVENT_TYPE_RAWKEYDOWN;
+ case WebInputEvent::KeyDown:
+ return PP_INPUTEVENT_TYPE_KEYDOWN;
+ case WebInputEvent::KeyUp:
+ return PP_INPUTEVENT_TYPE_KEYUP;
+ case WebInputEvent::Char:
+ return PP_INPUTEVENT_TYPE_CHAR;
+ case WebInputEvent::Undefined:
+ default:
+ return PP_INPUTEVENT_TYPE_UNDEFINED;
+ }
+}
+
+// Generates a PP_InputEvent with the fields common to all events, as well as
+// the event type from the given web event. Event-specific fields will be zero
+// initialized.
+PP_InputEvent GetPPEventWithCommonFieldsAndType(
+ const WebInputEvent& web_event) {
+ PP_InputEvent result;
+ memset(&result, 0, sizeof(PP_InputEvent));
+ result.type = ConvertEventTypes(web_event.type);
+ // TODO(brettw) http://code.google.com/p/chromium/issues/detail?id=57448
+ // This should use a tick count rather than the wall clock time that WebKit
+ // uses.
+ result.time_stamp = web_event.timeStampSeconds;
+ return result;
+}
+
+void AppendKeyEvent(const WebInputEvent& event,
+ std::vector<PP_InputEvent>* pp_events) {
+ const WebKeyboardEvent& key_event =
+ reinterpret_cast<const WebKeyboardEvent&>(event);
+ PP_InputEvent result = GetPPEventWithCommonFieldsAndType(event);
+ result.u.key.modifier = key_event.modifiers;
+ result.u.key.key_code = key_event.windowsKeyCode;
+ pp_events->push_back(result);
+}
+
+void AppendCharEvent(const WebInputEvent& event,
+ std::vector<PP_InputEvent>* pp_events) {
+ const WebKeyboardEvent& key_event =
+ reinterpret_cast<const WebKeyboardEvent&>(event);
+
+ // This is a bit complex, the input event will normally just have one 16-bit
+ // character in it, but may be zero or more than one. The text array is
+ // just padded with 0 values for the unused ones, but is not necessarily
+ // null-terminated.
+ //
+ // Here we see how many UTF-16 characters we have.
+ size_t utf16_char_count = 0;
+ while (utf16_char_count < WebKeyboardEvent::textLengthCap &&
+ key_event.text[utf16_char_count])
+ utf16_char_count++;
+
+ // Make a separate PP_InputEvent for each Unicode character in the input.
+ base::UTF16CharIterator iter(key_event.text, utf16_char_count);
+ while (!iter.end()) {
+ PP_InputEvent result = GetPPEventWithCommonFieldsAndType(event);
+ result.u.character.modifier = key_event.modifiers;
+
+ std::string utf8_char;
+ base::WriteUnicodeCharacter(iter.get(), &utf8_char);
+ base::strlcpy(result.u.character.text, utf8_char.c_str(),
+ sizeof(result.u.character.text));
+
+ pp_events->push_back(result);
+ iter.Advance();
+ }
+}
+
+void AppendMouseEvent(const WebInputEvent& event,
+ std::vector<PP_InputEvent>* pp_events) {
+ COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonNone) ==
+ static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_NONE),
+ MouseNone);
+ COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonLeft) ==
+ static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_LEFT),
+ MouseLeft);
+ COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonRight) ==
+ static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_RIGHT),
+ MouseRight);
+ COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonMiddle) ==
+ static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_MIDDLE),
+ MouseMiddle);
+
+ const WebMouseEvent& mouse_event =
+ reinterpret_cast<const WebMouseEvent&>(event);
+ PP_InputEvent result = GetPPEventWithCommonFieldsAndType(event);
+ result.u.mouse.modifier = mouse_event.modifiers;
+ result.u.mouse.button =
+ static_cast<PP_InputEvent_MouseButton>(mouse_event.button);
+ result.u.mouse.x = static_cast<float>(mouse_event.x);
+ result.u.mouse.y = static_cast<float>(mouse_event.y);
+ result.u.mouse.click_count = mouse_event.clickCount;
+ pp_events->push_back(result);
+}
+
+void AppendMouseWheelEvent(const WebInputEvent& event,
+ std::vector<PP_InputEvent>* pp_events) {
+ const WebMouseWheelEvent& mouse_wheel_event =
+ reinterpret_cast<const WebMouseWheelEvent&>(event);
+ PP_InputEvent result = GetPPEventWithCommonFieldsAndType(event);
+ result.u.wheel.modifier = mouse_wheel_event.modifiers;
+ result.u.wheel.delta_x = mouse_wheel_event.deltaX;
+ result.u.wheel.delta_y = mouse_wheel_event.deltaY;
+ result.u.wheel.wheel_ticks_x = mouse_wheel_event.wheelTicksX;
+ result.u.wheel.wheel_ticks_y = mouse_wheel_event.wheelTicksY;
+ result.u.wheel.scroll_by_page =
+ BoolToPPBool(!!mouse_wheel_event.scrollByPage);
+ pp_events->push_back(result);
+}
+
+WebKeyboardEvent* BuildKeyEvent(const PP_InputEvent& event) {
+ WebKeyboardEvent* key_event = new WebKeyboardEvent();
+ switch (event.type) {
+ case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
+ key_event->type = WebInputEvent::RawKeyDown;
+ break;
+ case PP_INPUTEVENT_TYPE_KEYDOWN:
+ key_event->type = WebInputEvent::KeyDown;
+ break;
+ case PP_INPUTEVENT_TYPE_KEYUP:
+ key_event->type = WebInputEvent::KeyUp;
+ break;
+ default:
+ NOTREACHED();
+ }
+ key_event->timeStampSeconds = event.time_stamp;
+ key_event->modifiers = event.u.key.modifier;
+ key_event->windowsKeyCode = event.u.key.key_code;
+ return key_event;
+}
+
+WebKeyboardEvent* BuildCharEvent(const PP_InputEvent& event) {
+ WebKeyboardEvent* key_event = new WebKeyboardEvent();
+ key_event->type = WebInputEvent::Char;
+ key_event->timeStampSeconds = event.time_stamp;
+ key_event->modifiers = event.u.character.modifier;
+
+ // Make sure to not read beyond the buffer in case some bad code doesn't
+ // NULL-terminate it (this is called from plugins).
+ size_t text_length_cap = WebKeyboardEvent::textLengthCap;
+ size_t text_len = 0;
+ while (text_len < text_length_cap && event.u.character.text[text_len])
+ text_len++;
+ string16 text16 = UTF8ToUTF16(std::string(event.u.character.text, text_len));
+
+ memset(key_event->text, 0, text_length_cap);
+ memset(key_event->unmodifiedText, 0, text_length_cap);
+ for (size_t i = 0;
+ i < std::min(text_length_cap, text16.size());
+ ++i)
+ key_event->text[i] = text16[i];
+ return key_event;
+}
+
+WebMouseEvent* BuildMouseEvent(const PP_InputEvent& event) {
+ WebMouseEvent* mouse_event = new WebMouseEvent();
+ switch (event.type) {
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ mouse_event->type = WebInputEvent::MouseDown;
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEUP:
+ mouse_event->type = WebInputEvent::MouseUp;
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE:
+ mouse_event->type = WebInputEvent::MouseMove;
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEENTER:
+ mouse_event->type = WebInputEvent::MouseEnter;
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE:
+ mouse_event->type = WebInputEvent::MouseLeave;
+ break;
+ default:
+ NOTREACHED();
+ }
+ mouse_event->timeStampSeconds = event.time_stamp;
+ mouse_event->modifiers = event.u.mouse.modifier;
+ mouse_event->button =
+ static_cast<WebMouseEvent::Button>(event.u.mouse.button);
+ mouse_event->x = static_cast<int>(event.u.mouse.x);
+ mouse_event->y = static_cast<int>(event.u.mouse.y);
+ mouse_event->clickCount = event.u.mouse.click_count;
+ return mouse_event;
+}
+
+WebMouseWheelEvent* BuildMouseWheelEvent(const PP_InputEvent& event) {
+ WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent();
+ mouse_wheel_event->type = WebInputEvent::MouseWheel;
+ mouse_wheel_event->timeStampSeconds = event.time_stamp;
+ mouse_wheel_event->modifiers = event.u.wheel.modifier;
+ mouse_wheel_event->deltaX = event.u.wheel.delta_x;
+ mouse_wheel_event->deltaY = event.u.wheel.delta_y;
+ mouse_wheel_event->wheelTicksX = event.u.wheel.wheel_ticks_x;
+ mouse_wheel_event->wheelTicksY = event.u.wheel.wheel_ticks_y;
+ mouse_wheel_event->scrollByPage = event.u.wheel.scroll_by_page;
+ return mouse_wheel_event;
+}
+
+} // namespace
+
+void CreatePPEvent(const WebInputEvent& event,
+ std::vector<PP_InputEvent>* pp_events) {
+ pp_events->clear();
+
+ switch (event.type) {
+ case WebInputEvent::MouseDown:
+ case WebInputEvent::MouseUp:
+ case WebInputEvent::MouseMove:
+ case WebInputEvent::MouseEnter:
+ case WebInputEvent::MouseLeave:
+ AppendMouseEvent(event, pp_events);
+ break;
+ case WebInputEvent::MouseWheel:
+ AppendMouseWheelEvent(event, pp_events);
+ break;
+ case WebInputEvent::RawKeyDown:
+ case WebInputEvent::KeyDown:
+ case WebInputEvent::KeyUp:
+ AppendKeyEvent(event, pp_events);
+ break;
+ case WebInputEvent::Char:
+ AppendCharEvent(event, pp_events);
+ break;
+ case WebInputEvent::Undefined:
+ default:
+ break;
+ }
+}
+
+WebInputEvent* CreateWebInputEvent(const PP_InputEvent& event) {
+ scoped_ptr<WebInputEvent> web_input_event;
+ switch (event.type) {
+ case PP_INPUTEVENT_TYPE_UNDEFINED:
+ return NULL;
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ case PP_INPUTEVENT_TYPE_MOUSEUP:
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE:
+ case PP_INPUTEVENT_TYPE_MOUSEENTER:
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE:
+ web_input_event.reset(BuildMouseEvent(event));
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEWHEEL:
+ web_input_event.reset(BuildMouseWheelEvent(event));
+ break;
+ case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYUP:
+ web_input_event.reset(BuildKeyEvent(event));
+ break;
+ case PP_INPUTEVENT_TYPE_CHAR:
+ web_input_event.reset(BuildCharEvent(event));
+ break;
+ }
+
+ return web_input_event.release();
+}
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/event_conversion.h b/webkit/plugins/ppapi/event_conversion.h
new file mode 100644
index 0000000..71beee6
--- /dev/null
+++ b/webkit/plugins/ppapi/event_conversion.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_EVENT_CONVERSION_H_
+#define WEBKIT_PLUGINS_PPAPI_EVENT_CONVERSION_H_
+
+#include <vector>
+
+struct PP_InputEvent;
+
+namespace WebKit {
+class WebInputEvent;
+}
+
+namespace webkit {
+namespace ppapi {
+
+// Converts the given WebKit event to one or possibly multiple PP_InputEvents.
+// The generated events will be filled into the given vector. On failure, no
+// events will ge generated and the vector will be empty.
+void CreatePPEvent(const WebKit::WebInputEvent& event,
+ std::vector<PP_InputEvent>* pp_events);
+
+// Creates a WebInputEvent from the given PP_InputEvent. If it fails, returns
+// NULL. The caller owns the created object on success.
+WebKit::WebInputEvent* CreateWebInputEvent(const PP_InputEvent& event);
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_EVENT_CONVERSION_H_
diff --git a/webkit/plugins/ppapi/file_callbacks.cc b/webkit/plugins/ppapi/file_callbacks.cc
new file mode 100644
index 0000000..9f991be
--- /dev/null
+++ b/webkit/plugins/ppapi/file_callbacks.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/file_callbacks.h"
+
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_file_system_dev.h"
+#include "ppapi/c/dev/pp_file_info_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "webkit/plugins/ppapi/ppb_directory_reader_impl.h"
+#include "webkit/plugins/ppapi/error_util.h"
+#include "webkit/plugins/ppapi/ppb_file_system_impl.h"
+#include "webkit/fileapi/file_system_types.h"
+
+namespace webkit {
+namespace ppapi {
+
+FileCallbacks::FileCallbacks(
+ const base::WeakPtr<PluginModule>& module,
+ PP_CompletionCallback callback,
+ PP_FileInfo_Dev* info,
+ scoped_refptr<PPB_FileSystem_Impl> file_system,
+ scoped_refptr<PPB_DirectoryReader_Impl> directory_reader)
+ : module_(module),
+ callback_(callback),
+ info_(info),
+ file_system_(file_system),
+ directory_reader_(directory_reader) {
+}
+
+FileCallbacks::~FileCallbacks() {}
+
+void FileCallbacks::DidSucceed() {
+ if (!module_.get() || !callback_.func)
+ return;
+
+ PP_RunCompletionCallback(&callback_, PP_OK);
+}
+
+void FileCallbacks::DidReadMetadata(
+ const base::PlatformFileInfo& file_info) {
+ if (!module_.get() || !callback_.func)
+ return;
+
+ DCHECK(info_);
+ DCHECK(file_system_);
+ info_->size = file_info.size;
+ info_->creation_time = file_info.creation_time.ToDoubleT();
+ info_->last_access_time = file_info.last_accessed.ToDoubleT();
+ info_->last_modified_time = file_info.last_modified.ToDoubleT();
+ info_->system_type = file_system_->type();
+ if (file_info.is_directory)
+ info_->type = PP_FILETYPE_DIRECTORY;
+ else
+ info_->type = PP_FILETYPE_REGULAR;
+
+ PP_RunCompletionCallback(&callback_, PP_OK);
+}
+
+void FileCallbacks::DidReadDirectory(
+ const std::vector<base::FileUtilProxy::Entry>& entries, bool has_more) {
+ if (!module_.get() || !callback_.func)
+ return;
+
+ DCHECK(directory_reader_);
+ directory_reader_->AddNewEntries(entries, has_more);
+
+ PP_RunCompletionCallback(&callback_, PP_OK);
+}
+
+void FileCallbacks::DidOpenFileSystem(const std::string&,
+ const FilePath& root_path) {
+ if (!module_.get() || !callback_.func)
+ return;
+
+ DCHECK(file_system_);
+ file_system_->set_root_path(root_path);
+ file_system_->set_opened(true);
+
+ PP_RunCompletionCallback(&callback_, PP_OK);
+}
+
+void FileCallbacks::DidFail(base::PlatformFileError error_code) {
+ RunCallback(error_code);
+}
+
+void FileCallbacks::DidWrite(int64 bytes, bool complete) {
+ NOTREACHED();
+}
+
+void FileCallbacks::RunCallback(base::PlatformFileError error_code) {
+ if (!module_.get() || !callback_.func)
+ return;
+
+ PP_RunCompletionCallback(
+ &callback_, PlatformFileErrorToPepperError(error_code));
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/file_callbacks.h b/webkit/plugins/ppapi/file_callbacks.h
new file mode 100644
index 0000000..4b96d1c
--- /dev/null
+++ b/webkit/plugins/ppapi/file_callbacks.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_FILE_CALLBACKS_H_
+#define WEBKIT_PLUGINS_PPAPI_FILE_CALLBACKS_H_
+
+#include "base/platform_file.h"
+#include "base/weak_ptr.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "webkit/fileapi/file_system_callback_dispatcher.h"
+
+struct PP_FileInfo_Dev;
+
+namespace base {
+class FilePath;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_DirectoryReader_Impl;
+class PPB_FileSystem_Impl;
+class PluginModule;
+
+// Instances of this class are deleted by FileSystemDispatcher.
+class FileCallbacks : public fileapi::FileSystemCallbackDispatcher {
+ public:
+ FileCallbacks(const base::WeakPtr<PluginModule>& module,
+ PP_CompletionCallback callback,
+ PP_FileInfo_Dev* info,
+ scoped_refptr<PPB_FileSystem_Impl> file_system,
+ scoped_refptr<PPB_DirectoryReader_Impl> directory_reader);
+ virtual ~FileCallbacks();
+
+ // FileSystemCallbackDispatcher implementation.
+ virtual void DidSucceed();
+ virtual void DidReadMetadata(const base::PlatformFileInfo& file_info);
+ virtual void DidReadDirectory(
+ const std::vector<base::FileUtilProxy::Entry>& entries, bool has_more);
+ virtual void DidOpenFileSystem(const std::string&,
+ const FilePath& root_path);
+ virtual void DidFail(base::PlatformFileError error_code);
+ virtual void DidWrite(int64 bytes, bool complete);
+
+ private:
+ void RunCallback(base::PlatformFileError error_code);
+
+ base::WeakPtr<PluginModule> module_;
+ PP_CompletionCallback callback_;
+ PP_FileInfo_Dev* info_;
+ scoped_refptr<PPB_FileSystem_Impl> file_system_;
+ scoped_refptr<PPB_DirectoryReader_Impl> directory_reader_;
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_FILE_CALLBACKS_H_
diff --git a/webkit/plugins/ppapi/fullscreen_container.h b/webkit/plugins/ppapi/fullscreen_container.h
new file mode 100644
index 0000000..8318282
--- /dev/null
+++ b/webkit/plugins/ppapi/fullscreen_container.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FULLSCREEN_CONTAINER_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FULLSCREEN_CONTAINER_IMPL_H_
+
+namespace WebKit {
+struct WebRect;
+} // namespace WebKit
+
+namespace webkit {
+namespace ppapi {
+
+// This class is like a lightweight WebPluginContainer for fullscreen PPAPI
+// plugins, that only handles painting.
+class FullscreenContainer {
+ public:
+ virtual ~FullscreenContainer() {}
+
+ // Invalidates the full plugin region.
+ virtual void Invalidate() = 0;
+
+ // Invalidates a partial region of the plugin.
+ virtual void InvalidateRect(const WebKit::WebRect&) = 0;
+
+ // Scrolls a partial region of the plugin in the given direction.
+ virtual void ScrollRect(int dx, int dy, const WebKit::WebRect&) = 0;
+
+ // Destroys the fullscreen window. This also destroys the FullscreenContainer
+ // instance.
+ virtual void Destroy() = 0;
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FULLSCREEN_CONTAINER_IMPL_H_
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc
new file mode 100644
index 0000000..93ace2c
--- /dev/null
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc
@@ -0,0 +1,190 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/mock_plugin_delegate.h"
+
+#include "base/message_loop_proxy.h"
+
+namespace webkit {
+namespace ppapi {
+
+MockPluginDelegate::MockPluginDelegate() {
+}
+
+MockPluginDelegate::~MockPluginDelegate() {
+}
+
+void MockPluginDelegate::InstanceCreated(PluginInstance* instance) {
+}
+
+void MockPluginDelegate::InstanceDeleted(PluginInstance* instance) {
+}
+
+MockPluginDelegate::PlatformImage2D* MockPluginDelegate::CreateImage2D(
+ int width,
+ int height) {
+ return NULL;
+}
+
+MockPluginDelegate::PlatformContext3D* MockPluginDelegate::CreateContext3D() {
+ return NULL;
+}
+
+MockPluginDelegate::PlatformVideoDecoder*
+MockPluginDelegate::CreateVideoDecoder(
+ const PP_VideoDecoderConfig_Dev& decoder_config) {
+ return NULL;
+}
+
+MockPluginDelegate::PlatformAudio* MockPluginDelegate::CreateAudio(
+ uint32_t sample_rate,
+ uint32_t sample_count,
+ PlatformAudio::Client* client) {
+ return NULL;
+}
+
+void MockPluginDelegate::NumberOfFindResultsChanged(int identifier,
+ int total,
+ bool final_result) {
+}
+
+void MockPluginDelegate::SelectedFindResultChanged(int identifier, int index) {
+}
+
+bool MockPluginDelegate::RunFileChooser(
+ const WebKit::WebFileChooserParams& params,
+ WebKit::WebFileChooserCompletion* chooser_completion) {
+ return false;
+}
+
+bool MockPluginDelegate::AsyncOpenFile(const FilePath& path,
+ int flags,
+ AsyncOpenFileCallback* callback) {
+ return false;
+}
+
+bool MockPluginDelegate::OpenFileSystem(
+ const GURL& url,
+ fileapi::FileSystemType type,
+ long long size,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+bool MockPluginDelegate::MakeDirectory(
+ const FilePath& path,
+ bool recursive,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+bool MockPluginDelegate::Query(
+ const FilePath& path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+bool MockPluginDelegate::Touch(
+ const FilePath& path,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+bool MockPluginDelegate::Delete(
+ const FilePath& path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+bool MockPluginDelegate::Rename(
+ const FilePath& file_path,
+ const FilePath& new_file_path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+bool MockPluginDelegate::ReadDirectory(
+ const FilePath& directory_path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ return false;
+}
+
+base::PlatformFileError MockPluginDelegate::OpenModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path,
+ int flags,
+ base::PlatformFile* file) {
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+base::PlatformFileError MockPluginDelegate::RenameModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path_from,
+ const FilePath& path_to) {
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+base::PlatformFileError MockPluginDelegate::DeleteModuleLocalFileOrDir(
+ const std::string& module_name,
+ const FilePath& path,
+ bool recursive) {
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+base::PlatformFileError MockPluginDelegate::CreateModuleLocalDir(
+ const std::string& module_name,
+ const FilePath& path) {
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+base::PlatformFileError MockPluginDelegate::QueryModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path,
+ base::PlatformFileInfo* info) {
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+base::PlatformFileError MockPluginDelegate::GetModuleLocalDirContents(
+ const std::string& module_name,
+ const FilePath& path,
+ DirContents* contents) {
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+scoped_refptr<base::MessageLoopProxy>
+MockPluginDelegate::GetFileThreadMessageLoopProxy() {
+ return scoped_refptr<base::MessageLoopProxy>();
+}
+
+FullscreenContainer* MockPluginDelegate::CreateFullscreenContainer(
+ PluginInstance* instance) {
+ return NULL;
+}
+
+std::string MockPluginDelegate::GetDefaultEncoding() {
+ return "iso-8859-1";
+}
+
+void MockPluginDelegate::ZoomLimitsChanged(double minimum_factor,
+ double maximum_factor) {
+}
+
+std::string MockPluginDelegate::ResolveProxy(const GURL& url) {
+ return std::string();
+}
+
+void MockPluginDelegate::DidStartLoading() {
+}
+
+void MockPluginDelegate::DidStopLoading() {
+}
+
+void MockPluginDelegate::SetContentRestriction(int restrictions) {
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h
new file mode 100644
index 0000000..4f83a80
--- /dev/null
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_MOCK_PLUGIN_DELEGATE_H_
+#define WEBKIT_PLUGINS_PPAPI_MOCK_PLUGIN_DELEGATE_H_
+
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+
+namespace webkit {
+namespace ppapi {
+
+class MockPluginDelegate : public PluginDelegate {
+ public:
+ MockPluginDelegate();
+ ~MockPluginDelegate();
+
+ virtual void InstanceCreated(PluginInstance* instance);
+ virtual void InstanceDeleted(PluginInstance* instance);
+ virtual PlatformImage2D* CreateImage2D(int width, int height);
+ virtual PlatformContext3D* CreateContext3D();
+ virtual PlatformVideoDecoder* CreateVideoDecoder(
+ const PP_VideoDecoderConfig_Dev& decoder_config);
+ virtual PlatformAudio* CreateAudio(uint32_t sample_rate,
+ uint32_t sample_count,
+ PlatformAudio::Client* client);
+ virtual void NumberOfFindResultsChanged(int identifier,
+ int total,
+ bool final_result);
+ virtual void SelectedFindResultChanged(int identifier, int index);
+ virtual bool RunFileChooser(
+ const WebKit::WebFileChooserParams& params,
+ WebKit::WebFileChooserCompletion* chooser_completion);
+ virtual bool AsyncOpenFile(const FilePath& path,
+ int flags,
+ AsyncOpenFileCallback* callback);
+ virtual bool OpenFileSystem(
+ const GURL& url,
+ fileapi::FileSystemType type,
+ long long size,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual bool MakeDirectory(
+ const FilePath& path,
+ bool recursive,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual bool Query(const FilePath& path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual bool Touch(const FilePath& path,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual bool Delete(const FilePath& path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual bool Rename(const FilePath& file_path,
+ const FilePath& new_file_path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual bool ReadDirectory(
+ const FilePath& directory_path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher);
+ virtual base::PlatformFileError OpenModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path,
+ int flags,
+ base::PlatformFile* file);
+ virtual base::PlatformFileError RenameModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path_from,
+ const FilePath& path_to);
+ virtual base::PlatformFileError DeleteModuleLocalFileOrDir(
+ const std::string& module_name,
+ const FilePath& path,
+ bool recursive);
+ virtual base::PlatformFileError CreateModuleLocalDir(
+ const std::string& module_name,
+ const FilePath& path);
+ virtual base::PlatformFileError QueryModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path,
+ base::PlatformFileInfo* info);
+ virtual base::PlatformFileError GetModuleLocalDirContents(
+ const std::string& module_name,
+ const FilePath& path,
+ DirContents* contents);
+ virtual scoped_refptr<base::MessageLoopProxy>
+ GetFileThreadMessageLoopProxy();
+ virtual FullscreenContainer* CreateFullscreenContainer(
+ PluginInstance* instance);
+ virtual std::string GetDefaultEncoding();
+ virtual void ZoomLimitsChanged(double minimum_factor,
+ double maximum_factor);
+ virtual std::string ResolveProxy(const GURL& url);
+ virtual void DidStartLoading();
+ virtual void DidStopLoading();
+ virtual void SetContentRestriction(int restrictions);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_MOCK_PLUGIN_DELEGATE_H_
diff --git a/webkit/plugins/ppapi/mock_resource.h b/webkit/plugins/ppapi/mock_resource.h
new file mode 100644
index 0000000..081c990
--- /dev/null
+++ b/webkit/plugins/ppapi/mock_resource.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_MOCK_RESOURCE_H_
+#define WEBKIT_PLUGINS_PPAPI_MOCK_RESOURCE_H_
+
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+// Tests can derive from this to implement special test-specific resources.
+// It's assumed that a test will only need one mock resource, so it can
+// static_cast to get its own implementation.
+class MockResource : public Resource {
+ public:
+ MockResource(PluginModule* module) : Resource(module) {}
+ ~MockResource() {}
+
+ virtual MockResource* AsMockResource() { return this; }
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_MOCK_RESOURCE_H_
diff --git a/webkit/plugins/ppapi/npapi_glue.cc b/webkit/plugins/ppapi/npapi_glue.cc
new file mode 100644
index 0000000..d22c13f
--- /dev/null
+++ b/webkit/plugins/ppapi/npapi_glue.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/npapi_glue.h"
+
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "base/string_util.h"
+#include "webkit/plugins/ppapi/plugin_object.h"
+#include "webkit/plugins/ppapi/var.h"
+#include "third_party/npapi/bindings/npapi.h"
+#include "third_party/npapi/bindings/npruntime.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+
+using WebKit::WebBindings;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+const char kInvalidPluginValue[] = "Error: Plugin returned invalid value.";
+
+} // namespace
+
+// Utilities -------------------------------------------------------------------
+
+bool PPVarToNPVariant(PP_Var var, NPVariant* result) {
+ switch (var.type) {
+ case PP_VARTYPE_UNDEFINED:
+ VOID_TO_NPVARIANT(*result);
+ break;
+ case PP_VARTYPE_NULL:
+ NULL_TO_NPVARIANT(*result);
+ break;
+ case PP_VARTYPE_BOOL:
+ BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
+ break;
+ case PP_VARTYPE_INT32:
+ INT32_TO_NPVARIANT(var.value.as_int, *result);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
+ break;
+ case PP_VARTYPE_STRING: {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
+ if (!string) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ const std::string& value = string->value();
+ STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), *result);
+ break;
+ }
+ case PP_VARTYPE_OBJECT: {
+ scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var));
+ if (!object) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ OBJECT_TO_NPVARIANT(WebBindings::retainObject(object->np_object()),
+ *result);
+ break;
+ }
+ }
+ return true;
+}
+
+// PPResultAndExceptionToNPResult ----------------------------------------------
+
+PPResultAndExceptionToNPResult::PPResultAndExceptionToNPResult(
+ NPObject* object_var,
+ NPVariant* np_result)
+ : object_var_(object_var),
+ np_result_(np_result),
+ exception_(PP_MakeUndefined()),
+ success_(false),
+ checked_exception_(false) {
+}
+
+PPResultAndExceptionToNPResult::~PPResultAndExceptionToNPResult() {
+ // The user should have called SetResult or CheckExceptionForNoResult
+ // before letting this class go out of scope, or the exception will have
+ // been lost.
+ DCHECK(checked_exception_);
+
+ ObjectVar::PluginReleasePPVar(exception_);
+}
+
+// Call this with the return value of the PPAPI function. It will convert
+// the result to the NPVariant output parameter and pass any exception on to
+// the JS engine. It will update the success flag and return it.
+bool PPResultAndExceptionToNPResult::SetResult(PP_Var result) {
+ DCHECK(!checked_exception_); // Don't call more than once.
+ DCHECK(np_result_); // Should be expecting a result.
+
+ checked_exception_ = true;
+
+ if (has_exception()) {
+ ThrowException();
+ success_ = false;
+ } else if (!PPVarToNPVariant(result, np_result_)) {
+ WebBindings::setException(object_var_, kInvalidPluginValue);
+ success_ = false;
+ } else {
+ success_ = true;
+ }
+
+ // No matter what happened, we need to release the reference to the
+ // value passed in. On success, a reference to this value will be in
+ // the np_result_.
+ Var::PluginReleasePPVar(result);
+ return success_;
+}
+
+// Call this after calling a PPAPI function that could have set the
+// exception. It will pass the exception on to the JS engine and update
+// the success flag.
+//
+// The success flag will be returned.
+bool PPResultAndExceptionToNPResult::CheckExceptionForNoResult() {
+ DCHECK(!checked_exception_); // Don't call more than once.
+ DCHECK(!np_result_); // Can't have a result when doing this.
+
+ checked_exception_ = true;
+
+ if (has_exception()) {
+ ThrowException();
+ success_ = false;
+ return false;
+ }
+ success_ = true;
+ return true;
+}
+
+// Call this to ignore any exception. This prevents the DCHECK from failing
+// in the destructor.
+void PPResultAndExceptionToNPResult::IgnoreException() {
+ checked_exception_ = true;
+}
+
+// Throws the current exception to JS. The exception must be set.
+void PPResultAndExceptionToNPResult::ThrowException() {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(exception_));
+ if (string) {
+ WebBindings::setException(object_var_, string->value().c_str());
+ }
+}
+
+// PPVarArrayFromNPVariantArray ------------------------------------------------
+
+PPVarArrayFromNPVariantArray::PPVarArrayFromNPVariantArray(PluginModule* module,
+ size_t size,
+ const NPVariant* variants)
+ : size_(size) {
+ if (size_ > 0) {
+ array_.reset(new PP_Var[size_]);
+ for (size_t i = 0; i < size_; i++)
+ array_[i] = Var::NPVariantToPPVar(module, &variants[i]);
+ }
+}
+
+PPVarArrayFromNPVariantArray::~PPVarArrayFromNPVariantArray() {
+ for (size_t i = 0; i < size_; i++)
+ Var::PluginReleasePPVar(array_[i]);
+}
+
+// PPVarFromNPObject -----------------------------------------------------------
+
+PPVarFromNPObject::PPVarFromNPObject(PluginModule* module, NPObject* object)
+ : var_(ObjectVar::NPObjectToPPVar(module, object)) {
+}
+
+PPVarFromNPObject::~PPVarFromNPObject() {
+ Var::PluginReleasePPVar(var_);
+}
+
+// NPObjectAccessorWithIdentifier ----------------------------------------------
+
+NPObjectAccessorWithIdentifier::NPObjectAccessorWithIdentifier(
+ NPObject* object,
+ NPIdentifier identifier,
+ bool allow_integer_identifier)
+ : object_(PluginObject::FromNPObject(object)),
+ identifier_(PP_MakeUndefined()) {
+ if (object_) {
+ identifier_ = Var::NPIdentifierToPPVar(object_->module(), identifier);
+ if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier)
+ identifier_.type = PP_VARTYPE_UNDEFINED; // Mark it invalid.
+ }
+}
+
+NPObjectAccessorWithIdentifier::~NPObjectAccessorWithIdentifier() {
+ Var::PluginReleasePPVar(identifier_);
+}
+
+} // namespace ppapi
+} // namespace webkit
diff --git a/webkit/plugins/ppapi/npapi_glue.h b/webkit/plugins/ppapi/npapi_glue.h
new file mode 100644
index 0000000..11fd82a
--- /dev/null
+++ b/webkit/plugins/ppapi/npapi_glue.h
@@ -0,0 +1,188 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_NPAPI_GLUE_H_
+#define WEBKIT_PLUGINS_PPAPI_NPAPI_GLUE_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/pp_var.h"
+
+struct NPObject;
+typedef struct _NPVariant NPVariant;
+typedef void* NPIdentifier;
+
+namespace webkit {
+namespace ppapi {
+
+class PluginModule;
+class PluginObject;
+
+// Utilities -------------------------------------------------------------------
+
+// Converts the given PP_Var to an NPVariant, returning true on success.
+// False means that the given variant is invalid. In this case, the result
+// NPVariant will be set to a void one.
+//
+// The contents of the PP_Var will be copied unless the PP_Var corresponds to
+// an object.
+bool PPVarToNPVariant(PP_Var var, NPVariant* result);
+
+// PPResultAndExceptionToNPResult ----------------------------------------------
+
+// Convenience object for converting a PPAPI call that can throw an exception
+// and optionally return a value, back to the NPAPI layer which expects a
+// NPVariant as a result.
+//
+// Normal usage is that you will pass the result of exception() to the
+// PPAPI function as the exception output parameter. Then you will either
+// call SetResult with the result of the PPAPI call, or
+// CheckExceptionForNoResult if the PPAPI call doesn't return a PP_Var.
+//
+// Both SetResult and CheckExceptionForNoResult will throw an exception to
+// the JavaScript library if the plugin reported an exception. SetResult
+// will additionally convert the result to an NPVariant and write it to the
+// output parameter given in the constructor.
+class PPResultAndExceptionToNPResult {
+ public:
+ // The object_var parameter is the object to associate any exception with.
+ // It may not be NULL.
+ //
+ // The np_result parameter is the NPAPI result output parameter. This may be
+ // NULL if there is no NPVariant result (like for HasProperty). If this is
+ // specified, you must call SetResult() to set it. If it is not, you must
+ // call CheckExceptionForNoResult to do the exception checking with no result
+ // conversion.
+ PPResultAndExceptionToNPResult(NPObject* object_var, NPVariant* np_result);
+
+ ~PPResultAndExceptionToNPResult();
+
+ // Returns true if an exception has been set.
+ bool has_exception() const { return exception_.type != PP_VARTYPE_UNDEFINED; }
+
+ // Returns a pointer to the exception. You would pass this to the PPAPI
+ // function as the exception parameter. If it is set to non-void, this object
+ // will take ownership of destroying it.
+ PP_Var* exception() { return &exception_; }
+
+ // Returns true if everything succeeded with no exception. This is valid only
+ // after calling SetResult/CheckExceptionForNoResult.
+ bool success() const {
+ return success_;
+ }
+
+ // Call this with the return value of the PPAPI function. It will convert
+ // the result to the NPVariant output parameter and pass any exception on to
+ // the JS engine. It will update the success flag and return it.
+ bool SetResult(PP_Var result);
+
+ // Call this after calling a PPAPI function that could have set the
+ // exception. It will pass the exception on to the JS engine and update
+ // the success flag.
+ //
+ // The success flag will be returned.
+ bool CheckExceptionForNoResult();
+
+ // Call this to ignore any exception. This prevents the DCHECK from failing
+ // in the destructor.
+ void IgnoreException();
+
+ private:
+ // Throws the current exception to JS. The exception must be set.
+ void ThrowException();
+
+ NPObject* object_var_; // Non-owning ref (see constructor).
+ NPVariant* np_result_; // Output value, possibly NULL (see constructor).
+ PP_Var exception_; // Exception set by the PPAPI call. We own a ref to it.
+ bool success_; // See the success() function above.
+ bool checked_exception_; // SetResult/CheckExceptionForNoResult was called.
+
+ DISALLOW_COPY_AND_ASSIGN(PPResultAndExceptionToNPResult);
+};
+
+// PPVarArrayFromNPVariantArray ------------------------------------------------
+
+// Converts an array of NPVariants to an array of PP_Var, and scopes the
+// ownership of the PP_Var. This is used when converting argument lists from
+// WebKit to the plugin.
+class PPVarArrayFromNPVariantArray {
+ public:
+ PPVarArrayFromNPVariantArray(PluginModule* module,
+ size_t size,
+ const NPVariant* variants);
+ ~PPVarArrayFromNPVariantArray();
+
+ PP_Var* array() { return array_.get(); }
+
+ private:
+ size_t size_;
+ scoped_array<PP_Var> array_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPVarArrayFromNPVariantArray);
+};
+
+// PPVarFromNPObject -----------------------------------------------------------
+
+// Converts an NPObject tp PP_Var, and scopes the ownership of the PP_Var. This
+// is used when converting 'this' pointer from WebKit to the plugin.
+class PPVarFromNPObject {
+ public:
+ PPVarFromNPObject(PluginModule* module, NPObject* object);
+ ~PPVarFromNPObject();
+
+ PP_Var var() const { return var_; }
+
+ private:
+ const PP_Var var_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPVarFromNPObject);
+};
+
+// NPObjectAccessorWithIdentifier ----------------------------------------------
+
+// Helper class for our NPObject wrapper. This converts a call from WebKit
+// where it gives us an NPObject and an NPIdentifier to an easily-accessible
+// ObjectVar (corresponding to the NPObject) and PP_Var (corresponding to the
+// NPIdentifier).
+//
+// If the NPObject or identifier is invalid, we'll set is_valid() to false.
+// The caller should check is_valid() before doing anything with the class.
+//
+// JS can't have integer functions, so when dealing with these, we don't want
+// to allow integer identifiers. The calling code can decode if it wants to
+// allow integer identifiers (like for property access) or prohibit them
+// (like for method calling) by setting |allow_integer_identifier|. If this
+// is false and the identifier is an integer, we'll set is_valid() to false.
+//
+// Getting an integer identifier in this case should be impossible. V8
+// shouldn't be allowing this, and the Pepper Var calls from the plugin are
+// supposed to error out before calling into V8 (which will then call us back).
+// Aside from an egregious error, the only time this could happen is an NPAPI
+// plugin calling us.
+class NPObjectAccessorWithIdentifier {
+ public:
+ NPObjectAccessorWithIdentifier(NPObject* object,
+ NPIdentifier identifier,
+ bool allow_integer_identifier);
+ ~NPObjectAccessorWithIdentifier();
+
+ // Returns true if both the object and identifier are valid.
+ bool is_valid() const {
+ return object_ && identifier_.type != PP_VARTYPE_UNDEFINED;
+ }
+
+ PluginObject* object() { return object_; }
+ PP_Var identifier() const { return identifier_; }
+
+ private:
+ PluginObject* object_;
+ PP_Var identifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(NPObjectAccessorWithIdentifier);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_NPAPI_GLUE_H_
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
new file mode 100644
index 0000000..fef6cff
--- /dev/null
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -0,0 +1,314 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PLUGIN_DELEGATE_H_
+#define WEBKIT_PLUGINS_PPAPI_PLUGIN_DELEGATE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/platform_file.h"
+#include "base/ref_counted.h"
+#include "base/shared_memory.h"
+#include "base/sync_socket.h"
+#include "gfx/size.h"
+#include "googleurl/src/gurl.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_stdint.h"
+#include "webkit/fileapi/file_system_types.h"
+#include "webkit/plugins/ppapi/dir_contents.h"
+
+class AudioMessageFilter;
+class GURL;
+
+namespace base {
+class MessageLoopProxy;
+class Time;
+}
+
+namespace fileapi {
+class FileSystemCallbackDispatcher;
+}
+
+namespace gfx {
+class Rect;
+}
+
+namespace gpu {
+namespace gles2 {
+class GLES2Implementation;
+}
+}
+
+namespace skia {
+class PlatformCanvas;
+}
+
+namespace WebKit {
+class WebFileChooserCompletion;
+struct WebFileChooserParams;
+}
+
+struct PP_VideoCompressedDataBuffer_Dev;
+struct PP_VideoDecoderConfig_Dev;
+struct PP_VideoUncompressedDataBuffer_Dev;
+
+class TransportDIB;
+
+namespace webkit {
+namespace ppapi {
+
+class FileIO;
+class PluginInstance;
+class FullscreenContainer;
+
+// Virtual interface that the browser implements to implement features for
+// PPAPI plugins.
+class PluginDelegate {
+ public:
+ // This class is implemented by the PluginDelegate implementation and is
+ // designed to manage the lifetime and communicatin with the proxy's
+ // HostDispatcher for out-of-process PPAPI plugins.
+ //
+ // The point of this is to avoid having a relationship from the PPAPI plugin
+ // implementation to the ppapi proxy code. Otherwise, things like the IPC
+ // system will be dependencies of the webkit directory, which we don't want.
+ //
+ // The PluginModule will scope the lifetime of this object to its own
+ // lifetime, so the implementation can use this to manage the HostDispatcher
+ // lifetime without introducing the dependency.
+ class OutOfProcessProxy {
+ public:
+ virtual ~OutOfProcessProxy() {}
+
+ // Implements GetInterface for the proxied plugin.
+ virtual const void* GetProxiedInterface(const char* name) = 0;
+
+ // Notification to the out-of-process layer that the given plugin instance
+ // has been created. This will happen before the normal PPB_Instance method
+ // calls so the out-of-process code can set up the tracking information for
+ // the new instance.
+ virtual void AddInstance(PP_Instance instance) = 0;
+
+ // Like AddInstance but removes the given instance. This is called after
+ // regular instance shutdown so the out-of-process code can clean up its
+ // tracking information.
+ virtual void RemoveInstance(PP_Instance instance) = 0;
+ };
+
+ // Represents an image. This is to allow the browser layer to supply a correct
+ // image representation. In Chrome, this will be a TransportDIB.
+ class PlatformImage2D {
+ public:
+ virtual ~PlatformImage2D() {}
+
+ // Caller will own the returned pointer, returns NULL on failure.
+ virtual skia::PlatformCanvas* Map() = 0;
+
+ // Returns the platform-specific shared memory handle of the data backing
+ // this image. This is used by PPAPI proxying to send the image to the
+ // out-of-process plugin. On success, the size in bytes will be placed into
+ // |*bytes_count|. Returns 0 on failure.
+ virtual intptr_t GetSharedMemoryHandle(uint32* byte_count) const = 0;
+
+ virtual TransportDIB* GetTransportDIB() const = 0;
+ };
+
+ class PlatformContext3D {
+ public:
+ virtual ~PlatformContext3D() {}
+
+ // Initialize the context.
+ virtual bool Init() = 0;
+
+ // Present the rendered frame to the compositor.
+ virtual bool SwapBuffers() = 0;
+
+ // Get the last EGL error.
+ virtual unsigned GetError() = 0;
+
+ // Resize the backing texture used as a back buffer by OpenGL.
+ virtual void ResizeBackingTexture(const gfx::Size& size) = 0;
+
+ // Set an optional callback that will be invoked when the side effects of
+ // a SwapBuffers call become visible to the compositor. Takes ownership
+ // of the callback.
+ virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0;
+
+ // If the plugin instance is backed by an OpenGL, return its ID in the
+ // compositors namespace. Otherwise return 0. Returns 0 by default.
+ virtual unsigned GetBackingTextureId() = 0;
+
+ // This call will return the address of the GLES2 implementation for this
+ // context that is constructed in Initialize() and is valid until this
+ // context is destroyed.
+ virtual gpu::gles2::GLES2Implementation* GetGLES2Implementation() = 0;
+ };
+
+ class PlatformAudio {
+ public:
+ class Client {
+ protected:
+ virtual ~Client() {}
+
+ public:
+ // Called when the stream is created.
+ virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size,
+ base::SyncSocket::Handle socket) = 0;
+ };
+
+ // Starts the playback. Returns false on error or if called before the
+ // stream is created or after the stream is closed.
+ virtual bool StartPlayback() = 0;
+
+ // Stops the playback. Returns false on error or if called before the stream
+ // is created or after the stream is closed.
+ virtual bool StopPlayback() = 0;
+
+ // Closes the stream. Make sure to call this before the object is
+ // destructed.
+ virtual void ShutDown() = 0;
+
+ protected:
+ virtual ~PlatformAudio() {}
+ };
+
+ class PlatformVideoDecoder {
+ public:
+ virtual ~PlatformVideoDecoder() {}
+
+ // Returns false on failure.
+ virtual bool Decode(PP_VideoCompressedDataBuffer_Dev& input_buffer) = 0;
+ virtual int32_t Flush(PP_CompletionCallback& callback) = 0;
+ virtual bool ReturnUncompressedDataBuffer(
+ PP_VideoUncompressedDataBuffer_Dev& buffer) = 0;
+ };
+
+ // Indicates that the given instance has been created.
+ virtual void InstanceCreated(PluginInstance* instance) = 0;
+
+ // Indicates that the given instance is being destroyed. This is called from
+ // the destructor, so it's important that the instance is not dereferenced
+ // from this call.
+ virtual void InstanceDeleted(PluginInstance* instance) = 0;
+
+ // The caller will own the pointer returned from this.
+ virtual PlatformImage2D* CreateImage2D(int width, int height) = 0;
+
+ // The caller will own the pointer returned from this.
+ virtual PlatformContext3D* CreateContext3D() = 0;
+
+ // The caller will own the pointer returned from this.
+ virtual PlatformVideoDecoder* CreateVideoDecoder(
+ const PP_VideoDecoderConfig_Dev& decoder_config) = 0;
+
+ // The caller will own the pointer returned from this.
+ virtual PlatformAudio* CreateAudio(uint32_t sample_rate,
+ uint32_t sample_count,
+ PlatformAudio::Client* client) = 0;
+
+ // Notifies that the number of find results has changed.
+ virtual void NumberOfFindResultsChanged(int identifier,
+ int total,
+ bool final_result) = 0;
+
+ // Notifies that the index of the currently selected item has been updated.
+ virtual void SelectedFindResultChanged(int identifier, int index) = 0;
+
+ // Runs a file chooser.
+ virtual bool RunFileChooser(
+ const WebKit::WebFileChooserParams& params,
+ WebKit::WebFileChooserCompletion* chooser_completion) = 0;
+
+ // Sends an async IPC to open a file.
+ typedef Callback2<base::PlatformFileError, base::PlatformFile
+ >::Type AsyncOpenFileCallback;
+ virtual bool AsyncOpenFile(const FilePath& path,
+ int flags,
+ AsyncOpenFileCallback* callback) = 0;
+ virtual bool OpenFileSystem(
+ const GURL& url,
+ fileapi::FileSystemType type,
+ long long size,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+ virtual bool MakeDirectory(
+ const FilePath& path,
+ bool recursive,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+ virtual bool Query(const FilePath& path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+ virtual bool Touch(const FilePath& path,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+ virtual bool Delete(const FilePath& path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+ virtual bool Rename(const FilePath& file_path,
+ const FilePath& new_file_path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+ virtual bool ReadDirectory(
+ const FilePath& directory_path,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) = 0;
+
+ virtual base::PlatformFileError OpenModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path,
+ int flags,
+ base::PlatformFile* file) = 0;
+ virtual base::PlatformFileError RenameModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path_from,
+ const FilePath& path_to) = 0;
+ virtual base::PlatformFileError DeleteModuleLocalFileOrDir(
+ const std::string& module_name,
+ const FilePath& path,
+ bool recursive) = 0;
+ virtual base::PlatformFileError CreateModuleLocalDir(
+ const std::string& module_name,
+ const FilePath& path) = 0;
+ virtual base::PlatformFileError QueryModuleLocalFile(
+ const std::string& module_name,
+ const FilePath& path,
+ base::PlatformFileInfo* info) = 0;
+ virtual base::PlatformFileError GetModuleLocalDirContents(
+ const std::string& module_name,
+ const FilePath& path,
+ DirContents* contents) = 0;
+
+ // Returns a MessageLoopProxy instance associated with the message loop
+ // of the file thread in this renderer.
+ virtual scoped_refptr<base::MessageLoopProxy>
+ GetFileThreadMessageLoopProxy() = 0;
+
+ // Create a fullscreen container for a plugin instance. This effectively
+ // switches the plugin to fullscreen.
+ virtual FullscreenContainer* CreateFullscreenContainer(
+ PluginInstance* instance) = 0;
+
+ // Returns a string with the name of the default 8-bit char encoding.
+ virtual std::string GetDefaultEncoding() = 0;
+
+ // Sets the mininum and maximium zoom factors.
+ virtual void ZoomLimitsChanged(double minimum_factor,
+ double maximum_factor) = 0;
+
+ // Retrieves the proxy information for the given URL in PAC format. On error,
+ // this will return an empty string.
+ virtual std::string ResolveProxy(const GURL& url) = 0;
+
+ // Tell the browser when resource loading starts/ends.
+ virtual void DidStartLoading() = 0;
+ virtual void DidStopLoading() = 0;
+
+ // Sets restrictions on how the content can be used (i.e. no print/copy).
+ virtual void SetContentRestriction(int restrictions) = 0;
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PLUGIN_DELEGATE_H_
diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc
new file mode 100644
index 0000000..96eadfb
--- /dev/null
+++ b/webkit/plugins/ppapi/plugin_module.cc
@@ -0,0 +1,498 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/plugin_module.h"
+
+#include <set>
+
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/c/dev/ppb_char_set_dev.h"
+#include "ppapi/c/dev/ppb_cursor_control_dev.h"
+#include "ppapi/c/dev/ppb_directory_reader_dev.h"
+#include "ppapi/c/dev/ppb_file_io_dev.h"
+#include "ppapi/c/dev/ppb_file_io_trusted_dev.h"
+#include "ppapi/c/dev/ppb_file_system_dev.h"
+#include "ppapi/c/dev/ppb_find_dev.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/dev/ppb_fullscreen_dev.h"
+#include "ppapi/c/dev/ppb_graphics_3d_dev.h"
+#include "ppapi/c/dev/ppb_opengles_dev.h"
+#include "ppapi/c/dev/ppb_scrollbar_dev.h"
+#include "ppapi/c/dev/ppb_testing_dev.h"
+#include "ppapi/c/dev/ppb_transport_dev.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppb_video_decoder_dev.h"
+#include "ppapi/c/dev/ppb_widget_dev.h"
+#include "ppapi/c/dev/ppb_zoom_dev.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_class.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/ppb_url_request_info.h"
+#include "ppapi/c/ppb_url_response_info.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppp.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/c/trusted/ppb_image_data_trusted.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_object.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_audio_impl.h"
+#include "webkit/plugins/ppapi/ppb_buffer_impl.h"
+#include "webkit/plugins/ppapi/ppb_char_set_impl.h"
+#include "webkit/plugins/ppapi/ppb_cursor_control_impl.h"
+#include "webkit/plugins/ppapi/ppb_directory_reader_impl.h"
+#include "webkit/plugins/ppapi/ppb_file_chooser_impl.h"
+#include "webkit/plugins/ppapi/ppb_file_io_impl.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/ppb_file_system_impl.h"
+#include "webkit/plugins/ppapi/ppb_flash.h"
+#include "webkit/plugins/ppapi/ppb_flash_impl.h"
+#include "webkit/plugins/ppapi/ppb_font_impl.h"
+#include "webkit/plugins/ppapi/ppb_graphics_2d_impl.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/ppb_pdf.h"
+#include "webkit/plugins/ppapi/ppb_pdf_impl.h"
+#include "webkit/plugins/ppapi/ppb_scrollbar_impl.h"
+#include "webkit/plugins/ppapi/ppb_transport_impl.h"
+#include "webkit/plugins/ppapi/ppb_url_loader_impl.h"
+#include "webkit/plugins/ppapi/ppb_url_request_info_impl.h"
+#include "webkit/plugins/ppapi/ppb_url_response_info_impl.h"
+#include "webkit/plugins/ppapi/ppb_url_util_impl.h"
+#include "webkit/plugins/ppapi/ppb_video_decoder_impl.h"
+#include "webkit/plugins/ppapi/ppb_widget_impl.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+#include "webkit/plugins/ppapi/var.h"
+#include "webkit/plugins/ppapi/var_object_class.h"
+
+#ifdef ENABLE_GPU
+#include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h"
+#endif // ENABLE_GPU
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// Maintains all currently loaded plugin libs for validating PP_Module
+// identifiers.
+typedef std::set<PluginModule*> PluginModuleSet;
+
+PluginModuleSet* GetLivePluginSet() {
+ static PluginModuleSet live_plugin_libs;
+ return &live_plugin_libs;
+}
+
+base::MessageLoopProxy* GetMainThreadMessageLoop() {
+ static scoped_refptr<base::MessageLoopProxy> proxy(
+ base::MessageLoopProxy::CreateForCurrentThread());
+ return proxy.get();
+}
+
+// PPB_Core --------------------------------------------------------------------
+
+void AddRefResource(PP_Resource resource) {
+ if (!ResourceTracker::Get()->AddRefResource(resource)) {
+ DLOG(WARNING) << "AddRefResource()ing a nonexistent resource";
+ }
+}
+
+void ReleaseResource(PP_Resource resource) {
+ if (!ResourceTracker::Get()->UnrefResource(resource)) {
+ DLOG(WARNING) << "ReleaseResource()ing a nonexistent resource";
+ }
+}
+
+void* MemAlloc(size_t num_bytes) {
+ return malloc(num_bytes);
+}
+
+void MemFree(void* ptr) {
+ free(ptr);
+}
+
+double GetTime() {
+ return base::Time::Now().ToDoubleT();
+}
+
+double GetTickTime() {
+ // TODO(brettw) http://code.google.com/p/chromium/issues/detail?id=57448
+ // This should be a tick timer rather than wall clock time, but needs to
+ // match message times, which also currently use wall clock time.
+ return GetTime();
+}
+
+void CallOnMainThread(int delay_in_msec,
+ PP_CompletionCallback callback,
+ int32_t result) {
+ GetMainThreadMessageLoop()->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableFunction(callback.func, callback.user_data, result),
+ delay_in_msec);
+}
+
+PP_Bool IsMainThread() {
+ return BoolToPPBool(GetMainThreadMessageLoop()->BelongsToCurrentThread());
+}
+
+const PPB_Core core_interface = {
+ &AddRefResource,
+ &ReleaseResource,
+ &MemAlloc,
+ &MemFree,
+ &GetTime,
+ &GetTickTime,
+ &CallOnMainThread,
+ &IsMainThread
+};
+
+// PPB_Testing -----------------------------------------------------------------
+
+PP_Bool ReadImageData(PP_Resource device_context_2d,
+ PP_Resource image,
+ const PP_Point* top_left) {
+ scoped_refptr<PPB_Graphics2D_Impl> context(
+ Resource::GetAs<PPB_Graphics2D_Impl>(device_context_2d));
+ if (!context.get())
+ return PP_FALSE;
+ return BoolToPPBool(context->ReadImageData(image, top_left));
+}
+
+void RunMessageLoop() {
+ bool old_state = MessageLoop::current()->NestableTasksAllowed();
+ MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoop::current()->Run();
+ MessageLoop::current()->SetNestableTasksAllowed(old_state);
+}
+
+void QuitMessageLoop() {
+ MessageLoop::current()->QuitNow();
+}
+
+uint32_t GetLiveObjectCount(PP_Module module_id) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return static_cast<uint32_t>(-1);
+ return ResourceTracker::Get()->GetLiveObjectsForModule(module);
+}
+
+const PPB_Testing_Dev testing_interface = {
+ &ReadImageData,
+ &RunMessageLoop,
+ &QuitMessageLoop,
+ &GetLiveObjectCount
+};
+
+// GetInterface ----------------------------------------------------------------
+
+const void* GetInterface(const char* name) {
+ // Please keep alphabetized by interface macro name with "special" stuff at
+ // the bottom.
+ if (strcmp(name, PPB_AUDIO_CONFIG_DEV_INTERFACE) == 0)
+ return PPB_AudioConfig_Impl::GetInterface();
+ if (strcmp(name, PPB_AUDIO_DEV_INTERFACE) == 0)
+ return PPB_Audio_Impl::GetInterface();
+ if (strcmp(name, PPB_AUDIO_TRUSTED_DEV_INTERFACE) == 0)
+ return PPB_Audio_Impl::GetTrustedInterface();
+ if (strcmp(name, PPB_BUFFER_DEV_INTERFACE) == 0)
+ return PPB_Buffer_Impl::GetInterface();
+ if (strcmp(name, PPB_CHAR_SET_DEV_INTERFACE) == 0)
+ return PPB_CharSet_Impl::GetInterface();
+ if (strcmp(name, PPB_CLASS_INTERFACE) == 0)
+ return VarObjectClass::GetInterface();
+ if (strcmp(name, PPB_CORE_INTERFACE) == 0)
+ return &core_interface;
+ if (strcmp(name, PPB_CURSOR_CONTROL_DEV_INTERFACE) == 0)
+ return GetCursorControlInterface();
+ if (strcmp(name, PPB_DIRECTORYREADER_DEV_INTERFACE) == 0)
+ return PPB_DirectoryReader_Impl::GetInterface();
+ if (strcmp(name, PPB_FILECHOOSER_DEV_INTERFACE) == 0)
+ return PPB_FileChooser_Impl::GetInterface();
+ if (strcmp(name, PPB_FILEIO_DEV_INTERFACE) == 0)
+ return PPB_FileIO_Impl::GetInterface();
+ if (strcmp(name, PPB_FILEIOTRUSTED_DEV_INTERFACE) == 0)
+ return PPB_FileIO_Impl::GetTrustedInterface();
+ if (strcmp(name, PPB_FILEREF_DEV_INTERFACE) == 0)
+ return PPB_FileRef_Impl::GetInterface();
+ if (strcmp(name, PPB_FILESYSTEM_DEV_INTERFACE) == 0)
+ return PPB_FileSystem_Impl::GetInterface();
+ if (strcmp(name, PPB_FIND_DEV_INTERFACE) == 0)
+ return PluginInstance::GetFindInterface();
+ if (strcmp(name, PPB_FLASH_INTERFACE) == 0)
+ return PPB_Flash_Impl::GetInterface();
+ if (strcmp(name, PPB_FONT_DEV_INTERFACE) == 0)
+ return PPB_Font_Impl::GetInterface();
+ if (strcmp(name, PPB_FULLSCREEN_DEV_INTERFACE) == 0)
+ return PluginInstance::GetFullscreenInterface();
+ if (strcmp(name, PPB_GRAPHICS_2D_INTERFACE) == 0)
+ return PPB_Graphics2D_Impl::GetInterface();
+ if (strcmp(name, PPB_IMAGEDATA_INTERFACE) == 0)
+ return PPB_ImageData_Impl::GetInterface();
+ if (strcmp(name, PPB_IMAGEDATA_TRUSTED_INTERFACE) == 0)
+ return PPB_ImageData_Impl::GetTrustedInterface();
+ if (strcmp(name, PPB_INSTANCE_INTERFACE) == 0)
+ return PluginInstance::GetInterface();
+ if (strcmp(name, PPB_PDF_INTERFACE) == 0)
+ return PPB_PDF_Impl::GetInterface();
+ if (strcmp(name, PPB_SCROLLBAR_DEV_INTERFACE) == 0)
+ return PPB_Scrollbar_Impl::GetInterface();
+ if (strcmp(name, PPB_TRANSPORT_DEV_INTERFACE) == 0)
+ return PPB_Transport_Impl::GetInterface();
+ if (strcmp(name, PPB_URLLOADER_INTERFACE) == 0)
+ return PPB_URLLoader_Impl::GetInterface();
+ if (strcmp(name, PPB_URLLOADERTRUSTED_INTERFACE) == 0)
+ return PPB_URLLoader_Impl::GetTrustedInterface();
+ if (strcmp(name, PPB_URLREQUESTINFO_INTERFACE) == 0)
+ return PPB_URLRequestInfo_Impl::GetInterface();
+ if (strcmp(name, PPB_URLRESPONSEINFO_INTERFACE) == 0)
+ return PPB_URLResponseInfo_Impl::GetInterface();
+ if (strcmp(name, PPB_URLUTIL_DEV_INTERFACE) == 0)
+ return PPB_UrlUtil_Impl::GetInterface();
+ if (strcmp(name, PPB_VAR_DEPRECATED_INTERFACE) == 0)
+ return Var::GetDeprecatedInterface();
+ if (strcmp(name, PPB_VAR_INTERFACE) == 0)
+ return Var::GetInterface();
+ if (strcmp(name, PPB_VIDEODECODER_DEV_INTERFACE) == 0)
+ return PPB_VideoDecoder_Impl::GetInterface();
+ if (strcmp(name, PPB_WIDGET_DEV_INTERFACE) == 0)
+ return PPB_Widget_Impl::GetInterface();
+ if (strcmp(name, PPB_ZOOM_DEV_INTERFACE) == 0)
+ return PluginInstance::GetZoomInterface();
+
+#ifdef ENABLE_GPU
+ if (strcmp(name, PPB_GRAPHICS_3D_DEV_INTERFACE) == 0)
+ return PPB_Graphics3D_Impl::GetInterface();
+ if (strcmp(name, PPB_OPENGLES_DEV_INTERFACE) == 0)
+ return PPB_Graphics3D_Impl::GetOpenGLESInterface();
+#endif // ENABLE_GPU
+
+ // Only support the testing interface when the command line switch is
+ // specified. This allows us to prevent people from (ab)using this interface
+ // in production code.
+ if (strcmp(name, PPB_TESTING_DEV_INTERFACE) == 0) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch("enable-pepper-testing"))
+ return &testing_interface;
+ }
+ return NULL;
+}
+
+// Gets the PPAPI entry points from the given library and places them into the
+// given structure. Returns true on success.
+bool LoadEntryPointsFromLibrary(const base::NativeLibrary& library,
+ PluginModule::EntryPoints* entry_points) {
+ entry_points->get_interface =
+ reinterpret_cast<PluginModule::GetInterfaceFunc>(
+ base::GetFunctionPointerFromNativeLibrary(library,
+ "PPP_GetInterface"));
+ if (!entry_points->get_interface) {
+ LOG(WARNING) << "No PPP_GetInterface in plugin library";
+ return false;
+ }
+
+ entry_points->initialize_module =
+ reinterpret_cast<PluginModule::PPP_InitializeModuleFunc>(
+ base::GetFunctionPointerFromNativeLibrary(library,
+ "PPP_InitializeModule"));
+ if (!entry_points->initialize_module) {
+ LOG(WARNING) << "No PPP_InitializeModule in plugin library";
+ return false;
+ }
+
+ // It's okay for PPP_ShutdownModule to not be defined and shutdown_module to
+ // be NULL.
+ entry_points->shutdown_module =
+ reinterpret_cast<PluginModule::PPP_ShutdownModuleFunc>(
+ base::GetFunctionPointerFromNativeLibrary(library,
+ "PPP_ShutdownModule"));
+
+ return true;
+}
+
+} // namespace
+
+PluginModule::EntryPoints::EntryPoints()
+ : get_interface(NULL),
+ initialize_module(NULL),
+ shutdown_module(NULL) {
+}
+
+// PluginModule ----------------------------------------------------------------
+
+PluginModule::PluginModule() : library_(NULL) {
+ pp_module_ = ResourceTracker::Get()->AddModule(this);
+ GetMainThreadMessageLoop(); // Initialize the main thread message loop.
+ GetLivePluginSet()->insert(this);
+}
+
+PluginModule::~PluginModule() {
+ // Free all the plugin objects. This will automatically clear the back-
+ // pointer from the NPObject so WebKit can't call into the plugin any more.
+ //
+ // Swap out the set so we can delete from it (the objects will try to
+ // unregister themselves inside the delete call).
+ PluginObjectSet plugin_object_copy;
+ live_plugin_objects_.swap(plugin_object_copy);
+ for (PluginObjectSet::iterator i = live_plugin_objects_.begin();
+ i != live_plugin_objects_.end(); ++i)
+ delete *i;
+
+ // When the module is being deleted, there should be no more instances still
+ // holding a reference to us.
+ DCHECK(instances_.empty());
+
+ GetLivePluginSet()->erase(this);
+
+ if (entry_points_.shutdown_module)
+ entry_points_.shutdown_module();
+
+ if (library_)
+ base::UnloadNativeLibrary(library_);
+
+ ResourceTracker::Get()->ModuleDeleted(pp_module_);
+}
+
+bool PluginModule::InitAsInternalPlugin(const EntryPoints& entry_points) {
+ entry_points_ = entry_points;
+ return InitializeModule();
+}
+
+bool PluginModule::InitAsLibrary(const FilePath& path) {
+ base::NativeLibrary library = base::LoadNativeLibrary(path);
+ if (!library)
+ return false;
+
+ if (!LoadEntryPointsFromLibrary(library, &entry_points_) ||
+ !InitializeModule()) {
+ base::UnloadNativeLibrary(library);
+ return false;
+ }
+
+ library_ = library;
+ return true;
+}
+
+void PluginModule::InitAsProxied(
+ PluginDelegate::OutOfProcessProxy* out_of_process_proxy) {
+ DCHECK(!out_of_process_proxy_.get());
+ out_of_process_proxy_.reset(out_of_process_proxy);
+}
+
+// static
+const PPB_Core* PluginModule::GetCore() {
+ return &core_interface;
+}
+
+// static
+PluginModule::GetInterfaceFunc PluginModule::GetLocalGetInterfaceFunc() {
+ return &GetInterface;
+}
+
+PluginInstance* PluginModule::CreateInstance(PluginDelegate* delegate) {
+ const PPP_Instance* plugin_instance_interface =
+ reinterpret_cast<const PPP_Instance*>(GetPluginInterface(
+ PPP_INSTANCE_INTERFACE));
+ if (!plugin_instance_interface) {
+ LOG(WARNING) << "Plugin doesn't support instance interface, failing.";
+ return NULL;
+ }
+ PluginInstance* instance = new PluginInstance(delegate, this,
+ plugin_instance_interface);
+ if (out_of_process_proxy_.get())
+ out_of_process_proxy_->AddInstance(instance->pp_instance());
+ return instance;
+}
+
+PluginInstance* PluginModule::GetSomeInstance() const {
+ // This will generally crash later if there is not actually any instance to
+ // return, so we force a crash now to make bugs easier to track down.
+ CHECK(!instances_.empty());
+ return *instances_.begin();
+}
+
+const void* PluginModule::GetPluginInterface(const char* name) const {
+ if (out_of_process_proxy_.get())
+ return out_of_process_proxy_->GetProxiedInterface(name);
+
+ // In-process plugins.
+ if (!entry_points_.get_interface)
+ return NULL;
+ return entry_points_.get_interface(name);
+}
+
+void PluginModule::InstanceCreated(PluginInstance* instance) {
+ instances_.insert(instance);
+}
+
+void PluginModule::InstanceDeleted(PluginInstance* instance) {
+ if (out_of_process_proxy_.get())
+ out_of_process_proxy_->RemoveInstance(instance->pp_instance());
+ instances_.erase(instance);
+}
+
+void PluginModule::AddNPObjectVar(ObjectVar* object_var) {
+ DCHECK(np_object_to_object_var_.find(object_var->np_object()) ==
+ np_object_to_object_var_.end()) << "ObjectVar already in map";
+ np_object_to_object_var_[object_var->np_object()] = object_var;
+}
+
+void PluginModule::RemoveNPObjectVar(ObjectVar* object_var) {
+ NPObjectToObjectVarMap::iterator found =
+ np_object_to_object_var_.find(object_var->np_object());
+ if (found == np_object_to_object_var_.end()) {
+ NOTREACHED() << "ObjectVar not registered.";
+ return;
+ }
+ if (found->second != object_var) {
+ NOTREACHED() << "ObjectVar doesn't match.";
+ return;
+ }
+ np_object_to_object_var_.erase(found);
+}
+
+ObjectVar* PluginModule::ObjectVarForNPObject(NPObject* np_object) const {
+ NPObjectToObjectVarMap::const_iterator found =
+ np_object_to_object_var_.find(np_object);
+ if (found == np_object_to_object_var_.end())
+ return NULL;
+ return found->second;
+}
+
+void PluginModule::AddPluginObject(PluginObject* plugin_object) {
+ DCHECK(live_plugin_objects_.find(plugin_object) ==
+ live_plugin_objects_.end());
+ live_plugin_objects_.insert(plugin_object);
+}
+
+void PluginModule::RemovePluginObject(PluginObject* plugin_object) {
+ // Don't actually verify that the object is in the set since during module
+ // deletion we'll be in the process of freeing them.
+ live_plugin_objects_.erase(plugin_object);
+}
+
+bool PluginModule::InitializeModule() {
+ DCHECK(!out_of_process_proxy_.get()) << "Don't call for proxied modules.";
+ int retval = entry_points_.initialize_module(pp_module(), &GetInterface);
+ if (retval != 0) {
+ LOG(WARNING) << "PPP_InitializeModule returned failure " << retval;
+ return false;
+ }
+ return true;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/plugin_module.h b/webkit/plugins/ppapi/plugin_module.h
new file mode 100644
index 0000000..39b5f1d
--- /dev/null
+++ b/webkit/plugins/ppapi/plugin_module.h
@@ -0,0 +1,182 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PLUGIN_MODULE_H_
+#define WEBKIT_PLUGINS_PPAPI_PLUGIN_MODULE_H_
+
+#include <map>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/native_library.h"
+#include "base/process.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/weak_ptr.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/ppb.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+
+class FilePath;
+class MessageLoop;
+typedef struct NPObject NPObject;
+struct PPB_Core;
+typedef void* NPIdentifier;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace pp {
+namespace proxy {
+class HostDispatcher;
+} // proxy
+} // pp
+
+namespace IPC {
+struct ChannelHandle;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class ObjectVar;
+class PluginDelegate;
+class PluginInstance;
+class PluginObject;
+
+// Represents one plugin library loaded into one renderer. This library may
+// have multiple instances.
+//
+// Note: to get from a PP_Instance to a PluginInstance*, use the
+// ResourceTracker.
+class PluginModule : public base::RefCounted<PluginModule>,
+ public base::SupportsWeakPtr<PluginModule> {
+ public:
+ typedef const void* (*GetInterfaceFunc)(const char*);
+ typedef int (*PPP_InitializeModuleFunc)(PP_Module, PPB_GetInterface);
+ typedef void (*PPP_ShutdownModuleFunc)();
+
+ struct EntryPoints {
+ // This structure is POD, with the constructor initializing to NULL.
+ EntryPoints();
+
+ GetInterfaceFunc get_interface;
+ PPP_InitializeModuleFunc initialize_module;
+ PPP_ShutdownModuleFunc shutdown_module; // Optional, may be NULL.
+ };
+
+ // You must call one of the Init functions to create a module of the type
+ // you desire.
+ PluginModule();
+
+ ~PluginModule();
+
+ // Initializes this module as an internal plugin with the given entrypoints.
+ // This is used for "plugins" compiled into Chrome. Returns true on success.
+ // False means that the plugin can not be used.
+ bool InitAsInternalPlugin(const EntryPoints& entry_points);
+
+ // Initializes this module using the given library path as the plugin.
+ // Returns true on success. False means that the plugin can not be used.
+ bool InitAsLibrary(const FilePath& path);
+
+ // Initializes this module for the given out of process proxy. This takes
+ // ownership of the given pointer, even in the failure case.
+ void InitAsProxied(PluginDelegate::OutOfProcessProxy* out_of_process_proxy);
+
+ static const PPB_Core* GetCore();
+
+ // Returns a pointer to the local GetInterface function for retrieving
+ // PPB interfaces.
+ static GetInterfaceFunc GetLocalGetInterfaceFunc();
+
+ // Returns the module handle. This may be used before Init() is called (the
+ // proxy needs this information to set itself up properly).
+ PP_Module pp_module() const { return pp_module_; }
+
+ void set_name(const std::string& name) { name_ = name; }
+ const std::string& name() const { return name_; }
+
+ PluginInstance* CreateInstance(PluginDelegate* delegate);
+
+ // Returns "some" plugin instance associated with this module. This is not
+ // guaranteed to be any one in particular. This is normally used to execute
+ // callbacks up to the browser layer that are not inherently per-instance,
+ // but the delegate lives only on the plugin instance so we need one of them.
+ PluginInstance* GetSomeInstance() const;
+
+ // Calls the plugin's GetInterface and returns the given interface pointer,
+ // which could be NULL.
+ const void* GetPluginInterface(const char* name) const;
+
+ // This module is associated with a set of instances. The PluginInstance
+ // object declares its association with this module in its destructor and
+ // releases us in its destructor.
+ void InstanceCreated(PluginInstance* instance);
+ void InstanceDeleted(PluginInstance* instance);
+
+ // Tracks all live ObjectVar. This is so we can map between PluginModule +
+ // NPObject and get the ObjectVar corresponding to it. This Add/Remove
+ // function should be called by the ObjectVar when it is created and
+ // destroyed.
+ void AddNPObjectVar(ObjectVar* object_var);
+ void RemoveNPObjectVar(ObjectVar* object_var);
+
+ // Looks up a previously registered ObjectVar for the given NPObject and
+ // module. Returns NULL if there is no ObjectVar corresponding to the given
+ // NPObject for the given module. See AddNPObjectVar above.
+ ObjectVar* ObjectVarForNPObject(NPObject* np_object) const;
+
+ // Tracks all live PluginObjects.
+ void AddPluginObject(PluginObject* plugin_object);
+ void RemovePluginObject(PluginObject* plugin_object);
+
+ private:
+ // Calls the InitializeModule entrypoint. The entrypoint must have been
+ // set and the plugin must not be out of process (we don't maintain
+ // entrypoints in that case).
+ bool InitializeModule();
+
+ PP_Module pp_module_;
+
+ // Manages the out of process proxy interface. The presence of this
+ // pointer indicates that the plugin is running out of process and that the
+ // entry_points_ aren't valid.
+ scoped_ptr<PluginDelegate::OutOfProcessProxy> out_of_process_proxy_;
+
+ // Holds a reference to the base::NativeLibrary handle if this PluginModule
+ // instance wraps functions loaded from a library. Can be NULL. If
+ // |library_| is non-NULL, PluginModule will attempt to unload the library
+ // during destruction.
+ base::NativeLibrary library_;
+
+ // Contains pointers to the entry points of the actual plugin implementation.
+ // These will be NULL for out-of-process plugins, which is indicated by the
+ // presence of the out_of_process_proxy_ value.
+ EntryPoints entry_points_;
+
+ // The name of the module.
+ std::string name_;
+
+ // Non-owning pointers to all instances associated with this module. When
+ // there are no more instances, this object should be deleted.
+ typedef std::set<PluginInstance*> PluginInstanceSet;
+ PluginInstanceSet instances_;
+
+ // Tracks all live ObjectVars used by this module so we can map NPObjects to
+ // the corresponding object. These are non-owning references.
+ typedef std::map<NPObject*, ObjectVar*> NPObjectToObjectVarMap;;
+ NPObjectToObjectVarMap np_object_to_object_var_;
+
+ typedef std::set<PluginObject*> PluginObjectSet;
+ PluginObjectSet live_plugin_objects_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginModule);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PLUGIN_MODULE_H_
diff --git a/webkit/plugins/ppapi/plugin_object.cc b/webkit/plugins/ppapi/plugin_object.cc
new file mode 100644
index 0000000..516f255
--- /dev/null
+++ b/webkit/plugins/ppapi/plugin_object.cc
@@ -0,0 +1,333 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/plugin_object.h"
+
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "third_party/npapi/bindings/npapi.h"
+#include "third_party/npapi/bindings/npruntime.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_class.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "webkit/plugins/ppapi/npapi_glue.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/resource.h"
+#include "webkit/plugins/ppapi/string.h"
+#include "webkit/plugins/ppapi/var.h"
+#include "webkit/plugins/ppapi/var_object_class.h"
+
+using WebKit::WebBindings;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+const char kInvalidValueException[] = "Error: Invalid value";
+
+// NPObject implementation in terms of PPP_Class_Deprecated --------------------
+
+NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) {
+ return PluginObject::AllocateObjectWrapper();
+}
+
+void WrapperClass_Deallocate(NPObject* np_object) {
+ PluginObject* plugin_object = PluginObject::FromNPObject(np_object);
+ if (!plugin_object)
+ return;
+ plugin_object->ppp_class()->Deallocate(plugin_object->ppp_class_data());
+ delete plugin_object;
+}
+
+void WrapperClass_Invalidate(NPObject* object) {
+}
+
+bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) {
+ NPObjectAccessorWithIdentifier accessor(object, method_name, false);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(
+ accessor.object()->GetNPObject(), NULL);
+ bool rv = accessor.object()->ppp_class()->HasMethod(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception());
+ result_converter.CheckExceptionForNoResult();
+ return rv;
+}
+
+bool WrapperClass_Invoke(NPObject* object, NPIdentifier method_name,
+ const NPVariant* argv, uint32_t argc,
+ NPVariant* result) {
+ NPObjectAccessorWithIdentifier accessor(object, method_name, false);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(
+ accessor.object()->GetNPObject(), result);
+ PPVarArrayFromNPVariantArray args(accessor.object()->module(), argc, argv);
+
+ return result_converter.SetResult(accessor.object()->ppp_class()->Call(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ argc, args.array(), result_converter.exception()));
+}
+
+bool WrapperClass_InvokeDefault(NPObject* np_object, const NPVariant* argv,
+ uint32_t argc, NPVariant* result) {
+ PluginObject* obj = PluginObject::FromNPObject(np_object);
+ if (!obj)
+ return false;
+
+ PPVarArrayFromNPVariantArray args(obj->module(), argc, argv);
+ PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result);
+
+ result_converter.SetResult(obj->ppp_class()->Call(
+ obj->ppp_class_data(), PP_MakeUndefined(), argc, args.array(),
+ result_converter.exception()));
+ return result_converter.success();
+}
+
+bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(
+ accessor.object()->GetNPObject(), NULL);
+ bool rv = accessor.object()->ppp_class()->HasProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception());
+ result_converter.CheckExceptionForNoResult();
+ return rv;
+}
+
+bool WrapperClass_GetProperty(NPObject* object, NPIdentifier property_name,
+ NPVariant* result) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(
+ accessor.object()->GetNPObject(), result);
+ return result_converter.SetResult(accessor.object()->ppp_class()->GetProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception()));
+}
+
+bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name,
+ const NPVariant* value) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(
+ accessor.object()->GetNPObject(), NULL);
+ PP_Var value_var = Var::NPVariantToPPVar(accessor.object()->module(), value);
+ accessor.object()->ppp_class()->SetProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(), value_var,
+ result_converter.exception());
+ Var::PluginReleasePPVar(value_var);
+ return result_converter.CheckExceptionForNoResult();
+}
+
+bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(
+ accessor.object()->GetNPObject(), NULL);
+ accessor.object()->ppp_class()->RemoveProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception());
+ return result_converter.CheckExceptionForNoResult();
+}
+
+bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values,
+ uint32_t* count) {
+ *values = NULL;
+ *count = 0;
+ PluginObject* obj = PluginObject::FromNPObject(object);
+ if (!obj)
+ return false;
+
+ uint32_t property_count = 0;
+ PP_Var* properties = NULL; // Must be freed!
+ PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), NULL);
+ obj->ppp_class()->GetAllPropertyNames(obj->ppp_class_data(),
+ &property_count, &properties,
+ result_converter.exception());
+
+ // Convert the array of PP_Var to an array of NPIdentifiers. If any
+ // conversions fail, we will set the exception.
+ if (!result_converter.has_exception()) {
+ if (property_count > 0) {
+ *values = static_cast<NPIdentifier*>(
+ malloc(sizeof(NPIdentifier) * property_count));
+ *count = 0; // Will be the number of items successfully converted.
+ for (uint32_t i = 0; i < property_count; ++i) {
+ if (!((*values)[i] = Var::PPVarToNPIdentifier(properties[i]))) {
+ // Throw an exception for the failed convertion.
+ *result_converter.exception() = StringVar::StringToPPVar(
+ obj->module(), kInvalidValueException);
+ break;
+ }
+ (*count)++;
+ }
+
+ if (result_converter.has_exception()) {
+ // We don't actually have to free the identifiers we converted since
+ // all identifiers leak anyway :( .
+ free(*values);
+ *values = NULL;
+ *count = 0;
+ }
+ }
+ }
+
+ // This will actually throw the exception, either from GetAllPropertyNames,
+ // or if anything was set during the conversion process.
+ result_converter.CheckExceptionForNoResult();
+
+ // Release the PP_Var that the plugin allocated. On success, they will all
+ // be converted to NPVariants, and on failure, we want them to just go away.
+ for (uint32_t i = 0; i < property_count; ++i)
+ Var::PluginReleasePPVar(properties[i]);
+ free(properties);
+ return result_converter.success();
+}
+
+bool WrapperClass_Construct(NPObject* object, const NPVariant* argv,
+ uint32_t argc, NPVariant* result) {
+ PluginObject* obj = PluginObject::FromNPObject(object);
+ if (!obj)
+ return false;
+
+ PPVarArrayFromNPVariantArray args(obj->module(), argc, argv);
+ PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result);
+ return result_converter.SetResult(obj->ppp_class()->Construct(
+ obj->ppp_class_data(), argc, args.array(),
+ result_converter.exception()));
+}
+
+const NPClass wrapper_class = {
+ NP_CLASS_STRUCT_VERSION,
+ WrapperClass_Allocate,
+ WrapperClass_Deallocate,
+ WrapperClass_Invalidate,
+ WrapperClass_HasMethod,
+ WrapperClass_Invoke,
+ WrapperClass_InvokeDefault,
+ WrapperClass_HasProperty,
+ WrapperClass_GetProperty,
+ WrapperClass_SetProperty,
+ WrapperClass_RemoveProperty,
+ WrapperClass_Enumerate,
+ WrapperClass_Construct
+};
+
+} // namespace
+
+// PluginObject ----------------------------------------------------------------
+
+struct PluginObject::NPObjectWrapper : public NPObject {
+ // Points to the var object that owns this wrapper. This value may be NULL
+ // if there is no var owning this wrapper. This can happen if the plugin
+ // releases all references to the var, but a reference to the underlying
+ // NPObject is still held by script on the page.
+ PluginObject* obj;
+};
+
+PluginObject::PluginObject(PluginModule* module,
+ NPObjectWrapper* object_wrapper,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data)
+ : module_(module),
+ object_wrapper_(object_wrapper),
+ ppp_class_(ppp_class),
+ ppp_class_data_(ppp_class_data) {
+ // Make the object wrapper refer back to this class so our NPObject
+ // implementation can call back into the Pepper layer.
+ object_wrapper_->obj = this;
+ module_->AddPluginObject(this);
+}
+
+PluginObject::~PluginObject() {
+ // The wrapper we made for this NPObject may still have a reference to it
+ // from JavaScript, so we clear out its ObjectVar back pointer which will
+ // cause all calls "up" to the plugin to become NOPs. Our ObjectVar base
+ // class will release our reference to the object, which may or may not
+ // delete the NPObject.
+ DCHECK(object_wrapper_->obj == this);
+ object_wrapper_->obj = NULL;
+ module_->RemovePluginObject(this);
+}
+
+PP_Var PluginObject::Create(PluginModule* module,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data) {
+ // This will internally end up calling our AllocateObjectWrapper via the
+ // WrapperClass_Allocated function which will have created an object wrapper
+ // appropriate for this class (derived from NPObject).
+ NPObjectWrapper* wrapper = static_cast<NPObjectWrapper*>(
+ WebBindings::createObject(NULL, const_cast<NPClass*>(&wrapper_class)));
+
+ // This object will register itself both with the NPObject and with the
+ // PluginModule. The NPObject will normally handle its lifetime, and it
+ // will get deleted in the destroy method. It may also get deleted when the
+ // plugin module is deallocated.
+ new PluginObject(module, wrapper, ppp_class, ppp_class_data);
+
+ // We can just use a normal ObjectVar to refer to this object from the
+ // plugin. It will hold a ref to the underlying NPObject which will in turn
+ // hold our pluginObject.
+ return ObjectVar::NPObjectToPPVar(module, wrapper);
+}
+
+NPObject* PluginObject::GetNPObject() const {
+ return object_wrapper_;
+}
+
+// static
+bool PluginObject::IsInstanceOf(NPObject* np_object,
+ const PPP_Class_Deprecated* ppp_class,
+ void** ppp_class_data) {
+ // Validate that this object is implemented by our wrapper class before
+ // trying to get the PluginObject.
+ if (np_object->_class != &wrapper_class)
+ return false;
+
+ PluginObject* plugin_object = FromNPObject(np_object);
+ if (!plugin_object)
+ return false; // Object is no longer alive.
+
+ if (plugin_object->ppp_class() != ppp_class)
+ return false;
+ if (ppp_class_data)
+ *ppp_class_data = plugin_object->ppp_class_data();
+ return true;
+}
+
+// static
+PluginObject* PluginObject::FromNPObject(NPObject* object) {
+ return static_cast<NPObjectWrapper*>(object)->obj;
+}
+
+// static
+NPObject* PluginObject::AllocateObjectWrapper() {
+ NPObjectWrapper* wrapper = new NPObjectWrapper;
+ memset(wrapper, 0, sizeof(NPObjectWrapper));
+ return wrapper;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/plugin_object.h b/webkit/plugins/ppapi/plugin_object.h
new file mode 100644
index 0000000..01637e5
--- /dev/null
+++ b/webkit/plugins/ppapi/plugin_object.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PLUGIN_OBJECT_H_
+#define WEBKIT_PLUGINS_PPAPI_PLUGIN_OBJECT_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+struct PP_Var;
+struct PPP_Class_Deprecated;
+typedef struct NPObject NPObject;
+typedef struct _NPVariant NPVariant;
+
+namespace webkit {
+namespace ppapi {
+
+class PluginModule;
+
+class PluginObject {
+ public:
+ virtual ~PluginObject();
+
+ // Allocates a new PluginObject and returns it as a PP_Var with a
+ // refcount of 1.
+ static PP_Var Create(PluginModule* module,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data);
+
+ PluginModule* module() const { return module_; }
+
+ const PPP_Class_Deprecated* ppp_class() { return ppp_class_; }
+ void* ppp_class_data() { return ppp_class_data_; };
+
+ NPObject* GetNPObject() const;
+
+ // Returns true if the given var is an object implemented by the same plugin
+ // that owns the var object, and that the class matches. If it matches,
+ // returns true and places the class data into |*ppp_class_data| (which can
+ // optionally be NULL if no class data is desired).
+ static bool IsInstanceOf(NPObject* np_object,
+ const PPP_Class_Deprecated* ppp_class,
+ void** ppp_class_data);
+
+ // Converts the given NPObject to the corresponding ObjectVar.
+ //
+ // The given NPObject must be one corresponding to a PluginObject or this
+ // will crash. If the object is a PluginObject but the plugin has gone
+ // away (the object could still be alive because of a reference from JS),
+ // then the return value will be NULL.
+ static PluginObject* FromNPObject(NPObject* object);
+
+ // Allocates a plugin wrapper object and returns it as an NPObject. This is
+ // used internally only.
+ static NPObject* AllocateObjectWrapper();
+
+ private:
+ struct NPObjectWrapper;
+
+ // This object must be created using the CreateObject function of the which
+ // will set up the correct NPObject.
+ //
+ // The NPObjectWrapper (an NPObject) should already have the reference
+ // incremented on it, and this class will take ownership of that reference.
+ PluginObject(PluginModule* module,
+ NPObjectWrapper* object_wrapper,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data);
+
+ PluginModule* module_;
+
+ // Holds a pointer to the NPObject wrapper backing the var. This class
+ // derives from NPObject and we hold a reference to it, so it must be
+ // refcounted. When the type is not an object, this value will be NULL.
+ //
+ // We don't actually own this pointer, it's the NPObject that actually
+ // owns us.
+ NPObjectWrapper* object_wrapper_;
+
+ const PPP_Class_Deprecated* ppp_class_;
+ void* ppp_class_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginObject);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PLUGIN_OBJECT_H_
diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc
new file mode 100644
index 0000000..3b7aff9
--- /dev/null
+++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc
@@ -0,0 +1,1186 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "gfx/rect.h"
+#include "gfx/skia_util.h"
+#include "ppapi/c/dev/ppb_find_dev.h"
+#include "ppapi/c/dev/ppb_fullscreen_dev.h"
+#include "ppapi/c/dev/ppb_zoom_dev.h"
+#include "ppapi/c/dev/ppp_find_dev.h"
+#include "ppapi/c/dev/ppp_selection_dev.h"
+#include "ppapi/c/dev/ppp_zoom_dev.h"
+#include "ppapi/c/pp_input_event.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppp_instance.h"
+#include "printing/native_metafile.h"
+#include "printing/units.h"
+#include "skia/ext/vector_platform_device.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/event_conversion.h"
+#include "webkit/plugins/ppapi/fullscreen_container.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppb_buffer_impl.h"
+#include "webkit/plugins/ppapi/ppb_graphics_2d_impl.h"
+#include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/ppb_url_loader_impl.h"
+#include "webkit/plugins/ppapi/ppp_pdf.h"
+#include "webkit/plugins/ppapi/string.h"
+#include "webkit/plugins/ppapi/var.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#endif
+
+#if defined(OS_WIN)
+#include "gfx/codec/jpeg_codec.h"
+#include "gfx/gdi_util.h"
+#endif
+
+using WebKit::WebBindings;
+using WebKit::WebCanvas;
+using WebKit::WebCursorInfo;
+using WebKit::WebDocument;
+using WebKit::WebFrame;
+using WebKit::WebInputEvent;
+using WebKit::WebPluginContainer;
+using WebKit::WebString;
+using WebKit::WebURLRequest;
+using WebKit::WebView;
+
+namespace webkit {
+namespace ppapi {
+
+#if defined(OS_WIN)
+// Exported by pdf.dll
+typedef bool (*RenderPDFPageToDCProc)(
+ const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
+ int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
+ int bounds_width, int bounds_height, bool fit_to_bounds,
+ bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds);
+#endif // defined(OS_WIN)
+
+namespace {
+
+#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
+ COMPILE_ASSERT(int(WebCursorInfo::webkit_name) == int(np_name), \
+ mismatching_enums)
+
+COMPILE_ASSERT_MATCHING_ENUM(TypePointer, PP_CURSORTYPE_POINTER);
+COMPILE_ASSERT_MATCHING_ENUM(TypeCross, PP_CURSORTYPE_CROSS);
+COMPILE_ASSERT_MATCHING_ENUM(TypeHand, PP_CURSORTYPE_HAND);
+COMPILE_ASSERT_MATCHING_ENUM(TypeIBeam, PP_CURSORTYPE_IBEAM);
+COMPILE_ASSERT_MATCHING_ENUM(TypeWait, PP_CURSORTYPE_WAIT);
+COMPILE_ASSERT_MATCHING_ENUM(TypeHelp, PP_CURSORTYPE_HELP);
+COMPILE_ASSERT_MATCHING_ENUM(TypeEastResize, PP_CURSORTYPE_EASTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthResize, PP_CURSORTYPE_NORTHRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastResize,
+ PP_CURSORTYPE_NORTHEASTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestResize,
+ PP_CURSORTYPE_NORTHWESTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeSouthResize, PP_CURSORTYPE_SOUTHRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastResize,
+ PP_CURSORTYPE_SOUTHEASTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestResize,
+ PP_CURSORTYPE_SOUTHWESTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeWestResize, PP_CURSORTYPE_WESTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthSouthResize,
+ PP_CURSORTYPE_NORTHSOUTHRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeEastWestResize, PP_CURSORTYPE_EASTWESTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastSouthWestResize,
+ PP_CURSORTYPE_NORTHEASTSOUTHWESTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestSouthEastResize,
+ PP_CURSORTYPE_NORTHWESTSOUTHEASTRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeColumnResize, PP_CURSORTYPE_COLUMNRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeRowResize, PP_CURSORTYPE_ROWRESIZE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeMiddlePanning, PP_CURSORTYPE_MIDDLEPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeEastPanning, PP_CURSORTYPE_EASTPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthPanning, PP_CURSORTYPE_NORTHPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastPanning,
+ PP_CURSORTYPE_NORTHEASTPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestPanning,
+ PP_CURSORTYPE_NORTHWESTPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeSouthPanning, PP_CURSORTYPE_SOUTHPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastPanning,
+ PP_CURSORTYPE_SOUTHEASTPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestPanning,
+ PP_CURSORTYPE_SOUTHWESTPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeWestPanning, PP_CURSORTYPE_WESTPANNING);
+COMPILE_ASSERT_MATCHING_ENUM(TypeMove, PP_CURSORTYPE_MOVE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeVerticalText, PP_CURSORTYPE_VERTICALTEXT);
+COMPILE_ASSERT_MATCHING_ENUM(TypeCell, PP_CURSORTYPE_CELL);
+COMPILE_ASSERT_MATCHING_ENUM(TypeContextMenu, PP_CURSORTYPE_CONTEXTMENU);
+COMPILE_ASSERT_MATCHING_ENUM(TypeAlias, PP_CURSORTYPE_ALIAS);
+COMPILE_ASSERT_MATCHING_ENUM(TypeProgress, PP_CURSORTYPE_PROGRESS);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNoDrop, PP_CURSORTYPE_NODROP);
+COMPILE_ASSERT_MATCHING_ENUM(TypeCopy, PP_CURSORTYPE_COPY);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNone, PP_CURSORTYPE_NONE);
+COMPILE_ASSERT_MATCHING_ENUM(TypeNotAllowed, PP_CURSORTYPE_NOTALLOWED);
+COMPILE_ASSERT_MATCHING_ENUM(TypeZoomIn, PP_CURSORTYPE_ZOOMIN);
+COMPILE_ASSERT_MATCHING_ENUM(TypeZoomOut, PP_CURSORTYPE_ZOOMOUT);
+COMPILE_ASSERT_MATCHING_ENUM(TypeCustom, PP_CURSORTYPE_CUSTOM);
+
+void RectToPPRect(const gfx::Rect& input, PP_Rect* output) {
+ *output = PP_MakeRectFromXYWH(input.x(), input.y(),
+ input.width(), input.height());
+}
+
+PP_Var GetWindowObject(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_MakeUndefined();
+ return instance->GetWindowObject();
+}
+
+PP_Var GetOwnerElementObject(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_MakeUndefined();
+ return instance->GetOwnerElementObject();
+}
+
+PP_Bool BindGraphics(PP_Instance instance_id, PP_Resource graphics_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+ return BoolToPPBool(instance->BindGraphics(graphics_id));
+}
+
+PP_Bool IsFullFrame(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+ return BoolToPPBool(instance->full_frame());
+}
+
+PP_Var ExecuteScript(PP_Instance instance_id,
+ PP_Var script,
+ PP_Var* exception) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_MakeUndefined();
+ return instance->ExecuteScript(script, exception);
+}
+
+const PPB_Instance ppb_instance = {
+ &GetWindowObject,
+ &GetOwnerElementObject,
+ &BindGraphics,
+ &IsFullFrame,
+ &ExecuteScript,
+};
+
+void NumberOfFindResultsChanged(PP_Instance instance_id,
+ int32_t total,
+ PP_Bool final_result) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+
+ DCHECK_NE(instance->find_identifier(), -1);
+ instance->delegate()->NumberOfFindResultsChanged(
+ instance->find_identifier(), total, PPBoolToBool(final_result));
+}
+
+void SelectedFindResultChanged(PP_Instance instance_id,
+ int32_t index) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+
+ DCHECK_NE(instance->find_identifier(), -1);
+ instance->delegate()->SelectedFindResultChanged(
+ instance->find_identifier(), index);
+}
+
+const PPB_Find_Dev ppb_find = {
+ &NumberOfFindResultsChanged,
+ &SelectedFindResultChanged,
+};
+
+PP_Bool IsFullscreen(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+ return BoolToPPBool(instance->IsFullscreen());
+}
+
+PP_Bool SetFullscreen(PP_Instance instance_id, PP_Bool fullscreen) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+ return BoolToPPBool(instance->SetFullscreen(PPBoolToBool(fullscreen)));
+}
+
+const PPB_Fullscreen_Dev ppb_fullscreen = {
+ &IsFullscreen,
+ &SetFullscreen,
+};
+
+void ZoomChanged(PP_Instance instance_id, double factor) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+
+ // We only want to tell the page to change its zoom if the whole page is the
+ // PDF. If we're in an iframe, then don't do anything.
+ WebFrame* frame = instance->container()->element().document().frame();
+ if (!frame->view()->mainFrame()->document().isPluginDocument())
+ return;
+
+ double zoom_level = WebView::zoomFactorToZoomLevel(factor);
+ // The conversino from zoom level to factor, and back, can introduce rounding
+ // errors. i.e. WebKit originally tells us 3.0, but by the time we tell the
+ // plugin and it tells us back, the level becomes 3.000000000004. Need to
+ // round or else otherwise if the user zooms out, it will go to 3.0 instead of
+ // 2.0.
+ int rounded =
+ static_cast<int>(zoom_level + (zoom_level > 0 ? 0.001 : -0.001));
+ if (abs(rounded - zoom_level) < 0.001)
+ zoom_level = rounded;
+ instance->container()->zoomLevelChanged(zoom_level);
+}
+
+void ZoomLimitsChanged(PP_Instance instance_id,
+ double minimum_factor,
+ double maximium_factor) {
+ if (minimum_factor > maximium_factor) {
+ NOTREACHED();
+ return;
+ }
+
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+ instance->delegate()->ZoomLimitsChanged(minimum_factor, maximium_factor);
+}
+
+const PPB_Zoom_Dev ppb_zoom = {
+ &ZoomChanged,
+ &ZoomLimitsChanged
+};
+
+} // namespace
+
+PluginInstance::PluginInstance(PluginDelegate* delegate,
+ PluginModule* module,
+ const PPP_Instance* instance_interface)
+ : delegate_(delegate),
+ module_(module),
+ instance_interface_(instance_interface),
+ pp_instance_(0),
+ container_(NULL),
+ full_frame_(false),
+ has_webkit_focus_(false),
+ has_content_area_focus_(false),
+ find_identifier_(-1),
+ plugin_find_interface_(NULL),
+ plugin_pdf_interface_(NULL),
+ plugin_selection_interface_(NULL),
+ plugin_zoom_interface_(NULL),
+#if defined (OS_LINUX)
+ num_pages_(0),
+ pdf_output_done_(false),
+#endif // defined (OS_LINUX)
+ plugin_print_interface_(NULL),
+ plugin_graphics_3d_interface_(NULL),
+ always_on_top_(false),
+ fullscreen_container_(NULL) {
+ pp_instance_ = ResourceTracker::Get()->AddInstance(this);
+
+ memset(&current_print_settings_, 0, sizeof(current_print_settings_));
+ DCHECK(delegate);
+ module_->InstanceCreated(this);
+ delegate_->InstanceCreated(this);
+}
+
+PluginInstance::~PluginInstance() {
+ FOR_EACH_OBSERVER(Observer, observers_, InstanceDestroyed(this));
+
+ delegate_->InstanceDeleted(this);
+ module_->InstanceDeleted(this);
+
+ ResourceTracker::Get()->InstanceDeleted(pp_instance_);
+}
+
+// static
+const PPB_Instance* PluginInstance::GetInterface() {
+ return &ppb_instance;
+}
+
+// static
+const PPB_Find_Dev* PluginInstance::GetFindInterface() {
+ return &ppb_find;
+}
+
+// static
+const PPB_Fullscreen_Dev* PluginInstance::GetFullscreenInterface() {
+ return &ppb_fullscreen;
+}
+
+// static
+const PPB_Zoom_Dev* PluginInstance::GetZoomInterface() {
+ return &ppb_zoom;
+}
+
+void PluginInstance::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void PluginInstance::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void PluginInstance::Paint(WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const gfx::Rect& paint_rect) {
+ if (bound_graphics_2d())
+ bound_graphics_2d()->Paint(canvas, plugin_rect, paint_rect);
+}
+
+void PluginInstance::InvalidateRect(const gfx::Rect& rect) {
+ if (fullscreen_container_) {
+ if (rect.IsEmpty())
+ fullscreen_container_->Invalidate();
+ else
+ fullscreen_container_->InvalidateRect(rect);
+ } else {
+ if (!container_ || position_.IsEmpty())
+ return; // Nothing to do.
+ if (rect.IsEmpty())
+ container_->invalidate();
+ else
+ container_->invalidateRect(rect);
+ }
+}
+
+void PluginInstance::ScrollRect(int dx, int dy, const gfx::Rect& rect) {
+ if (fullscreen_container_) {
+ fullscreen_container_->ScrollRect(dx, dy, rect);
+ } else {
+ if (full_frame_) {
+ container_->scrollRect(dx, dy, rect);
+ } else {
+ // Can't do optimized scrolling since there could be other elements on top
+ // of us.
+ InvalidateRect(rect);
+ }
+ }
+}
+
+unsigned PluginInstance::GetBackingTextureId() {
+ if (!bound_graphics_3d())
+ return 0;
+
+ return bound_graphics_3d()->GetBackingTextureId();
+}
+
+void PluginInstance::CommitBackingTexture() {
+ container_->commitBackingTexture();
+}
+
+PP_Var PluginInstance::GetWindowObject() {
+ if (!container_)
+ return PP_MakeUndefined();
+
+ WebFrame* frame = container_->element().document().frame();
+ if (!frame)
+ return PP_MakeUndefined();
+
+ return ObjectVar::NPObjectToPPVar(module(), frame->windowObject());
+}
+
+PP_Var PluginInstance::GetOwnerElementObject() {
+ if (!container_)
+ return PP_MakeUndefined();
+ return ObjectVar::NPObjectToPPVar(module(),
+ container_->scriptableObjectForElement());
+}
+
+bool PluginInstance::BindGraphics(PP_Resource graphics_id) {
+ if (!graphics_id) {
+ // Special-case clearing the current device.
+ if (bound_graphics_.get()) {
+ if (bound_graphics_2d()) {
+ bound_graphics_2d()->BindToInstance(NULL);
+ } else if (bound_graphics_.get()) {
+ bound_graphics_3d()->SetSwapBuffersCallback(NULL);
+ bound_graphics_3d()->BindToInstance(NULL);
+ }
+ InvalidateRect(gfx::Rect());
+ }
+ bound_graphics_ = NULL;
+ return true;
+ }
+
+ scoped_refptr<PPB_Graphics2D_Impl> graphics_2d =
+ Resource::GetAs<PPB_Graphics2D_Impl>(graphics_id);
+ scoped_refptr<PPB_Graphics3D_Impl> graphics_3d =
+ Resource::GetAs<PPB_Graphics3D_Impl>(graphics_id);
+
+ if (graphics_2d) {
+ if (!graphics_2d->BindToInstance(this))
+ return false; // Can't bind to more than one instance.
+
+ // See http://crbug.com/49403: this can be further optimized by keeping the
+ // old device around and painting from it.
+ if (bound_graphics_2d()) {
+ // Start the new image with the content of the old image until the plugin
+ // repaints.
+ const SkBitmap* old_backing_bitmap =
+ bound_graphics_2d()->image_data()->GetMappedBitmap();
+ SkRect old_size = SkRect::MakeWH(
+ SkScalar(static_cast<float>(old_backing_bitmap->width())),
+ SkScalar(static_cast<float>(old_backing_bitmap->height())));
+
+ SkCanvas canvas(*graphics_2d->image_data()->GetMappedBitmap());
+ canvas.drawBitmap(*old_backing_bitmap, 0, 0);
+
+ // Fill in any extra space with white.
+ canvas.clipRect(old_size, SkRegion::kDifference_Op);
+ canvas.drawARGB(255, 255, 255, 255);
+ }
+
+ bound_graphics_ = graphics_2d;
+ // BindToInstance will have invalidated the plugin if necessary.
+ } else if (graphics_3d) {
+ if (!graphics_3d->BindToInstance(this))
+ return false;
+
+ bound_graphics_ = graphics_3d;
+ bound_graphics_3d()->SetSwapBuffersCallback(
+ NewCallback(this, &PluginInstance::CommitBackingTexture));
+ }
+
+ return true;
+}
+
+bool PluginInstance::SetCursor(PP_CursorType_Dev type) {
+ cursor_.reset(new WebCursorInfo(static_cast<WebCursorInfo::Type>(type)));
+ return true;
+}
+
+PP_Var PluginInstance::ExecuteScript(PP_Var script, PP_Var* exception) {
+ TryCatch try_catch(module(), exception);
+ if (try_catch.has_exception())
+ return PP_MakeUndefined();
+
+ // Convert the script into an inconvenient NPString object.
+ scoped_refptr<StringVar> script_string(StringVar::FromPPVar(script));
+ if (!script_string) {
+ try_catch.SetException("Script param to ExecuteScript must be a string.");
+ return PP_MakeUndefined();
+ }
+ NPString np_script;
+ np_script.UTF8Characters = script_string->value().c_str();
+ np_script.UTF8Length = script_string->value().length();
+
+ // Get the current frame to pass to the evaluate function.
+ WebFrame* frame = container_->element().document().frame();
+ if (!frame) {
+ try_catch.SetException("No frame to execute script in.");
+ return PP_MakeUndefined();
+ }
+
+ NPVariant result;
+ bool ok = WebBindings::evaluate(NULL, frame->windowObject(), &np_script,
+ &result);
+ if (!ok) {
+ // TODO(brettw) bug 54011: The TryCatch isn't working properly and
+ // doesn't actually catch this exception.
+ try_catch.SetException("Exception caught");
+ WebBindings::releaseVariantValue(&result);
+ return PP_MakeUndefined();
+ }
+
+ PP_Var ret = Var::NPVariantToPPVar(module_, &result);
+ WebBindings::releaseVariantValue(&result);
+ return ret;
+}
+
+void PluginInstance::Delete() {
+ instance_interface_->DidDestroy(pp_instance());
+
+ if (fullscreen_container_) {
+ fullscreen_container_->Destroy();
+ fullscreen_container_ = NULL;
+ }
+ container_ = NULL;
+}
+
+bool PluginInstance::Initialize(WebPluginContainer* container,
+ const std::vector<std::string>& arg_names,
+ const std::vector<std::string>& arg_values,
+ bool full_frame) {
+ container_ = container;
+ full_frame_ = full_frame;
+
+ size_t argc = 0;
+ scoped_array<const char*> argn(new const char*[arg_names.size()]);
+ scoped_array<const char*> argv(new const char*[arg_names.size()]);
+ for (size_t i = 0; i < arg_names.size(); ++i) {
+ argn[argc] = arg_names[i].c_str();
+ argv[argc] = arg_values[i].c_str();
+ argc++;
+ }
+
+ return PPBoolToBool(instance_interface_->DidCreate(pp_instance(),
+ argc,
+ argn.get(),
+ argv.get()));
+}
+
+bool PluginInstance::HandleDocumentLoad(PPB_URLLoader_Impl* loader) {
+ Resource::ScopedResourceId resource(loader);
+ return PPBoolToBool(instance_interface_->HandleDocumentLoad(pp_instance(),
+ resource.id));
+}
+
+bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event,
+ WebCursorInfo* cursor_info) {
+ std::vector<PP_InputEvent> pp_events;
+ CreatePPEvent(event, &pp_events);
+
+ // Each input event may generate more than one PP_InputEvent.
+ bool rv = false;
+ for (size_t i = 0; i < pp_events.size(); i++) {
+ rv |= PPBoolToBool(instance_interface_->HandleInputEvent(pp_instance(),
+ &pp_events[i]));
+ }
+
+ if (cursor_.get())
+ *cursor_info = *cursor_;
+ return rv;
+}
+
+PP_Var PluginInstance::GetInstanceObject() {
+ return instance_interface_->GetInstanceObject(pp_instance());
+}
+
+void PluginInstance::ViewChanged(const gfx::Rect& position,
+ const gfx::Rect& clip) {
+ if (position.size() != position_.size() && bound_graphics_3d()) {
+ // TODO(apatrick): This is a hack to force the back buffer to resize.
+ // It is obviously wrong to call SwapBuffers when a partial frame has
+ // potentially been rendered. Plan is to embed resize commands in the
+ // command buffer just before ViewChanged is called.
+ bound_graphics_3d()->ResizeBackingTexture(position.size());
+ bound_graphics_3d()->SwapBuffers();
+ }
+
+ position_ = position;
+
+ if (clip.IsEmpty()) {
+ // WebKit can give weird (x,y) positions for empty clip rects (since the
+ // position technically doesn't matter). But we want to make these
+ // consistent since this is given to the plugin, so force everything to 0
+ // in the "everything is clipped" case.
+ clip_ = gfx::Rect();
+ } else {
+ clip_ = clip;
+ }
+
+ PP_Rect pp_position, pp_clip;
+ RectToPPRect(position_, &pp_position);
+ RectToPPRect(clip_, &pp_clip);
+ instance_interface_->DidChangeView(pp_instance(), &pp_position, &pp_clip);
+}
+
+void PluginInstance::SetWebKitFocus(bool has_focus) {
+ if (has_webkit_focus_ == has_focus)
+ return;
+
+ bool old_plugin_focus = PluginHasFocus();
+ has_webkit_focus_ = has_focus;
+ if (PluginHasFocus() != old_plugin_focus) {
+ instance_interface_->DidChangeFocus(pp_instance(),
+ BoolToPPBool(PluginHasFocus()));
+ }
+}
+
+void PluginInstance::SetContentAreaFocus(bool has_focus) {
+ if (has_content_area_focus_ == has_focus)
+ return;
+
+ bool old_plugin_focus = PluginHasFocus();
+ has_content_area_focus_ = has_focus;
+ if (PluginHasFocus() != old_plugin_focus) {
+ instance_interface_->DidChangeFocus(pp_instance(),
+ BoolToPPBool(PluginHasFocus()));
+ }
+}
+
+void PluginInstance::ViewInitiatedPaint() {
+ if (bound_graphics_2d())
+ bound_graphics_2d()->ViewInitiatedPaint();
+}
+
+void PluginInstance::ViewFlushedPaint() {
+ if (bound_graphics_2d())
+ bound_graphics_2d()->ViewFlushedPaint();
+}
+
+bool PluginInstance::GetBitmapForOptimizedPluginPaint(
+ const gfx::Rect& paint_bounds,
+ TransportDIB** dib,
+ gfx::Rect* location,
+ gfx::Rect* clip) {
+ if (!always_on_top_)
+ return false;
+ if (!bound_graphics_2d() || !bound_graphics_2d()->is_always_opaque())
+ return false;
+
+ // We specifically want to compare against the area covered by the backing
+ // store when seeing if we cover the given paint bounds, since the backing
+ // store could be smaller than the declared plugin area.
+ PPB_ImageData_Impl* image_data = bound_graphics_2d()->image_data();
+ gfx::Rect plugin_backing_store_rect(position_.origin(),
+ gfx::Size(image_data->width(),
+ image_data->height()));
+ gfx::Rect clip_page(clip_);
+ clip_page.Offset(position_.origin());
+ gfx::Rect plugin_paint_rect = plugin_backing_store_rect.Intersect(clip_page);
+ if (!plugin_paint_rect.Contains(paint_bounds))
+ return false;
+
+ *dib = image_data->platform_image()->GetTransportDIB();
+ *location = plugin_backing_store_rect;
+ *clip = clip_page;
+ return true;
+}
+
+string16 PluginInstance::GetSelectedText(bool html) {
+ if (!LoadSelectionInterface())
+ return string16();
+
+ PP_Var rv = plugin_selection_interface_->GetSelectedText(pp_instance(),
+ BoolToPPBool(html));
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(rv));
+ Var::PluginReleasePPVar(rv); // Release the ref the plugin transfered to us.
+ if (!string)
+ return string16();
+ return UTF8ToUTF16(string->value());
+}
+
+string16 PluginInstance::GetLinkAtPosition(const gfx::Point& point) {
+ if (!LoadPdfInterface())
+ return string16();
+
+ PP_Point p;
+ p.x = point.x();
+ p.y = point.y();
+ PP_Var rv = plugin_pdf_interface_->GetLinkAtPosition(pp_instance(), p);
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(rv));
+ Var::PluginReleasePPVar(rv); // Release the ref the plugin transfered to us.
+ if (!string)
+ return string16();
+ return UTF8ToUTF16(string->value());
+}
+
+void PluginInstance::Zoom(double factor, bool text_only) {
+ if (!LoadZoomInterface())
+ return;
+ plugin_zoom_interface_->Zoom(pp_instance(), factor, BoolToPPBool(text_only));
+}
+
+bool PluginInstance::StartFind(const string16& search_text,
+ bool case_sensitive,
+ int identifier) {
+ if (!LoadFindInterface())
+ return false;
+ find_identifier_ = identifier;
+ return PPBoolToBool(
+ plugin_find_interface_->StartFind(
+ pp_instance(),
+ UTF16ToUTF8(search_text.c_str()).c_str(),
+ BoolToPPBool(case_sensitive)));
+}
+
+void PluginInstance::SelectFindResult(bool forward) {
+ if (LoadFindInterface())
+ plugin_find_interface_->SelectFindResult(pp_instance(),
+ BoolToPPBool(forward));
+}
+
+void PluginInstance::StopFind() {
+ if (!LoadFindInterface())
+ return;
+ find_identifier_ = -1;
+ plugin_find_interface_->StopFind(pp_instance());
+}
+
+bool PluginInstance::LoadFindInterface() {
+ if (!plugin_find_interface_) {
+ plugin_find_interface_ =
+ reinterpret_cast<const PPP_Find_Dev*>(module_->GetPluginInterface(
+ PPP_FIND_DEV_INTERFACE));
+ }
+
+ return !!plugin_find_interface_;
+}
+
+bool PluginInstance::LoadPdfInterface() {
+ if (!plugin_pdf_interface_) {
+ plugin_pdf_interface_ =
+ reinterpret_cast<const PPP_Pdf*>(module_->GetPluginInterface(
+ PPP_PDF_INTERFACE));
+ }
+
+ return !!plugin_pdf_interface_;
+}
+
+bool PluginInstance::LoadSelectionInterface() {
+ if (!plugin_selection_interface_) {
+ plugin_selection_interface_ =
+ reinterpret_cast<const PPP_Selection_Dev*>(module_->GetPluginInterface(
+ PPP_SELECTION_DEV_INTERFACE));
+ }
+
+ return !!plugin_selection_interface_;
+}
+
+bool PluginInstance::LoadZoomInterface() {
+ if (!plugin_zoom_interface_) {
+ plugin_zoom_interface_ =
+ reinterpret_cast<const PPP_Zoom_Dev*>(module_->GetPluginInterface(
+ PPP_ZOOM_DEV_INTERFACE));
+ }
+
+ return !!plugin_zoom_interface_;
+}
+
+bool PluginInstance::PluginHasFocus() const {
+ return has_webkit_focus_ && has_content_area_focus_;
+}
+
+bool PluginInstance::GetPreferredPrintOutputFormat(
+ PP_PrintOutputFormat_Dev* format) {
+ if (!plugin_print_interface_) {
+ plugin_print_interface_ =
+ reinterpret_cast<const PPP_Printing_Dev*>(module_->GetPluginInterface(
+ PPP_PRINTING_DEV_INTERFACE));
+ }
+ if (!plugin_print_interface_)
+ return false;
+ uint32_t format_count = 0;
+ PP_PrintOutputFormat_Dev* supported_formats =
+ plugin_print_interface_->QuerySupportedFormats(pp_instance(),
+ &format_count);
+ if (!supported_formats)
+ return false;
+
+ bool found_supported_format = false;
+ for (uint32_t index = 0; index < format_count; index++) {
+ if (supported_formats[index] == PP_PRINTOUTPUTFORMAT_PDF) {
+ // If we found PDF, we are done.
+ found_supported_format = true;
+ *format = PP_PRINTOUTPUTFORMAT_PDF;
+ break;
+ } else if (supported_formats[index] == PP_PRINTOUTPUTFORMAT_RASTER) {
+ // We found raster. Keep looking.
+ found_supported_format = true;
+ *format = PP_PRINTOUTPUTFORMAT_RASTER;
+ }
+ }
+ PluginModule::GetCore()->MemFree(supported_formats);
+ return found_supported_format;
+}
+
+bool PluginInstance::SupportsPrintInterface() {
+ PP_PrintOutputFormat_Dev format;
+ return GetPreferredPrintOutputFormat(&format);
+}
+
+int PluginInstance::PrintBegin(const gfx::Rect& printable_area,
+ int printer_dpi) {
+ PP_PrintOutputFormat_Dev format;
+ if (!GetPreferredPrintOutputFormat(&format)) {
+ // PrintBegin should not have been called since SupportsPrintInterface
+ // would have returned false;
+ NOTREACHED();
+ return 0;
+ }
+
+ PP_PrintSettings_Dev print_settings;
+ RectToPPRect(printable_area, &print_settings.printable_area);
+ print_settings.dpi = printer_dpi;
+ print_settings.orientation = PP_PRINTORIENTATION_NORMAL;
+ print_settings.grayscale = PP_FALSE;
+ print_settings.format = format;
+ int num_pages = plugin_print_interface_->Begin(pp_instance(),
+ &print_settings);
+ if (!num_pages)
+ return 0;
+ current_print_settings_ = print_settings;
+#if defined (OS_LINUX)
+ num_pages_ = num_pages;
+ pdf_output_done_ = false;
+#endif // (OS_LINUX)
+ return num_pages;
+}
+
+bool PluginInstance::PrintPage(int page_number, WebKit::WebCanvas* canvas) {
+ DCHECK(plugin_print_interface_);
+ PP_PrintPageNumberRange_Dev page_range;
+#if defined(OS_LINUX)
+ if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF) {
+ // On Linux we will try and output all pages as PDF in the first call to
+ // PrintPage. This is a temporary hack.
+ // TODO(sanjeevr): Remove this hack and fix this by changing the print
+ // interfaces for WebFrame and WebPlugin.
+ if (page_number != 0)
+ return pdf_output_done_;
+ page_range.first_page_number = 0;
+ page_range.last_page_number = num_pages_ - 1;
+ }
+#else // defined(OS_LINUX)
+ page_range.first_page_number = page_range.last_page_number = page_number;
+#endif // defined(OS_LINUX)
+
+ PP_Resource print_output =
+ plugin_print_interface_->PrintPages(pp_instance(), &page_range, 1);
+
+ if (!print_output)
+ return false;
+
+ bool ret = false;
+
+ if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF)
+ ret = PrintPDFOutput(print_output, canvas);
+ else if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_RASTER)
+ ret = PrintRasterOutput(print_output, canvas);
+
+ // Now we need to release the print output resource.
+ PluginModule::GetCore()->ReleaseResource(print_output);
+
+ return ret;
+}
+
+void PluginInstance::PrintEnd() {
+ DCHECK(plugin_print_interface_);
+ if (plugin_print_interface_)
+ plugin_print_interface_->End(pp_instance());
+ memset(&current_print_settings_, 0, sizeof(current_print_settings_));
+#if defined(OS_MACOSX)
+ last_printed_page_ = NULL;
+#elif defined(OS_LINUX)
+ num_pages_ = 0;
+ pdf_output_done_ = false;
+#endif // defined(OS_LINUX)
+}
+
+bool PluginInstance::IsFullscreen() {
+ return fullscreen_container_ != NULL;
+}
+
+bool PluginInstance::SetFullscreen(bool fullscreen) {
+ bool is_fullscreen = (fullscreen_container_ != NULL);
+ if (fullscreen == is_fullscreen)
+ return true;
+ VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off");
+ if (fullscreen) {
+ fullscreen_container_ = delegate_->CreateFullscreenContainer(this);
+ } else {
+ fullscreen_container_->Destroy();
+ fullscreen_container_ = NULL;
+ // TODO(piman): currently the fullscreen container resizes the plugin to the
+ // fullscreen size so we need to reset the size here. Eventually it will
+ // transparently scale and this won't be necessary.
+ if (container_) {
+ container_->reportGeometry();
+ container_->invalidate();
+ }
+ }
+ return true;
+}
+
+bool PluginInstance::NavigateToURL(const char* url, const char* target) {
+ if (!url || !target || !container_)
+ return false;
+
+ WebDocument document = container_->element().document();
+ GURL complete_url = document.completeURL(WebString::fromUTF8(url));
+ // Don't try to deal with the security issues of javascript.
+ if (complete_url.SchemeIs("javascript"))
+ return false;
+
+ WebURLRequest request(complete_url);
+ document.frame()->setReferrerForRequest(request, GURL());
+ request.setHTTPMethod(WebString::fromUTF8("GET"));
+ request.setFirstPartyForCookies(document.firstPartyForCookies());
+
+ WebString target_str = WebString::fromUTF8(target);
+ container_->loadFrameRequest(request, target_str, false, NULL);
+ return true;
+}
+
+bool PluginInstance::PrintPDFOutput(PP_Resource print_output,
+ WebKit::WebCanvas* canvas) {
+ scoped_refptr<PPB_Buffer_Impl> buffer(
+ Resource::GetAs<PPB_Buffer_Impl>(print_output));
+ if (!buffer.get() || !buffer->is_mapped() || !buffer->size()) {
+ NOTREACHED();
+ return false;
+ }
+#if defined(OS_WIN)
+ // For Windows, we need the PDF DLL to render the output PDF to a DC.
+ HMODULE pdf_module = GetModuleHandle(L"pdf.dll");
+ if (!pdf_module)
+ return false;
+ RenderPDFPageToDCProc render_proc =
+ reinterpret_cast<RenderPDFPageToDCProc>(
+ GetProcAddress(pdf_module, "RenderPDFPageToDC"));
+ if (!render_proc)
+ return false;
+#endif // defined(OS_WIN)
+
+ bool ret = false;
+#if defined(OS_LINUX)
+ // On Linux we need to get the backing PdfPsMetafile and write the bits
+ // directly.
+ cairo_t* context = canvas->beginPlatformPaint();
+ printing::NativeMetafile* metafile =
+ printing::NativeMetafile::FromCairoContext(context);
+ DCHECK(metafile);
+ if (metafile) {
+ ret = metafile->SetRawData(buffer->mapped_buffer(), buffer->size());
+ if (ret)
+ pdf_output_done_ = true;
+ }
+ canvas->endPlatformPaint();
+#elif defined(OS_MACOSX)
+ printing::NativeMetafile metafile;
+ // Create a PDF metafile and render from there into the passed in context.
+ if (metafile.Init(buffer->mapped_buffer(), buffer->size())) {
+ // Flip the transform.
+ CGContextSaveGState(canvas);
+ CGContextTranslateCTM(canvas, 0,
+ current_print_settings_.printable_area.size.height);
+ CGContextScaleCTM(canvas, 1.0, -1.0);
+ CGRect page_rect;
+ page_rect.origin.x = current_print_settings_.printable_area.point.x;
+ page_rect.origin.y = current_print_settings_.printable_area.point.y;
+ page_rect.size.width = current_print_settings_.printable_area.size.width;
+ page_rect.size.height = current_print_settings_.printable_area.size.height;
+
+ ret = metafile.RenderPage(1, canvas, page_rect, true, false, true, true);
+ CGContextRestoreGState(canvas);
+ }
+#elif defined(OS_WIN)
+ // On Windows, we now need to render the PDF to the DC that backs the
+ // supplied canvas.
+ skia::VectorPlatformDevice& device =
+ static_cast<skia::VectorPlatformDevice&>(
+ canvas->getTopPlatformDevice());
+ HDC dc = device.getBitmapDC();
+ gfx::Size size_in_pixels;
+ size_in_pixels.set_width(
+ printing::ConvertUnit(current_print_settings_.printable_area.size.width,
+ static_cast<int>(printing::kPointsPerInch),
+ current_print_settings_.dpi));
+ size_in_pixels.set_height(
+ printing::ConvertUnit(current_print_settings_.printable_area.size.height,
+ static_cast<int>(printing::kPointsPerInch),
+ current_print_settings_.dpi));
+ // We need to render using the actual printer DPI (rendering to a smaller
+ // set of pixels leads to a blurry output). However, we need to counter the
+ // scaling up that will happen in the browser.
+ XFORM xform = {0};
+ xform.eM11 = xform.eM22 = static_cast<float>(printing::kPointsPerInch) /
+ static_cast<float>(current_print_settings_.dpi);
+ ModifyWorldTransform(dc, &xform, MWT_LEFTMULTIPLY);
+
+ ret = render_proc(buffer->mapped_buffer(), buffer->size(), 0, dc,
+ current_print_settings_.dpi, current_print_settings_.dpi,
+ 0, 0, size_in_pixels.width(),
+ size_in_pixels.height(), true, false, true, true);
+#endif // defined(OS_WIN)
+
+ return ret;
+}
+
+bool PluginInstance::PrintRasterOutput(PP_Resource print_output,
+ WebKit::WebCanvas* canvas) {
+ scoped_refptr<PPB_ImageData_Impl> image(
+ Resource::GetAs<PPB_ImageData_Impl>(print_output));
+ if (!image.get() || !image->is_mapped())
+ return false;
+
+ const SkBitmap* bitmap = image->GetMappedBitmap();
+ if (!bitmap)
+ return false;
+
+ // Draw the printed image into the supplied canvas.
+ SkIRect src_rect;
+ src_rect.set(0, 0, bitmap->width(), bitmap->height());
+ SkRect dest_rect;
+ dest_rect.set(
+ SkIntToScalar(current_print_settings_.printable_area.point.x),
+ SkIntToScalar(current_print_settings_.printable_area.point.y),
+ SkIntToScalar(current_print_settings_.printable_area.point.x +
+ current_print_settings_.printable_area.size.width),
+ SkIntToScalar(current_print_settings_.printable_area.point.y +
+ current_print_settings_.printable_area.size.height));
+ bool draw_to_canvas = true;
+ gfx::Rect dest_rect_gfx;
+ dest_rect_gfx.set_x(current_print_settings_.printable_area.point.x);
+ dest_rect_gfx.set_y(current_print_settings_.printable_area.point.y);
+ dest_rect_gfx.set_width(current_print_settings_.printable_area.size.width);
+ dest_rect_gfx.set_height(current_print_settings_.printable_area.size.height);
+
+#if defined(OS_WIN)
+ // Since this is a raster output, the size of the bitmap can be
+ // huge (especially at high printer DPIs). On Windows, this can
+ // result in a HUGE EMF (on Mac and Linux the output goes to PDF
+ // which appears to Flate compress the bitmap). So, if this bitmap
+ // is larger than 20 MB, we save the bitmap as a JPEG into the EMF
+ // DC. Note: We chose JPEG over PNG because JPEG compression seems
+ // way faster (about 4 times faster).
+ static const int kCompressionThreshold = 20 * 1024 * 1024;
+ if (bitmap->getSize() > kCompressionThreshold) {
+ DrawJPEGToPlatformDC(*bitmap, dest_rect_gfx, canvas);
+ draw_to_canvas = false;
+ }
+#endif // defined(OS_WIN)
+#if defined(OS_MACOSX)
+ draw_to_canvas = false;
+ DrawSkBitmapToCanvas(*bitmap, canvas, dest_rect_gfx,
+ current_print_settings_.printable_area.size.height);
+ // See comments in the header file.
+ last_printed_page_ = image;
+#else // defined(OS_MACOSX)
+ if (draw_to_canvas)
+ canvas->drawBitmapRect(*bitmap, &src_rect, dest_rect);
+#endif // defined(OS_MACOSX)
+ return true;
+}
+
+#if defined(OS_WIN)
+bool PluginInstance::DrawJPEGToPlatformDC(
+ const SkBitmap& bitmap,
+ const gfx::Rect& printable_area,
+ WebKit::WebCanvas* canvas) {
+ skia::VectorPlatformDevice& device =
+ static_cast<skia::VectorPlatformDevice&>(
+ canvas->getTopPlatformDevice());
+ HDC dc = device.getBitmapDC();
+ // TODO(sanjeevr): This is a temporary hack. If we output a JPEG
+ // to the EMF, the EnumEnhMetaFile call fails in the browser
+ // process. The failure also happens if we output nothing here.
+ // We need to investigate the reason for this failure and fix it.
+ // In the meantime this temporary hack of drawing an empty
+ // rectangle in the DC gets us by.
+ Rectangle(dc, 0, 0, 0, 0);
+
+ // Ideally we should add JPEG compression to the VectorPlatformDevice class
+ // However, Skia currently has no JPEG compression code and we cannot
+ // depend on gfx/jpeg_codec.h in Skia. So we do the compression here.
+ SkAutoLockPixels lock(bitmap);
+ DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
+ const uint32_t* pixels =
+ static_cast<const uint32_t*>(bitmap.getPixels());
+ std::vector<unsigned char> compressed_image;
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ bool encoded = gfx::JPEGCodec::Encode(
+ reinterpret_cast<const unsigned char*>(pixels),
+ gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(), bitmap.height(),
+ static_cast<int>(bitmap.rowBytes()), 100, &compressed_image);
+ UMA_HISTOGRAM_TIMES("PepperPluginPrint.RasterBitmapCompressTime",
+ base::TimeTicks::Now() - start_time);
+ if (!encoded) {
+ NOTREACHED();
+ return false;
+ }
+ BITMAPINFOHEADER bmi = {0};
+ gfx::CreateBitmapHeader(bitmap.width(), bitmap.height(), &bmi);
+ bmi.biCompression = BI_JPEG;
+ bmi.biSizeImage = compressed_image.size();
+ bmi.biHeight = -bmi.biHeight;
+ StretchDIBits(dc, printable_area.x(), printable_area.y(),
+ printable_area.width(), printable_area.height(),
+ 0, 0, bitmap.width(), bitmap.height(),
+ &compressed_image.front(),
+ reinterpret_cast<const BITMAPINFO*>(&bmi),
+ DIB_RGB_COLORS, SRCCOPY);
+ return true;
+}
+#endif // OS_WIN
+
+#if defined(OS_MACOSX)
+void PluginInstance::DrawSkBitmapToCanvas(
+ const SkBitmap& bitmap, WebKit::WebCanvas* canvas,
+ const gfx::Rect& dest_rect,
+ int canvas_height) {
+ SkAutoLockPixels lock(bitmap);
+ DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
+ base::mac::ScopedCFTypeRef<CGDataProviderRef> data_provider(
+ CGDataProviderCreateWithData(
+ NULL, bitmap.getAddr32(0, 0),
+ bitmap.rowBytes() * bitmap.height(), NULL));
+ base::mac::ScopedCFTypeRef<CGImageRef> image(
+ CGImageCreate(
+ bitmap.width(), bitmap.height(),
+ 8, 32, bitmap.rowBytes(),
+ mac_util::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ data_provider, NULL, false, kCGRenderingIntentDefault));
+
+ // Flip the transform
+ CGContextSaveGState(canvas);
+ CGContextTranslateCTM(canvas, 0, canvas_height);
+ CGContextScaleCTM(canvas, 1.0, -1.0);
+
+ CGRect bounds;
+ bounds.origin.x = dest_rect.x();
+ bounds.origin.y = canvas_height - dest_rect.y() - dest_rect.height();
+ bounds.size.width = dest_rect.width();
+ bounds.size.height = dest_rect.height();
+
+ CGContextDrawImage(canvas, bounds, image);
+ CGContextRestoreGState(canvas);
+}
+#endif // defined(OS_MACOSX)
+
+PPB_Graphics2D_Impl* PluginInstance::bound_graphics_2d() const {
+ if (bound_graphics_.get() == NULL)
+ return NULL;
+
+ return bound_graphics_->Cast<PPB_Graphics2D_Impl>();
+}
+
+PPB_Graphics3D_Impl* PluginInstance::bound_graphics_3d() const {
+ if (bound_graphics_.get() == NULL)
+ return NULL;
+
+ return bound_graphics_->Cast<PPB_Graphics3D_Impl>();
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h
new file mode 100644
index 0000000..c2a87f5
--- /dev/null
+++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h
@@ -0,0 +1,320 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPAPI_PLUGIN_INSTANCE_H_
+#define WEBKIT_PLUGINS_PPAPI_PPAPI_PLUGIN_INSTANCE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "gfx/rect.h"
+#include "ppapi/c/dev/pp_cursor_type_dev.h"
+#include "ppapi/c/dev/ppp_graphics_3d_dev.h"
+#include "ppapi/c/dev/ppp_printing_dev.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
+
+struct PP_Var;
+struct PPB_Instance;
+struct PPB_Find_Dev;
+struct PPB_Fullscreen_Dev;
+struct PPB_Zoom_Dev;
+struct PPP_Find_Dev;
+struct PPP_Instance;
+struct PPP_Pdf;
+struct PPP_Selection_Dev;
+struct PPP_Zoom_Dev;
+
+class SkBitmap;
+class TransportDIB;
+
+namespace gfx {
+class Rect;
+}
+
+namespace WebKit {
+struct WebCursorInfo;
+class WebInputEvent;
+class WebPluginContainer;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class FullscreenContainer;
+class PluginDelegate;
+class PluginModule;
+class PPB_Graphics2D_Impl;
+class PPB_Graphics3D_Impl;
+class PPB_ImageData_Impl;
+class PPB_URLLoader_Impl;
+class Resource;
+
+// Represents one time a plugin appears on one web page.
+//
+// Note: to get from a PP_Instance to a PluginInstance*, use the
+// ResourceTracker.
+class PluginInstance : public base::RefCounted<PluginInstance> {
+ public:
+ class Observer {
+ public:
+ // Indicates that the instance is being destroyed. This will be called from
+ // the instance's destructor so don't do anything in this callback that
+ // uses the instance.
+ virtual void InstanceDestroyed(PluginInstance* instance) = 0;
+ };
+
+ PluginInstance(PluginDelegate* delegate,
+ PluginModule* module,
+ const PPP_Instance* instance_interface);
+ ~PluginInstance();
+
+ static const PPB_Instance* GetInterface();
+
+ // Returns a pointer to the interface implementing PPB_Find that is
+ // exposed to the plugin.
+ static const PPB_Find_Dev* GetFindInterface();
+ static const PPB_Fullscreen_Dev* GetFullscreenInterface();
+ static const PPB_Zoom_Dev* GetZoomInterface();
+
+ PluginDelegate* delegate() const { return delegate_; }
+ PluginModule* module() const { return module_.get(); }
+
+ WebKit::WebPluginContainer* container() const { return container_; }
+
+ const gfx::Rect& position() const { return position_; }
+ const gfx::Rect& clip() const { return clip_; }
+
+ int find_identifier() const { return find_identifier_; }
+
+ void set_always_on_top(bool on_top) { always_on_top_ = on_top; }
+
+ // Returns the PP_Instance uniquely identifying this instance. Guaranteed
+ // nonzero.
+ PP_Instance pp_instance() const { return pp_instance_; }
+
+ // Other classes can register an observer for instance events. These pointers
+ // are NOT owned by the Instance. If the object implementing the observer
+ // goes away, it must take care to unregister itself.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Paints the current backing store to the web page.
+ void Paint(WebKit::WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const gfx::Rect& paint_rect);
+
+ // Schedules a paint of the page for the given region. The coordinates are
+ // relative to the top-left of the plugin. This does nothing if the plugin
+ // has not yet been positioned. You can supply an empty gfx::Rect() to
+ // invalidate the entire plugin.
+ void InvalidateRect(const gfx::Rect& rect);
+
+ // Schedules a scroll of the plugin. This uses optimized scrolling only for
+ // full-frame plugins, as otherwise there could be other elements on top. The
+ // slow path can also be triggered if there is an overlapping frame.
+ void ScrollRect(int dx, int dy, const gfx::Rect& rect);
+
+ // If the plugin instance is backed by a texture, return its texture ID in the
+ // compositor's namespace. Otherwise return 0. Returns 0 by default.
+ virtual unsigned GetBackingTextureId();
+
+ // Commit the backing texture to the screen once the side effects some
+ // rendering up to an offscreen SwapBuffers are visible.
+ void CommitBackingTexture();
+
+ // PPB_Instance implementation.
+ PP_Var GetWindowObject();
+ PP_Var GetOwnerElementObject();
+ bool BindGraphics(PP_Resource graphics_id);
+ bool full_frame() const { return full_frame_; }
+ bool SetCursor(PP_CursorType_Dev type);
+ PP_Var ExecuteScript(PP_Var script, PP_Var* exception);
+
+ // PPP_Instance pass-through.
+ void Delete();
+ bool Initialize(WebKit::WebPluginContainer* container,
+ const std::vector<std::string>& arg_names,
+ const std::vector<std::string>& arg_values,
+ bool full_frame);
+ bool HandleDocumentLoad(PPB_URLLoader_Impl* loader);
+ bool HandleInputEvent(const WebKit::WebInputEvent& event,
+ WebKit::WebCursorInfo* cursor_info);
+ PP_Var GetInstanceObject();
+ void ViewChanged(const gfx::Rect& position, const gfx::Rect& clip);
+
+ // Notifications about focus changes, see has_webkit_focus_ below.
+ void SetWebKitFocus(bool has_focus);
+ void SetContentAreaFocus(bool has_focus);
+
+ // Notifications that the view has rendered the page and that it has been
+ // flushed to the screen. These messages are used to send Flush callbacks to
+ // the plugin for DeviceContext2D.
+ void ViewInitiatedPaint();
+ void ViewFlushedPaint();
+
+ // If this plugin can be painted merely by copying the backing store to the
+ // screen, and the plugin bounds encloses the given paint bounds, returns
+ // true. In this case, the location, clipping, and ID of the backing store
+ // will be filled into the given output parameters.
+ bool GetBitmapForOptimizedPluginPaint(
+ const gfx::Rect& paint_bounds,
+ TransportDIB** dib,
+ gfx::Rect* dib_bounds,
+ gfx::Rect* clip);
+
+ string16 GetSelectedText(bool html);
+ string16 GetLinkAtPosition(const gfx::Point& point);
+ void Zoom(double factor, bool text_only);
+ bool StartFind(const string16& search_text,
+ bool case_sensitive,
+ int identifier);
+ void SelectFindResult(bool forward);
+ void StopFind();
+
+ bool SupportsPrintInterface();
+ int PrintBegin(const gfx::Rect& printable_area, int printer_dpi);
+ bool PrintPage(int page_number, WebKit::WebCanvas* canvas);
+ void PrintEnd();
+
+ void Graphics3DContextLost();
+
+ // Implementation of PPB_Fullscreen_Dev.
+ bool IsFullscreen();
+ bool SetFullscreen(bool fullscreen);
+
+ // Implementation of PPB_Flash.
+ bool NavigateToURL(const char* url, const char* target);
+
+ private:
+ bool LoadFindInterface();
+ bool LoadPdfInterface();
+ bool LoadSelectionInterface();
+ bool LoadZoomInterface();
+
+ // Determines if we think the plugin has focus, both content area and webkit
+ // (see has_webkit_focus_ below).
+ bool PluginHasFocus() const;
+
+ // Queries the plugin for supported print formats and sets |format| to the
+ // best format to use. Returns false if the plugin does not support any
+ // print format that we can handle (we can handle raster and PDF).
+ bool GetPreferredPrintOutputFormat(PP_PrintOutputFormat_Dev* format);
+ bool PrintPDFOutput(PP_Resource print_output, WebKit::WebCanvas* canvas);
+ bool PrintRasterOutput(PP_Resource print_output, WebKit::WebCanvas* canvas);
+#if defined(OS_WIN)
+ bool DrawJPEGToPlatformDC(const SkBitmap& bitmap,
+ const gfx::Rect& printable_area,
+ WebKit::WebCanvas* canvas);
+#elif defined(OS_MACOSX)
+ // Draws the given kARGB_8888_Config bitmap to the specified canvas starting
+ // at the specified destination rect.
+ void DrawSkBitmapToCanvas(const SkBitmap& bitmap, WebKit::WebCanvas* canvas,
+ const gfx::Rect& dest_rect, int canvas_height);
+#endif // OS_MACOSX
+
+ // Get the bound graphics context as a concrete 2D graphics context or returns
+ // null if the context is not 2D.
+ PPB_Graphics2D_Impl* bound_graphics_2d() const;
+
+ // Get the bound graphics context as a concrete 3D graphics context or returns
+ // null if the context is not 3D.
+ PPB_Graphics3D_Impl* bound_graphics_3d() const;
+
+ PluginDelegate* delegate_;
+ scoped_refptr<PluginModule> module_;
+ const PPP_Instance* instance_interface_;
+
+ PP_Instance pp_instance_;
+
+ // NULL until we have been initialized.
+ WebKit::WebPluginContainer* container_;
+
+ // Indicates whether this is a full frame instance, which means it represents
+ // an entire document rather than an embed tag.
+ bool full_frame_;
+
+ // Position in the viewport (which moves as the page is scrolled) of this
+ // plugin. This will be a 0-sized rectangle if the plugin has not yet been
+ // laid out.
+ gfx::Rect position_;
+
+ // Current clip rect. This will be empty if the plugin is not currently
+ // visible. This is in the plugin's coordinate system, so fully visible will
+ // be (0, 0, w, h) regardless of scroll position.
+ gfx::Rect clip_;
+
+ // The current device context for painting in 2D or 3D.
+ scoped_refptr<Resource> bound_graphics_;
+
+ // We track two types of focus, one from WebKit, which is the focus among
+ // all elements of the page, one one from the browser, which is whether the
+ // tab/window has focus. We tell the plugin it has focus only when both of
+ // these values are set to true.
+ bool has_webkit_focus_;
+ bool has_content_area_focus_;
+
+ // The id of the current find operation, or -1 if none is in process.
+ int find_identifier_;
+
+ // The plugin-provided interfaces.
+ const PPP_Find_Dev* plugin_find_interface_;
+ const PPP_Pdf* plugin_pdf_interface_;
+ const PPP_Selection_Dev* plugin_selection_interface_;
+ const PPP_Zoom_Dev* plugin_zoom_interface_;
+
+ // This is only valid between a successful PrintBegin call and a PrintEnd
+ // call.
+ PP_PrintSettings_Dev current_print_settings_;
+#if defined(OS_MACOSX)
+ // On the Mac, when we draw the bitmap to the PDFContext, it seems necessary
+ // to keep the pixels valid until CGContextEndPage is called. We use this
+ // variable to hold on to the pixels.
+ scoped_refptr<PPB_ImageData_Impl> last_printed_page_;
+#elif defined(OS_LINUX)
+ // On Linux, we always send all pages from the renderer to the browser.
+ // So, if the plugin supports printPagesAsPDF we print the entire output
+ // in one shot in the first call to PrintPage.
+ // (This is a temporary hack until we change the WebFrame and WebPlugin print
+ // interfaces).
+ // Specifies the total number of pages to be printed. It it set in PrintBegin.
+ int32 num_pages_;
+ // Specifies whether we have already output all pages. This is used to ignore
+ // subsequent PrintPage requests.
+ bool pdf_output_done_;
+#endif // defined(OS_LINUX)
+
+ // The plugin print interface.
+ const PPP_Printing_Dev* plugin_print_interface_;
+
+ // The plugin 3D interface.
+ const PPP_Graphics3D_Dev* plugin_graphics_3d_interface_;
+
+ // Containes the cursor if it's set by the plugin.
+ scoped_ptr<WebKit::WebCursorInfo> cursor_;
+
+ // Set to true if this plugin thinks it will always be on top. This allows us
+ // to use a more optimized painting path in some cases.
+ bool always_on_top_;
+
+ // Plugin container for fullscreen mode. NULL if not in fullscreen mode.
+ FullscreenContainer* fullscreen_container_;
+
+ // Non-owning pointers to all active observers.
+ ObserverList<Observer, false> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginInstance);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPAPI_PLUGIN_INSTANCE_H_
diff --git a/webkit/plugins/ppapi/ppapi_unittest.cc b/webkit/plugins/ppapi/ppapi_unittest.cc
new file mode 100644
index 0000000..12cb99d
--- /dev/null
+++ b/webkit/plugins/ppapi/ppapi_unittest.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppapi_unittest.h"
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppp_instance.h"
+#include "webkit/plugins/ppapi/mock_plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PpapiUnittest* current_unittest = NULL;
+
+const void* MockGetInterface(const char* interface_name) {
+ return current_unittest->GetMockInterface(interface_name);
+}
+
+int MockInitializeModule(PP_Module, PPB_GetInterface) {
+ return PP_OK;
+}
+
+// PPP_Instance implementation ------------------------------------------------
+
+PP_Bool Instance_DidCreate(PP_Instance pp_instance,
+ uint32_t argc,
+ const char* argn[],
+ const char* argv[]) {
+ return PP_TRUE;
+}
+
+void Instance_DidDestroy(PP_Instance instance) {
+}
+
+void Instance_DidChangeView(PP_Instance pp_instance,
+ const PP_Rect* position,
+ const PP_Rect* clip) {
+}
+
+void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
+}
+
+PP_Bool Instance_HandleInputEvent(PP_Instance pp_instance,
+ const PP_InputEvent* event) {
+ return PP_FALSE;
+}
+
+PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
+ PP_Resource pp_url_loader) {
+ return PP_FALSE;
+}
+
+PP_Var Instance_GetInstanceObject(PP_Instance pp_instance) {
+ return PP_MakeUndefined();
+}
+
+static PPP_Instance mock_instance_interface = {
+ &Instance_DidCreate,
+ &Instance_DidDestroy,
+ &Instance_DidChangeView,
+ &Instance_DidChangeFocus,
+ &Instance_HandleInputEvent,
+ &Instance_HandleDocumentLoad,
+ &Instance_GetInstanceObject
+};
+
+} // namespace
+
+// PpapiUnittest --------------------------------------------------------------
+
+PpapiUnittest::PpapiUnittest() {
+ DCHECK(!current_unittest);
+ current_unittest = this;
+}
+
+PpapiUnittest::~PpapiUnittest() {
+ DCHECK(current_unittest == this);
+ current_unittest = NULL;
+}
+
+void PpapiUnittest::SetUp() {
+ delegate_.reset(new MockPluginDelegate);
+
+ // Initialize the mock module.
+ module_ = new PluginModule;
+ PluginModule::EntryPoints entry_points;
+ entry_points.get_interface = &MockGetInterface;
+ entry_points.initialize_module = &MockInitializeModule;
+ ASSERT_TRUE(module_->InitAsInternalPlugin(entry_points));
+
+ // Initialize the mock instance.
+ instance_ = new PluginInstance(delegate_.get(), module(),
+ static_cast<const PPP_Instance*>(
+ GetMockInterface(PPP_INSTANCE_INTERFACE)));
+}
+
+void PpapiUnittest::TearDown() {
+}
+
+const void* PpapiUnittest::GetMockInterface(const char* interface_name) const {
+ if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
+ return &mock_instance_interface;
+ return NULL;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppapi_unittest.h b/webkit/plugins/ppapi/ppapi_unittest.h
new file mode 100644
index 0000000..ae15467
--- /dev/null
+++ b/webkit/plugins/ppapi/ppapi_unittest.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPAPI_UNITTEST_H_
+#define WEBKIT_PLUGINS_PPAPI_PPAPI_UNITTEST_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace webkit {
+namespace ppapi {
+
+class MockPluginDelegate;
+class PluginInstance;
+class PluginModule;
+
+class PpapiUnittest : public testing::Test {
+ public:
+ PpapiUnittest();
+ virtual ~PpapiUnittest();
+
+ virtual void SetUp();
+ virtual void TearDown();
+
+ PluginModule* module() const { return module_.get(); }
+ PluginInstance* instance() const { return instance_.get(); }
+
+ // Provides access to the interfaces implemented by the test. The default one
+ // implements PPP_INSTANCE.
+ virtual const void* GetMockInterface(const char* interface_name) const;
+
+ private:
+ scoped_ptr<MockPluginDelegate> delegate_;
+
+ // Note: module must be declared first since we want it to get destroyed last.
+ scoped_refptr<PluginModule> module_;
+ scoped_refptr<PluginInstance> instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiUnittest);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_GLUE_PPAPI_PLUGINS_PPAPI_UNITTEST_H_
diff --git a/webkit/plugins/ppapi/ppapi_webplugin_impl.cc b/webkit/plugins/ppapi/ppapi_webplugin_impl.cc
new file mode 100644
index 0000000..e760198
--- /dev/null
+++ b/webkit/plugins/ppapi/ppapi_webplugin_impl.cc
@@ -0,0 +1,229 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
+
+#include <cmath>
+
+#include "base/message_loop.h"
+#include "ppapi/c/pp_var.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_url_loader_impl.h"
+#include "webkit/plugins/ppapi/var.h"
+
+using WebKit::WebCanvas;
+using WebKit::WebPluginContainer;
+using WebKit::WebPluginParams;
+using WebKit::WebPoint;
+using WebKit::WebRect;
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebVector;
+using WebKit::WebView;
+
+namespace webkit {
+namespace ppapi {
+
+struct WebPluginImpl::InitData {
+ scoped_refptr<PluginModule> module;
+ base::WeakPtr<PluginDelegate> delegate;
+ std::vector<std::string> arg_names;
+ std::vector<std::string> arg_values;
+};
+
+WebPluginImpl::WebPluginImpl(
+ PluginModule* plugin_module,
+ const WebPluginParams& params,
+ const base::WeakPtr<PluginDelegate>& plugin_delegate)
+ : init_data_(new InitData()),
+ full_frame_(params.loadManually) {
+ DCHECK(plugin_module);
+ init_data_->module = plugin_module;
+ init_data_->delegate = plugin_delegate;
+ for (size_t i = 0; i < params.attributeNames.size(); ++i) {
+ init_data_->arg_names.push_back(params.attributeNames[i].utf8());
+ init_data_->arg_values.push_back(params.attributeValues[i].utf8());
+ }
+}
+
+WebPluginImpl::~WebPluginImpl() {
+}
+
+bool WebPluginImpl::initialize(WebPluginContainer* container) {
+ // The plugin delegate may have gone away.
+ if (!init_data_->delegate)
+ return false;
+
+ instance_ = init_data_->module->CreateInstance(init_data_->delegate);
+ if (!instance_)
+ return false;
+
+ bool success = instance_->Initialize(container,
+ init_data_->arg_names,
+ init_data_->arg_values,
+ full_frame_);
+ if (!success) {
+ instance_->Delete();
+ instance_ = NULL;
+ return false;
+ }
+
+ init_data_.reset();
+ return true;
+}
+
+void WebPluginImpl::destroy() {
+ if (instance_) {
+ instance_->Delete();
+ instance_ = NULL;
+ }
+
+ MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+NPObject* WebPluginImpl::scriptableObject() {
+ scoped_refptr<ObjectVar> object(
+ ObjectVar::FromPPVar(instance_->GetInstanceObject()));
+ if (object)
+ return object->np_object();
+ return NULL;
+}
+
+void WebPluginImpl::paint(WebCanvas* canvas, const WebRect& rect) {
+ if (!instance_->IsFullscreen())
+ instance_->Paint(canvas, plugin_rect_, rect);
+}
+
+void WebPluginImpl::updateGeometry(
+ const WebRect& window_rect,
+ const WebRect& clip_rect,
+ const WebVector<WebRect>& cut_outs_rects,
+ bool is_visible) {
+ plugin_rect_ = window_rect;
+ if (!instance_->IsFullscreen())
+ instance_->ViewChanged(plugin_rect_, clip_rect);
+}
+
+unsigned WebPluginImpl::getBackingTextureId() {
+ return instance_->GetBackingTextureId();
+}
+
+void WebPluginImpl::updateFocus(bool focused) {
+ instance_->SetWebKitFocus(focused);
+}
+
+void WebPluginImpl::updateVisibility(bool visible) {
+}
+
+bool WebPluginImpl::acceptsInputEvents() {
+ return true;
+}
+
+bool WebPluginImpl::handleInputEvent(const WebKit::WebInputEvent& event,
+ WebKit::WebCursorInfo& cursor_info) {
+ if (instance_->IsFullscreen())
+ return false;
+ return instance_->HandleInputEvent(event, &cursor_info);
+}
+
+void WebPluginImpl::didReceiveResponse(
+ const WebKit::WebURLResponse& response) {
+ DCHECK(!document_loader_);
+
+ document_loader_ = new PPB_URLLoader_Impl(instance_, true);
+ document_loader_->didReceiveResponse(NULL, response);
+
+ if (!instance_->HandleDocumentLoad(document_loader_))
+ document_loader_ = NULL;
+}
+
+void WebPluginImpl::didReceiveData(const char* data, int data_length) {
+ if (document_loader_)
+ document_loader_->didReceiveData(NULL, data, data_length);
+}
+
+void WebPluginImpl::didFinishLoading() {
+ if (document_loader_) {
+ document_loader_->didFinishLoading(NULL, 0);
+ document_loader_ = NULL;
+ }
+}
+
+void WebPluginImpl::didFailLoading(const WebKit::WebURLError& error) {
+ if (document_loader_) {
+ document_loader_->didFail(NULL, error);
+ document_loader_ = NULL;
+ }
+}
+
+void WebPluginImpl::didFinishLoadingFrameRequest(const WebKit::WebURL& url,
+ void* notify_data) {
+}
+
+void WebPluginImpl::didFailLoadingFrameRequest(
+ const WebKit::WebURL& url,
+ void* notify_data,
+ const WebKit::WebURLError& error) {
+}
+
+bool WebPluginImpl::hasSelection() const {
+ return !selectionAsText().isEmpty();
+}
+
+WebString WebPluginImpl::selectionAsText() const {
+ return instance_->GetSelectedText(false);
+}
+
+WebString WebPluginImpl::selectionAsMarkup() const {
+ return instance_->GetSelectedText(true);
+}
+
+WebURL WebPluginImpl::linkAtPosition(const WebPoint& position) const {
+ return GURL(instance_->GetLinkAtPosition(position));
+}
+
+void WebPluginImpl::setZoomLevel(double level, bool text_only) {
+ instance_->Zoom(WebView::zoomLevelToZoomFactor(level), text_only);
+}
+
+bool WebPluginImpl::startFind(const WebKit::WebString& search_text,
+ bool case_sensitive,
+ int identifier) {
+ return instance_->StartFind(search_text, case_sensitive, identifier);
+}
+
+void WebPluginImpl::selectFindResult(bool forward) {
+ instance_->SelectFindResult(forward);
+}
+
+void WebPluginImpl::stopFind() {
+ instance_->StopFind();
+}
+
+bool WebPluginImpl::supportsPaginatedPrint() {
+ return instance_->SupportsPrintInterface();
+}
+
+int WebPluginImpl::printBegin(const WebKit::WebRect& printable_area,
+ int printer_dpi) {
+ return instance_->PrintBegin(printable_area, printer_dpi);
+}
+
+bool WebPluginImpl::printPage(int page_number,
+ WebKit::WebCanvas* canvas) {
+ return instance_->PrintPage(page_number, canvas);
+}
+
+void WebPluginImpl::printEnd() {
+ return instance_->PrintEnd();
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppapi_webplugin_impl.h b/webkit/plugins/ppapi/ppapi_webplugin_impl.h
new file mode 100644
index 0000000..0f86ca6
--- /dev/null
+++ b/webkit/plugins/ppapi/ppapi_webplugin_impl.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPAPI_WEBPLUGIN_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPAPI_WEBPLUGIN_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/weak_ptr.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "gfx/rect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h"
+
+namespace WebKit {
+struct WebPluginParams;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PluginDelegate;
+class PluginInstance;
+class PluginModule;
+class PPB_URLLoader_Impl;
+
+class WebPluginImpl : public WebKit::WebPlugin {
+ public:
+ WebPluginImpl(PluginModule* module,
+ const WebKit::WebPluginParams& params,
+ const base::WeakPtr<PluginDelegate>& plugin_delegate);
+
+ private:
+ friend class DeleteTask<WebPluginImpl>;
+
+ ~WebPluginImpl();
+
+ // WebKit::WebPlugin implementation.
+ virtual bool initialize(WebKit::WebPluginContainer* container);
+ virtual void destroy();
+ virtual NPObject* scriptableObject();
+ virtual void paint(WebKit::WebCanvas* canvas, const WebKit::WebRect& rect);
+ virtual void updateGeometry(
+ const WebKit::WebRect& frame_rect,
+ const WebKit::WebRect& clip_rect,
+ const WebKit::WebVector<WebKit::WebRect>& cut_outs_rects,
+ bool is_visible);
+ virtual unsigned getBackingTextureId();
+ virtual void updateFocus(bool focused);
+ virtual void updateVisibility(bool visible);
+ virtual bool acceptsInputEvents();
+ virtual bool handleInputEvent(const WebKit::WebInputEvent& event,
+ WebKit::WebCursorInfo& cursor_info);
+ virtual void didReceiveResponse(const WebKit::WebURLResponse& response);
+ virtual void didReceiveData(const char* data, int data_length);
+ virtual void didFinishLoading();
+ virtual void didFailLoading(const WebKit::WebURLError&);
+ virtual void didFinishLoadingFrameRequest(const WebKit::WebURL& url,
+ void* notify_data);
+ virtual void didFailLoadingFrameRequest(const WebKit::WebURL& url,
+ void* notify_data,
+ const WebKit::WebURLError& error);
+ virtual bool hasSelection() const;
+ virtual WebKit::WebString selectionAsText() const;
+ virtual WebKit::WebString selectionAsMarkup() const;
+ virtual WebKit::WebURL linkAtPosition(const WebKit::WebPoint& position) const;
+ virtual void setZoomLevel(double level, bool text_only);
+ virtual bool startFind(const WebKit::WebString& search_text,
+ bool case_sensitive,
+ int identifier);
+ virtual void selectFindResult(bool forward);
+ virtual void stopFind();
+ virtual bool supportsPaginatedPrint();
+ virtual int printBegin(const WebKit::WebRect& printable_area,
+ int printer_dpi);
+ virtual bool printPage(int page_number, WebKit::WebCanvas* canvas);
+ virtual void printEnd();
+
+ struct InitData;
+
+ scoped_ptr<InitData> init_data_; // Cleared upon successful initialization.
+ // True if the instance represents the entire document in a frame instead of
+ // being an embedded resource.
+ bool full_frame_;
+ scoped_refptr<PluginInstance> instance_;
+ scoped_refptr<PPB_URLLoader_Impl> document_loader_;
+ gfx::Rect plugin_rect_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebPluginImpl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPAPI_WEBPLUGIN_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_audio_impl.cc b/webkit/plugins/ppapi/ppb_audio_impl.cc
new file mode 100644
index 0000000..db11eba
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_audio_impl.cc
@@ -0,0 +1,365 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_audio_impl.h"
+
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_audio_dev.h"
+#include "ppapi/c/dev/ppb_audio_trusted_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "webkit/plugins/ppapi/common.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// PPB_AudioConfig -------------------------------------------------------------
+
+uint32_t RecommendSampleFrameCount(uint32_t requested_sample_frame_count);
+
+PP_Resource CreateStereo16bit(PP_Module module_id,
+ PP_AudioSampleRate_Dev sample_rate,
+ uint32_t sample_frame_count) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ // TODO(brettw): Currently we don't actually check what the hardware
+ // supports, so just allow sample rates of the "guaranteed working" ones.
+ if (sample_rate != PP_AUDIOSAMPLERATE_44100 &&
+ sample_rate != PP_AUDIOSAMPLERATE_48000)
+ return 0;
+
+ // TODO(brettw): Currently we don't actually query to get a value from the
+ // hardware, so just validate the range.
+ if (RecommendSampleFrameCount(sample_frame_count) != sample_frame_count)
+ return 0;
+
+ scoped_refptr<PPB_AudioConfig_Impl> config(
+ new PPB_AudioConfig_Impl(module, sample_rate, sample_frame_count));
+ return config->GetReference();
+}
+
+uint32_t RecommendSampleFrameCount(uint32_t requested_sample_frame_count) {
+ // TODO(brettw) Currently we don't actually query to get a value from the
+ // hardware, so we always return the input for in-range values.
+ if (requested_sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT)
+ return PP_AUDIOMINSAMPLEFRAMECOUNT;
+ if (requested_sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT)
+ return PP_AUDIOMAXSAMPLEFRAMECOUNT;
+ return requested_sample_frame_count;
+}
+
+PP_Bool IsAudioConfig(PP_Resource resource) {
+ scoped_refptr<PPB_AudioConfig_Impl> config =
+ Resource::GetAs<PPB_AudioConfig_Impl>(resource);
+ return BoolToPPBool(!!config);
+}
+
+PP_AudioSampleRate_Dev GetSampleRate(PP_Resource config_id) {
+ scoped_refptr<PPB_AudioConfig_Impl> config =
+ Resource::GetAs<PPB_AudioConfig_Impl>(config_id);
+ return config ? config->sample_rate() : PP_AUDIOSAMPLERATE_NONE;
+}
+
+uint32_t GetSampleFrameCount(PP_Resource config_id) {
+ scoped_refptr<PPB_AudioConfig_Impl> config =
+ Resource::GetAs<PPB_AudioConfig_Impl>(config_id);
+ return config ? config->sample_frame_count() : 0;
+}
+
+const PPB_AudioConfig_Dev ppb_audioconfig = {
+ &CreateStereo16bit,
+ &RecommendSampleFrameCount,
+ &IsAudioConfig,
+ &GetSampleRate,
+ &GetSampleFrameCount
+};
+
+// PPB_Audio -------------------------------------------------------------------
+
+PP_Resource Create(PP_Instance instance_id, PP_Resource config_id,
+ PPB_Audio_Callback user_callback, void* user_data) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+ if (!user_callback)
+ return 0;
+ scoped_refptr<PPB_Audio_Impl> audio(
+ new PPB_Audio_Impl(instance->module(), instance_id));
+ if (!audio->Init(instance->delegate(), config_id,
+ user_callback, user_data))
+ return 0;
+ return audio->GetReference();
+}
+
+PP_Bool IsAudio(PP_Resource resource) {
+ scoped_refptr<PPB_Audio_Impl> audio =
+ Resource::GetAs<PPB_Audio_Impl>(resource);
+ return BoolToPPBool(!!audio);
+}
+
+PP_Resource GetCurrentConfig(PP_Resource audio_id) {
+ scoped_refptr<PPB_Audio_Impl> audio = Resource::GetAs<PPB_Audio_Impl>(audio_id);
+ return audio ? audio->GetCurrentConfig() : 0;
+}
+
+PP_Bool StartPlayback(PP_Resource audio_id) {
+ scoped_refptr<PPB_Audio_Impl> audio =
+ Resource::GetAs<PPB_Audio_Impl>(audio_id);
+ return audio ? BoolToPPBool(audio->StartPlayback()) : PP_FALSE;
+}
+
+PP_Bool StopPlayback(PP_Resource audio_id) {
+ scoped_refptr<PPB_Audio_Impl> audio =
+ Resource::GetAs<PPB_Audio_Impl>(audio_id);
+ return audio ? BoolToPPBool(audio->StopPlayback()) : PP_FALSE;
+}
+
+const PPB_Audio_Dev ppb_audio = {
+ &Create,
+ &IsAudio,
+ &GetCurrentConfig,
+ &StartPlayback,
+ &StopPlayback,
+};
+
+// PPB_AudioTrusted ------------------------------------------------------------
+
+PP_Resource CreateTrusted(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+ scoped_refptr<PPB_Audio_Impl> audio(new PPB_Audio_Impl(instance->module(), instance_id));
+ return audio->GetReference();
+}
+
+int32_t Open(PP_Resource audio_id,
+ PP_Resource config_id,
+ PP_CompletionCallback created) {
+ scoped_refptr<PPB_Audio_Impl> audio =
+ Resource::GetAs<PPB_Audio_Impl>(audio_id);
+ if (!audio)
+ return PP_ERROR_BADRESOURCE;
+ if (!created.func)
+ return PP_ERROR_BADARGUMENT;
+ PP_Instance instance_id = audio->pp_instance();
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_ERROR_FAILED;
+ return audio->Open(instance->delegate(), config_id, created);
+}
+
+int32_t GetSyncSocket(PP_Resource audio_id, int* sync_socket) {
+ scoped_refptr<PPB_Audio_Impl> audio =
+ Resource::GetAs<PPB_Audio_Impl>(audio_id);
+ if (audio)
+ return audio->GetSyncSocket(sync_socket);
+ return PP_ERROR_BADRESOURCE;
+}
+
+int32_t GetSharedMemory(PP_Resource audio_id,
+ int* shm_handle,
+ uint32_t* shm_size) {
+ scoped_refptr<PPB_Audio_Impl> audio =
+ Resource::GetAs<PPB_Audio_Impl>(audio_id);
+ if (audio)
+ return audio->GetSharedMemory(shm_handle, shm_size);
+ return PP_ERROR_BADRESOURCE;
+}
+
+const PPB_AudioTrusted_Dev ppb_audiotrusted = {
+ &CreateTrusted,
+ &Open,
+ &GetSyncSocket,
+ &GetSharedMemory,
+};
+
+} // namespace
+
+// PPB_AudioConfig_Impl --------------------------------------------------------
+
+PPB_AudioConfig_Impl::PPB_AudioConfig_Impl(
+ PluginModule* module,
+ PP_AudioSampleRate_Dev sample_rate,
+ uint32_t sample_frame_count)
+ : Resource(module),
+ sample_rate_(sample_rate),
+ sample_frame_count_(sample_frame_count) {
+}
+
+const PPB_AudioConfig_Dev* PPB_AudioConfig_Impl::GetInterface() {
+ return &ppb_audioconfig;
+}
+
+size_t PPB_AudioConfig_Impl::BufferSize() {
+ // TODO(audio): as more options become available, we'll need to
+ // have additional code here to correctly calculate the size in
+ // bytes of an audio buffer. For now, only support two channel
+ // int16_t sample buffers.
+ const int kChannels = 2;
+ const int kSizeOfSample = sizeof(int16_t);
+ return static_cast<size_t>(sample_frame_count_ * kSizeOfSample * kChannels);
+}
+
+PPB_AudioConfig_Impl* PPB_AudioConfig_Impl::AsPPB_AudioConfig_Impl() {
+ return this;
+}
+
+// PPB_Audio_Impl --------------------------------------------------------------
+
+PPB_Audio_Impl::PPB_Audio_Impl(PluginModule* module, PP_Instance instance_id)
+ : Resource(module),
+ pp_instance_(instance_id),
+ audio_(NULL),
+ create_callback_pending_(false) {
+ create_callback_ = PP_MakeCompletionCallback(NULL, NULL);
+}
+
+PPB_Audio_Impl::~PPB_Audio_Impl() {
+ // Calling ShutDown() makes sure StreamCreated cannot be called anymore.
+ audio_->ShutDown();
+ audio_ = NULL;
+
+ // If the completion callback hasn't fired yet, do so here
+ // with an error condition.
+ if (create_callback_pending_) {
+ PP_RunCompletionCallback(&create_callback_, PP_ERROR_ABORTED);
+ create_callback_pending_ = false;
+ }
+}
+
+const PPB_Audio_Dev* PPB_Audio_Impl::GetInterface() {
+ return &ppb_audio;
+}
+
+const PPB_AudioTrusted_Dev* PPB_Audio_Impl::GetTrustedInterface() {
+ return &ppb_audiotrusted;
+}
+
+PPB_Audio_Impl* PPB_Audio_Impl::AsPPB_Audio_Impl() {
+ return this;
+}
+
+bool PPB_Audio_Impl::Init(PluginDelegate* plugin_delegate,
+ PP_Resource config_id,
+ PPB_Audio_Callback callback, void* user_data) {
+ CHECK(!audio_);
+ config_ = Resource::GetAs<PPB_AudioConfig_Impl>(config_id);
+ if (!config_)
+ return false;
+ SetCallback(callback, user_data);
+
+ // When the stream is created, we'll get called back on StreamCreated().
+ audio_ = plugin_delegate->CreateAudio(config_->sample_rate(),
+ config_->sample_frame_count(),
+ this);
+ return audio_ != NULL;
+}
+
+PP_Resource PPB_Audio_Impl::GetCurrentConfig() {
+ return config_->GetReference();
+}
+
+bool PPB_Audio_Impl::StartPlayback() {
+ if (playing())
+ return true;
+ SetStartPlaybackState();
+ return audio_->StartPlayback();
+}
+
+bool PPB_Audio_Impl::StopPlayback() {
+ if (!playing())
+ return true;
+ if (!audio_->StopPlayback())
+ return false;
+ SetStopPlaybackState();
+ return true;
+}
+
+int32_t PPB_Audio_Impl::Open(PluginDelegate* plugin_delegate,
+ PP_Resource config_id,
+ PP_CompletionCallback create_callback) {
+ DCHECK(!audio_);
+ config_ = Resource::GetAs<PPB_AudioConfig_Impl>(config_id);
+ if (!config_)
+ return PP_ERROR_BADRESOURCE;
+
+ // When the stream is created, we'll get called back on StreamCreated().
+ audio_ = plugin_delegate->CreateAudio(config_->sample_rate(),
+ config_->sample_frame_count(),
+ this);
+ if (!audio_)
+ return PP_ERROR_FAILED;
+
+ // At this point, we are guaranteeing ownership of the completion
+ // callback. Audio promises to fire the completion callback
+ // once and only once.
+ create_callback_ = create_callback;
+ create_callback_pending_ = true;
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) {
+ if (socket_for_create_callback_.get()) {
+#if defined(OS_POSIX)
+ *sync_socket = socket_for_create_callback_->handle();
+#elif defined(OS_WIN)
+ *sync_socket = reinterpret_cast<int>(socket_for_create_callback_->handle());
+#else
+ #error "Platform not supported."
+#endif
+ return PP_OK;
+ }
+ return PP_ERROR_FAILED;
+}
+
+int32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, uint32_t* shm_size) {
+ if (shared_memory_for_create_callback_.get()) {
+#if defined(OS_POSIX)
+ *shm_handle = shared_memory_for_create_callback_->handle().fd;
+#elif defined(OS_WIN)
+ *shm_handle = reinterpret_cast<int>(
+ shared_memory_for_create_callback_->handle());
+#else
+ #error "Platform not supported."
+#endif
+ *shm_size = shared_memory_size_for_create_callback_;
+ return PP_OK;
+ }
+ return PP_ERROR_FAILED;
+}
+
+void PPB_Audio_Impl::StreamCreated(
+ base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size,
+ base::SyncSocket::Handle socket_handle) {
+ if (create_callback_pending_) {
+ // Trusted side of proxy can specify a callback to recieve handles. In
+ // this case we don't need to map any data or start the thread since it
+ // will be handled by the proxy.
+ shared_memory_for_create_callback_.reset(
+ new base::SharedMemory(shared_memory_handle, false));
+ shared_memory_size_for_create_callback_ = shared_memory_size;
+ socket_for_create_callback_.reset(new base::SyncSocket(socket_handle));
+
+ PP_RunCompletionCallback(&create_callback_, 0);
+ create_callback_pending_ = false;
+
+ // It might be nice to close the handles here to free up some system
+ // resources, but we can't since there's a race condition. The handles must
+ // be valid until they're sent over IPC, which is done from the I/O thread
+ // which will often get done after this code executes. We could do
+ // something more elaborate like an ACK from the plugin or post a task to
+ // the I/O thread and back, but this extra complexity doesn't seem worth it
+ // just to clean up these handles faster.
+ } else {
+ SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle);
+ }
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_audio_impl.h b/webkit/plugins/ppapi/ppb_audio_impl.h
new file mode 100644
index 0000000..bcab4a4
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_audio_impl.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_DEVICE_CONTEXT_AUDIO_H_
+#define WEBKIT_PLUGINS_PPAPI_DEVICE_CONTEXT_AUDIO_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/shared_memory.h"
+#include "base/sync_socket.h"
+#include "ppapi/c/dev/ppb_audio_dev.h"
+#include "ppapi/c/dev/ppb_audio_config_dev.h"
+#include "ppapi/c/dev/ppb_audio_trusted_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/shared_impl/audio_impl.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+class PluginModule;
+
+class PPB_AudioConfig_Impl : public Resource {
+ public:
+ PPB_AudioConfig_Impl(PluginModule* module,
+ PP_AudioSampleRate_Dev sample_rate,
+ uint32_t sample_frame_count);
+ size_t BufferSize();
+ static const PPB_AudioConfig_Dev* GetInterface();
+
+ PP_AudioSampleRate_Dev sample_rate() { return sample_rate_; }
+ uint32_t sample_frame_count() { return sample_frame_count_; }
+
+ private:
+ // Resource override.
+ virtual PPB_AudioConfig_Impl* AsPPB_AudioConfig_Impl();
+
+ PP_AudioSampleRate_Dev sample_rate_;
+ uint32_t sample_frame_count_;
+};
+
+// Some of the backend functionality of this class is implemented by the
+// AudioImpl so it can be shared with the proxy.
+class PPB_Audio_Impl : public Resource,
+ public pp::shared_impl::AudioImpl,
+ public PluginDelegate::PlatformAudio::Client {
+ public:
+ explicit PPB_Audio_Impl(PluginModule* module, PP_Instance instance_id);
+ virtual ~PPB_Audio_Impl();
+
+ static const PPB_Audio_Dev* GetInterface();
+ static const PPB_AudioTrusted_Dev* GetTrustedInterface();
+
+ PP_Instance pp_instance() {
+ return pp_instance_;
+ }
+
+ // PPB_Audio implementation.
+ bool Init(PluginDelegate* plugin_delegate,
+ PP_Resource config_id,
+ PPB_Audio_Callback user_callback, void* user_data);
+ PP_Resource GetCurrentConfig();
+ bool StartPlayback();
+ bool StopPlayback();
+
+ // PPB_Audio_Trusted implementation.
+ int32_t Open(PluginDelegate* plugin_delegate,
+ PP_Resource config_id,
+ PP_CompletionCallback create_callback);
+ int32_t GetSyncSocket(int* sync_socket);
+ int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size);
+
+ // Resource override.
+ virtual PPB_Audio_Impl* AsPPB_Audio_Impl();
+
+ private:
+ // PluginDelegate::PlatformAudio::Client implementation.
+ virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size_,
+ base::SyncSocket::Handle socket);
+
+ // AudioConfig used for creating this Audio object.
+ scoped_refptr<PPB_AudioConfig_Impl> config_;
+
+ // Plugin instance that owns this audio object.
+ PP_Instance pp_instance_;
+
+ // PluginDelegate audio object that we delegate audio IPC through.
+ PluginDelegate::PlatformAudio* audio_;
+
+ // Is a create callback pending to fire?
+ bool create_callback_pending_;
+
+ // Trusted callback invoked from StreamCreated.
+ PP_CompletionCallback create_callback_;
+
+ // When a create callback is being issued, these will save the info for
+ // querying from the callback. The proxy uses this to get the handles to the
+ // other process instead of mapping them in the renderer. These will be
+ // invalid all other times.
+ scoped_ptr<base::SharedMemory> shared_memory_for_create_callback_;
+ size_t shared_memory_size_for_create_callback_;
+ scoped_ptr<base::SyncSocket> socket_for_create_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_DEVICE_CONTEXT_AUDIO_H_
diff --git a/webkit/plugins/ppapi/ppb_buffer_impl.cc b/webkit/plugins/ppapi/ppb_buffer_impl.cc
new file mode 100644
index 0000000..1c67ec3
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_buffer_impl.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_buffer_impl.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Module module_id, uint32_t size) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ scoped_refptr<PPB_Buffer_Impl> buffer(new PPB_Buffer_Impl(module));
+ if (!buffer->Init(size))
+ return 0;
+
+ return buffer->GetReference();
+}
+
+PP_Bool IsPPB_Buffer_Impl(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Buffer_Impl>(resource));
+}
+
+PP_Bool Describe(PP_Resource resource, uint32_t* size_in_bytes) {
+ scoped_refptr<PPB_Buffer_Impl> buffer(
+ Resource::GetAs<PPB_Buffer_Impl>(resource));
+ if (!buffer)
+ return PP_FALSE;
+ buffer->Describe(size_in_bytes);
+ return PP_TRUE;
+}
+
+void* Map(PP_Resource resource) {
+ scoped_refptr<PPB_Buffer_Impl> buffer(
+ Resource::GetAs<PPB_Buffer_Impl>(resource));
+ if (!buffer)
+ return NULL;
+ return buffer->Map();
+}
+
+void Unmap(PP_Resource resource) {
+ scoped_refptr<PPB_Buffer_Impl> buffer(
+ Resource::GetAs<PPB_Buffer_Impl>(resource));
+ if (!buffer)
+ return;
+ return buffer->Unmap();
+}
+
+const PPB_Buffer_Dev ppb_buffer = {
+ &Create,
+ &IsPPB_Buffer_Impl,
+ &Describe,
+ &Map,
+ &Unmap,
+};
+
+} // namespace
+
+PPB_Buffer_Impl::PPB_Buffer_Impl(PluginModule* module)
+ : Resource(module),
+ size_(0) {
+}
+
+PPB_Buffer_Impl::~PPB_Buffer_Impl() {
+}
+
+// static
+const PPB_Buffer_Dev* PPB_Buffer_Impl::GetInterface() {
+ return &ppb_buffer;
+}
+
+PPB_Buffer_Impl* PPB_Buffer_Impl::AsPPB_Buffer_Impl() {
+ return this;
+}
+
+bool PPB_Buffer_Impl::Init(uint32_t size) {
+ if (size == 0)
+ return false;
+ Unmap();
+ size_ = size;
+ return true;
+}
+
+void PPB_Buffer_Impl::Describe(uint32_t* size_in_bytes) const {
+ *size_in_bytes = size_;
+}
+
+void* PPB_Buffer_Impl::Map() {
+ if (size_ == 0)
+ return NULL;
+
+ if (!is_mapped()) {
+ mem_buffer_.reset(new unsigned char[size_]);
+ memset(mem_buffer_.get(), 0, size_);
+ }
+ return mem_buffer_.get();
+}
+
+void PPB_Buffer_Impl::Unmap() {
+ mem_buffer_.reset();
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_buffer_impl.h b/webkit/plugins/ppapi/ppb_buffer_impl.h
new file mode 100644
index 0000000..9642e51
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_buffer_impl.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_BUFFER_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_BUFFER_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_Buffer_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+
+class PPB_Buffer_Impl : public Resource {
+ public:
+ explicit PPB_Buffer_Impl(PluginModule* module);
+ virtual ~PPB_Buffer_Impl();
+
+ uint32_t size() const { return size_; }
+ unsigned char* mapped_buffer() { return mem_buffer_.get(); }
+
+ // Returns true if this buffer is mapped. False means that the buffer is
+ // either invalid or not mapped.
+ bool is_mapped() const { return !!mem_buffer_.get(); }
+
+ // Returns a pointer to the interface implementing PPB_PPB_Buffer_Impl that is
+ // exposed to the plugin.
+ static const PPB_Buffer_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_Buffer_Impl* AsPPB_Buffer_Impl();
+
+ // PPB_PPB_Buffer_Impl implementation.
+ bool Init(uint32_t size);
+ void Describe(uint32_t* size_in_bytes) const;
+ void* Map();
+ void Unmap();
+
+ private:
+ uint32_t size_;
+ scoped_array<unsigned char> mem_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Buffer_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_BUFFER_IMPL_H_
+
diff --git a/webkit/plugins/ppapi/ppb_char_set_impl.cc b/webkit/plugins/ppapi/ppb_char_set_impl.cc
new file mode 100644
index 0000000..edab32e
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_char_set_impl.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_char_set_impl.h"
+
+#include <stdlib.h>
+
+#include "base/i18n/icu_string_conversions.h"
+#include "ppapi/c/dev/ppb_char_set_dev.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_cb.h"
+#include "unicode/ucnv_err.h"
+#include "unicode/ustring.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/var.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// Converts the given PP error handling behavior to the version in base,
+// placing the result in |*result| and returning true on success. Returns false
+// if the enum is invalid.
+bool PPToBaseConversionError(PP_CharSet_ConversionError on_error,
+ base::OnStringConversionError::Type* result) {
+ switch (on_error) {
+ case PP_CHARSET_CONVERSIONERROR_FAIL:
+ *result = base::OnStringConversionError::FAIL;
+ return true;
+ case PP_CHARSET_CONVERSIONERROR_SKIP:
+ *result = base::OnStringConversionError::SKIP;
+ return true;
+ case PP_CHARSET_CONVERSIONERROR_SUBSTITUTE:
+ *result = base::OnStringConversionError::SUBSTITUTE;
+ return true;
+ default:
+ return false;
+ }
+}
+
+// The "substitution" behavior of this function does not match the
+// implementation in base, so we partially duplicate the code from
+// icu_string_conversions.cc with the correct error handling setup required
+// by this PPAPI interface.
+char* UTF16ToCharSet(const uint16_t* utf16, uint32_t utf16_len,
+ const char* output_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) {
+ *output_length = 0;
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter* converter = ucnv_open(output_char_set, &status);
+ if (!U_SUCCESS(status))
+ return NULL;
+
+ int encoded_max_length = UCNV_GET_MAX_BYTES_FOR_STRING(utf16_len,
+ ucnv_getMaxCharSize(converter));
+
+ // Setup our error handler.
+ switch (on_error) {
+ case PP_CHARSET_CONVERSIONERROR_FAIL:
+ ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_STOP, 0,
+ NULL, NULL, &status);
+ break;
+ case PP_CHARSET_CONVERSIONERROR_SKIP:
+ ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SKIP, 0,
+ NULL, NULL, &status);
+ break;
+ case PP_CHARSET_CONVERSIONERROR_SUBSTITUTE: {
+ // ICU sets the substitution char for some character sets (like latin1)
+ // to be the ASCII "substitution character" (26). We want to use '?'
+ // instead for backwards-compat with Windows behavior.
+ char subst_chars[32];
+ int8_t subst_chars_len = 32;
+ ucnv_getSubstChars(converter, subst_chars, &subst_chars_len, &status);
+ if (subst_chars_len == 1 && subst_chars[0] == 26) {
+ // Override to the question mark character if possible. When using
+ // setSubstString, the input is a Unicode character. The function will
+ // try to convert it to the destination character set and fail if that
+ // can not be converted to the destination character set.
+ //
+ // We just ignore any failure. If the dest char set has no
+ // representation for '?', then we'll just stick to the ICU default
+ // substitution character.
+ UErrorCode subst_status = U_ZERO_ERROR;
+ UChar question_mark = '?';
+ ucnv_setSubstString(converter, &question_mark, 1, &subst_status);
+ }
+
+ ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0,
+ NULL, NULL, &status);
+ break;
+ }
+ default:
+ return NULL;
+ }
+
+ // ucnv_fromUChars returns size not including terminating null.
+ char* encoded = static_cast<char*>(malloc(encoded_max_length + 1));
+ int actual_size = ucnv_fromUChars(converter, encoded,
+ encoded_max_length, reinterpret_cast<const UChar*>(utf16), utf16_len,
+ &status);
+ ucnv_close(converter);
+ if (!U_SUCCESS(status)) {
+ free(encoded);
+ return NULL;
+ }
+ encoded[actual_size] = 0;
+ *output_length = actual_size;
+ return encoded;
+}
+
+uint16_t* CharSetToUTF16(const char* input, uint32_t input_len,
+ const char* input_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) {
+ *output_length = 0;
+
+ base::OnStringConversionError::Type base_on_error;
+ if (!PPToBaseConversionError(on_error, &base_on_error))
+ return NULL; // Invalid enum value.
+
+ // We can convert this call to the implementation in base to avoid code
+ // duplication, although this does introduce an extra copy of the data.
+ string16 output;
+ if (!base::CodepageToUTF16(std::string(input, input_len), input_char_set,
+ base_on_error, &output))
+ return NULL;
+
+ uint16_t* ret_buf = static_cast<uint16_t*>(
+ malloc((output.size() + 1) * sizeof(uint16_t)));
+ if (!ret_buf)
+ return NULL;
+
+ *output_length = static_cast<uint32_t>(output.size());
+ memcpy(ret_buf, output.c_str(), (output.size() + 1) * sizeof(uint16_t));
+ return ret_buf;
+}
+
+PP_Var GetDefaultCharSet(PP_Module pp_module) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(pp_module);
+ if (!module)
+ return PP_MakeUndefined();
+
+ std::string encoding =
+ module->GetSomeInstance()->delegate()->GetDefaultEncoding();
+ return StringVar::StringToPPVar(module, encoding);
+}
+
+const PPB_CharSet_Dev ppb_charset = {
+ &UTF16ToCharSet,
+ &CharSetToUTF16,
+ &GetDefaultCharSet
+};
+
+} // namespace
+
+// static
+const struct PPB_CharSet_Dev* PPB_CharSet_Impl::GetInterface() {
+ return &ppb_charset;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_char_set_impl.h b/webkit/plugins/ppapi/ppb_char_set_impl.h
new file mode 100644
index 0000000..9c16e05
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_char_set_impl.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_CHAR_SET_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_CHAR_SET_IMPL_H_
+
+struct PPB_CharSet_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_CharSet_Impl {
+ public:
+ // Returns a pointer to the interface implementing PPB_CharSet that is
+ // exposed to the plugin.
+ static const PPB_CharSet_Dev* GetInterface();
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_CHAR_SET_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_cursor_control_impl.cc b/webkit/plugins/ppapi/ppb_cursor_control_impl.cc
new file mode 100644
index 0000000..d7b5119
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_cursor_control_impl.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_cursor_control_impl.h"
+
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "ppapi/c/dev/pp_cursor_type_dev.h"
+#include "ppapi/c/dev/ppb_cursor_control_dev.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_resource.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Bool SetCursor(PP_Instance instance_id,
+ PP_CursorType_Dev type,
+ PP_Resource custom_image_id,
+ const PP_Point* hot_spot) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+
+ scoped_refptr<PPB_ImageData_Impl> custom_image(
+ Resource::GetAs<PPB_ImageData_Impl>(custom_image_id));
+ if (custom_image.get()) {
+ // TODO(neb): implement custom cursors.
+ NOTIMPLEMENTED();
+ return PP_FALSE;
+ }
+
+ return BoolToPPBool(instance->SetCursor(type));
+}
+
+PP_Bool LockCursor(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+
+ // TODO(neb): implement cursor locking.
+ return PP_FALSE;
+}
+
+PP_Bool UnlockCursor(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+
+ // TODO(neb): implement cursor locking.
+ return PP_FALSE;
+}
+
+PP_Bool HasCursorLock(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+
+ // TODO(neb): implement cursor locking.
+ return PP_FALSE;
+}
+
+PP_Bool CanLockCursor(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_FALSE;
+
+ // TODO(neb): implement cursor locking.
+ return PP_FALSE;
+}
+
+const PPB_CursorControl_Dev cursor_control_interface = {
+ &SetCursor,
+ &LockCursor,
+ &UnlockCursor,
+ &HasCursorLock,
+ &CanLockCursor
+};
+
+} // namespace
+
+const PPB_CursorControl_Dev* GetCursorControlInterface() {
+ return &cursor_control_interface;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_cursor_control_impl.h b/webkit/plugins/ppapi/ppb_cursor_control_impl.h
new file mode 100644
index 0000000..dcce132a
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_cursor_control_impl.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_CURSOR_CONTROL_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_CURSOR_CONTROL_IMPL_H_
+
+struct PPB_CursorControl_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+// There's no class implementing CursorControl so we just expose a getter for
+// the interface implemented in the .cc file here.
+const PPB_CursorControl_Dev* GetCursorControlInterface();
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_CURSOR_CONTROL_IMPL_H_
+
diff --git a/webkit/plugins/ppapi/ppb_directory_reader_impl.cc b/webkit/plugins/ppapi/ppb_directory_reader_impl.cc
new file mode 100644
index 0000000..1f5c97c
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_directory_reader_impl.cc
@@ -0,0 +1,167 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_directory_reader_impl.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/dev/ppb_directory_reader_dev.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/file_callbacks.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/ppb_file_system_impl.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+std::string FilePathStringToUTF8String(const FilePath::StringType& str) {
+#if defined(OS_WIN)
+ return WideToUTF8(str);
+#elif defined(OS_POSIX)
+ return str;
+#else
+#error "Unsupported platform."
+#endif
+}
+
+FilePath::StringType UTF8StringToFilePathString(const std::string& str) {
+#if defined(OS_WIN)
+ return UTF8ToWide(str);
+#elif defined(OS_POSIX)
+ return str;
+#else
+#error "Unsupported platform."
+#endif
+}
+
+PP_Resource Create(PP_Resource directory_ref_id) {
+ scoped_refptr<PPB_FileRef_Impl> directory_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(directory_ref_id));
+ if (!directory_ref)
+ return 0;
+
+ PPB_DirectoryReader_Impl* reader = new PPB_DirectoryReader_Impl(directory_ref);
+ return reader->GetReference();
+}
+
+PP_Bool IsDirectoryReader(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_DirectoryReader_Impl>(resource));
+}
+
+int32_t GetNextEntry(PP_Resource reader_id,
+ PP_DirectoryEntry_Dev* entry,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_DirectoryReader_Impl> reader(
+ Resource::GetAs<PPB_DirectoryReader_Impl>(reader_id));
+ if (!reader)
+ return PP_ERROR_BADRESOURCE;
+
+ return reader->GetNextEntry(entry, callback);
+}
+
+const PPB_DirectoryReader_Dev ppb_directoryreader = {
+ &Create,
+ &IsDirectoryReader,
+ &GetNextEntry
+};
+
+} // namespace
+
+PPB_DirectoryReader_Impl::PPB_DirectoryReader_Impl(
+ PPB_FileRef_Impl* directory_ref)
+ : Resource(directory_ref->module()),
+ directory_ref_(directory_ref),
+ has_more_(true),
+ entry_(NULL) {
+}
+
+PPB_DirectoryReader_Impl::~PPB_DirectoryReader_Impl() {
+}
+
+const PPB_DirectoryReader_Dev* PPB_DirectoryReader_Impl::GetInterface() {
+ return &ppb_directoryreader;
+}
+
+PPB_DirectoryReader_Impl*
+PPB_DirectoryReader_Impl::AsPPB_DirectoryReader_Impl() {
+ return this;
+}
+
+int32_t PPB_DirectoryReader_Impl::GetNextEntry(
+ PP_DirectoryEntry_Dev* entry,
+ PP_CompletionCallback callback) {
+ if (directory_ref_->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
+ return PP_ERROR_FAILED;
+
+ entry_ = entry;
+ if (FillUpEntry()) {
+ entry_ = NULL;
+ return PP_OK;
+ }
+
+ PluginInstance* instance = directory_ref_->GetFileSystem()->instance();
+ if (!instance->delegate()->ReadDirectory(
+ directory_ref_->GetSystemPath(),
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, NULL, NULL, this)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+void PPB_DirectoryReader_Impl::AddNewEntries(
+ const std::vector<base::FileUtilProxy::Entry>& entries, bool has_more) {
+ DCHECK(!entries.empty());
+ has_more_ = has_more;
+ std::string dir_path = directory_ref_->GetPath();
+ if (dir_path[dir_path.size() - 1] != '/')
+ dir_path += '/';
+ FilePath::StringType dir_file_path = UTF8StringToFilePathString(dir_path);
+ for (std::vector<base::FileUtilProxy::Entry>::const_iterator it =
+ entries.begin(); it != entries.end(); it++) {
+ base::FileUtilProxy::Entry entry;
+ entry.name = dir_file_path + it->name;
+ entry.is_directory = it->is_directory;
+ entries_.push(entry);
+ }
+
+ FillUpEntry();
+ entry_ = NULL;
+}
+
+bool PPB_DirectoryReader_Impl::FillUpEntry() {
+ DCHECK(entry_);
+ if (!entries_.empty()) {
+ base::FileUtilProxy::Entry dir_entry = entries_.front();
+ entries_.pop();
+ if (entry_->file_ref)
+ ResourceTracker::Get()->UnrefResource(entry_->file_ref);
+ PPB_FileRef_Impl* file_ref =
+ new PPB_FileRef_Impl(module(), directory_ref_->GetFileSystem(),
+ FilePathStringToUTF8String(dir_entry.name));
+ entry_->file_ref = file_ref->GetReference();
+ entry_->file_type =
+ (dir_entry.is_directory ? PP_FILETYPE_DIRECTORY : PP_FILETYPE_REGULAR);
+ return true;
+ }
+
+ if (!has_more_) {
+ entry_->file_ref = 0;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_directory_reader_impl.h b/webkit/plugins/ppapi/ppb_directory_reader_impl.h
new file mode 100644
index 0000000..6e6dfdf
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_directory_reader_impl.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_DIRECTORY_READER_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_DIRECTORY_READER_IMPL_H_
+
+#include <queue>
+
+#include "base/file_util_proxy.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PP_CompletionCallback;
+struct PP_DirectoryEntry_Dev;
+struct PPB_DirectoryReader_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_FileRef_Impl;
+
+class PPB_DirectoryReader_Impl : public Resource {
+ public:
+ explicit PPB_DirectoryReader_Impl(PPB_FileRef_Impl* directory_ref);
+ virtual ~PPB_DirectoryReader_Impl();
+
+ // Returns a pointer to the interface implementing PPB_DirectoryReader that
+ // is exposed to the plugin.
+ static const PPB_DirectoryReader_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_DirectoryReader_Impl* AsPPB_DirectoryReader_Impl();
+
+ // PPB_DirectoryReader implementation.
+ int32_t GetNextEntry(PP_DirectoryEntry_Dev* entry,
+ PP_CompletionCallback callback);
+
+ void AddNewEntries(const std::vector<base::FileUtilProxy::Entry>& entries,
+ bool has_more);
+
+ private:
+ bool FillUpEntry();
+
+ scoped_refptr<PPB_FileRef_Impl> directory_ref_;
+ std::queue<base::FileUtilProxy::Entry> entries_;
+ bool has_more_;
+ PP_DirectoryEntry_Dev* entry_;
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_DIRECTORY_READER_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_file_chooser_impl.cc b/webkit/plugins/ppapi/ppb_file_chooser_impl.cc
new file mode 100644
index 0000000..b8e4a79
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_chooser_impl.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_file_chooser_impl.h"
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFileChooserCompletion.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFileChooserParams.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebCString;
+using WebKit::WebFileChooserCompletion;
+using WebKit::WebFileChooserParams;
+using WebKit::WebString;
+using WebKit::WebVector;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Instance instance_id,
+ const PP_FileChooserOptions_Dev* options) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ if ((options->mode != PP_FILECHOOSERMODE_OPEN) &&
+ (options->mode != PP_FILECHOOSERMODE_OPENMULTIPLE))
+ return 0;
+
+ PPB_FileChooser_Impl* chooser = new PPB_FileChooser_Impl(instance, options);
+ return chooser->GetReference();
+}
+
+PP_Bool IsFileChooser(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_FileChooser_Impl>(resource));
+}
+
+int32_t Show(PP_Resource chooser_id, PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileChooser_Impl> chooser(
+ Resource::GetAs<PPB_FileChooser_Impl>(chooser_id));
+ if (!chooser)
+ return PP_ERROR_BADRESOURCE;
+
+ return chooser->Show(callback);
+}
+
+PP_Resource GetNextChosenFile(PP_Resource chooser_id) {
+ scoped_refptr<PPB_FileChooser_Impl> chooser(
+ Resource::GetAs<PPB_FileChooser_Impl>(chooser_id));
+ if (!chooser)
+ return 0;
+
+ scoped_refptr<PPB_FileRef_Impl> file_ref(chooser->GetNextChosenFile());
+ if (!file_ref)
+ return 0;
+
+ return file_ref->GetReference();
+}
+
+const PPB_FileChooser_Dev ppb_filechooser = {
+ &Create,
+ &IsFileChooser,
+ &Show,
+ &GetNextChosenFile
+};
+
+class FileChooserCompletionImpl : public WebFileChooserCompletion {
+ public:
+ FileChooserCompletionImpl(PPB_FileChooser_Impl* file_chooser)
+ : file_chooser_(file_chooser) {
+ DCHECK(file_chooser_);
+ }
+
+ virtual ~FileChooserCompletionImpl() {}
+
+ virtual void didChooseFile(const WebVector<WebString>& file_names) {
+ std::vector<std::string> files;
+ for (size_t i = 0; i < file_names.size(); i++)
+ files.push_back(file_names[i].utf8().data());
+
+ file_chooser_->StoreChosenFiles(files);
+ }
+
+ private:
+ PPB_FileChooser_Impl* file_chooser_;
+};
+
+} // namespace
+
+PPB_FileChooser_Impl::PPB_FileChooser_Impl(PluginInstance* instance,
+ const PP_FileChooserOptions_Dev* options)
+ : Resource(instance->module()),
+ delegate_(instance->delegate()),
+ mode_(options->mode),
+ accept_mime_types_(options->accept_mime_types),
+ completion_callback_() {
+}
+
+PPB_FileChooser_Impl::~PPB_FileChooser_Impl() {
+}
+
+// static
+const PPB_FileChooser_Dev* PPB_FileChooser_Impl::GetInterface() {
+ return &ppb_filechooser;
+}
+
+PPB_FileChooser_Impl* PPB_FileChooser_Impl::AsPPB_FileChooser_Impl() {
+ return this;
+}
+
+void PPB_FileChooser_Impl::StoreChosenFiles(
+ const std::vector<std::string>& files) {
+ next_chosen_file_index_ = 0;
+ std::vector<std::string>::const_iterator end_it = files.end();
+ for (std::vector<std::string>::const_iterator it = files.begin();
+ it != end_it; it++) {
+ chosen_files_.push_back(make_scoped_refptr(
+ new PPB_FileRef_Impl(module(), FilePath().AppendASCII(*it))));
+ }
+
+ if (!completion_callback_.func)
+ return;
+
+ PP_CompletionCallback callback = {0};
+ std::swap(callback, completion_callback_);
+ PP_RunCompletionCallback(&callback, 0);
+}
+
+int32_t PPB_FileChooser_Impl::Show(PP_CompletionCallback callback) {
+ DCHECK((mode_ == PP_FILECHOOSERMODE_OPEN) ||
+ (mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE));
+ DCHECK(!completion_callback_.func);
+ completion_callback_ = callback;
+
+ WebFileChooserParams params;
+ params.multiSelect = (mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE);
+ params.acceptTypes = WebString::fromUTF8(accept_mime_types_);
+ params.directory = false;
+
+ return delegate_->RunFileChooser(
+ params, new FileChooserCompletionImpl(this));
+}
+
+scoped_refptr<PPB_FileRef_Impl> PPB_FileChooser_Impl::GetNextChosenFile() {
+ if (next_chosen_file_index_ >= chosen_files_.size())
+ return NULL;
+
+ return chosen_files_[next_chosen_file_index_++];
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_file_chooser_impl.h b/webkit/plugins/ppapi/ppb_file_chooser_impl.h
new file mode 100644
index 0000000..d60b503
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_chooser_impl.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FILE_CHOOSER_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FILE_CHOOSER_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "ppapi/c/dev/ppb_file_chooser_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+class PluginDelegate;
+class PluginInstance;
+class PPB_FileRef_Impl;
+
+class PPB_FileChooser_Impl : public Resource {
+ public:
+ PPB_FileChooser_Impl(PluginInstance* instance,
+ const PP_FileChooserOptions_Dev* options);
+ virtual ~PPB_FileChooser_Impl();
+
+ // Returns a pointer to the interface implementing PPB_FileChooser that is
+ // exposed to the plugin.
+ static const PPB_FileChooser_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_FileChooser_Impl* AsPPB_FileChooser_Impl();
+
+ // Stores the list of selected files.
+ void StoreChosenFiles(const std::vector<std::string>& files);
+
+ // PPB_FileChooser implementation.
+ int32_t Show(PP_CompletionCallback callback);
+ scoped_refptr<PPB_FileRef_Impl> GetNextChosenFile();
+
+ private:
+ PluginDelegate* delegate_;
+ PP_FileChooserMode_Dev mode_;
+ std::string accept_mime_types_;
+ PP_CompletionCallback completion_callback_;
+ std::vector< scoped_refptr<PPB_FileRef_Impl> > chosen_files_;
+ size_t next_chosen_file_index_;
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FILE_CHOOSER_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_file_io_impl.cc b/webkit/plugins/ppapi/ppb_file_io_impl.cc
new file mode 100644
index 0000000..4597809
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_io_impl.cc
@@ -0,0 +1,443 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_file_io_impl.h"
+
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/file_util_proxy.h"
+#include "base/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "base/logging.h"
+#include "base/time.h"
+#include "ppapi/c/dev/ppb_file_io_dev.h"
+#include "ppapi/c/dev/ppb_file_io_trusted_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Module module_id) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ PPB_FileIO_Impl* file_io = new PPB_FileIO_Impl(module);
+ return file_io->GetReference();
+}
+
+PP_Bool IsFileIO(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_FileIO_Impl>(resource));
+}
+
+int32_t Open(PP_Resource file_io_id,
+ PP_Resource file_ref_id,
+ int32_t open_flags,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ return file_io->Open(file_ref, open_flags, callback);
+}
+
+int32_t Query(PP_Resource file_io_id,
+ PP_FileInfo_Dev* info,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->Query(info, callback);
+}
+
+int32_t Touch(PP_Resource file_io_id,
+ PP_Time last_access_time,
+ PP_Time last_modified_time,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->Touch(last_access_time, last_modified_time, callback);
+}
+
+int32_t Read(PP_Resource file_io_id,
+ int64_t offset,
+ char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->Read(offset, buffer, bytes_to_read, callback);
+}
+
+int32_t Write(PP_Resource file_io_id,
+ int64_t offset,
+ const char* buffer,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->Write(offset, buffer, bytes_to_write, callback);
+}
+
+int32_t SetLength(PP_Resource file_io_id,
+ int64_t length,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->SetLength(length, callback);
+}
+
+int32_t Flush(PP_Resource file_io_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->Flush(callback);
+}
+
+void Close(PP_Resource file_io_id) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return;
+ file_io->Close();
+}
+
+const PPB_FileIO_Dev ppb_fileio = {
+ &Create,
+ &IsFileIO,
+ &Open,
+ &Query,
+ &Touch,
+ &Read,
+ &Write,
+ &SetLength,
+ &Flush,
+ &Close
+};
+
+int32_t GetOSFileDescriptor(PP_Resource file_io_id) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->GetOSFileDescriptor();
+}
+
+int32_t WillWrite(PP_Resource file_io_id,
+ int64_t offset,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->WillWrite(offset, bytes_to_write, callback);
+}
+
+int32_t WillSetLength(PP_Resource file_io_id,
+ int64_t length,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileIO_Impl> file_io(Resource::GetAs<PPB_FileIO_Impl>(file_io_id));
+ if (!file_io)
+ return PP_ERROR_BADRESOURCE;
+ return file_io->WillSetLength(length, callback);
+}
+
+const PPB_FileIOTrusted_Dev ppb_fileiotrusted = {
+ &GetOSFileDescriptor,
+ &WillWrite,
+ &WillSetLength
+};
+
+int PlatformFileErrorToPepperError(base::PlatformFileError error_code) {
+ switch (error_code) {
+ case base::PLATFORM_FILE_OK:
+ return PP_OK;
+ case base::PLATFORM_FILE_ERROR_EXISTS:
+ return PP_ERROR_FILEEXISTS;
+ case base::PLATFORM_FILE_ERROR_NOT_FOUND:
+ return PP_ERROR_FILENOTFOUND;
+ case base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
+ return PP_ERROR_NOACCESS;
+ case base::PLATFORM_FILE_ERROR_NO_MEMORY:
+ return PP_ERROR_NOMEMORY;
+ case base::PLATFORM_FILE_ERROR_NO_SPACE:
+ return PP_ERROR_NOSPACE;
+ case base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+ default:
+ return PP_ERROR_FAILED;
+ }
+}
+
+} // namespace
+
+PPB_FileIO_Impl::PPB_FileIO_Impl(PluginModule* module)
+ : Resource(module),
+ delegate_(module->GetSomeInstance()->delegate()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)),
+ file_(base::kInvalidPlatformFileValue),
+ callback_(),
+ info_(NULL) {
+}
+
+PPB_FileIO_Impl::~PPB_FileIO_Impl() {
+ Close();
+}
+
+// static
+const PPB_FileIO_Dev* PPB_FileIO_Impl::GetInterface() {
+ return &ppb_fileio;
+}
+
+// static
+const PPB_FileIOTrusted_Dev* PPB_FileIO_Impl::GetTrustedInterface() {
+ return &ppb_fileiotrusted;
+}
+
+PPB_FileIO_Impl* PPB_FileIO_Impl::AsPPB_FileIO_Impl() {
+ return this;
+}
+
+int32_t PPB_FileIO_Impl::Open(PPB_FileRef_Impl* file_ref,
+ int32_t open_flags,
+ PP_CompletionCallback callback) {
+ if (file_ != base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ int flags = 0;
+ if (open_flags & PP_FILEOPENFLAG_READ)
+ flags |= base::PLATFORM_FILE_READ;
+ if (open_flags & PP_FILEOPENFLAG_WRITE) {
+ flags |= base::PLATFORM_FILE_WRITE;
+ flags |= base::PLATFORM_FILE_WRITE_ATTRIBUTES;
+ }
+
+ if (open_flags & PP_FILEOPENFLAG_TRUNCATE) {
+ DCHECK(open_flags & PP_FILEOPENFLAG_WRITE);
+ flags |= base::PLATFORM_FILE_TRUNCATE;
+ } else if (open_flags & PP_FILEOPENFLAG_CREATE) {
+ if (open_flags & PP_FILEOPENFLAG_EXCLUSIVE)
+ flags |= base::PLATFORM_FILE_CREATE;
+ else
+ flags |= base::PLATFORM_FILE_OPEN_ALWAYS;
+ } else
+ flags |= base::PLATFORM_FILE_OPEN;
+
+ file_system_type_ = file_ref->GetFileSystemType();
+ if (!delegate_->AsyncOpenFile(
+ file_ref->GetSystemPath(), flags,
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::AsyncOpenFileCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_FileIO_Impl::Query(PP_FileInfo_Dev* info,
+ PP_CompletionCallback callback) {
+ if (file_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ DCHECK(!info_);
+ DCHECK(info);
+ info_ = info;
+
+ if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
+ delegate_->GetFileThreadMessageLoopProxy(), file_,
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ PP_CompletionCallback callback) {
+ if (file_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ if (!base::FileUtilProxy::Touch(
+ delegate_->GetFileThreadMessageLoopProxy(),
+ file_, base::Time::FromDoubleT(last_access_time),
+ base::Time::FromDoubleT(last_modified_time),
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_FileIO_Impl::Read(int64_t offset,
+ char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ if (file_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ if (!base::FileUtilProxy::Read(
+ delegate_->GetFileThreadMessageLoopProxy(),
+ file_, offset, buffer, bytes_to_read,
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadWriteCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_FileIO_Impl::Write(int64_t offset,
+ const char* buffer,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback) {
+ if (file_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ if (!base::FileUtilProxy::Write(
+ delegate_->GetFileThreadMessageLoopProxy(),
+ file_, offset, buffer, bytes_to_write,
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadWriteCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_FileIO_Impl::SetLength(int64_t length,
+ PP_CompletionCallback callback) {
+ if (file_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ if (!base::FileUtilProxy::Truncate(
+ delegate_->GetFileThreadMessageLoopProxy(),
+ file_, length,
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) {
+ if (file_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ DCHECK(!callback_.func);
+ callback_ = callback;
+
+ if (!base::FileUtilProxy::Flush(
+ delegate_->GetFileThreadMessageLoopProxy(), file_,
+ callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+void PPB_FileIO_Impl::Close() {
+ if (file_ != base::kInvalidPlatformFileValue)
+ base::FileUtilProxy::Close(
+ delegate_->GetFileThreadMessageLoopProxy(), file_, NULL);
+}
+
+int32_t PPB_FileIO_Impl::GetOSFileDescriptor() {
+#if defined(OS_POSIX)
+ return file_;
+#elif defined(OS_WIN)
+ return reinterpret_cast<uintptr_t>(file_);
+#else
+#error "Platform not supported."
+#endif
+}
+
+int32_t PPB_FileIO_Impl::WillWrite(int64_t offset,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback) {
+ // TODO(dumi): implement me
+ return PP_OK;
+}
+
+int32_t PPB_FileIO_Impl::WillSetLength(int64_t length,
+ PP_CompletionCallback callback) {
+ // TODO(dumi): implement me
+ return PP_OK;
+}
+
+void PPB_FileIO_Impl::RunPendingCallback(int result) {
+ if (!callback_.func)
+ return;
+
+ PP_CompletionCallback callback = {0};
+ std::swap(callback, callback_);
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) {
+ RunPendingCallback(PlatformFileErrorToPepperError(error_code));
+}
+
+void PPB_FileIO_Impl::AsyncOpenFileCallback(
+ base::PlatformFileError error_code,
+ base::PlatformFile file) {
+ DCHECK(file_ == base::kInvalidPlatformFileValue);
+ file_ = file;
+ RunPendingCallback(PlatformFileErrorToPepperError(error_code));
+}
+
+void PPB_FileIO_Impl::QueryInfoCallback(
+ base::PlatformFileError error_code,
+ const base::PlatformFileInfo& file_info) {
+ DCHECK(info_);
+ if (error_code == base::PLATFORM_FILE_OK) {
+ info_->size = file_info.size;
+ info_->creation_time = file_info.creation_time.ToDoubleT();
+ info_->last_access_time = file_info.last_accessed.ToDoubleT();
+ info_->last_modified_time = file_info.last_modified.ToDoubleT();
+ info_->system_type = file_system_type_;
+ if (file_info.is_directory)
+ info_->type = PP_FILETYPE_DIRECTORY;
+ else
+ info_->type = PP_FILETYPE_REGULAR;
+ }
+ RunPendingCallback(PlatformFileErrorToPepperError(error_code));
+}
+
+void PPB_FileIO_Impl::ReadWriteCallback(base::PlatformFileError error_code,
+ int bytes_read_or_written) {
+ if (error_code != base::PLATFORM_FILE_OK)
+ RunPendingCallback(PlatformFileErrorToPepperError(error_code));
+ else
+ RunPendingCallback(bytes_read_or_written);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_file_io_impl.h b/webkit/plugins/ppapi/ppb_file_io_impl.h
new file mode 100644
index 0000000..be3865e
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_io_impl.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FILE_IO_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FILE_IO_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/platform_file.h"
+#include "base/scoped_callback_factory.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/dev/pp_file_info_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_time.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PP_CompletionCallback;
+struct PPB_FileIO_Dev;
+struct PPB_FileIOTrusted_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PluginModule;
+class PPB_FileRef_Impl;
+
+class PPB_FileIO_Impl : public Resource {
+ public:
+ explicit PPB_FileIO_Impl(PluginModule* module);
+ virtual ~PPB_FileIO_Impl();
+
+ // Returns a pointer to the interface implementing PPB_FileIO that is exposed
+ // to the plugin.
+ static const PPB_FileIO_Dev* GetInterface();
+
+ // Returns a pointer to the interface implementing PPB_FileIOTrusted that is
+ // exposed to the plugin.
+ static const PPB_FileIOTrusted_Dev* GetTrustedInterface();
+
+ // Resource overrides.
+ virtual PPB_FileIO_Impl* AsPPB_FileIO_Impl();
+
+ // PPB_FileIO implementation.
+ int32_t Open(PPB_FileRef_Impl* file_ref,
+ int32_t open_flags,
+ PP_CompletionCallback callback);
+ int32_t Query(PP_FileInfo_Dev* info,
+ PP_CompletionCallback callback);
+ int32_t Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ PP_CompletionCallback callback);
+ int32_t Read(int64_t offset,
+ char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback);
+ int32_t Write(int64_t offset,
+ const char* buffer,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback);
+ int32_t SetLength(int64_t length,
+ PP_CompletionCallback callback);
+ int32_t Flush(PP_CompletionCallback callback);
+ void Close();
+
+ // PPB_FileIOTrusted implementation.
+ int32_t GetOSFileDescriptor();
+ int32_t WillWrite(int64_t offset,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback);
+ int32_t WillSetLength(int64_t length,
+ PP_CompletionCallback callback);
+
+ void RunPendingCallback(int result);
+ void StatusCallback(base::PlatformFileError error_code);
+ void AsyncOpenFileCallback(base::PlatformFileError error_code,
+ base::PlatformFile file);
+ void QueryInfoCallback(base::PlatformFileError error_code,
+ const base::PlatformFileInfo& file_info);
+ void ReadWriteCallback(base::PlatformFileError error_code,
+ int bytes_read_or_written);
+
+ private:
+ PluginDelegate* delegate_;
+ base::ScopedCallbackFactory<PPB_FileIO_Impl> callback_factory_;
+
+ base::PlatformFile file_;
+ PP_FileSystemType_Dev file_system_type_;
+
+ PP_CompletionCallback callback_;
+ PP_FileInfo_Dev* info_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileIO_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FILE_IO_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_file_ref_impl.cc b/webkit/plugins/ppapi/ppb_file_ref_impl.cc
new file mode 100644
index 0000000..79676df
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_ref_impl.cc
@@ -0,0 +1,359 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "ppapi/c/pp_errors.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/file_callbacks.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_directory_reader_impl.h"
+#include "webkit/plugins/ppapi/ppb_file_system_impl.h"
+#include "webkit/plugins/ppapi/var.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+bool IsValidLocalPath(const std::string& path) {
+ // The path must start with '/'
+ if (path.empty() || path[0] != '/')
+ return false;
+
+ // The path must contain valid UTF-8 characters.
+ if (!IsStringUTF8(path))
+ return false;
+
+ return true;
+}
+
+void TrimTrailingSlash(std::string* path) {
+ // If this path ends with a slash, then normalize it away unless path is the
+ // root path.
+ if (path->size() > 1 && path->at(path->size() - 1) == '/')
+ path->erase(path->size() - 1, 1);
+}
+
+PP_Resource Create(PP_Resource file_system_id, const char* path) {
+ scoped_refptr<PPB_FileSystem_Impl> file_system(
+ Resource::GetAs<PPB_FileSystem_Impl>(file_system_id));
+ if (!file_system)
+ return 0;
+
+ if (!file_system->instance())
+ return 0;
+
+ std::string validated_path(path);
+ if (!IsValidLocalPath(validated_path))
+ return 0;
+ TrimTrailingSlash(&validated_path);
+
+ PPB_FileRef_Impl* file_ref =
+ new PPB_FileRef_Impl(file_system->instance()->module(),
+ file_system, validated_path);
+ return file_ref->GetReference();
+}
+
+PP_Bool IsFileRef(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_FileRef_Impl>(resource));
+}
+
+PP_FileSystemType_Dev GetFileSystemType(PP_Resource file_ref_id) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_FILESYSTEMTYPE_EXTERNAL;
+ return file_ref->GetFileSystemType();
+}
+
+PP_Var GetName(PP_Resource file_ref_id) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_MakeUndefined();
+ return StringVar::StringToPPVar(file_ref->module(), file_ref->GetName());
+}
+
+PP_Var GetPath(PP_Resource file_ref_id) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_MakeUndefined();
+
+ if (file_ref->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
+ return PP_MakeUndefined();
+
+ return StringVar::StringToPPVar(file_ref->module(), file_ref->GetPath());
+}
+
+PP_Resource GetParent(PP_Resource file_ref_id) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return 0;
+
+ if (file_ref->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
+ return 0;
+
+ scoped_refptr<PPB_FileRef_Impl> parent_ref(file_ref->GetParent());
+ if (!parent_ref)
+ return 0;
+
+ return parent_ref->GetReference();
+}
+
+int32_t MakeDirectory(PP_Resource directory_ref_id,
+ PP_Bool make_ancestors,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileRef_Impl> directory_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(directory_ref_id));
+ if (!directory_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileSystem_Impl> file_system = directory_ref->GetFileSystem();
+ if (!file_system || !file_system->opened() ||
+ (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL))
+ return PP_ERROR_NOACCESS;
+
+ PluginInstance* instance = file_system->instance();
+ if (!instance->delegate()->MakeDirectory(
+ directory_ref->GetSystemPath(), PPBoolToBool(make_ancestors),
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, NULL, NULL, NULL)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Query(PP_Resource file_ref_id,
+ PP_FileInfo_Dev* info,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileSystem_Impl> file_system = file_ref->GetFileSystem();
+ if (!file_system || !file_system->opened() ||
+ (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL))
+ return PP_ERROR_NOACCESS;
+
+ PluginInstance* instance = file_system->instance();
+ if (!instance->delegate()->Query(
+ file_ref->GetSystemPath(),
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, info, file_system, NULL)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Touch(PP_Resource file_ref_id,
+ PP_Time last_access_time,
+ PP_Time last_modified_time,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileSystem_Impl> file_system = file_ref->GetFileSystem();
+ if (!file_system || !file_system->opened() ||
+ (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL))
+ return PP_ERROR_NOACCESS;
+
+ PluginInstance* instance = file_system->instance();
+ if (!instance->delegate()->Touch(
+ file_ref->GetSystemPath(), base::Time::FromDoubleT(last_access_time),
+ base::Time::FromDoubleT(last_modified_time),
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, NULL, NULL, NULL)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Delete(PP_Resource file_ref_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileSystem_Impl> file_system = file_ref->GetFileSystem();
+ if (!file_system || !file_system->opened() ||
+ (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL))
+ return PP_ERROR_NOACCESS;
+
+ PluginInstance* instance = file_system->instance();
+ if (!instance->delegate()->Delete(
+ file_ref->GetSystemPath(),
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, NULL, NULL, NULL)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Rename(PP_Resource file_ref_id,
+ PP_Resource new_file_ref_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileRef_Impl> new_file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(new_file_ref_id));
+ if (!new_file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_FileSystem_Impl> file_system = file_ref->GetFileSystem();
+ if (!file_system || !file_system->opened() ||
+ (file_system != new_file_ref->GetFileSystem()) ||
+ (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL))
+ return PP_ERROR_NOACCESS;
+
+ PluginInstance* instance = file_system->instance();
+ if (!instance->delegate()->Rename(
+ file_ref->GetSystemPath(), new_file_ref->GetSystemPath(),
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, NULL, NULL, NULL)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+const PPB_FileRef_Dev ppb_fileref = {
+ &Create,
+ &IsFileRef,
+ &GetFileSystemType,
+ &GetName,
+ &GetPath,
+ &GetParent,
+ &MakeDirectory,
+ &Query,
+ &Touch,
+ &Delete,
+ &Rename
+};
+
+} // namespace
+
+PPB_FileRef_Impl::PPB_FileRef_Impl()
+ : Resource(NULL),
+ file_system_(NULL) {
+}
+
+PPB_FileRef_Impl::PPB_FileRef_Impl(PluginModule* module,
+ scoped_refptr<PPB_FileSystem_Impl> file_system,
+ const std::string& validated_path)
+ : Resource(module),
+ file_system_(file_system),
+ virtual_path_(validated_path) {
+}
+
+PPB_FileRef_Impl::PPB_FileRef_Impl(PluginModule* module,
+ const FilePath& external_file_path)
+ : Resource(module),
+ file_system_(NULL),
+ system_path_(external_file_path) {
+}
+
+PPB_FileRef_Impl::~PPB_FileRef_Impl() {
+}
+
+// static
+const PPB_FileRef_Dev* PPB_FileRef_Impl::GetInterface() {
+ return &ppb_fileref;
+}
+
+PPB_FileRef_Impl* PPB_FileRef_Impl::AsPPB_FileRef_Impl() {
+ return this;
+}
+
+std::string PPB_FileRef_Impl::GetName() const {
+ if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL) {
+ FilePath::StringType path = system_path_.value();
+ size_t pos = path.rfind(FilePath::kSeparators[0]);
+ DCHECK(pos != FilePath::StringType::npos);
+#if defined(OS_WIN)
+ return WideToUTF8(path.substr(pos + 1));
+#elif defined(OS_POSIX)
+ return path.substr(pos + 1);
+#else
+#error "Unsupported platform."
+#endif
+ }
+
+ if (virtual_path_.size() == 1 && virtual_path_[0] == '/')
+ return virtual_path_;
+
+ // There should always be a leading slash at least!
+ size_t pos = virtual_path_.rfind('/');
+ DCHECK(pos != std::string::npos);
+
+ return virtual_path_.substr(pos + 1);
+}
+
+scoped_refptr<PPB_FileRef_Impl> PPB_FileRef_Impl::GetParent() {
+ if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
+ return new PPB_FileRef_Impl();
+
+ // There should always be a leading slash at least!
+ size_t pos = virtual_path_.rfind('/');
+ DCHECK(pos != std::string::npos);
+
+ // If the path is "/foo", then we want to include the slash.
+ if (pos == 0)
+ pos++;
+ std::string parent_path = virtual_path_.substr(0, pos);
+
+ PPB_FileRef_Impl* parent_ref = new PPB_FileRef_Impl(module(), file_system_,
+ parent_path);
+ return parent_ref;
+}
+
+scoped_refptr<PPB_FileSystem_Impl> PPB_FileRef_Impl::GetFileSystem() const {
+ return file_system_;
+}
+
+PP_FileSystemType_Dev PPB_FileRef_Impl::GetFileSystemType() const {
+ if (!file_system_)
+ return PP_FILESYSTEMTYPE_EXTERNAL;
+
+ return file_system_->type();
+}
+
+std::string PPB_FileRef_Impl::GetPath() const {
+ return virtual_path_;
+}
+
+FilePath PPB_FileRef_Impl::GetSystemPath() const {
+ if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
+ return system_path_;
+
+ // Since |virtual_path_| starts with a '/', it is considered an absolute path
+ // on POSIX systems. We need to remove the '/' before calling Append() or we
+ // will run into a DCHECK.
+ FilePath virtual_file_path(
+#if defined(OS_WIN)
+ UTF8ToWide(virtual_path_.substr(1))
+#elif defined(OS_POSIX)
+ virtual_path_.substr(1)
+#else
+#error "Unsupported platform."
+#endif
+ );
+ return file_system_->root_path().Append(virtual_file_path);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_file_ref_impl.h b/webkit/plugins/ppapi/ppb_file_ref_impl.h
new file mode 100644
index 0000000..40924e7
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_ref_impl.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FILE_REF_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FILE_REF_IMPL_H_
+
+#include <string>
+
+#include "base/file_path.h"
+#include "ppapi/c/dev/ppb_file_ref_dev.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_FileSystem_Impl;
+class PluginInstance;
+class PluginModule;
+
+class PPB_FileRef_Impl : public Resource {
+ public:
+ PPB_FileRef_Impl();
+ PPB_FileRef_Impl(PluginModule* module,
+ scoped_refptr<PPB_FileSystem_Impl> file_system,
+ const std::string& validated_path);
+ PPB_FileRef_Impl(PluginModule* module,
+ const FilePath& external_file_path);
+ virtual ~PPB_FileRef_Impl();
+
+ // Returns a pointer to the interface implementing PPB_FileRef that is
+ // exposed to the plugin.
+ static const PPB_FileRef_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_FileRef_Impl* AsPPB_FileRef_Impl();
+
+ // PPB_FileRef implementation.
+ std::string GetName() const;
+ scoped_refptr<PPB_FileRef_Impl> GetParent();
+
+ // Returns the file system to which this PPB_FileRef_Impl belongs.
+ scoped_refptr<PPB_FileSystem_Impl> GetFileSystem() const;
+
+ // Returns the type of the file system to which this PPB_FileRef_Impl belongs.
+ PP_FileSystemType_Dev GetFileSystemType() const;
+
+ // Returns the virtual path (i.e., the path that the pepper plugin sees)
+ // corresponding to this file.
+ std::string GetPath() const;
+
+ // Returns the system path corresponding to this file.
+ FilePath GetSystemPath() const;
+
+ private:
+ scoped_refptr<PPB_FileSystem_Impl> file_system_;
+ std::string virtual_path_; // UTF-8 encoded
+ FilePath system_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FILE_REF_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_file_system_impl.cc b/webkit/plugins/ppapi/ppb_file_system_impl.cc
new file mode 100644
index 0000000..fea8327
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_system_impl.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_file_system_impl.h"
+
+#include "base/ref_counted.h"
+#include "ppapi/c/dev/ppb_file_system_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
+#include "webkit/fileapi/file_system_types.h"
+#include "webkit/plugins/ppapi/file_callbacks.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_directory_reader_impl.h"
+#include "webkit/plugins/ppapi/resource.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Instance instance, PP_FileSystemType_Dev type) {
+ PluginInstance* plugin_instance =
+ ResourceTracker::Get()->GetInstance(instance);
+ if (!plugin_instance)
+ return 0;
+
+ PPB_FileSystem_Impl* file_system =
+ new PPB_FileSystem_Impl(plugin_instance, type);
+ return file_system->GetReference();
+}
+
+int32_t Open(PP_Resource file_system_id,
+ int64 expected_size,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_FileSystem_Impl> file_system(
+ Resource::GetAs<PPB_FileSystem_Impl>(file_system_id));
+ if (!file_system)
+ return PP_ERROR_BADRESOURCE;
+
+ if (file_system->opened())
+ return PP_OK;
+
+ if ((file_system->type() != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
+ (file_system->type() != PP_FILESYSTEMTYPE_LOCALTEMPORARY))
+ return PP_ERROR_FAILED;
+
+ PluginInstance* instance = file_system->instance();
+ fileapi::FileSystemType file_system_type =
+ (file_system->type() == PP_FILESYSTEMTYPE_LOCALTEMPORARY ?
+ fileapi::kFileSystemTypeTemporary :
+ fileapi::kFileSystemTypePersistent);
+ if (!instance->delegate()->OpenFileSystem(
+ instance->container()->element().document().frame()->url(),
+ file_system_type, expected_size,
+ new FileCallbacks(instance->module()->AsWeakPtr(),
+ callback, NULL, file_system, NULL)))
+ return PP_ERROR_FAILED;
+
+ return PP_ERROR_WOULDBLOCK;
+}
+
+const PPB_FileSystem_Dev ppb_filesystem = {
+ &Create,
+ &Open
+};
+
+} // namespace
+
+PPB_FileSystem_Impl::PPB_FileSystem_Impl(PluginInstance* instance,
+ PP_FileSystemType_Dev type)
+ : Resource(instance->module()),
+ instance_(instance),
+ type_(type),
+ opened_(false) {
+}
+
+PPB_FileSystem_Impl* PPB_FileSystem_Impl::AsPPB_FileSystem_Impl() {
+ return this;
+}
+
+const PPB_FileSystem_Dev* PPB_FileSystem_Impl::GetInterface() {
+ return &ppb_filesystem;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_file_system_impl.h b/webkit/plugins/ppapi/ppb_file_system_impl.h
new file mode 100644
index 0000000..2b3e7af
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_file_system_impl.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FILE_SYSTEM_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FILE_SYSTEM_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "ppapi/c/dev/pp_file_info_dev.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_FileSystem_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+
+class PPB_FileSystem_Impl : public Resource {
+ public:
+ // Returns a pointer to the interface implementing PPB_FileSystem that is
+ // exposed to the plugin.
+ static const PPB_FileSystem_Dev* GetInterface();
+
+ PPB_FileSystem_Impl(PluginInstance* instance, PP_FileSystemType_Dev type);
+ virtual PPB_FileSystem_Impl* AsPPB_FileSystem_Impl();
+
+ PluginInstance* instance() { return instance_; }
+ PP_FileSystemType_Dev type() { return type_; }
+ const FilePath& root_path() const { return root_path_; }
+ void set_root_path(const FilePath& root_path) { root_path_ = root_path; }
+ bool opened() const { return opened_; }
+ void set_opened(bool opened) { opened_ = opened; }
+
+ private:
+ PluginInstance* instance_;
+ PP_FileSystemType_Dev type_;
+ FilePath root_path_;
+ bool opened_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileSystem_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FILE_SYSTEM_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_flash.h b/webkit/plugins/ppapi/ppb_flash.h
new file mode 100644
index 0000000..607adcd
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_flash.h
@@ -0,0 +1,117 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PEPPER_PPB_FLASH_H_
+#define WEBKIT_PLUGINS_PEPPER_PPB_FLASH_H_
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+
+#define PPB_FLASH_INTERFACE "PPB_Flash;1"
+
+#ifdef _WIN32
+typedef HANDLE PP_FileHandle;
+static const PP_FileHandle PP_kInvalidFileHandle = NULL;
+#else
+typedef int PP_FileHandle;
+static const PP_FileHandle PP_kInvalidFileHandle = -1;
+#endif
+
+struct PP_FontDescription_Dev;
+struct PP_FileInfo_Dev;
+
+struct PP_DirEntry_Dev {
+ const char* name;
+ bool is_dir;
+};
+
+struct PP_DirContents_Dev {
+ int32_t count;
+ PP_DirEntry_Dev* entries;
+};
+
+struct PPB_Flash {
+ // Sets or clears the rendering hint that the given plugin instance is always
+ // on top of page content. Somewhat more optimized painting can be used in
+ // this case.
+ void (*SetInstanceAlwaysOnTop)(PP_Instance instance, bool on_top);
+
+ bool (*DrawGlyphs)(PP_Resource pp_image_data,
+ const PP_FontDescription_Dev* font_desc,
+ uint32_t color,
+ PP_Point position,
+ PP_Rect clip,
+ const float transformation[3][3],
+ uint32_t glyph_count,
+ const uint16_t glyph_indices[],
+ const PP_Point glyph_advances[]);
+
+ // Retrieves the proxy that will be used for the given URL. The result will
+ // be a string in PAC format, or an undefined var on error.
+ PP_Var (*GetProxyForURL)(PP_Module module, const char* url);
+
+ // Opens a module-local file, returning a file descriptor (posix) or a HANDLE
+ // (win32) into file. Module-local file paths (here and below) are
+ // '/'-separated UTF-8 strings, relative to a module-specific root. The return
+ // value is the ppapi error, PP_OK if success, one of the PP_ERROR_* in case
+ // of failure.
+ int32_t (*OpenModuleLocalFile)(PP_Module module,
+ const char* path,
+ int32_t mode,
+ PP_FileHandle* file);
+
+ // Renames a module-local file. The return value is the ppapi error, PP_OK if
+ // success, one of the PP_ERROR_* in case of failure.
+ int32_t (*RenameModuleLocalFile)(PP_Module module,
+ const char* path_from,
+ const char* path_to);
+
+ // Deletes a module-local file or directory. If recursive is set and the path
+ // points to a directory, deletes all the contents of the directory. The
+ // return value is the ppapi error, PP_OK if success, one of the PP_ERROR_* in
+ // case of failure.
+ int32_t (*DeleteModuleLocalFileOrDir)(PP_Module module,
+ const char* path,
+ bool recursive);
+
+ // Creates a module-local directory. The return value is the ppapi error,
+ // PP_OK if success, one of the PP_ERROR_* in case of failure.
+ int32_t (*CreateModuleLocalDir)(PP_Module module, const char* path);
+
+ // Queries information about a module-local file. The return value is the
+ // ppapi error, PP_OK if success, one of the PP_ERROR_* in case of failure.
+ int32_t (*QueryModuleLocalFile)(PP_Module module,
+ const char* path,
+ PP_FileInfo_Dev* info);
+
+ // Gets the list of files contained in a module-local directory. The return
+ // value is the ppapi error, PP_OK if success, one of the PP_ERROR_* in case
+ // of failure. If non-NULL, the returned contents should be freed with
+ // FreeModuleLocalDirContents.
+ int32_t (*GetModuleLocalDirContents)(PP_Module module,
+ const char* path,
+ PP_DirContents_Dev** contents);
+
+ // Frees the data allocated by GetModuleLocalDirContents.
+ void (*FreeModuleLocalDirContents)(PP_Module module,
+ PP_DirContents_Dev* contents);
+
+ // Navigate to URL. May open a new tab if target is not "_self". Return true
+ // if success. This differs from javascript:window.open() in that it bypasses
+ // the popup blocker, even when this is not called from an event handler.
+ bool (*NavigateToURL)(PP_Instance instance,
+ const char* url,
+ const char* target);
+};
+
+#endif // WEBKIT_GLUE_PLUGINS_PPB_FLASH_H_
diff --git a/webkit/plugins/ppapi/ppb_flash_impl.cc b/webkit/plugins/ppapi/ppb_flash_impl.cc
new file mode 100644
index 0000000..b6340df
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_flash_impl.cc
@@ -0,0 +1,246 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_flash_impl.h"
+
+#include <string.h>
+
+#include "base/file_path.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "googleurl/src/gurl.h"
+#include "ppapi/c/dev/pp_file_info_dev.h"
+#include "ppapi/c/dev/ppb_file_io_dev.h"
+#include "webkit/plugins/ppapi/error_util.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_flash.h"
+#include "webkit/plugins/ppapi/var.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PluginInstance* GetSomeInstance(PP_Module pp_module) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(pp_module);
+ if (!module)
+ return NULL;
+
+ return module->GetSomeInstance();
+}
+
+void SetInstanceAlwaysOnTop(PP_Instance pp_instance, bool on_top) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->set_always_on_top(on_top);
+}
+
+PP_Var GetProxyForURL(PP_Module pp_module, const char* url) {
+ PluginInstance* instance = GetSomeInstance(pp_module);
+ if (!instance)
+ return PP_MakeUndefined();
+
+ GURL gurl(url);
+ if (!gurl.is_valid())
+ return PP_MakeUndefined();
+
+ std::string proxy_host = instance->delegate()->ResolveProxy(gurl);
+ if (proxy_host.empty())
+ return PP_MakeUndefined(); // No proxy.
+ return StringVar::StringToPPVar(instance->module(), proxy_host);
+}
+
+FilePath GetFilePathFromUTF8(const char* path) {
+#if defined(OS_WIN)
+ return FilePath(UTF8ToUTF16(path));
+#else
+ return FilePath(path);
+#endif
+}
+
+int32_t OpenModuleLocalFile(PP_Module module,
+ const char* path,
+ int32_t mode,
+ PP_FileHandle* file) {
+ PluginInstance* instance = GetSomeInstance(module);
+ if (!instance)
+ return PP_ERROR_FAILED;
+
+ int flags = 0;
+ if (mode & PP_FILEOPENFLAG_READ)
+ flags |= base::PLATFORM_FILE_READ;
+ if (mode & PP_FILEOPENFLAG_WRITE) {
+ flags |= base::PLATFORM_FILE_WRITE;
+ flags |= base::PLATFORM_FILE_WRITE_ATTRIBUTES;
+ }
+ if (mode & PP_FILEOPENFLAG_TRUNCATE) {
+ DCHECK(mode & PP_FILEOPENFLAG_WRITE);
+ flags |= base::PLATFORM_FILE_TRUNCATE;
+ }
+
+ if (mode & PP_FILEOPENFLAG_CREATE) {
+ if (mode & PP_FILEOPENFLAG_EXCLUSIVE)
+ flags |= base::PLATFORM_FILE_CREATE;
+ else
+ flags |= base::PLATFORM_FILE_OPEN_ALWAYS;
+ } else {
+ flags |= base::PLATFORM_FILE_OPEN;
+ }
+
+ base::PlatformFile base_file;
+ base::PlatformFileError result = instance->delegate()->OpenModuleLocalFile(
+ instance->module()->name(),
+ GetFilePathFromUTF8(path),
+ flags,
+ &base_file);
+ *file = base_file;
+ return PlatformFileErrorToPepperError(result);
+}
+
+
+int32_t RenameModuleLocalFile(PP_Module module,
+ const char* path_from,
+ const char* path_to) {
+ PluginInstance* instance = GetSomeInstance(module);
+ if (!instance)
+ return PP_ERROR_FAILED;
+
+ base::PlatformFileError result = instance->delegate()->RenameModuleLocalFile(
+ instance->module()->name(),
+ GetFilePathFromUTF8(path_from),
+ GetFilePathFromUTF8(path_to));
+ return PlatformFileErrorToPepperError(result);
+}
+
+int32_t DeleteModuleLocalFileOrDir(PP_Module module,
+ const char* path,
+ bool recursive) {
+ PluginInstance* instance = GetSomeInstance(module);
+ if (!instance)
+ return PP_ERROR_FAILED;
+
+ base::PlatformFileError result =
+ instance->delegate()->DeleteModuleLocalFileOrDir(
+ instance->module()->name(), GetFilePathFromUTF8(path), recursive);
+ return PlatformFileErrorToPepperError(result);
+}
+
+int32_t CreateModuleLocalDir(PP_Module module, const char* path) {
+ PluginInstance* instance = GetSomeInstance(module);
+ if (!instance)
+ return PP_ERROR_FAILED;
+
+ base::PlatformFileError result = instance->delegate()->CreateModuleLocalDir(
+ instance->module()->name(), GetFilePathFromUTF8(path));
+ return PlatformFileErrorToPepperError(result);
+}
+
+int32_t QueryModuleLocalFile(PP_Module module,
+ const char* path,
+ PP_FileInfo_Dev* info) {
+ PluginInstance* instance = GetSomeInstance(module);
+ if (!instance)
+ return PP_ERROR_FAILED;
+
+ base::PlatformFileInfo file_info;
+ base::PlatformFileError result = instance->delegate()->QueryModuleLocalFile(
+ instance->module()->name(), GetFilePathFromUTF8(path), &file_info);
+ if (result == base::PLATFORM_FILE_OK) {
+ info->size = file_info.size;
+ info->creation_time = file_info.creation_time.ToDoubleT();
+ info->last_access_time = file_info.last_accessed.ToDoubleT();
+ info->last_modified_time = file_info.last_modified.ToDoubleT();
+ info->system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+ if (file_info.is_directory)
+ info->type = PP_FILETYPE_DIRECTORY;
+ else
+ info->type = PP_FILETYPE_REGULAR;
+ }
+ return PlatformFileErrorToPepperError(result);
+}
+
+int32_t GetModuleLocalDirContents(PP_Module module,
+ const char* path,
+ PP_DirContents_Dev** contents) {
+ PluginInstance* instance = GetSomeInstance(module);
+ if (!instance)
+ return PP_ERROR_FAILED;
+
+ *contents = NULL;
+ DirContents pepper_contents;
+ base::PlatformFileError result =
+ instance->delegate()->GetModuleLocalDirContents(
+ instance->module()->name(),
+ GetFilePathFromUTF8(path),
+ &pepper_contents);
+
+ if (result != base::PLATFORM_FILE_OK)
+ return PlatformFileErrorToPepperError(result);
+
+ *contents = new PP_DirContents_Dev;
+ size_t count = pepper_contents.size();
+ (*contents)->count = count;
+ (*contents)->entries = new PP_DirEntry_Dev[count];
+ for (size_t i = 0; i < count; ++i) {
+ PP_DirEntry_Dev& entry = (*contents)->entries[i];
+#if defined(OS_WIN)
+ const std::string& name = UTF16ToUTF8(pepper_contents[i].name.value());
+#else
+ const std::string& name = pepper_contents[i].name.value();
+#endif
+ size_t size = name.size() + 1;
+ char* name_copy = new char[size];
+ memcpy(name_copy, name.c_str(), size);
+ entry.name = name_copy;
+ entry.is_dir = pepper_contents[i].is_dir;
+ }
+ return PP_OK;
+}
+
+void FreeModuleLocalDirContents(PP_Module module,
+ PP_DirContents_Dev* contents) {
+ DCHECK(contents);
+ for (int32_t i = 0; i < contents->count; ++i) {
+ delete [] contents->entries[i].name;
+ }
+ delete [] contents->entries;
+ delete contents;
+}
+
+bool NavigateToURL(PP_Instance pp_instance,
+ const char* url,
+ const char* target) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance);
+ if (!instance)
+ return false;
+ return instance->NavigateToURL(url, target);
+}
+
+const PPB_Flash ppb_flash = {
+ &SetInstanceAlwaysOnTop,
+ &PPB_Flash_Impl::DrawGlyphs,
+ &GetProxyForURL,
+ &OpenModuleLocalFile,
+ &RenameModuleLocalFile,
+ &DeleteModuleLocalFileOrDir,
+ &CreateModuleLocalDir,
+ &QueryModuleLocalFile,
+ &GetModuleLocalDirContents,
+ &FreeModuleLocalDirContents,
+ &NavigateToURL,
+};
+
+} // namespace
+
+// static
+const PPB_Flash* PPB_Flash_Impl::GetInterface() {
+ return &ppb_flash;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_flash_impl.h b/webkit/plugins/ppapi/ppb_flash_impl.h
new file mode 100644
index 0000000..44ed224
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_flash_impl.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FLASH_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FLASH_IMPL_H_
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PP_FontDescription_Dev;
+struct PPB_Flash;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_Flash_Impl {
+ public:
+ // Returns a pointer to the interface implementing PPB_Flash that is
+ // exposed to the plugin.
+ static const PPB_Flash* GetInterface();
+
+ static bool DrawGlyphs(PP_Resource pp_image_data,
+ const PP_FontDescription_Dev* font_desc,
+ uint32_t color,
+ PP_Point position,
+ PP_Rect clip,
+ const float transformation[3][3],
+ uint32_t glyph_count,
+ const uint16_t glyph_indices[],
+ const PP_Point glyph_advances[])
+#if defined(OS_LINUX)
+ ;
+#else
+ { return false; }
+#endif
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_Flash_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FLASH_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_flash_impl_linux.cc b/webkit/plugins/ppapi/ppb_flash_impl_linux.cc
new file mode 100644
index 0000000..23290eb
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_flash_impl_linux.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_flash_impl.h"
+
+#include "skia/ext/platform_canvas.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPoint.h"
+#include "third_party/skia/include/core/SkTemplates.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/var.h"
+
+namespace webkit {
+namespace ppapi {
+
+bool PPB_Flash_Impl::DrawGlyphs(PP_Resource pp_image_data,
+ const PP_FontDescription_Dev* font_desc,
+ uint32_t color,
+ PP_Point position,
+ PP_Rect clip,
+ const float transformation[3][3],
+ uint32_t glyph_count,
+ const uint16_t glyph_indices[],
+ const PP_Point glyph_advances[]) {
+ scoped_refptr<PPB_ImageData_Impl> image_resource(
+ Resource::GetAs<PPB_ImageData_Impl>(pp_image_data));
+ if (!image_resource.get())
+ return false;
+ ImageDataAutoMapper mapper(image_resource);
+ if (!mapper.is_valid())
+ return false;
+
+ // Set up the typeface.
+ scoped_refptr<StringVar> face_name(StringVar::FromPPVar(font_desc->face));
+ if (!face_name)
+ return false;
+ int style = SkTypeface::kNormal;
+ if (font_desc->weight >= PP_FONTWEIGHT_BOLD)
+ style |= SkTypeface::kBold;
+ if (font_desc->italic)
+ style |= SkTypeface::kItalic;
+ SkTypeface* typeface =
+ SkTypeface::CreateFromName(face_name->value().c_str(),
+ static_cast<SkTypeface::Style>(style));
+ if (!typeface)
+ return false;
+
+ // Set up the canvas.
+ SkCanvas* canvas = image_resource->mapped_canvas();
+ canvas->save();
+
+ // Clip is applied in pixels before the transform.
+ SkRect clip_rect = { clip.point.x, clip.point.y,
+ clip.point.x + clip.size.width,
+ clip.point.y + clip.size.height };
+ canvas->clipRect(clip_rect);
+
+ // -- Do not return early below this. The canvas needs restoring and the
+ // typeface will leak if it's not assigned to the paint (it's refcounted and
+ // the refcount is currently 0).
+
+ // Convert & set the matrix.
+ SkMatrix matrix;
+ matrix.set(SkMatrix::kMScaleX, SkFloatToScalar(transformation[0][0]));
+ matrix.set(SkMatrix::kMSkewX, SkFloatToScalar(transformation[0][1]));
+ matrix.set(SkMatrix::kMTransX, SkFloatToScalar(transformation[0][2]));
+ matrix.set(SkMatrix::kMSkewY, SkFloatToScalar(transformation[1][0]));
+ matrix.set(SkMatrix::kMScaleY, SkFloatToScalar(transformation[1][1]));
+ matrix.set(SkMatrix::kMTransY, SkFloatToScalar(transformation[1][2]));
+ matrix.set(SkMatrix::kMPersp0, SkFloatToScalar(transformation[2][0]));
+ matrix.set(SkMatrix::kMPersp1, SkFloatToScalar(transformation[2][1]));
+ matrix.set(SkMatrix::kMPersp2, SkFloatToScalar(transformation[2][2]));
+ canvas->concat(matrix);
+
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setAntiAlias(true);
+ paint.setHinting(SkPaint::kFull_Hinting);
+ paint.setTextSize(SkIntToScalar(font_desc->size));
+ paint.setTypeface(typeface); // Takes a ref and manages lifetime.
+ paint.setSubpixelText(true);
+ paint.setLCDRenderText(true);
+
+ SkScalar x = SkIntToScalar(position.x);
+ SkScalar y = SkIntToScalar(position.y);
+
+ // Build up the skia advances.
+ SkAutoSTMalloc<32, SkPoint> storage(glyph_count);
+ SkPoint* sk_positions = storage.get();
+ for (uint32_t i = 0; i < glyph_count; i++) {
+ sk_positions[i].set(x, y);
+ x += SkFloatToScalar(glyph_advances[i].x);
+ y += SkFloatToScalar(glyph_advances[i].y);
+ }
+
+ canvas->drawPosText(glyph_indices, glyph_count * 2, sk_positions, paint);
+
+ canvas->restore();
+ return true;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_font_impl.cc b/webkit/plugins/ppapi/ppb_font_impl.cc
new file mode 100644
index 0000000..d0faee9
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_font_impl.cc
@@ -0,0 +1,302 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_font_impl.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/pp_rect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFont.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFontDescription.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFloatPoint.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFloatRect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebTextRun.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/string.h"
+#include "webkit/plugins/ppapi/var.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebFloatPoint;
+using WebKit::WebFloatRect;
+using WebKit::WebFont;
+using WebKit::WebFontDescription;
+using WebKit::WebRect;
+using WebKit::WebTextRun;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+bool IsPPFontDescriptionValid(const PP_FontDescription_Dev& desc) {
+ // Check validity of UTF-8.
+ if (desc.face.type != PP_VARTYPE_STRING &&
+ desc.face.type != PP_VARTYPE_UNDEFINED)
+ return false;
+
+ // Check enum ranges.
+ if (static_cast<int>(desc.family) < PP_FONTFAMILY_DEFAULT ||
+ static_cast<int>(desc.family) > PP_FONTFAMILY_MONOSPACE)
+ return false;
+ if (static_cast<int>(desc.weight) < PP_FONTWEIGHT_100 ||
+ static_cast<int>(desc.weight) > PP_FONTWEIGHT_900)
+ return false;
+
+ // Check for excessive sizes which may cause layout to get confused.
+ if (desc.size > 200)
+ return false;
+
+ return true;
+}
+
+// The PP_* version lacks "None", so is just one value shifted from the
+// WebFontDescription version. These values are checked in
+// PPFontDescToWebFontDesc to make sure the conversion is correct. This is a
+// macro so it can also be used in the COMPILE_ASSERTS.
+#define PP_FONTFAMILY_TO_WEB_FONTFAMILY(f) \
+ static_cast<WebFontDescription::GenericFamily>(f + 1)
+
+// Assumes the given PP_FontDescription has been validated.
+WebFontDescription PPFontDescToWebFontDesc(const PP_FontDescription_Dev& font) {
+ // Verify that the enums match so we can just static cast.
+ COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight100) ==
+ static_cast<int>(PP_FONTWEIGHT_100),
+ FontWeight100);
+ COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight900) ==
+ static_cast<int>(PP_FONTWEIGHT_900),
+ FontWeight900);
+ COMPILE_ASSERT(WebFontDescription::GenericFamilyStandard ==
+ PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_DEFAULT),
+ StandardFamily);
+ COMPILE_ASSERT(WebFontDescription::GenericFamilySerif ==
+ PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SERIF),
+ SerifFamily);
+ COMPILE_ASSERT(WebFontDescription::GenericFamilySansSerif ==
+ PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SANSSERIF),
+ SansSerifFamily);
+ COMPILE_ASSERT(WebFontDescription::GenericFamilyMonospace ==
+ PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_MONOSPACE),
+ MonospaceFamily);
+
+ WebFontDescription result;
+ scoped_refptr<StringVar> face_name(StringVar::FromPPVar(font.face));
+ if (face_name)
+ result.family = UTF8ToUTF16(face_name->value());
+ result.genericFamily = PP_FONTFAMILY_TO_WEB_FONTFAMILY(font.family);
+ result.size = static_cast<float>(font.size);
+ result.italic = PPBoolToBool(font.italic);
+ result.smallCaps = PPBoolToBool(font.small_caps);
+ result.weight = static_cast<WebFontDescription::Weight>(font.weight);
+ result.letterSpacing = static_cast<short>(font.letter_spacing);
+ result.wordSpacing = static_cast<short>(font.word_spacing);
+ return result;
+}
+
+// Converts the given PP_TextRun to a WebTextRun, returning true on success.
+// False means the input was invalid.
+bool PPTextRunToWebTextRun(const PP_TextRun_Dev* run, WebTextRun* output) {
+ scoped_refptr<StringVar> text_string(StringVar::FromPPVar(run->text));
+ if (!text_string)
+ return false;
+ *output = WebTextRun(UTF8ToUTF16(text_string->value()),
+ PPBoolToBool(run->rtl),
+ PPBoolToBool(run->override_direction));
+ return true;
+}
+
+PP_Resource Create(PP_Module module_id,
+ const PP_FontDescription_Dev* description) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ if (!IsPPFontDescriptionValid(*description))
+ return 0;
+
+ scoped_refptr<PPB_Font_Impl> font(new PPB_Font_Impl(module, *description));
+ return font->GetReference();
+}
+
+PP_Bool IsFont(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Font_Impl>(resource).get());
+}
+
+PP_Bool Describe(PP_Resource font_id,
+ PP_FontDescription_Dev* description,
+ PP_FontMetrics_Dev* metrics) {
+ scoped_refptr<PPB_Font_Impl> font(Resource::GetAs<PPB_Font_Impl>(font_id));
+ if (!font.get())
+ return PP_FALSE;
+ return BoolToPPBool(font->Describe(description, metrics));
+}
+
+PP_Bool DrawTextAt(PP_Resource font_id,
+ PP_Resource image_data,
+ const PP_TextRun_Dev* text,
+ const PP_Point* position,
+ uint32_t color,
+ const PP_Rect* clip,
+ PP_Bool image_data_is_opaque) {
+ scoped_refptr<PPB_Font_Impl> font(Resource::GetAs<PPB_Font_Impl>(font_id));
+ if (!font.get())
+ return PP_FALSE;
+ return BoolToPPBool(font->DrawTextAt(image_data, text, position, color, clip,
+ PPBoolToBool(image_data_is_opaque)));
+}
+
+int32_t MeasureText(PP_Resource font_id, const PP_TextRun_Dev* text) {
+ scoped_refptr<PPB_Font_Impl> font(Resource::GetAs<PPB_Font_Impl>(font_id));
+ if (!font.get())
+ return -1;
+ return font->MeasureText(text);
+}
+
+uint32_t CharacterOffsetForPixel(PP_Resource font_id,
+ const PP_TextRun_Dev* text,
+ int32_t pixel_position) {
+ scoped_refptr<PPB_Font_Impl> font(Resource::GetAs<PPB_Font_Impl>(font_id));
+ if (!font.get())
+ return false;
+ return font->CharacterOffsetForPixel(text, pixel_position);
+}
+
+int32_t PixelOffsetForCharacter(PP_Resource font_id,
+ const PP_TextRun_Dev* text,
+ uint32_t char_offset) {
+ scoped_refptr<PPB_Font_Impl> font(Resource::GetAs<PPB_Font_Impl>(font_id));
+ if (!font.get())
+ return false;
+ return font->PixelOffsetForCharacter(text, char_offset);
+}
+
+const PPB_Font_Dev ppb_font = {
+ &Create,
+ &IsFont,
+ &Describe,
+ &DrawTextAt,
+ &MeasureText,
+ &CharacterOffsetForPixel,
+ &PixelOffsetForCharacter
+};
+
+} // namespace
+
+PPB_Font_Impl::PPB_Font_Impl(PluginModule* module,
+ const PP_FontDescription_Dev& desc)
+ : Resource(module) {
+ WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc);
+ font_.reset(WebFont::create(web_font_desc));
+}
+
+PPB_Font_Impl::~PPB_Font_Impl() {
+}
+
+// static
+const PPB_Font_Dev* PPB_Font_Impl::GetInterface() {
+ return &ppb_font;
+}
+
+PPB_Font_Impl* PPB_Font_Impl::AsPPB_Font_Impl() {
+ return this;
+}
+
+bool PPB_Font_Impl::Describe(PP_FontDescription_Dev* description,
+ PP_FontMetrics_Dev* metrics) {
+ if (description->face.type != PP_VARTYPE_UNDEFINED)
+ return false;
+
+ WebFontDescription web_desc = font_->fontDescription();
+
+ // While converting the other way in PPFontDescToWebFontDesc we validated
+ // that the enums can be casted.
+ description->face = StringVar::StringToPPVar(module(),
+ UTF16ToUTF8(web_desc.family));
+ description->family = static_cast<PP_FontFamily_Dev>(web_desc.genericFamily);
+ description->size = static_cast<uint32_t>(web_desc.size);
+ description->weight = static_cast<PP_FontWeight_Dev>(web_desc.weight);
+ description->italic = BoolToPPBool(web_desc.italic);
+ description->small_caps = BoolToPPBool(web_desc.smallCaps);
+
+ metrics->height = font_->height();
+ metrics->ascent = font_->ascent();
+ metrics->descent = font_->descent();
+ metrics->line_spacing = font_->lineSpacing();
+ metrics->x_height = static_cast<int32_t>(font_->xHeight());
+
+ return true;
+}
+
+bool PPB_Font_Impl::DrawTextAt(PP_Resource image_data,
+ const PP_TextRun_Dev* text,
+ const PP_Point* position,
+ uint32_t color,
+ const PP_Rect* clip,
+ bool image_data_is_opaque) {
+ WebTextRun run;
+ if (!PPTextRunToWebTextRun(text, &run))
+ return false;
+
+ // Get and map the image data we're painting to.
+ scoped_refptr<PPB_ImageData_Impl> image_resource(
+ Resource::GetAs<PPB_ImageData_Impl>(image_data));
+ if (!image_resource.get())
+ return false;
+ ImageDataAutoMapper mapper(image_resource);
+ if (!mapper.is_valid())
+ return false;
+
+ // Convert position and clip.
+ WebFloatPoint web_position(static_cast<float>(position->x),
+ static_cast<float>(position->y));
+ WebRect web_clip;
+ if (!clip) {
+ // Use entire canvas.
+ web_clip = WebRect(0, 0, image_resource->width(), image_resource->height());
+ } else {
+ web_clip = WebRect(clip->point.x, clip->point.y,
+ clip->size.width, clip->size.height);
+ }
+
+ font_->drawText(webkit_glue::ToWebCanvas(image_resource->mapped_canvas()),
+ run, web_position, color, web_clip, image_data_is_opaque);
+ return true;
+}
+
+int32_t PPB_Font_Impl::MeasureText(const PP_TextRun_Dev* text) {
+ WebTextRun run;
+ if (!PPTextRunToWebTextRun(text, &run))
+ return -1;
+ return font_->calculateWidth(run);
+}
+
+uint32_t PPB_Font_Impl::CharacterOffsetForPixel(const PP_TextRun_Dev* text,
+ int32_t pixel_position) {
+ WebTextRun run;
+ if (!PPTextRunToWebTextRun(text, &run))
+ return -1;
+
+ return static_cast<uint32_t>(font_->offsetForPosition(
+ run, static_cast<float>(pixel_position)));
+}
+
+int32_t PPB_Font_Impl::PixelOffsetForCharacter(const PP_TextRun_Dev* text,
+ uint32_t char_offset) {
+ WebTextRun run;
+ if (!PPTextRunToWebTextRun(text, &run))
+ return -1;
+ if (char_offset >= run.text.length())
+ return -1;
+
+ WebFloatRect rect = font_->selectionRectForText(
+ run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset);
+ return static_cast<int>(rect.width);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_font_impl.h b/webkit/plugins/ppapi/ppb_font_impl.h
new file mode 100644
index 0000000..ff70330
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_font_impl.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_FONT_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_FONT_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace WebKit {
+class WebFont;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+
+class PPB_Font_Impl : public Resource {
+ public:
+ PPB_Font_Impl(PluginModule* module, const PP_FontDescription_Dev& desc);
+ virtual ~PPB_Font_Impl();
+
+ // Returns a pointer to the interface implementing PPB_Font that is exposed to
+ // the plugin.
+ static const PPB_Font_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_Font_Impl* AsPPB_Font_Impl();
+
+ // PPB_Font implementation.
+ bool Describe(PP_FontDescription_Dev* description,
+ PP_FontMetrics_Dev* metrics);
+ bool DrawTextAt(PP_Resource image_data,
+ const PP_TextRun_Dev* text,
+ const PP_Point* position,
+ uint32_t color,
+ const PP_Rect* clip,
+ bool image_data_is_opaque);
+ int32_t MeasureText(const PP_TextRun_Dev* text);
+ uint32_t CharacterOffsetForPixel(const PP_TextRun_Dev* text,
+ int32_t pixel_position);
+ int32_t PixelOffsetForCharacter(const PP_TextRun_Dev* text,
+ uint32_t char_offset);
+
+ private:
+ scoped_ptr<WebKit::WebFont> font_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Font_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_FONT_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_graphics_2d_impl.cc b/webkit/plugins/ppapi/ppb_graphics_2d_impl.cc
new file mode 100644
index 0000000..89435ff
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_graphics_2d_impl.cc
@@ -0,0 +1,652 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_graphics_2d_impl.h"
+
+#include <iterator>
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "gfx/blit.h"
+#include "gfx/point.h"
+#include "gfx/rect.h"
+#include "skia/ext/platform_canvas.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#endif
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// Converts a rect inside an image of the given dimensions. The rect may be
+// NULL to indicate it should be the entire image. If the rect is outside of
+// the image, this will do nothing and return false.
+bool ValidateAndConvertRect(const PP_Rect* rect,
+ int image_width, int image_height,
+ gfx::Rect* dest) {
+ if (!rect) {
+ // Use the entire image area.
+ *dest = gfx::Rect(0, 0, image_width, image_height);
+ } else {
+ // Validate the passed-in area.
+ if (rect->point.x < 0 || rect->point.y < 0 ||
+ rect->size.width <= 0 || rect->size.height <= 0)
+ return false;
+
+ // Check the max bounds, being careful of overflow.
+ if (static_cast<int64>(rect->point.x) +
+ static_cast<int64>(rect->size.width) >
+ static_cast<int64>(image_width))
+ return false;
+ if (static_cast<int64>(rect->point.y) +
+ static_cast<int64>(rect->size.height) >
+ static_cast<int64>(image_height))
+ return false;
+
+ *dest = gfx::Rect(rect->point.x, rect->point.y,
+ rect->size.width, rect->size.height);
+ }
+ return true;
+}
+
+// Converts BGRA <-> RGBA.
+void ConvertBetweenBGRAandRGBA(const uint32_t* input,
+ int pixel_length,
+ uint32_t* output) {
+ for (int i = 0; i < pixel_length; i++) {
+ const unsigned char* pixel_in =
+ reinterpret_cast<const unsigned char*>(&input[i]);
+ unsigned char* pixel_out = reinterpret_cast<unsigned char*>(&output[i]);
+ pixel_out[0] = pixel_in[2];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[0];
+ pixel_out[3] = pixel_in[3];
+ }
+}
+
+// Converts ImageData from PP_IMAGEDATAFORMAT_BGRA_PREMUL to
+// PP_IMAGEDATAFORMAT_RGBA_PREMUL, or reverse.
+void ConvertImageData(PPB_ImageData_Impl* src_image, const SkIRect& src_rect,
+ PPB_ImageData_Impl* dest_image, const SkRect& dest_rect) {
+ DCHECK(src_image->format() != dest_image->format());
+ DCHECK(PPB_ImageData_Impl::IsImageDataFormatSupported(src_image->format()));
+ DCHECK(PPB_ImageData_Impl::IsImageDataFormatSupported(dest_image->format()));
+
+ const SkBitmap* src_bitmap = src_image->GetMappedBitmap();
+ const SkBitmap* dest_bitmap = dest_image->GetMappedBitmap();
+ if (src_rect.width() == src_image->width() &&
+ dest_rect.width() == dest_image->width()) {
+ // Fast path if the full line needs to be converted.
+ ConvertBetweenBGRAandRGBA(
+ src_bitmap->getAddr32(static_cast<int>(src_rect.fLeft),
+ static_cast<int>(src_rect.fTop)),
+ src_rect.width() * src_rect.height(),
+ dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
+ static_cast<int>(dest_rect.fTop)));
+ } else {
+ // Slow path where we convert line by line.
+ for (int y = 0; y < src_rect.height(); y++) {
+ ConvertBetweenBGRAandRGBA(
+ src_bitmap->getAddr32(static_cast<int>(src_rect.fLeft),
+ static_cast<int>(src_rect.fTop + y)),
+ src_rect.width(),
+ dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
+ static_cast<int>(dest_rect.fTop + y)));
+ }
+ }
+}
+
+PP_Resource Create(PP_Module module_id,
+ const PP_Size* size,
+ PP_Bool is_always_opaque) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ scoped_refptr<PPB_Graphics2D_Impl> context(new PPB_Graphics2D_Impl(module));
+ if (!context->Init(size->width, size->height, PPBoolToBool(is_always_opaque)))
+ return 0;
+ return context->GetReference();
+}
+
+PP_Bool IsGraphics2D(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Graphics2D_Impl>(resource));
+}
+
+PP_Bool Describe(PP_Resource graphics_2d,
+ PP_Size* size,
+ PP_Bool* is_always_opaque) {
+ scoped_refptr<PPB_Graphics2D_Impl> context(
+ Resource::GetAs<PPB_Graphics2D_Impl>(graphics_2d));
+ if (!context)
+ return PP_FALSE;
+ return context->Describe(size, is_always_opaque);
+}
+
+void PaintImageData(PP_Resource graphics_2d,
+ PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) {
+ scoped_refptr<PPB_Graphics2D_Impl> context(
+ Resource::GetAs<PPB_Graphics2D_Impl>(graphics_2d));
+ if (context)
+ context->PaintImageData(image_data, top_left, src_rect);
+}
+
+void Scroll(PP_Resource graphics_2d,
+ const PP_Rect* clip_rect,
+ const PP_Point* amount) {
+ scoped_refptr<PPB_Graphics2D_Impl> context(
+ Resource::GetAs<PPB_Graphics2D_Impl>(graphics_2d));
+ if (context)
+ context->Scroll(clip_rect, amount);
+}
+
+void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) {
+ scoped_refptr<PPB_Graphics2D_Impl> context(
+ Resource::GetAs<PPB_Graphics2D_Impl>(graphics_2d));
+ if (context)
+ context->ReplaceContents(image_data);
+}
+
+int32_t Flush(PP_Resource graphics_2d,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_Graphics2D_Impl> context(
+ Resource::GetAs<PPB_Graphics2D_Impl>(graphics_2d));
+ if (!context)
+ return PP_ERROR_BADRESOURCE;
+ return context->Flush(callback);
+}
+
+const PPB_Graphics2D ppb_graphics_2d = {
+ &Create,
+ &IsGraphics2D,
+ &Describe,
+ &PaintImageData,
+ &Scroll,
+ &ReplaceContents,
+ &Flush
+};
+
+} // namespace
+
+struct PPB_Graphics2D_Impl::QueuedOperation {
+ enum Type {
+ PAINT,
+ SCROLL,
+ REPLACE
+ };
+
+ QueuedOperation(Type t)
+ : type(t),
+ paint_x(0),
+ paint_y(0),
+ scroll_dx(0),
+ scroll_dy(0) {
+ }
+
+ Type type;
+
+ // Valid when type == PAINT.
+ scoped_refptr<PPB_ImageData_Impl> paint_image;
+ int paint_x, paint_y;
+ gfx::Rect paint_src_rect;
+
+ // Valid when type == SCROLL.
+ gfx::Rect scroll_clip_rect;
+ int scroll_dx, scroll_dy;
+
+ // Valid when type == REPLACE.
+ scoped_refptr<PPB_ImageData_Impl> replace_image;
+};
+
+PPB_Graphics2D_Impl::PPB_Graphics2D_Impl(PluginModule* module)
+ : Resource(module),
+ bound_instance_(NULL),
+ flushed_any_data_(false),
+ offscreen_flush_pending_(false),
+ is_always_opaque_(false) {
+}
+
+PPB_Graphics2D_Impl::~PPB_Graphics2D_Impl() {
+}
+
+// static
+const PPB_Graphics2D* PPB_Graphics2D_Impl::GetInterface() {
+ return &ppb_graphics_2d;
+}
+
+bool PPB_Graphics2D_Impl::Init(int width, int height, bool is_always_opaque) {
+ // The underlying PPB_ImageData_Impl will validate the dimensions.
+ image_data_ = new PPB_ImageData_Impl(module());
+ if (!image_data_->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
+ width, height, true) ||
+ !image_data_->Map()) {
+ image_data_ = NULL;
+ return false;
+ }
+ is_always_opaque_ = is_always_opaque;
+ return true;
+}
+
+PPB_Graphics2D_Impl* PPB_Graphics2D_Impl::AsPPB_Graphics2D_Impl() {
+ return this;
+}
+
+PP_Bool PPB_Graphics2D_Impl::Describe(PP_Size* size, PP_Bool* is_always_opaque) {
+ size->width = image_data_->width();
+ size->height = image_data_->height();
+ *is_always_opaque = PP_FALSE; // TODO(brettw) implement this.
+ return PP_TRUE;
+}
+
+void PPB_Graphics2D_Impl::PaintImageData(PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) {
+ if (!top_left)
+ return;
+
+ scoped_refptr<PPB_ImageData_Impl> image_resource(
+ Resource::GetAs<PPB_ImageData_Impl>(image_data));
+ if (!image_resource)
+ return;
+
+ QueuedOperation operation(QueuedOperation::PAINT);
+ operation.paint_image = image_resource;
+ if (!ValidateAndConvertRect(src_rect, image_resource->width(),
+ image_resource->height(),
+ &operation.paint_src_rect))
+ return;
+
+ // Validate the bitmap position using the previously-validated rect, there
+ // should be no painted area outside of the image.
+ int64 x64 = static_cast<int64>(top_left->x);
+ int64 y64 = static_cast<int64>(top_left->y);
+ if (x64 + static_cast<int64>(operation.paint_src_rect.x()) < 0 ||
+ x64 + static_cast<int64>(operation.paint_src_rect.right()) >
+ image_data_->width())
+ return;
+ if (y64 + static_cast<int64>(operation.paint_src_rect.y()) < 0 ||
+ y64 + static_cast<int64>(operation.paint_src_rect.bottom()) >
+ image_data_->height())
+ return;
+ operation.paint_x = top_left->x;
+ operation.paint_y = top_left->y;
+
+ queued_operations_.push_back(operation);
+}
+
+void PPB_Graphics2D_Impl::Scroll(const PP_Rect* clip_rect,
+ const PP_Point* amount) {
+ QueuedOperation operation(QueuedOperation::SCROLL);
+ if (!ValidateAndConvertRect(clip_rect,
+ image_data_->width(),
+ image_data_->height(),
+ &operation.scroll_clip_rect))
+ return;
+
+ // If we're being asked to scroll by more than the clip rect size, just
+ // ignore this scroll command and say it worked.
+ int32 dx = amount->x;
+ int32 dy = amount->y;
+ if (dx <= -image_data_->width() || dx >= image_data_->width() ||
+ dy <= -image_data_->height() || dy >= image_data_->height())
+ return;
+
+ operation.scroll_dx = dx;
+ operation.scroll_dy = dy;
+
+ queued_operations_.push_back(operation);
+}
+
+void PPB_Graphics2D_Impl::ReplaceContents(PP_Resource image_data) {
+ scoped_refptr<PPB_ImageData_Impl> image_resource(
+ Resource::GetAs<PPB_ImageData_Impl>(image_data));
+ if (!image_resource)
+ return;
+ if (!PPB_ImageData_Impl::IsImageDataFormatSupported(
+ image_resource->format()))
+ return;
+
+ if (image_resource->width() != image_data_->width() ||
+ image_resource->height() != image_data_->height())
+ return;
+
+ QueuedOperation operation(QueuedOperation::REPLACE);
+ operation.replace_image = image_resource;
+ queued_operations_.push_back(operation);
+}
+
+int32_t PPB_Graphics2D_Impl::Flush(const PP_CompletionCallback& callback) {
+ // Don't allow more than one pending flush at a time.
+ if (HasPendingFlush())
+ return PP_ERROR_INPROGRESS;
+
+ // TODO(brettw) check that the current thread is not the main one and
+ // implement blocking flushes in this case.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ bool nothing_visible = true;
+ for (size_t i = 0; i < queued_operations_.size(); i++) {
+ QueuedOperation& operation = queued_operations_[i];
+ gfx::Rect op_rect;
+ switch (operation.type) {
+ case QueuedOperation::PAINT:
+ ExecutePaintImageData(operation.paint_image,
+ operation.paint_x, operation.paint_y,
+ operation.paint_src_rect,
+ &op_rect);
+ break;
+ case QueuedOperation::SCROLL:
+ ExecuteScroll(operation.scroll_clip_rect,
+ operation.scroll_dx, operation.scroll_dy,
+ &op_rect);
+ break;
+ case QueuedOperation::REPLACE:
+ ExecuteReplaceContents(operation.replace_image, &op_rect);
+ break;
+ }
+
+ // We need the rect to be in terms of the current clip rect of the plugin
+ // since that's what will actually be painted. If we issue an invalidate
+ // for a clipped-out region, WebKit will do nothing and we won't get any
+ // ViewInitiatedPaint/ViewFlushedPaint calls, leaving our callback stranded.
+ gfx::Rect visible_changed_rect;
+ if (bound_instance_ && !op_rect.IsEmpty())
+ visible_changed_rect = bound_instance_->clip().Intersect(op_rect);
+
+ if (bound_instance_ && !visible_changed_rect.IsEmpty()) {
+ if (operation.type == QueuedOperation::SCROLL) {
+ bound_instance_->ScrollRect(operation.scroll_dx, operation.scroll_dy,
+ visible_changed_rect);
+ } else {
+ bound_instance_->InvalidateRect(visible_changed_rect);
+ }
+ nothing_visible = false;
+ }
+ }
+ queued_operations_.clear();
+ flushed_any_data_ = true;
+
+ if (nothing_visible) {
+ // There's nothing visible to invalidate so just schedule the callback to
+ // execute in the next round of the message loop.
+ ScheduleOffscreenCallback(FlushCallbackData(callback));
+ } else {
+ unpainted_flush_callback_.Set(callback);
+ }
+ return PP_ERROR_WOULDBLOCK;
+}
+
+bool PPB_Graphics2D_Impl::ReadImageData(PP_Resource image,
+ const PP_Point* top_left) {
+ // Get and validate the image object to paint into.
+ scoped_refptr<PPB_ImageData_Impl> image_resource(
+ Resource::GetAs<PPB_ImageData_Impl>(image));
+ if (!image_resource)
+ return false;
+ if (!PPB_ImageData_Impl::IsImageDataFormatSupported(
+ image_resource->format()))
+ return false; // Must be in the right format.
+
+ // Validate the bitmap position.
+ int x = top_left->x;
+ if (x < 0 ||
+ static_cast<int64>(x) + static_cast<int64>(image_resource->width()) >
+ image_data_->width())
+ return false;
+ int y = top_left->y;
+ if (y < 0 ||
+ static_cast<int64>(y) + static_cast<int64>(image_resource->height()) >
+ image_data_->height())
+ return false;
+
+ ImageDataAutoMapper auto_mapper(image_resource);
+ if (!auto_mapper.is_valid())
+ return false;
+
+ SkIRect src_irect = { x, y,
+ x + image_resource->width(),
+ y + image_resource->height() };
+ SkRect dest_rect = { SkIntToScalar(0),
+ SkIntToScalar(0),
+ SkIntToScalar(image_resource->width()),
+ SkIntToScalar(image_resource->height()) };
+
+ ImageDataAutoMapper auto_mapper2(image_data_);
+ if (image_resource->format() != image_data_->format()) {
+ // Convert the image data if the format does not match.
+ ConvertImageData(image_data_, src_irect, image_resource.get(), dest_rect);
+ } else {
+ skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas();
+
+ // We want to replace the contents of the bitmap rather than blend.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(),
+ &src_irect, dest_rect, &paint);
+ }
+ return true;
+}
+
+bool PPB_Graphics2D_Impl::BindToInstance(PluginInstance* new_instance) {
+ if (bound_instance_ == new_instance)
+ return true; // Rebinding the same device, nothing to do.
+ if (bound_instance_ && new_instance)
+ return false; // Can't change a bound device.
+
+ if (!new_instance) {
+ // When the device is detached, we'll not get any more paint callbacks so
+ // we need to clear the list, but we still want to issue any pending
+ // callbacks to the plugin.
+ if (!unpainted_flush_callback_.is_null()) {
+ ScheduleOffscreenCallback(unpainted_flush_callback_);
+ unpainted_flush_callback_.Clear();
+ }
+ if (!painted_flush_callback_.is_null()) {
+ ScheduleOffscreenCallback(painted_flush_callback_);
+ painted_flush_callback_.Clear();
+ }
+ } else if (flushed_any_data_) {
+ // Only schedule a paint if this backing store has had any data flushed to
+ // it. This is an optimization. A "normal" plugin will first allocated a
+ // backing store, bind it, and then execute their normal painting and
+ // update loop. If binding a device always invalidated, it would mean we
+ // would get one paint for the bind, and one for the first time the plugin
+ // actually painted something. By not bothering to schedule an invalidate
+ // when an empty device is initially bound, we can save an extra paint for
+ // many plugins during the critical page initialization phase.
+ new_instance->InvalidateRect(gfx::Rect());
+ }
+
+ bound_instance_ = new_instance;
+ return true;
+}
+
+void PPB_Graphics2D_Impl::Paint(WebKit::WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const gfx::Rect& paint_rect) {
+ ImageDataAutoMapper auto_mapper(image_data_);
+ const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap();
+
+#if defined(OS_MACOSX)
+ SkAutoLockPixels lock(backing_bitmap);
+
+ base::mac::ScopedCFTypeRef<CGDataProviderRef> data_provider(
+ CGDataProviderCreateWithData(
+ NULL, backing_bitmap.getAddr32(0, 0),
+ backing_bitmap.rowBytes() * backing_bitmap.height(), NULL));
+ base::mac::ScopedCFTypeRef<CGImageRef> image(
+ CGImageCreate(
+ backing_bitmap.width(), backing_bitmap.height(),
+ 8, 32, backing_bitmap.rowBytes(),
+ mac_util::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ data_provider, NULL, false, kCGRenderingIntentDefault));
+
+ // Flip the transform
+ CGContextSaveGState(canvas);
+ float window_height = static_cast<float>(CGBitmapContextGetHeight(canvas));
+ CGContextTranslateCTM(canvas, 0, window_height);
+ CGContextScaleCTM(canvas, 1.0, -1.0);
+
+ CGRect bounds;
+ bounds.origin.x = plugin_rect.origin().x();
+ bounds.origin.y = window_height - plugin_rect.origin().y() -
+ backing_bitmap.height();
+ bounds.size.width = backing_bitmap.width();
+ bounds.size.height = backing_bitmap.height();
+
+ // TODO(brettw) bug 56673: do a direct memcpy instead of going through CG
+ // if the is_always_opaque_ flag is set.
+
+ CGContextDrawImage(canvas, bounds, image);
+ CGContextRestoreGState(canvas);
+#else
+ SkPaint paint;
+ if (is_always_opaque_) {
+ // When we know the device is opaque, we can disable blending for slightly
+ // more optimized painting.
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ }
+
+ gfx::Point origin(plugin_rect.origin().x(), plugin_rect.origin().y());
+ canvas->drawBitmap(backing_bitmap,
+ SkIntToScalar(plugin_rect.origin().x()),
+ SkIntToScalar(plugin_rect.origin().y()),
+ &paint);
+#endif
+}
+
+void PPB_Graphics2D_Impl::ViewInitiatedPaint() {
+ // Move any "unpainted" callback to the painted state. See
+ // |unpainted_flush_callback_| in the header for more.
+ if (!unpainted_flush_callback_.is_null()) {
+ DCHECK(painted_flush_callback_.is_null());
+ std::swap(painted_flush_callback_, unpainted_flush_callback_);
+ }
+}
+
+void PPB_Graphics2D_Impl::ViewFlushedPaint() {
+ // Notify any "painted" callback. See |unpainted_flush_callback_| in the
+ // header for more.
+ if (!painted_flush_callback_.is_null()) {
+ // We must clear this variable before issuing the callback. It will be
+ // common for the plugin to issue another invalidate in response to a flush
+ // callback, and we don't want to think that a callback is already pending.
+ FlushCallbackData callback;
+ std::swap(callback, painted_flush_callback_);
+ callback.Execute(PP_OK);
+ }
+}
+
+void PPB_Graphics2D_Impl::ExecutePaintImageData(PPB_ImageData_Impl* image,
+ int x, int y,
+ const gfx::Rect& src_rect,
+ gfx::Rect* invalidated_rect) {
+ // Ensure the source image is mapped to read from it.
+ ImageDataAutoMapper auto_mapper(image);
+ if (!auto_mapper.is_valid())
+ return;
+
+ // Portion within the source image to cut out.
+ SkIRect src_irect = { src_rect.x(), src_rect.y(),
+ src_rect.right(), src_rect.bottom() };
+
+ // Location within the backing store to copy to.
+ *invalidated_rect = src_rect;
+ invalidated_rect->Offset(x, y);
+ SkRect dest_rect = { SkIntToScalar(invalidated_rect->x()),
+ SkIntToScalar(invalidated_rect->y()),
+ SkIntToScalar(invalidated_rect->right()),
+ SkIntToScalar(invalidated_rect->bottom()) };
+
+ if (image->format() != image_data_->format()) {
+ // Convert the image data if the format does not match.
+ ConvertImageData(image, src_irect, image_data_, dest_rect);
+ } else {
+ // We're guaranteed to have a mapped canvas since we mapped it in Init().
+ skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
+
+ // We want to replace the contents of the bitmap rather than blend.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ backing_canvas->drawBitmapRect(*image->GetMappedBitmap(),
+ &src_irect, dest_rect, &paint);
+ }
+}
+
+void PPB_Graphics2D_Impl::ExecuteScroll(const gfx::Rect& clip,
+ int dx, int dy,
+ gfx::Rect* invalidated_rect) {
+ gfx::ScrollCanvas(image_data_->mapped_canvas(),
+ clip, gfx::Point(dx, dy));
+ *invalidated_rect = clip;
+}
+
+void PPB_Graphics2D_Impl::ExecuteReplaceContents(PPB_ImageData_Impl* image,
+ gfx::Rect* invalidated_rect) {
+ if (image->format() != image_data_->format()) {
+ DCHECK(image->width() == image_data_->width() &&
+ image->height() == image_data_->height());
+ // Convert the image data if the format does not match.
+ SkIRect src_irect = { 0, 0, image->width(), image->height() };
+ SkRect dest_rect = { SkIntToScalar(0),
+ SkIntToScalar(0),
+ SkIntToScalar(image_data_->width()),
+ SkIntToScalar(image_data_->height()) };
+ ConvertImageData(image, src_irect, image_data_, dest_rect);
+ } else {
+ image_data_->Swap(image);
+ }
+ *invalidated_rect = gfx::Rect(0, 0,
+ image_data_->width(), image_data_->height());
+}
+
+void PPB_Graphics2D_Impl::ScheduleOffscreenCallback(
+ const FlushCallbackData& callback) {
+ DCHECK(!HasPendingFlush());
+ offscreen_flush_pending_ = true;
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &PPB_Graphics2D_Impl::ExecuteOffscreenCallback,
+ callback));
+}
+
+void PPB_Graphics2D_Impl::ExecuteOffscreenCallback(FlushCallbackData data) {
+ DCHECK(offscreen_flush_pending_);
+
+ // We must clear this flag before issuing the callback. It will be
+ // common for the plugin to issue another invalidate in response to a flush
+ // callback, and we don't want to think that a callback is already pending.
+ offscreen_flush_pending_ = false;
+ data.Execute(PP_OK);
+}
+
+bool PPB_Graphics2D_Impl::HasPendingFlush() const {
+ return !unpainted_flush_callback_.is_null() ||
+ !painted_flush_callback_.is_null() ||
+ offscreen_flush_pending_;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_graphics_2d_impl.h b/webkit/plugins/ppapi/ppb_graphics_2d_impl.h
new file mode 100644
index 0000000..40f2e5d
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_graphics_2d_impl.h
@@ -0,0 +1,182 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_GRAPHICS_2D_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_GRAPHICS_2D_IMPL_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_Graphics2D;
+
+namespace gfx {
+class Rect;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_ImageData_Impl;
+class PluginInstance;
+class PluginModule;
+
+class PPB_Graphics2D_Impl : public Resource {
+ public:
+ PPB_Graphics2D_Impl(PluginModule* module);
+ virtual ~PPB_Graphics2D_Impl();
+
+ // Returns a pointer to the interface implementing PPB_ImageData that is
+ // exposed to the plugin.
+ static const PPB_Graphics2D* GetInterface();
+
+ bool Init(int width, int height, bool is_always_opaque);
+
+ bool is_always_opaque() const { return is_always_opaque_; }
+
+ // Resource override.
+ virtual PPB_Graphics2D_Impl* AsPPB_Graphics2D_Impl();
+
+ // PPB_Graphics2D functions.
+ PP_Bool Describe(PP_Size* size, PP_Bool* is_always_opaque);
+ void PaintImageData(PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect);
+ void Scroll(const PP_Rect* clip_rect, const PP_Point* amount);
+ void ReplaceContents(PP_Resource image_data);
+ int32_t Flush(const PP_CompletionCallback& callback);
+
+ bool ReadImageData(PP_Resource image, const PP_Point* top_left);
+
+ // Assciates this device with the given plugin instance. You can pass NULL to
+ // clear the existing device. Returns true on success. In this case, a
+ // repaint of the page will also be scheduled. Failure means that the device
+ // is already bound to a different instance, and nothing will happen.
+ bool BindToInstance(PluginInstance* new_instance);
+
+ // Paints the current backing store to the web page.
+ void Paint(WebKit::WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const gfx::Rect& paint_rect);
+
+ // Notifications that the view has rendered the page and that it has been
+ // flushed to the screen. These messages are used to send Flush callbacks to
+ // the plugin. See
+ void ViewInitiatedPaint();
+ void ViewFlushedPaint();
+
+ PPB_ImageData_Impl* image_data() { return image_data_.get(); }
+
+ private:
+ // Tracks a call to flush that requires a callback.
+ class FlushCallbackData {
+ public:
+ FlushCallbackData() {
+ Clear();
+ }
+
+ FlushCallbackData(const PP_CompletionCallback& callback) {
+ Set(callback);
+ }
+
+ bool is_null() const { return !callback_.func; }
+
+ void Set(const PP_CompletionCallback& callback) {
+ callback_ = callback;
+ }
+
+ void Clear() {
+ callback_ = PP_MakeCompletionCallback(NULL, 0);
+ }
+
+ void Execute(int32_t result) {
+ PP_RunCompletionCallback(&callback_, result);
+ }
+
+ private:
+ PP_CompletionCallback callback_;
+ };
+
+ // Called internally to execute the different queued commands. The
+ // parameters to these functions will have already been validated. The last
+ // rect argument will be filled by each function with the area affected by
+ // the update that requires invalidation. If there were no pixels changed,
+ // this rect can be untouched.
+ void ExecutePaintImageData(PPB_ImageData_Impl* image,
+ int x, int y,
+ const gfx::Rect& src_rect,
+ gfx::Rect* invalidated_rect);
+ void ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
+ gfx::Rect* invalidated_rect);
+ void ExecuteReplaceContents(PPB_ImageData_Impl* image,
+ gfx::Rect* invalidated_rect);
+
+ // Schedules the offscreen callback to be fired at a future time. This
+ // will add the given item to the offscreen_flush_callbacks_ vector.
+ void ScheduleOffscreenCallback(const FlushCallbackData& callback);
+
+ // Function scheduled to execute by ScheduleOffscreenCallback that actually
+ // issues the offscreen callbacks.
+ void ExecuteOffscreenCallback(FlushCallbackData data);
+
+ // Returns true if there is any type of flush callback pending.
+ bool HasPendingFlush() const;
+
+ scoped_refptr<PPB_ImageData_Impl> image_data_;
+
+ // Non-owning pointer to the plugin instance this context is currently bound
+ // to, if any. If the context is currently unbound, this will be NULL.
+ PluginInstance* bound_instance_;
+
+ // Keeps track of all drawing commands queued before a Flush call.
+ struct QueuedOperation;
+ typedef std::vector<QueuedOperation> OperationQueue;
+ OperationQueue queued_operations_;
+
+ // Indicates whether any changes have been flushed to the backing store.
+ // This is initially false and is set to true at the first Flush() call.
+ bool flushed_any_data_;
+
+ // The plugin can give us one "Flush" at a time. This flush will either be in
+ // the "unpainted" state (in which case unpainted_flush_callback_ will be
+ // non-NULL) or painted, in which case painted_flush_callback_ will be
+ // non-NULL). There can also be an offscreen callback which is handled
+ // separately (see offscreen_callback_pending_). Only one of these three
+ // things may be set at a time to enforce the "only one pending flush at a
+ // time" constraint.
+ //
+ // "Unpainted" ones are flush requests which have never been painted. These
+ // could have been done while the RenderView was already waiting for an ACK
+ // from a previous paint, so won't generate a new one yet.
+ //
+ // "Painted" ones are those flushes that have been painted by RenderView, but
+ // for which the ACK from the browser has not yet been received.
+ //
+ // When we get updates from a plugin with a callback, it is first added to
+ // the unpainted callbacks. When the renderer has initiated a paint, we'll
+ // move it to the painted callbacks list. When the renderer receives a flush,
+ // we'll execute the callback and remove it from the list.
+ FlushCallbackData unpainted_flush_callback_;
+ FlushCallbackData painted_flush_callback_;
+
+ // When doing offscreen flushes, we issue a task that issues the callback
+ // later. This is set when one of those tasks is pending so that we can
+ // enforce the "only one pending flush at a time" constraint in the API.
+ bool offscreen_flush_pending_;
+
+ // Set to true if the plugin declares that this device will always be opaque.
+ // This allows us to do more optimized painting in some cases.
+ bool is_always_opaque_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Graphics2D_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_GRAPHICS_2D_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc b/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc
new file mode 100644
index 0000000..0355262
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc
@@ -0,0 +1,263 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_graphics_3d_impl.h"
+
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "base/lazy_instance.h"
+#include "base/thread_local.h"
+#include "ppapi/c/dev/ppb_graphics_3d_dev.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+static base::LazyInstance<base::ThreadLocalPointer<PPB_Graphics3D_Impl> >
+ g_current_context_key(base::LINKER_INITIALIZED);
+
+// Size of the transfer buffer.
+enum { kTransferBufferSize = 512 * 1024 };
+
+PP_Bool IsGraphics3D(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Graphics3D_Impl>(resource));
+}
+
+PP_Bool GetConfigs(int32_t* configs, int32_t config_size, int32_t* num_config) {
+ // TODO(neb): Implement me!
+ return PP_FALSE;
+}
+
+PP_Bool ChooseConfig(const int32_t* attrib_list, int32_t* configs,
+ int32_t config_size, int32_t* num_config) {
+ // TODO(neb): Implement me!
+ return PP_FALSE;
+}
+
+PP_Bool GetConfigAttrib(int32_t config, int32_t attribute, int32_t* value) {
+ // TODO(neb): Implement me!
+ return PP_FALSE;
+}
+
+const char* QueryString(int32_t name) {
+ switch (name) {
+ case EGL_CLIENT_APIS:
+ return "OpenGL_ES";
+ case EGL_EXTENSIONS:
+ return "";
+ case EGL_VENDOR:
+ return "Google";
+ case EGL_VERSION:
+ return "1.0 Google";
+ default:
+ return NULL;
+ }
+}
+
+PP_Resource CreateContext(PP_Instance instance_id, int32_t config,
+ int32_t share_context,
+ const int32_t* attrib_list) {
+ DCHECK_EQ(0, share_context);
+
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance) {
+ return 0;
+ }
+
+ scoped_refptr<PPB_Graphics3D_Impl> context(
+ new PPB_Graphics3D_Impl(instance->module()));
+ if (!context->Init(instance_id, config, attrib_list)) {
+ return 0;
+ }
+
+ return context->GetReference();
+}
+
+void* GetProcAddress(const char* name) {
+ // TODO(neb): Implement me!
+ return NULL;
+}
+
+PP_Bool MakeCurrent(PP_Resource graphics3d) {
+ if (!graphics3d) {
+ PPB_Graphics3D_Impl::ResetCurrent();
+ return PP_TRUE;
+ } else {
+ scoped_refptr<PPB_Graphics3D_Impl> context(
+ Resource::GetAs<PPB_Graphics3D_Impl>(graphics3d));
+ return BoolToPPBool(context.get() && context->MakeCurrent());
+ }
+}
+
+PP_Resource GetCurrentContext() {
+ PPB_Graphics3D_Impl* current_context = PPB_Graphics3D_Impl::GetCurrent();
+ return current_context ? current_context->GetReference() : 0;
+}
+
+PP_Bool SwapBuffers(PP_Resource graphics3d) {
+ scoped_refptr<PPB_Graphics3D_Impl> context(
+ Resource::GetAs<PPB_Graphics3D_Impl>(graphics3d));
+ return BoolToPPBool(context && context->SwapBuffers());
+}
+
+uint32_t GetError() {
+ // Technically, this should return the last error that occurred on the current
+ // thread, rather than an error associated with a particular context.
+ // TODO(apatrick): Fix this.
+ PPB_Graphics3D_Impl* current_context = PPB_Graphics3D_Impl::GetCurrent();
+ if (!current_context)
+ return 0;
+
+ return current_context->GetError();
+}
+
+const PPB_Graphics3D_Dev ppb_graphics3d = {
+ &IsGraphics3D,
+ &GetConfigs,
+ &ChooseConfig,
+ &GetConfigAttrib,
+ &QueryString,
+ &CreateContext,
+ &GetProcAddress,
+ &MakeCurrent,
+ &GetCurrentContext,
+ &SwapBuffers,
+ &GetError
+};
+
+} // namespace
+
+PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginModule* module)
+ : Resource(module),
+ bound_instance_(NULL) {
+}
+
+const PPB_Graphics3D_Dev* PPB_Graphics3D_Impl::GetInterface() {
+ return &ppb_graphics3d;
+}
+
+PPB_Graphics3D_Impl* PPB_Graphics3D_Impl::GetCurrent() {
+ return g_current_context_key.Get().Get();
+}
+
+void PPB_Graphics3D_Impl::ResetCurrent() {
+ g_current_context_key.Get().Set(NULL);
+}
+
+PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() {
+ Destroy();
+}
+
+PPB_Graphics3D_Impl* PPB_Graphics3D_Impl::AsPPB_Graphics3D_Impl() {
+ return this;
+}
+
+bool PPB_Graphics3D_Impl::Init(PP_Instance instance_id, int32_t config,
+ const int32_t* attrib_list) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance) {
+ return false;
+ }
+
+ // Create and initialize the objects required to issue GLES2 calls.
+ platform_context_.reset(instance->delegate()->CreateContext3D());
+ if (!platform_context_.get()) {
+ Destroy();
+ return false;
+ }
+
+ if (!platform_context_->Init()) {
+ Destroy();
+ return false;
+ }
+
+ gles2_implementation_ = platform_context_->GetGLES2Implementation();
+ DCHECK(gles2_implementation_);
+
+ return true;
+}
+
+bool PPB_Graphics3D_Impl::BindToInstance(PluginInstance* new_instance) {
+ if (bound_instance_ == new_instance)
+ return true; // Rebinding the same device, nothing to do.
+ if (bound_instance_ && new_instance)
+ return false; // Can't change a bound device.
+
+ if (new_instance) {
+ // Resize the backing texture to the size of the instance when it is bound.
+ platform_context_->ResizeBackingTexture(new_instance->position().size());
+
+ // This is a temporary hack. The SwapBuffers is issued to force the resize
+ // to take place before any subsequent rendering. This might lead to a
+ // partially rendered frame being displayed. It is also not thread safe
+ // since the SwapBuffers is written to the command buffer and that command
+ // buffer might be written to by another thread.
+ // TODO(apatrick): Figure out the semantics of binding and resizing.
+ platform_context_->SwapBuffers();
+ }
+
+ bound_instance_ = new_instance;
+ return true;
+}
+
+bool PPB_Graphics3D_Impl::MakeCurrent() {
+ if (!platform_context_.get())
+ return false;
+
+ g_current_context_key.Get().Set(this);
+
+ // TODO(apatrick): Return false on context lost.
+ return true;
+}
+
+bool PPB_Graphics3D_Impl::SwapBuffers() {
+ if (!platform_context_.get())
+ return false;
+
+ return platform_context_->SwapBuffers();
+}
+
+unsigned PPB_Graphics3D_Impl::GetError() {
+ if (!platform_context_.get())
+ return 0;
+
+ return platform_context_->GetError();
+}
+
+void PPB_Graphics3D_Impl::ResizeBackingTexture(const gfx::Size& size) {
+ if (!platform_context_.get())
+ return;
+
+ platform_context_->ResizeBackingTexture(size);
+}
+
+void PPB_Graphics3D_Impl::SetSwapBuffersCallback(Callback0::Type* callback) {
+ if (!platform_context_.get())
+ return;
+
+ platform_context_->SetSwapBuffersCallback(callback);
+}
+
+unsigned PPB_Graphics3D_Impl::GetBackingTextureId() {
+ if (!platform_context_.get())
+ return 0;
+
+ return platform_context_->GetBackingTextureId();
+}
+
+void PPB_Graphics3D_Impl::Destroy() {
+ if (GetCurrent() == this) {
+ ResetCurrent();
+ }
+
+ gles2_implementation_ = NULL;
+
+ platform_context_.reset();
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_graphics_3d_impl.h b/webkit/plugins/ppapi/ppb_graphics_3d_impl.h
new file mode 100644
index 0000000..8124979
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_graphics_3d_impl.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_GRAPHICS_3D_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_GRAPHICS_3D_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/scoped_ptr.h"
+#include "gfx/size.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "ppapi/c/pp_instance.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace gpu {
+namespace gles2 {
+class GLES2Implementation;
+} // namespace gles2
+} // namespace gpu
+
+struct PPB_Graphics3D_Dev;
+struct PPB_OpenGLES_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_Graphics3D_Impl : public Resource {
+ public:
+ explicit PPB_Graphics3D_Impl(PluginModule* module);
+
+ virtual ~PPB_Graphics3D_Impl();
+
+ static const PPB_Graphics3D_Dev* GetInterface();
+ static const PPB_OpenGLES_Dev* GetOpenGLESInterface();
+
+ static bool Shutdown();
+
+ static PPB_Graphics3D_Impl* GetCurrent();
+
+ static void ResetCurrent();
+
+ // Resource override.
+ virtual PPB_Graphics3D_Impl* AsPPB_Graphics3D_Impl();
+
+ bool Init(PP_Instance instance_id, int32_t config,
+ const int32_t* attrib_list);
+
+ // Associates this PPB_Graphics3D_Impl with the given plugin instance. You can pass
+ // NULL to clear the existing device. Returns true on success. In this case,
+ // the last rendered frame is displayed.
+ // TODO(apatrick): Figure out the best semantics here.
+ bool BindToInstance(PluginInstance* new_instance);
+
+ bool MakeCurrent();
+
+ bool SwapBuffers();
+
+ unsigned GetError();
+
+ void ResizeBackingTexture(const gfx::Size& size);
+
+ void SetSwapBuffersCallback(Callback0::Type* callback);
+
+ unsigned GetBackingTextureId();
+
+ gpu::gles2::GLES2Implementation* impl() {
+ return gles2_implementation_;
+ }
+
+ private:
+ void Destroy();
+
+ // Non-owning pointer to the plugin instance this context is currently bound
+ // to, if any. If the context is currently unbound, this will be NULL.
+ PluginInstance* bound_instance_;
+
+ // PluginDelegate's 3D Context. Responsible for providing the command buffer.
+ scoped_ptr<PluginDelegate::PlatformContext3D> platform_context_;
+
+ // GLES2 Implementation instance. Owned by the platform context's GGL context.
+ gpu::gles2::GLES2Implementation* gles2_implementation_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Graphics3D_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_GRAPHICS_3D_IMPL_H_
+
diff --git a/webkit/plugins/ppapi/ppb_image_data_impl.cc b/webkit/plugins/ppapi/ppb_image_data_impl.cc
new file mode 100644
index 0000000..ee89cc3
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_image_data_impl.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_image_data_impl.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "skia/ext/platform_canvas.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/trusted/ppb_image_data_trusted.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_ImageDataFormat GetNativeImageDataFormat() {
+ return PPB_ImageData_Impl::GetNativeImageDataFormat();
+}
+
+PP_Bool IsImageDataFormatSupported(PP_ImageDataFormat format) {
+ return BoolToPPBool(PPB_ImageData_Impl::IsImageDataFormatSupported(format));
+}
+
+PP_Resource Create(PP_Module module_id,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ scoped_refptr<PPB_ImageData_Impl> data(new PPB_ImageData_Impl(module));
+ if (!data->Init(format,
+ size->width,
+ size->height,
+ PPBoolToBool(init_to_zero))) {
+ return 0;
+ }
+
+ return data->GetReference();
+}
+
+PP_Bool IsImageData(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_ImageData_Impl>(resource));
+}
+
+PP_Bool Describe(PP_Resource resource, PP_ImageDataDesc* desc) {
+ // Give predictable values on failure.
+ memset(desc, 0, sizeof(PP_ImageDataDesc));
+
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ Resource::GetAs<PPB_ImageData_Impl>(resource));
+ if (!image_data)
+ return PP_FALSE;
+ image_data->Describe(desc);
+ return PP_TRUE;
+}
+
+void* Map(PP_Resource resource) {
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ Resource::GetAs<PPB_ImageData_Impl>(resource));
+ if (!image_data)
+ return NULL;
+ return image_data->Map();
+}
+
+void Unmap(PP_Resource resource) {
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ Resource::GetAs<PPB_ImageData_Impl>(resource));
+ if (image_data)
+ image_data->Unmap();
+}
+
+int32_t GetSharedMemory(PP_Resource resource,
+ int* handle,
+ uint32_t* byte_count) {
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ Resource::GetAs<PPB_ImageData_Impl>(resource));
+ if (image_data) {
+ *handle = image_data->GetSharedMemoryHandle(byte_count);
+ return PP_OK;
+ }
+ return PP_ERROR_BADRESOURCE;
+}
+
+const PPB_ImageData ppb_imagedata = {
+ &GetNativeImageDataFormat,
+ &IsImageDataFormatSupported,
+ &Create,
+ &IsImageData,
+ &Describe,
+ &Map,
+ &Unmap,
+};
+
+const PPB_ImageDataTrusted ppb_imagedata_trusted = {
+ &GetSharedMemory,
+};
+
+} // namespace
+
+PPB_ImageData_Impl::PPB_ImageData_Impl(PluginModule* module)
+ : Resource(module),
+ format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
+ width_(0),
+ height_(0) {
+}
+
+PPB_ImageData_Impl::~PPB_ImageData_Impl() {
+}
+
+// static
+const PPB_ImageData* PPB_ImageData_Impl::GetInterface() {
+ return &ppb_imagedata;
+}
+
+// static
+const PPB_ImageDataTrusted* PPB_ImageData_Impl::GetTrustedInterface() {
+ return &ppb_imagedata_trusted;
+}
+
+// static
+PP_ImageDataFormat PPB_ImageData_Impl::GetNativeImageDataFormat() {
+ if (SK_B32_SHIFT == 0)
+ return PP_IMAGEDATAFORMAT_BGRA_PREMUL;
+ else if (SK_R32_SHIFT == 0)
+ return PP_IMAGEDATAFORMAT_RGBA_PREMUL;
+ else
+ return PP_IMAGEDATAFORMAT_BGRA_PREMUL; // Default to something on failure.
+}
+
+// static
+bool PPB_ImageData_Impl::IsImageDataFormatSupported(
+ PP_ImageDataFormat format) {
+ return format == PP_IMAGEDATAFORMAT_BGRA_PREMUL ||
+ format == PP_IMAGEDATAFORMAT_RGBA_PREMUL;
+}
+
+PPB_ImageData_Impl* PPB_ImageData_Impl::AsPPB_ImageData_Impl() {
+ return this;
+}
+
+bool PPB_ImageData_Impl::Init(PP_ImageDataFormat format,
+ int width, int height,
+ bool init_to_zero) {
+ // TODO(brettw) this should be called only on the main thread!
+ // TODO(brettw) use init_to_zero when we implement caching.
+ if (!IsImageDataFormatSupported(format))
+ return false; // Only support this one format for now.
+ if (width <= 0 || height <= 0)
+ return false;
+ if (static_cast<int64>(width) * static_cast<int64>(height) >=
+ std::numeric_limits<int32>::max())
+ return false; // Prevent overflow of signed 32-bit ints.
+
+ platform_image_.reset(
+ module()->GetSomeInstance()->delegate()->CreateImage2D(width, height));
+ format_ = format;
+ width_ = width;
+ height_ = height;
+ return !!platform_image_.get();
+}
+
+void PPB_ImageData_Impl::Describe(PP_ImageDataDesc* desc) const {
+ desc->format = format_;
+ desc->size.width = width_;
+ desc->size.height = height_;
+ desc->stride = width_ * 4;
+}
+
+void* PPB_ImageData_Impl::Map() {
+ if (!mapped_canvas_.get()) {
+ mapped_canvas_.reset(platform_image_->Map());
+ if (!mapped_canvas_.get())
+ return NULL;
+ }
+ const SkBitmap& bitmap =
+ mapped_canvas_->getTopPlatformDevice().accessBitmap(true);
+
+ // Our platform bitmaps are set to opaque by default, which we don't want.
+ const_cast<SkBitmap&>(bitmap).setIsOpaque(false);
+
+ bitmap.lockPixels();
+ return bitmap.getAddr32(0, 0);
+}
+
+void PPB_ImageData_Impl::Unmap() {
+ // This is currently unimplemented, which is OK. The data will just always
+ // be around once it's mapped. Chrome's TransportDIB isn't currently
+ // unmappable without freeing it, but this may be something we want to support
+ // in the future to save some memory.
+}
+
+int PPB_ImageData_Impl::GetSharedMemoryHandle(uint32* byte_count) const {
+ return platform_image_->GetSharedMemoryHandle(byte_count);
+}
+
+const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const {
+ if (!mapped_canvas_.get())
+ return NULL;
+ return &mapped_canvas_->getTopPlatformDevice().accessBitmap(false);
+}
+
+void PPB_ImageData_Impl::Swap(PPB_ImageData_Impl* other) {
+ swap(other->platform_image_, platform_image_);
+ swap(other->mapped_canvas_, mapped_canvas_);
+ std::swap(other->format_, format_);
+ std::swap(other->width_, width_);
+ std::swap(other->height_, height_);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_image_data_impl.h b/webkit/plugins/ppapi/ppb_image_data_impl.h
new file mode 100644
index 0000000..e036d39
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_image_data_impl.h
@@ -0,0 +1,134 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_IMAGE_DATA_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_IMAGE_DATA_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace skia {
+class PlatformCanvas;
+}
+
+struct PPB_ImageDataTrusted;
+class SkBitmap;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_ImageData_Impl : public Resource {
+ public:
+ explicit PPB_ImageData_Impl(PluginModule* module);
+ virtual ~PPB_ImageData_Impl();
+
+ int width() const { return width_; }
+ int height() const { return height_; }
+
+ // Returns the image format.
+ PP_ImageDataFormat format() const { return format_; }
+
+ // Returns true if this image is mapped. False means that the image is either
+ // invalid or not mapped. See ImageDataAutoMapper below.
+ bool is_mapped() const { return !!mapped_canvas_.get(); }
+
+ PluginDelegate::PlatformImage2D* platform_image() const {
+ return platform_image_.get();
+ }
+
+ // Returns a pointer to the interface implementing PPB_ImageData that is
+ // exposed to the plugin.
+ static const PPB_ImageData* GetInterface();
+ static const PPB_ImageDataTrusted* GetTrustedInterface();
+
+ // Returns the image data format used by the browser. If the plugin uses the
+ // same format, there is no conversion. Otherwise the browser will be in
+ // charge of converting from a supported format to its native format.
+ static PP_ImageDataFormat GetNativeImageDataFormat();
+
+ // Returns true if the format is supported by the browser.
+ static bool IsImageDataFormatSupported(PP_ImageDataFormat format);
+
+ // Resource overrides.
+ virtual PPB_ImageData_Impl* AsPPB_ImageData_Impl();
+
+ // PPB_ImageData implementation.
+ bool Init(PP_ImageDataFormat format,
+ int width, int height,
+ bool init_to_zero);
+ void Describe(PP_ImageDataDesc* desc) const;
+ void* Map();
+ void Unmap();
+
+ // PPB_ImageDataTrusted implementation.
+ int GetSharedMemoryHandle(uint32* byte_count) const;
+
+ // The mapped bitmap and canvas will be NULL if the image is not mapped.
+ skia::PlatformCanvas* mapped_canvas() const { return mapped_canvas_.get(); }
+ const SkBitmap* GetMappedBitmap() const;
+
+ // Swaps the guts of this image data with another.
+ void Swap(PPB_ImageData_Impl* other);
+
+ private:
+ // This will be NULL before initialization, and if this PPB_ImageData_Impl is
+ // swapped with another.
+ scoped_ptr<PluginDelegate::PlatformImage2D> platform_image_;
+
+ // When the device is mapped, this is the image. Null when umapped.
+ scoped_ptr<skia::PlatformCanvas> mapped_canvas_;
+
+ PP_ImageDataFormat format_;
+ int width_;
+ int height_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_ImageData_Impl);
+};
+
+// Manages mapping an image resource if necessary. Use this to ensure the
+// image is mapped. The destructor will put the image back into the previous
+// state. You must check is_valid() to make sure the image was successfully
+// mapped before using it.
+//
+// Example:
+// ImageDataAutoMapper mapper(image_data);
+// if (!mapper.is_valid())
+// return utter_failure;
+// image_data->mapped_canvas()->blah(); // Guaranteed valid.
+class ImageDataAutoMapper {
+ public:
+ ImageDataAutoMapper(PPB_ImageData_Impl* image_data)
+ : image_data_(image_data) {
+ if (image_data_->is_mapped()) {
+ is_valid_ = true;
+ needs_unmap_ = false;
+ } else {
+ is_valid_ = needs_unmap_ = !!image_data_->Map();
+ }
+ }
+
+ ~ImageDataAutoMapper() {
+ if (needs_unmap_)
+ image_data_->Unmap();
+ }
+
+ // Check this to see if the image was successfully mapped. If this is false,
+ // the image could not be mapped and is unusable.
+ bool is_valid() const { return is_valid_; }
+
+ private:
+ PPB_ImageData_Impl* image_data_;
+ bool is_valid_;
+ bool needs_unmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageDataAutoMapper);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_IMAGE_DATA_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_open_gl_es_impl.cc b/webkit/plugins/ppapi/ppb_open_gl_es_impl.cc
new file mode 100644
index 0000000..8d64168
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_open_gl_es_impl.cc
@@ -0,0 +1,673 @@
+// Copyright (c) 2010 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.
+
+// This file is auto-generated. DO NOT EDIT!
+
+#include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h"
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "ppapi/c/dev/ppb_opengles_dev.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+void ActiveTexture(GLenum texture) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ActiveTexture(texture);
+}
+void AttachShader(GLuint program, GLuint shader) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->AttachShader(program, shader);
+}
+void BindAttribLocation(GLuint program, GLuint index, const char* name) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BindAttribLocation(program, index, name);
+}
+void BindBuffer(GLenum target, GLuint buffer) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BindBuffer(target, buffer);
+}
+void BindFramebuffer(GLenum target, GLuint framebuffer) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BindFramebuffer(target, framebuffer);
+}
+void BindRenderbuffer(GLenum target, GLuint renderbuffer) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BindRenderbuffer(target, renderbuffer);
+}
+void BindTexture(GLenum target, GLuint texture) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BindTexture(target, texture);
+}
+void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BlendColor(red, green, blue, alpha);
+}
+void BlendEquation(GLenum mode) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BlendEquation(mode);
+}
+void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BlendEquationSeparate(modeRGB, modeAlpha);
+}
+void BlendFunc(GLenum sfactor, GLenum dfactor) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BlendFunc(sfactor, dfactor);
+}
+void BlendFuncSeparate(
+ GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BlendFuncSeparate(
+ srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void BufferData(
+ GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BufferData(target, size, data, usage);
+}
+void BufferSubData(
+ GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->BufferSubData(target, offset, size, data);
+}
+GLenum CheckFramebufferStatus(GLenum target) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->CheckFramebufferStatus(target);
+}
+void Clear(GLbitfield mask) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Clear(mask);
+}
+void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ClearColor(red, green, blue, alpha);
+}
+void ClearDepthf(GLclampf depth) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ClearDepthf(depth);
+}
+void ClearStencil(GLint s) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ClearStencil(s);
+}
+void ColorMask(
+ GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ColorMask(red, green, blue, alpha);
+}
+void CompileShader(GLuint shader) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->CompileShader(shader);
+}
+void CompressedTexImage2D(
+ GLenum target, GLint level, GLenum internalformat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize, const void* data) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->CompressedTexImage2D(
+ target, level, internalformat, width, height, border, imageSize, data);
+}
+void CompressedTexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->CompressedTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void CopyTexImage2D(
+ GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->CopyTexImage2D(
+ target, level, internalformat, x, y, width, height, border);
+}
+void CopyTexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
+ GLsizei width, GLsizei height) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->CopyTexSubImage2D(
+ target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint CreateProgram() {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->CreateProgram();
+}
+GLuint CreateShader(GLenum type) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->CreateShader(type);
+}
+void CullFace(GLenum mode) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->CullFace(mode);
+}
+void DeleteBuffers(GLsizei n, const GLuint* buffers) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DeleteBuffers(n, buffers);
+}
+void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DeleteFramebuffers(n, framebuffers);
+}
+void DeleteProgram(GLuint program) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DeleteProgram(program);
+}
+void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DeleteRenderbuffers(n, renderbuffers);
+}
+void DeleteShader(GLuint shader) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DeleteShader(shader);
+}
+void DeleteTextures(GLsizei n, const GLuint* textures) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DeleteTextures(n, textures);
+}
+void DepthFunc(GLenum func) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DepthFunc(func);
+}
+void DepthMask(GLboolean flag) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DepthMask(flag);
+}
+void DepthRangef(GLclampf zNear, GLclampf zFar) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DepthRangef(zNear, zFar);
+}
+void DetachShader(GLuint program, GLuint shader) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DetachShader(program, shader);
+}
+void Disable(GLenum cap) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Disable(cap);
+}
+void DisableVertexAttribArray(GLuint index) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DisableVertexAttribArray(index);
+}
+void DrawArrays(GLenum mode, GLint first, GLsizei count) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DrawArrays(mode, first, count);
+}
+void DrawElements(
+ GLenum mode, GLsizei count, GLenum type, const void* indices) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->DrawElements(mode, count, type, indices);
+}
+void Enable(GLenum cap) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Enable(cap);
+}
+void EnableVertexAttribArray(GLuint index) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->EnableVertexAttribArray(index);
+}
+void Finish() {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Finish();
+}
+void Flush() {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Flush();
+}
+void FramebufferRenderbuffer(
+ GLenum target, GLenum attachment, GLenum renderbuffertarget,
+ GLuint renderbuffer) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->FramebufferRenderbuffer(
+ target, attachment, renderbuffertarget, renderbuffer);
+}
+void FramebufferTexture2D(
+ GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
+ GLint level) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->FramebufferTexture2D(
+ target, attachment, textarget, texture, level);
+}
+void FrontFace(GLenum mode) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->FrontFace(mode);
+}
+void GenBuffers(GLsizei n, GLuint* buffers) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GenBuffers(n, buffers);
+}
+void GenerateMipmap(GLenum target) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GenerateMipmap(target);
+}
+void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GenFramebuffers(n, framebuffers);
+}
+void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GenRenderbuffers(n, renderbuffers);
+}
+void GenTextures(GLsizei n, GLuint* textures) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GenTextures(n, textures);
+}
+void GetActiveAttrib(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+ GLenum* type, char* name) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetActiveAttrib(
+ program, index, bufsize, length, size, type, name);
+}
+void GetActiveUniform(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+ GLenum* type, char* name) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetActiveUniform(
+ program, index, bufsize, length, size, type, name);
+}
+void GetAttachedShaders(
+ GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetAttachedShaders(
+ program, maxcount, count, shaders);
+}
+GLint GetAttribLocation(GLuint program, const char* name) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->GetAttribLocation(program, name);
+}
+void GetBooleanv(GLenum pname, GLboolean* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetBooleanv(pname, params);
+}
+void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetBufferParameteriv(
+ target, pname, params);
+}
+GLenum GetError() {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->GetError();
+}
+void GetFloatv(GLenum pname, GLfloat* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetFloatv(pname, params);
+}
+void GetFramebufferAttachmentParameteriv(
+ GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetFramebufferAttachmentParameteriv(
+ target, attachment, pname, params);
+}
+void GetIntegerv(GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetIntegerv(pname, params);
+}
+void GetProgramiv(GLuint program, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetProgramiv(program, pname, params);
+}
+void GetProgramInfoLog(
+ GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetProgramInfoLog(
+ program, bufsize, length, infolog);
+}
+void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetRenderbufferParameteriv(
+ target, pname, params);
+}
+void GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetShaderiv(shader, pname, params);
+}
+void GetShaderInfoLog(
+ GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetShaderInfoLog(
+ shader, bufsize, length, infolog);
+}
+void GetShaderPrecisionFormat(
+ GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetShaderPrecisionFormat(
+ shadertype, precisiontype, range, precision);
+}
+void GetShaderSource(
+ GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetShaderSource(
+ shader, bufsize, length, source);
+}
+const GLubyte* GetString(GLenum name) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->GetString(name);
+}
+void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetTexParameterfv(target, pname, params);
+}
+void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetTexParameteriv(target, pname, params);
+}
+void GetUniformfv(GLuint program, GLint location, GLfloat* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetUniformfv(program, location, params);
+}
+void GetUniformiv(GLuint program, GLint location, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetUniformiv(program, location, params);
+}
+GLint GetUniformLocation(GLuint program, const char* name) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->GetUniformLocation(program, name);
+}
+void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetVertexAttribfv(index, pname, params);
+}
+void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetVertexAttribiv(index, pname, params);
+}
+void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->GetVertexAttribPointerv(
+ index, pname, pointer);
+}
+void Hint(GLenum target, GLenum mode) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Hint(target, mode);
+}
+GLboolean IsBuffer(GLuint buffer) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsBuffer(buffer);
+}
+GLboolean IsEnabled(GLenum cap) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsEnabled(cap);
+}
+GLboolean IsFramebuffer(GLuint framebuffer) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsFramebuffer(framebuffer);
+}
+GLboolean IsProgram(GLuint program) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsProgram(program);
+}
+GLboolean IsRenderbuffer(GLuint renderbuffer) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsRenderbuffer(renderbuffer);
+}
+GLboolean IsShader(GLuint shader) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsShader(shader);
+}
+GLboolean IsTexture(GLuint texture) {
+ return PPB_Graphics3D_Impl::GetCurrent()->impl()->IsTexture(texture);
+}
+void LineWidth(GLfloat width) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->LineWidth(width);
+}
+void LinkProgram(GLuint program) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->LinkProgram(program);
+}
+void PixelStorei(GLenum pname, GLint param) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->PixelStorei(pname, param);
+}
+void PolygonOffset(GLfloat factor, GLfloat units) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->PolygonOffset(factor, units);
+}
+void ReadPixels(
+ GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ void* pixels) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ReadPixels(
+ x, y, width, height, format, type, pixels);
+}
+void ReleaseShaderCompiler() {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ReleaseShaderCompiler();
+}
+void RenderbufferStorage(
+ GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->RenderbufferStorage(
+ target, internalformat, width, height);
+}
+void SampleCoverage(GLclampf value, GLboolean invert) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->SampleCoverage(value, invert);
+}
+void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Scissor(x, y, width, height);
+}
+void ShaderBinary(
+ GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary,
+ GLsizei length) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ShaderBinary(
+ n, shaders, binaryformat, binary, length);
+}
+void ShaderSource(
+ GLuint shader, GLsizei count, const char** str, const GLint* length) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ShaderSource(shader, count, str, length);
+}
+void StencilFunc(GLenum func, GLint ref, GLuint mask) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->StencilFunc(func, ref, mask);
+}
+void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->StencilFuncSeparate(face, func, ref, mask);
+}
+void StencilMask(GLuint mask) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->StencilMask(mask);
+}
+void StencilMaskSeparate(GLenum face, GLuint mask) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->StencilMaskSeparate(face, mask);
+}
+void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->StencilOp(fail, zfail, zpass);
+}
+void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->StencilOpSeparate(
+ face, fail, zfail, zpass);
+}
+void TexImage2D(
+ GLenum target, GLint level, GLint internalformat, GLsizei width,
+ GLsizei height, GLint border, GLenum format, GLenum type,
+ const void* pixels) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->TexImage2D(
+ target, level, internalformat, width, height, border, format, type,
+ pixels);
+}
+void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->TexParameterf(target, pname, param);
+}
+void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->TexParameterfv(target, pname, params);
+}
+void TexParameteri(GLenum target, GLenum pname, GLint param) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->TexParameteri(target, pname, param);
+}
+void TexParameteriv(GLenum target, GLenum pname, const GLint* params) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->TexParameteriv(target, pname, params);
+}
+void TexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format, GLenum type, const void* pixels) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->TexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void Uniform1f(GLint location, GLfloat x) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform1f(location, x);
+}
+void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform1fv(location, count, v);
+}
+void Uniform1i(GLint location, GLint x) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform1i(location, x);
+}
+void Uniform1iv(GLint location, GLsizei count, const GLint* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform1iv(location, count, v);
+}
+void Uniform2f(GLint location, GLfloat x, GLfloat y) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform2f(location, x, y);
+}
+void Uniform2fv(GLint location, GLsizei count, const GLfloat* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform2fv(location, count, v);
+}
+void Uniform2i(GLint location, GLint x, GLint y) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform2i(location, x, y);
+}
+void Uniform2iv(GLint location, GLsizei count, const GLint* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform2iv(location, count, v);
+}
+void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform3f(location, x, y, z);
+}
+void Uniform3fv(GLint location, GLsizei count, const GLfloat* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform3fv(location, count, v);
+}
+void Uniform3i(GLint location, GLint x, GLint y, GLint z) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform3i(location, x, y, z);
+}
+void Uniform3iv(GLint location, GLsizei count, const GLint* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform3iv(location, count, v);
+}
+void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform4f(location, x, y, z, w);
+}
+void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform4fv(location, count, v);
+}
+void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform4i(location, x, y, z, w);
+}
+void Uniform4iv(GLint location, GLsizei count, const GLint* v) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Uniform4iv(location, count, v);
+}
+void UniformMatrix2fv(
+ GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->UniformMatrix2fv(
+ location, count, transpose, value);
+}
+void UniformMatrix3fv(
+ GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->UniformMatrix3fv(
+ location, count, transpose, value);
+}
+void UniformMatrix4fv(
+ GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->UniformMatrix4fv(
+ location, count, transpose, value);
+}
+void UseProgram(GLuint program) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->UseProgram(program);
+}
+void ValidateProgram(GLuint program) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->ValidateProgram(program);
+}
+void VertexAttrib1f(GLuint indx, GLfloat x) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib1f(indx, x);
+}
+void VertexAttrib1fv(GLuint indx, const GLfloat* values) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib1fv(indx, values);
+}
+void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib2f(indx, x, y);
+}
+void VertexAttrib2fv(GLuint indx, const GLfloat* values) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib2fv(indx, values);
+}
+void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib3f(indx, x, y, z);
+}
+void VertexAttrib3fv(GLuint indx, const GLfloat* values) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib3fv(indx, values);
+}
+void VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib4f(indx, x, y, z, w);
+}
+void VertexAttrib4fv(GLuint indx, const GLfloat* values) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttrib4fv(indx, values);
+}
+void VertexAttribPointer(
+ GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
+ const void* ptr) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->VertexAttribPointer(
+ indx, size, type, normalized, stride, ptr);
+}
+void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->Viewport(x, y, width, height);
+}
+void SwapBuffers() {
+ PPB_Graphics3D_Impl::GetCurrent()->impl()->SwapBuffers();
+}
+
+const struct PPB_OpenGLES_Dev ppb_opengles = {
+ &ActiveTexture,
+ &AttachShader,
+ &BindAttribLocation,
+ &BindBuffer,
+ &BindFramebuffer,
+ &BindRenderbuffer,
+ &BindTexture,
+ &BlendColor,
+ &BlendEquation,
+ &BlendEquationSeparate,
+ &BlendFunc,
+ &BlendFuncSeparate,
+ &BufferData,
+ &BufferSubData,
+ &CheckFramebufferStatus,
+ &Clear,
+ &ClearColor,
+ &ClearDepthf,
+ &ClearStencil,
+ &ColorMask,
+ &CompileShader,
+ &CompressedTexImage2D,
+ &CompressedTexSubImage2D,
+ &CopyTexImage2D,
+ &CopyTexSubImage2D,
+ &CreateProgram,
+ &CreateShader,
+ &CullFace,
+ &DeleteBuffers,
+ &DeleteFramebuffers,
+ &DeleteProgram,
+ &DeleteRenderbuffers,
+ &DeleteShader,
+ &DeleteTextures,
+ &DepthFunc,
+ &DepthMask,
+ &DepthRangef,
+ &DetachShader,
+ &Disable,
+ &DisableVertexAttribArray,
+ &DrawArrays,
+ &DrawElements,
+ &Enable,
+ &EnableVertexAttribArray,
+ &Finish,
+ &Flush,
+ &FramebufferRenderbuffer,
+ &FramebufferTexture2D,
+ &FrontFace,
+ &GenBuffers,
+ &GenerateMipmap,
+ &GenFramebuffers,
+ &GenRenderbuffers,
+ &GenTextures,
+ &GetActiveAttrib,
+ &GetActiveUniform,
+ &GetAttachedShaders,
+ &GetAttribLocation,
+ &GetBooleanv,
+ &GetBufferParameteriv,
+ &GetError,
+ &GetFloatv,
+ &GetFramebufferAttachmentParameteriv,
+ &GetIntegerv,
+ &GetProgramiv,
+ &GetProgramInfoLog,
+ &GetRenderbufferParameteriv,
+ &GetShaderiv,
+ &GetShaderInfoLog,
+ &GetShaderPrecisionFormat,
+ &GetShaderSource,
+ &GetString,
+ &GetTexParameterfv,
+ &GetTexParameteriv,
+ &GetUniformfv,
+ &GetUniformiv,
+ &GetUniformLocation,
+ &GetVertexAttribfv,
+ &GetVertexAttribiv,
+ &GetVertexAttribPointerv,
+ &Hint,
+ &IsBuffer,
+ &IsEnabled,
+ &IsFramebuffer,
+ &IsProgram,
+ &IsRenderbuffer,
+ &IsShader,
+ &IsTexture,
+ &LineWidth,
+ &LinkProgram,
+ &PixelStorei,
+ &PolygonOffset,
+ &ReadPixels,
+ &ReleaseShaderCompiler,
+ &RenderbufferStorage,
+ &SampleCoverage,
+ &Scissor,
+ &ShaderBinary,
+ &ShaderSource,
+ &StencilFunc,
+ &StencilFuncSeparate,
+ &StencilMask,
+ &StencilMaskSeparate,
+ &StencilOp,
+ &StencilOpSeparate,
+ &TexImage2D,
+ &TexParameterf,
+ &TexParameterfv,
+ &TexParameteri,
+ &TexParameteriv,
+ &TexSubImage2D,
+ &Uniform1f,
+ &Uniform1fv,
+ &Uniform1i,
+ &Uniform1iv,
+ &Uniform2f,
+ &Uniform2fv,
+ &Uniform2i,
+ &Uniform2iv,
+ &Uniform3f,
+ &Uniform3fv,
+ &Uniform3i,
+ &Uniform3iv,
+ &Uniform4f,
+ &Uniform4fv,
+ &Uniform4i,
+ &Uniform4iv,
+ &UniformMatrix2fv,
+ &UniformMatrix3fv,
+ &UniformMatrix4fv,
+ &UseProgram,
+ &ValidateProgram,
+ &VertexAttrib1f,
+ &VertexAttrib1fv,
+ &VertexAttrib2f,
+ &VertexAttrib2fv,
+ &VertexAttrib3f,
+ &VertexAttrib3fv,
+ &VertexAttrib4f,
+ &VertexAttrib4fv,
+ &VertexAttribPointer,
+ &Viewport,
+ &SwapBuffers
+};
+
+} // namespace
+
+const PPB_OpenGLES_Dev* PPB_Graphics3D_Impl::GetOpenGLESInterface() {
+ return &ppb_opengles;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_pdf.h b/webkit/plugins/ppapi/ppb_pdf.h
new file mode 100644
index 0000000..38d1763
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_pdf.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2010 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 WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_
+#define WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_
+
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+
+#define PPB_PDF_INTERFACE "PPB_PDF;1"
+
+// From the public PPB_Font_Dev file.
+struct PP_FontDescription_Dev;
+
+typedef enum {
+ PP_RESOURCESTRING_PDFGETPASSWORD = 0,
+ PP_RESOURCESTRING_PDFLOADING = 1,
+ PP_RESOURCESTRING_PDFLOAD_FAILED = 2,
+} PP_ResourceString;
+
+typedef enum {
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTH = 0,
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTH_HOVER = 1,
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTH_PRESSED = 2,
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTW = 3,
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER = 4,
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED = 5,
+ PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN = 6,
+ PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_HOVER = 7,
+ PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_PRESSED = 8,
+ PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT = 9,
+ PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER = 10,
+ PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED = 11,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_0 = 12,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_1 = 13,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_2 = 14,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_3 = 15,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_4 = 16,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_5 = 17,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_6 = 18,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_7 = 19,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_8 = 20,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_9 = 21,
+ PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_NUM_BACKGROUND = 22,
+} PP_ResourceImage;
+
+typedef enum {
+ PP_PRIVATEFONTCHARSET_ANSI = 0,
+ PP_PRIVATEFONTCHARSET_DEFAULT = 1,
+ PP_PRIVATEFONTCHARSET_SYMBOL = 2,
+ PP_PRIVATEFONTCHARSET_MAC = 77,
+ PP_PRIVATEFONTCHARSET_SHIFTJIS = 128,
+ PP_PRIVATEFONTCHARSET_HANGUL = 129,
+ PP_PRIVATEFONTCHARSET_JOHAB = 130,
+ PP_PRIVATEFONTCHARSET_GB2312 =134,
+ PP_PRIVATEFONTCHARSET_CHINESEBIG5 = 136,
+ PP_PRIVATEFONTCHARSET_GREEK = 161,
+ PP_PRIVATEFONTCHARSET_TURKISH = 162,
+ PP_PRIVATEFONTCHARSET_VIETNAMESE = 163,
+ PP_PRIVATEFONTCHARSET_HEBREW = 177,
+ PP_PRIVATEFONTCHARSET_ARABIC = 178,
+ PP_PRIVATEFONTCHARSET_BALTIC = 186,
+ PP_PRIVATEFONTCHARSET_RUSSIAN = 204,
+ PP_PRIVATEFONTCHARSET_THAI = 222,
+ PP_PRIVATEFONTCHARSET_EASTEUROPE = 238,
+ PP_PRIVATEFONTCHARSET_OEM = 255
+} PP_PrivateFontCharset;
+
+struct PP_PrivateFontFileDescription {
+ const char* face;
+ uint32_t weight;
+ bool italic;
+};
+
+struct PP_PrivateFindResult {
+ int start_index;
+ int length;
+};
+
+struct PPB_PDF {
+ // Returns a localized string.
+ PP_Var (*GetLocalizedString)(PP_Module module, PP_ResourceString string_id);
+
+ // Returns a resource image.
+ PP_Resource (*GetResourceImage)(PP_Module module,
+ PP_ResourceImage image_id);
+
+ // Returns a resource identifying a font file corresponding to the given font
+ // request after applying the browser-specific fallback.
+ //
+ // Currently Linux-only.
+ PP_Resource (*GetFontFileWithFallback)(
+ PP_Module module,
+ const PP_FontDescription_Dev* description,
+ PP_PrivateFontCharset charset);
+
+ // Given a resource previously returned by GetFontFileWithFallback, returns
+ // a pointer to the requested font table. Linux only.
+ bool (*GetFontTableForPrivateFontFile)(PP_Resource font_file,
+ uint32_t table,
+ void* output,
+ uint32_t* output_length);
+
+ // Search the given string using ICU. Use PPB_Core's MemFree on results when
+ // done.
+ void (*SearchString)(
+ PP_Module module,
+ const unsigned short* string,
+ const unsigned short* term,
+ bool case_sensitive,
+ PP_PrivateFindResult** results,
+ int* count);
+
+ // Since WebFrame doesn't know about PPAPI requests, it'll think the page has
+ // finished loading even if there are outstanding requests by the plugin.
+ // Take this out once WebFrame knows about requests by PPAPI plugins.
+ void (*DidStartLoading)(PP_Instance instance);
+ void (*DidStopLoading)(PP_Instance instance);
+
+ // Sets content restriction for a full-page plugin (i.e. can't copy/print).
+ // The value is a bitfield of ContentRestriction enums.
+ void (*SetContentRestriction)(PP_Instance instance, int restrictions);
+
+ // Use UMA so we know average pdf page count.
+ void (*HistogramPDFPageCount)(int count);
+
+ // Notifies the browser that the given action has been performed.
+ void (*UserMetricsRecordAction)(PP_Var action);
+};
+
+#endif // WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_
diff --git a/webkit/plugins/ppapi/ppb_pdf_impl.cc b/webkit/plugins/ppapi/ppb_pdf_impl.cc
new file mode 100644
index 0000000..4d4721f
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_pdf_impl.cc
@@ -0,0 +1,302 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_pdf_impl.h"
+
+#include "app/resource_bundle.h"
+#include "base/metrics/histogram.h"
+#include "base/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "grit/webkit_resources.h"
+#include "grit/webkit_strings.h"
+#include "skia/ext/platform_canvas.h"
+#include "ppapi/c/pp_resource.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/icu/public/i18n/unicode/usearch.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/ppb_pdf.h"
+#include "webkit/plugins/ppapi/var.h"
+
+namespace webkit {
+namespace ppapi {
+
+#if defined(OS_LINUX)
+class PrivateFontFile : public Resource {
+ public:
+ PrivateFontFile(PluginModule* module, int fd)
+ : Resource(module),
+ fd_(fd) {
+ }
+ virtual ~PrivateFontFile() {
+ }
+
+ // Resource overrides.
+ PrivateFontFile* AsPrivateFontFile() { return this; }
+
+ bool GetFontTable(uint32_t table,
+ void* output,
+ uint32_t* output_length);
+
+ private:
+ int fd_;
+};
+#endif
+
+namespace {
+
+struct ResourceImageInfo {
+ PP_ResourceImage pp_id;
+ int res_id;
+};
+
+static const ResourceImageInfo kResourceImageMap[] = {
+ { PP_RESOURCEIMAGE_PDF_BUTTON_FTH, IDR_PDF_BUTTON_FTH },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_FTH_HOVER, IDR_PDF_BUTTON_FTH_HOVER },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_FTH_PRESSED, IDR_PDF_BUTTON_FTH_PRESSED },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_FTW, IDR_PDF_BUTTON_FTW },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER, IDR_PDF_BUTTON_FTW_HOVER },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED, IDR_PDF_BUTTON_FTW_PRESSED },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN, IDR_PDF_BUTTON_ZOOMIN },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_HOVER, IDR_PDF_BUTTON_ZOOMIN_HOVER },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_PRESSED, IDR_PDF_BUTTON_ZOOMIN_PRESSED },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT, IDR_PDF_BUTTON_ZOOMOUT },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER, IDR_PDF_BUTTON_ZOOMOUT_HOVER },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED,
+ IDR_PDF_BUTTON_ZOOMOUT_PRESSED },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_0, IDR_PDF_THUMBNAIL_0 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_1, IDR_PDF_THUMBNAIL_1 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_2, IDR_PDF_THUMBNAIL_2 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_3, IDR_PDF_THUMBNAIL_3 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_4, IDR_PDF_THUMBNAIL_4 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_5, IDR_PDF_THUMBNAIL_5 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_6, IDR_PDF_THUMBNAIL_6 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_7, IDR_PDF_THUMBNAIL_7 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_8, IDR_PDF_THUMBNAIL_8 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_9, IDR_PDF_THUMBNAIL_9 },
+ { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_NUM_BACKGROUND,
+ IDR_PDF_THUMBNAIL_NUM_BACKGROUND },
+};
+
+PP_Var GetLocalizedString(PP_Module module_id, PP_ResourceString string_id) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return PP_MakeUndefined();
+
+ std::string rv;
+ if (string_id == PP_RESOURCESTRING_PDFGETPASSWORD) {
+ rv = UTF16ToUTF8(webkit_glue::GetLocalizedString(IDS_PDF_NEED_PASSWORD));
+ } else if (string_id == PP_RESOURCESTRING_PDFLOADING) {
+ rv = UTF16ToUTF8(webkit_glue::GetLocalizedString(IDS_PDF_PAGE_LOADING));
+ } else if (string_id == PP_RESOURCESTRING_PDFLOAD_FAILED) {
+ rv = UTF16ToUTF8(webkit_glue::GetLocalizedString(IDS_PDF_PAGE_LOAD_FAILED));
+ } else {
+ NOTREACHED();
+ }
+
+ return StringVar::StringToPPVar(module, rv);
+}
+
+PP_Resource GetResourceImage(PP_Module module_id, PP_ResourceImage image_id) {
+ int res_id = 0;
+ for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
+ if (kResourceImageMap[i].pp_id == image_id) {
+ res_id = kResourceImageMap[i].res_id;
+ break;
+ }
+ }
+ if (res_id == 0)
+ return 0;
+
+ SkBitmap* res_bitmap =
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(res_id);
+
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+ scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl(module));
+ if (!image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
+ res_bitmap->width(), res_bitmap->height(), false)) {
+ return 0;
+ }
+
+ ImageDataAutoMapper mapper(image_data);
+ if (!mapper.is_valid())
+ return 0;
+
+ skia::PlatformCanvas* canvas = image_data->mapped_canvas();
+ SkBitmap& ret_bitmap =
+ const_cast<SkBitmap&>(canvas->getTopPlatformDevice().accessBitmap(true));
+ if (!res_bitmap->copyTo(&ret_bitmap, SkBitmap::kARGB_8888_Config, NULL)) {
+ return 0;
+ }
+
+ return image_data->GetReference();
+}
+
+PP_Resource GetFontFileWithFallback(
+ PP_Module module_id,
+ const PP_FontDescription_Dev* description,
+ PP_PrivateFontCharset charset) {
+#if defined(OS_LINUX)
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ scoped_refptr<StringVar> face_name(StringVar::FromPPVar(description->face));
+ if (!face_name)
+ return 0;
+
+ int fd = webkit_glue::MatchFontWithFallback(
+ face_name->value().c_str(),
+ description->weight >= PP_FONTWEIGHT_BOLD,
+ description->italic,
+ charset);
+ if (fd == -1)
+ return 0;
+
+ scoped_refptr<PrivateFontFile> font(new PrivateFontFile(module, fd));
+
+ return font->GetReference();
+#else
+ // For trusted PPAPI plugins, this is only needed in Linux since font loading
+ // on Windows and Mac works through the renderer sandbox.
+ return 0;
+#endif
+}
+
+bool GetFontTableForPrivateFontFile(PP_Resource font_file,
+ uint32_t table,
+ void* output,
+ uint32_t* output_length) {
+#if defined(OS_LINUX)
+ scoped_refptr<PrivateFontFile> font(
+ Resource::GetAs<PrivateFontFile>(font_file));
+ if (!font.get())
+ return false;
+ return font->GetFontTable(table, output, output_length);
+#else
+ return false;
+#endif
+}
+
+void SearchString(PP_Module module,
+ const unsigned short* input_string,
+ const unsigned short* input_term,
+ bool case_sensitive,
+ PP_PrivateFindResult** results,
+ int* count) {
+ const char16* string = reinterpret_cast<const char16*>(input_string);
+ const char16* term = reinterpret_cast<const char16*>(input_term);
+
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch* searcher = usearch_open(
+ term, -1, string, -1, webkit_glue::GetWebKitLocale().c_str(), 0,
+ &status);
+ DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
+ status == U_USING_DEFAULT_WARNING);
+ UCollationStrength strength = case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY;
+
+ UCollator* collator = usearch_getCollator(searcher);
+ if (ucol_getStrength(collator) != strength) {
+ ucol_setStrength(collator, strength);
+ usearch_reset(searcher);
+ }
+
+ status = U_ZERO_ERROR;
+ int match_start = usearch_first(searcher, &status);
+ DCHECK(status == U_ZERO_ERROR);
+
+ std::vector<PP_PrivateFindResult> pp_results;
+ while (match_start != USEARCH_DONE) {
+ size_t matched_length = usearch_getMatchedLength(searcher);
+ PP_PrivateFindResult result;
+ result.start_index = match_start;
+ result.length = matched_length;
+ pp_results.push_back(result);
+ match_start = usearch_next(searcher, &status);
+ DCHECK(status == U_ZERO_ERROR);
+ }
+
+ *count = pp_results.size();
+ if (*count) {
+ *results = reinterpret_cast<PP_PrivateFindResult*>(
+ malloc(*count * sizeof(PP_PrivateFindResult)));
+ memcpy(*results, &pp_results[0], *count * sizeof(PP_PrivateFindResult));
+ } else {
+ *results = NULL;
+ }
+
+ usearch_close(searcher);
+}
+
+void DidStartLoading(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+ instance->delegate()->DidStartLoading();
+}
+
+void DidStopLoading(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+ instance->delegate()->DidStopLoading();
+}
+
+void SetContentRestriction(PP_Instance instance_id, int restrictions) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return;
+ instance->delegate()->SetContentRestriction(restrictions);
+}
+
+void HistogramPDFPageCount(int count) {
+ UMA_HISTOGRAM_COUNTS_10000("PDF.PageCount", count);
+}
+
+void UserMetricsRecordAction(PP_Var action) {
+ scoped_refptr<StringVar> action_str(StringVar::FromPPVar(action));
+ if (action_str)
+ webkit_glue::UserMetricsRecordAction(action_str->value());
+}
+
+const PPB_PDF ppb_pdf = {
+ &GetLocalizedString,
+ &GetResourceImage,
+ &GetFontFileWithFallback,
+ &GetFontTableForPrivateFontFile,
+ &SearchString,
+ &DidStartLoading,
+ &DidStopLoading,
+ &SetContentRestriction,
+ &HistogramPDFPageCount,
+ &UserMetricsRecordAction
+};
+
+} // namespace
+
+// static
+const PPB_PDF* PPB_PDF_Impl::GetInterface() {
+ return &ppb_pdf;
+}
+
+#if defined(OS_LINUX)
+bool PrivateFontFile::GetFontTable(uint32_t table,
+ void* output,
+ uint32_t* output_length) {
+ size_t temp_size = static_cast<size_t>(*output_length);
+ bool rv = webkit_glue::GetFontTable(
+ fd_, table, static_cast<uint8_t*>(output), &temp_size);
+ *output_length = static_cast<uint32_t>(temp_size);
+ return rv;
+}
+#endif
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_pdf_impl.h b/webkit/plugins/ppapi/ppb_pdf_impl.h
new file mode 100644
index 0000000..f630667
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_pdf_impl.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 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 WEBKIT_GLUE_PLUGINS_PPB_PDF_IMPL_H_
+#define WEBKIT_GLUE_PLUGINS_PPB_PDF_IMPL_H_
+
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_PDF;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_PDF_Impl {
+ public:
+ // Returns a pointer to the interface implementing PPB_PDF that is exposed
+ // to the plugin.
+ static const PPB_PDF* GetInterface();
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_GLUE_PLUGINS_PPB_PDF_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_scrollbar_impl.cc b/webkit/plugins/ppapi/ppb_scrollbar_impl.cc
new file mode 100644
index 0000000..c436748
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_scrollbar_impl.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_scrollbar_impl.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "ppapi/c/dev/ppp_scrollbar_dev.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebScrollbar.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/event_conversion.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/glue/webkit_glue.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+using WebKit::WebInputEvent;
+using WebKit::WebRect;
+using WebKit::WebScrollbar;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Instance instance_id, PP_Bool vertical) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ scoped_refptr<PPB_Scrollbar_Impl> scrollbar(
+ new PPB_Scrollbar_Impl(instance, PPBoolToBool(vertical)));
+ return scrollbar->GetReference();
+}
+
+PP_Bool IsScrollbar(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Scrollbar_Impl>(resource));
+}
+
+uint32_t GetThickness() {
+ return WebScrollbar::defaultThickness();
+}
+
+uint32_t GetValue(PP_Resource resource) {
+ scoped_refptr<PPB_Scrollbar_Impl> scrollbar(
+ Resource::GetAs<PPB_Scrollbar_Impl>(resource));
+ if (!scrollbar)
+ return 0;
+ return scrollbar->GetValue();
+}
+
+void SetValue(PP_Resource resource, uint32_t value) {
+ scoped_refptr<PPB_Scrollbar_Impl> scrollbar(
+ Resource::GetAs<PPB_Scrollbar_Impl>(resource));
+ if (scrollbar)
+ scrollbar->SetValue(value);
+}
+
+void SetDocumentSize(PP_Resource resource, uint32_t size) {
+ scoped_refptr<PPB_Scrollbar_Impl> scrollbar(
+ Resource::GetAs<PPB_Scrollbar_Impl>(resource));
+ if (scrollbar)
+ scrollbar->SetDocumentSize(size);
+}
+
+void SetTickMarks(PP_Resource resource,
+ const PP_Rect* tick_marks,
+ uint32_t count) {
+ scoped_refptr<PPB_Scrollbar_Impl> scrollbar(
+ Resource::GetAs<PPB_Scrollbar_Impl>(resource));
+ if (scrollbar)
+ scrollbar->SetTickMarks(tick_marks, count);
+}
+
+void ScrollBy(PP_Resource resource, PP_ScrollBy_Dev unit, int32_t multiplier) {
+ scoped_refptr<PPB_Scrollbar_Impl> scrollbar(
+ Resource::GetAs<PPB_Scrollbar_Impl>(resource));
+ if (scrollbar)
+ scrollbar->ScrollBy(unit, multiplier);
+}
+
+const PPB_Scrollbar_Dev ppb_scrollbar = {
+ &Create,
+ &IsScrollbar,
+ &GetThickness,
+ &GetValue,
+ &SetValue,
+ &SetDocumentSize,
+ &SetTickMarks,
+ &ScrollBy
+};
+
+} // namespace
+
+PPB_Scrollbar_Impl::PPB_Scrollbar_Impl(PluginInstance* instance, bool vertical)
+ : PPB_Widget_Impl(instance) {
+ scrollbar_.reset(WebScrollbar::create(
+ static_cast<WebKit::WebScrollbarClient*>(this),
+ vertical ? WebScrollbar::Vertical : WebScrollbar::Horizontal));
+}
+
+PPB_Scrollbar_Impl::~PPB_Scrollbar_Impl() {
+}
+
+// static
+const PPB_Scrollbar_Dev* PPB_Scrollbar_Impl::GetInterface() {
+ return &ppb_scrollbar;
+}
+
+PPB_Scrollbar_Impl* PPB_Scrollbar_Impl::AsPPB_Scrollbar_Impl() {
+ return this;
+}
+
+uint32_t PPB_Scrollbar_Impl::GetValue() {
+ return scrollbar_->value();
+}
+
+void PPB_Scrollbar_Impl::SetValue(uint32_t value) {
+ scrollbar_->setValue(value);
+}
+
+void PPB_Scrollbar_Impl::SetDocumentSize(uint32_t size) {
+ scrollbar_->setDocumentSize(size);
+}
+
+void PPB_Scrollbar_Impl::SetTickMarks(const PP_Rect* tick_marks,
+ uint32_t count) {
+ tickmarks_.resize(count);
+ for (uint32 i = 0; i < count; ++i) {
+ tickmarks_[i] = WebRect(tick_marks[i].point.x,
+ tick_marks[i].point.y,
+ tick_marks[i].size.width,
+ tick_marks[i].size.height);;
+ }
+ PP_Rect rect = location();
+ Invalidate(&rect);
+}
+
+void PPB_Scrollbar_Impl::ScrollBy(PP_ScrollBy_Dev unit, int32_t multiplier) {
+ WebScrollbar::ScrollDirection direction = multiplier >= 0 ?
+ WebScrollbar::ScrollForward : WebScrollbar::ScrollBackward;
+ float fmultiplier = 1.0;
+
+ WebScrollbar::ScrollGranularity granularity;
+ if (unit == PP_SCROLLBY_LINE) {
+ granularity = WebScrollbar::ScrollByLine;
+ } else if (unit == PP_SCROLLBY_PAGE) {
+ granularity = WebScrollbar::ScrollByPage;
+ } else if (unit == PP_SCROLLBY_DOCUMENT) {
+ granularity = WebScrollbar::ScrollByDocument;
+ } else {
+ granularity = WebScrollbar::ScrollByPixel;
+ fmultiplier = static_cast<float>(multiplier);
+ if (fmultiplier < 0)
+ fmultiplier *= -1;
+ }
+ scrollbar_->scroll(direction, granularity, fmultiplier);
+}
+
+bool PPB_Scrollbar_Impl::Paint(const PP_Rect* rect, PPB_ImageData_Impl* image) {
+ gfx::Rect gfx_rect(rect->point.x,
+ rect->point.y,
+ rect->size.width,
+ rect->size.height);
+ skia::PlatformCanvas* canvas = image->mapped_canvas();
+ if (!canvas)
+ return false;
+ scrollbar_->paint(webkit_glue::ToWebCanvas(canvas), gfx_rect);
+
+#if defined(OS_WIN)
+ if (base::win::GetVersion() == base::win::VERSION_XP) {
+ canvas->getTopPlatformDevice().makeOpaque(
+ gfx_rect.x(), gfx_rect.y(), gfx_rect.width(), gfx_rect.height());
+ }
+#endif
+
+ return true;
+}
+
+bool PPB_Scrollbar_Impl::HandleEvent(const PP_InputEvent* event) {
+ scoped_ptr<WebInputEvent> web_input_event(CreateWebInputEvent(*event));
+ if (!web_input_event.get())
+ return false;
+
+ return scrollbar_->handleInputEvent(*web_input_event.get());
+}
+
+void PPB_Scrollbar_Impl::SetLocationInternal(const PP_Rect* location) {
+ scrollbar_->setLocation(WebRect(location->point.x,
+ location->point.y,
+ location->size.width,
+ location->size.height));
+}
+
+void PPB_Scrollbar_Impl::valueChanged(WebKit::WebScrollbar* scrollbar) {
+ const PPP_Scrollbar_Dev* ppp_scrollbar =
+ static_cast<const PPP_Scrollbar_Dev*>(
+ module()->GetPluginInterface(PPP_SCROLLBAR_DEV_INTERFACE));
+ if (!ppp_scrollbar)
+ return;
+ ScopedResourceId resource(this);
+ ppp_scrollbar->ValueChanged(
+ instance()->pp_instance(), resource.id, scrollbar_->value());
+}
+
+void PPB_Scrollbar_Impl::invalidateScrollbarRect(
+ WebKit::WebScrollbar* scrollbar,
+ const WebKit::WebRect& rect) {
+ gfx::Rect gfx_rect(rect.x,
+ rect.y,
+ rect.width,
+ rect.height);
+ dirty_ = dirty_.Union(gfx_rect);
+ // Can't call into the client to tell them about the invalidate right away,
+ // since the PPB_Scrollbar_Impl code is still in the middle of updating its
+ // internal state.
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &PPB_Scrollbar_Impl::NotifyInvalidate));
+}
+
+void PPB_Scrollbar_Impl::getTickmarks(
+ WebKit::WebScrollbar* scrollbar,
+ WebKit::WebVector<WebKit::WebRect>* tick_marks) const {
+ if (tickmarks_.empty()) {
+ WebRect* rects = NULL;
+ tick_marks->assign(rects, 0);
+ } else {
+ tick_marks->assign(&tickmarks_[0], tickmarks_.size());
+ }
+}
+
+void PPB_Scrollbar_Impl::NotifyInvalidate() {
+ if (dirty_.IsEmpty())
+ return;
+ PP_Rect pp_rect;
+ pp_rect.point.x = dirty_.x();
+ pp_rect.point.y = dirty_.y();
+ pp_rect.size.width = dirty_.width();
+ pp_rect.size.height = dirty_.height();
+ dirty_ = gfx::Rect();
+ Invalidate(&pp_rect);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_scrollbar_impl.h b/webkit/plugins/ppapi/ppb_scrollbar_impl.h
new file mode 100644
index 0000000..532c05b
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_scrollbar_impl.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_SCROLLBAR_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_SCROLLBAR_IMPL_H_
+
+#include <vector>
+
+#include "gfx/rect.h"
+#include "ppapi/c/dev/ppb_scrollbar_dev.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebScrollbarClient.h"
+#include "webkit/plugins/ppapi/ppb_widget_impl.h"
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+
+class PPB_Scrollbar_Impl : public PPB_Widget_Impl,
+ public WebKit::WebScrollbarClient {
+ public:
+ PPB_Scrollbar_Impl(PluginInstance* instance, bool vertical);
+ virtual ~PPB_Scrollbar_Impl();
+
+ // Returns a pointer to the interface implementing PPB_Scrollbar that is
+ // exposed to the plugin.
+ static const PPB_Scrollbar_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_Scrollbar_Impl* AsPPB_Scrollbar_Impl();
+
+ // PPB_Scrollbar implementation.
+ uint32_t GetValue();
+ void SetValue(uint32_t value);
+ void SetDocumentSize(uint32_t size);
+ void SetTickMarks(const PP_Rect* tick_marks, uint32_t count);
+ void ScrollBy(PP_ScrollBy_Dev unit, int32_t multiplier);
+
+ // PPB_Widget implementation.
+ virtual bool Paint(const PP_Rect* rect, PPB_ImageData_Impl* image);
+ virtual bool HandleEvent(const PP_InputEvent* event);
+ virtual void SetLocationInternal(const PP_Rect* location);
+
+ private:
+ // WebKit::WebScrollbarClient implementation.
+ virtual void valueChanged(WebKit::WebScrollbar* scrollbar);
+ virtual void invalidateScrollbarRect(WebKit::WebScrollbar* scrollbar,
+ const WebKit::WebRect& rect);
+ virtual void getTickmarks(
+ WebKit::WebScrollbar* scrollbar,
+ WebKit::WebVector<WebKit::WebRect>* tick_marks) const;
+
+ void NotifyInvalidate();
+
+ gfx::Rect dirty_;
+ std::vector<WebKit::WebRect> tickmarks_;
+ scoped_ptr<WebKit::WebScrollbar> scrollbar_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Scrollbar_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_SCROLLBAR_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_transport_impl.cc b/webkit/plugins/ppapi/ppb_transport_impl.cc
new file mode 100644
index 0000000..bcd4f6a
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_transport_impl.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_transport_impl.h"
+
+#include "base/singleton.h"
+#include "base/thread_local.h"
+#include "ppapi/c/dev/ppb_transport_dev.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// Creates a new transport object with the specified name
+// using the specified protocol.
+PP_Resource CreateTransport(PP_Module module,
+ const char* name,
+ const char* proto) {
+ // TODO(juberti): implement me
+ PP_Resource p(0);
+ return p;
+}
+
+// Returns whether or not resource is PPB_Transport_Impl
+PP_Bool IsTransport(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Transport_Impl>(resource));
+}
+
+// Returns whether the transport is currently writable
+// (i.e. can send data to the remote peer)
+PP_Bool IsWritable(PP_Resource transport) {
+ // TODO(juberti): impelement me
+ return PP_FALSE;
+}
+
+
+// TODO(juberti): other getters/setters
+// connect state
+// connect type, protocol
+// RTT
+
+
+// Establishes a connection to the remote peer.
+// Returns PP_ERROR_WOULDBLOCK and notifies on |cb|
+// when connectivity is established (or timeout occurs).
+int32_t Connect(PP_Resource transport,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): impelement me
+ return 0;
+}
+
+
+// Obtains another ICE candidate address to be provided
+// to the remote peer. Returns PP_ERROR_WOULDBLOCK
+// if there are no more addresses to be sent.
+int32_t GetNextAddress(PP_Resource transport,
+ PP_Var* address,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Provides an ICE candidate address that was received
+// from the remote peer.
+int32_t ReceiveRemoteAddress(PP_Resource transport,
+ PP_Var address) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Like recv(), receives data. Returns PP_ERROR_WOULDBLOCK
+// if there is currently no data to receive.
+int32_t Recv(PP_Resource transport,
+ void* data,
+ uint32_t len,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Like send(), sends data. Returns PP_ERROR_WOULDBLOCK
+// if the socket is currently flow-controlled.
+int32_t Send(PP_Resource transport,
+ const void* data,
+ uint32_t len,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Disconnects from the remote peer.
+int32_t Close(PP_Resource transport) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+const PPB_Transport_Dev ppb_transport = {
+ &CreateTransport,
+ &IsTransport,
+ &IsWritable,
+ &Connect,
+ &GetNextAddress,
+ &ReceiveRemoteAddress,
+ &Recv,
+ &Send,
+ &Close,
+};
+
+} // namespace
+
+PPB_Transport_Impl::PPB_Transport_Impl(PluginModule* module)
+ : Resource(module) {
+ // TODO(juberti): impl
+}
+
+const PPB_Transport_Dev* PPB_Transport_Impl::GetInterface() {
+ return &ppb_transport;
+}
+
+PPB_Transport_Impl::~PPB_Transport_Impl() {
+ // TODO(juberti): teardown
+}
+
+PPB_Transport_Impl* PPB_Transport_Impl::AsPPB_Transport_Impl() {
+ return this;
+}
+
+bool PPB_Transport_Impl::Init(const char* name, const char* proto) {
+ // TODO(juberti): impl
+ return false;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_transport_impl.h b/webkit/plugins/ppapi/ppb_transport_impl.h
new file mode 100644
index 0000000..7a98a37
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_transport_impl.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_TRANSPORT_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_TRANSPORT_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_Transport_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_Transport_Impl : public Resource {
+ public:
+ explicit PPB_Transport_Impl(PluginModule* module);
+ virtual ~PPB_Transport_Impl();
+
+ static const PPB_Transport_Dev* GetInterface();
+ virtual PPB_Transport_Impl* AsPPB_Transport_Impl();
+
+ bool Init(const char* name,
+ const char* proto);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_Transport_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_TRANSPORT_IMPL_H_
+
diff --git a/webkit/plugins/ppapi/ppb_url_loader_impl.cc b/webkit/plugins/ppapi/ppb_url_loader_impl.cc
new file mode 100644
index 0000000..14b91f8
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_loader_impl.cc
@@ -0,0 +1,559 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_url_loader_impl.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "webkit/appcache/web_application_cache_host_impl.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_url_request_info_impl.h"
+#include "webkit/plugins/ppapi/ppb_url_response_info_impl.h"
+
+using appcache::WebApplicationCacheHostImpl;
+using WebKit::WebFrame;
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebURLError;
+using WebKit::WebURLLoader;
+using WebKit::WebURLRequest;
+using WebKit::WebURLResponse;
+
+#ifdef _MSC_VER
+// Do not warn about use of std::copy with raw pointers.
+#pragma warning(disable : 4996)
+#endif
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Resource Create(PP_Instance instance_id) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ PPB_URLLoader_Impl* loader = new PPB_URLLoader_Impl(instance, false);
+ return loader->GetReference();
+}
+
+PP_Bool IsURLLoader(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_URLLoader_Impl>(resource));
+}
+
+int32_t Open(PP_Resource loader_id,
+ PP_Resource request_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<PPB_URLRequestInfo_Impl> request(
+ Resource::GetAs<PPB_URLRequestInfo_Impl>(request_id));
+ if (!request)
+ return PP_ERROR_BADRESOURCE;
+
+ return loader->Open(request, callback);
+}
+
+int32_t FollowRedirect(PP_Resource loader_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return PP_ERROR_BADRESOURCE;
+
+ return loader->FollowRedirect(callback);
+}
+
+PP_Bool GetUploadProgress(PP_Resource loader_id,
+ int64_t* bytes_sent,
+ int64_t* total_bytes_to_be_sent) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return PP_FALSE;
+
+ return BoolToPPBool(loader->GetUploadProgress(bytes_sent,
+ total_bytes_to_be_sent));
+}
+
+PP_Bool GetDownloadProgress(PP_Resource loader_id,
+ int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return PP_FALSE;
+
+ return BoolToPPBool(loader->GetDownloadProgress(bytes_received,
+ total_bytes_to_be_received));
+}
+
+PP_Resource GetResponseInfo(PP_Resource loader_id) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return 0;
+
+ PPB_URLResponseInfo_Impl* response_info = loader->response_info();
+ if (!response_info)
+ return 0;
+
+ return response_info->GetReference();
+}
+
+int32_t ReadResponseBody(PP_Resource loader_id,
+ char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return PP_ERROR_BADRESOURCE;
+
+ return loader->ReadResponseBody(buffer, bytes_to_read, callback);
+}
+
+int32_t FinishStreamingToFile(PP_Resource loader_id,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return PP_ERROR_BADRESOURCE;
+
+ return loader->FinishStreamingToFile(callback);
+}
+
+void Close(PP_Resource loader_id) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return;
+
+ loader->Close();
+}
+
+const PPB_URLLoader ppb_urlloader = {
+ &Create,
+ &IsURLLoader,
+ &Open,
+ &FollowRedirect,
+ &GetUploadProgress,
+ &GetDownloadProgress,
+ &GetResponseInfo,
+ &ReadResponseBody,
+ &FinishStreamingToFile,
+ &Close
+};
+
+void GrantUniversalAccess(PP_Resource loader_id) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return;
+
+ loader->GrantUniversalAccess();
+}
+
+void SetStatusCallback(PP_Resource loader_id,
+ PP_URLLoaderTrusted_StatusCallback cb) {
+ scoped_refptr<PPB_URLLoader_Impl> loader(
+ Resource::GetAs<PPB_URLLoader_Impl>(loader_id));
+ if (!loader)
+ return;
+ loader->SetStatusCallback(cb);
+}
+
+const PPB_URLLoaderTrusted ppb_urlloadertrusted = {
+ &GrantUniversalAccess,
+ &SetStatusCallback
+};
+
+WebKit::WebFrame* GetFrame(PluginInstance* instance) {
+ return instance->container()->element().document().frame();
+}
+
+} // namespace
+
+PPB_URLLoader_Impl::PPB_URLLoader_Impl(PluginInstance* instance,
+ bool main_document_loader)
+ : Resource(instance->module()),
+ instance_(instance),
+ main_document_loader_(main_document_loader),
+ pending_callback_(),
+ bytes_sent_(0),
+ total_bytes_to_be_sent_(-1),
+ bytes_received_(0),
+ total_bytes_to_be_received_(-1),
+ user_buffer_(NULL),
+ user_buffer_size_(0),
+ done_status_(PP_ERROR_WOULDBLOCK),
+ has_universal_access_(false),
+ status_callback_(NULL) {
+ instance->AddObserver(this);
+}
+
+PPB_URLLoader_Impl::~PPB_URLLoader_Impl() {
+ if (instance_)
+ instance_->RemoveObserver(this);
+}
+
+// static
+const PPB_URLLoader* PPB_URLLoader_Impl::GetInterface() {
+ return &ppb_urlloader;
+}
+
+// static
+const PPB_URLLoaderTrusted* PPB_URLLoader_Impl::GetTrustedInterface() {
+ return &ppb_urlloadertrusted;
+}
+
+PPB_URLLoader_Impl* PPB_URLLoader_Impl::AsPPB_URLLoader_Impl() {
+ return this;
+}
+
+int32_t PPB_URLLoader_Impl::Open(PPB_URLRequestInfo_Impl* request,
+ PP_CompletionCallback callback) {
+ if (loader_.get())
+ return PP_ERROR_INPROGRESS;
+
+ // We only support non-blocking calls.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ WebFrame* frame = GetFrame(instance_);
+ if (!frame)
+ return PP_ERROR_FAILED;
+ WebURLRequest web_request(request->ToWebURLRequest(frame));
+
+ int32_t rv = CanRequest(frame, web_request.url());
+ if (rv != PP_OK)
+ return rv;
+
+ frame->dispatchWillSendRequest(web_request);
+
+ // Sets the appcache host id to allow retrieval from the appcache.
+ if (WebApplicationCacheHostImpl* appcache_host =
+ WebApplicationCacheHostImpl::FromFrame(frame)) {
+ appcache_host->willStartSubResourceRequest(web_request);
+ }
+
+ loader_.reset(WebKit::webKitClient()->createURLLoader());
+ if (!loader_.get())
+ return PP_ERROR_FAILED;
+
+ loader_->loadAsynchronously(web_request, this);
+
+ request_info_ = scoped_refptr<PPB_URLRequestInfo_Impl>(request);
+ pending_callback_ = callback;
+
+ // Notify completion when we receive a redirect or response headers.
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_URLLoader_Impl::FollowRedirect(PP_CompletionCallback callback) {
+ if (pending_callback_.func)
+ return PP_ERROR_INPROGRESS;
+
+ // We only support non-blocking calls.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ WebURL redirect_url = GURL(response_info_->redirect_url());
+
+ int32_t rv = CanRequest(GetFrame(instance_), redirect_url);
+ if (rv != PP_OK)
+ return rv;
+
+ pending_callback_ = callback;
+ loader_->setDefersLoading(false); // Allow the redirect to continue.
+ return PP_ERROR_WOULDBLOCK;
+}
+
+bool PPB_URLLoader_Impl::GetUploadProgress(int64_t* bytes_sent,
+ int64_t* total_bytes_to_be_sent) {
+ if (!RecordUploadProgress()) {
+ *bytes_sent = 0;
+ *total_bytes_to_be_sent = 0;
+ return false;
+ }
+ *bytes_sent = bytes_sent_;
+ *total_bytes_to_be_sent = total_bytes_to_be_sent_;
+ return true;
+}
+
+bool PPB_URLLoader_Impl::GetDownloadProgress(
+ int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) {
+ if (!RecordDownloadProgress()) {
+ *bytes_received = 0;
+ *total_bytes_to_be_received = 0;
+ return false;
+ }
+ *bytes_received = bytes_received_;
+ *total_bytes_to_be_received = total_bytes_to_be_received_;
+ return true;
+}
+
+int32_t PPB_URLLoader_Impl::ReadResponseBody(char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ if (!response_info_ || response_info_->body())
+ return PP_ERROR_FAILED;
+ if (bytes_to_read <= 0 || !buffer)
+ return PP_ERROR_BADARGUMENT;
+ if (pending_callback_.func)
+ return PP_ERROR_INPROGRESS;
+
+ // We only support non-blocking calls.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ user_buffer_ = buffer;
+ user_buffer_size_ = bytes_to_read;
+
+ if (!buffer_.empty())
+ return FillUserBuffer();
+
+ // We may have already reached EOF.
+ if (done_status_ != PP_ERROR_WOULDBLOCK) {
+ user_buffer_ = NULL;
+ user_buffer_size_ = 0;
+ return done_status_;
+ }
+
+ pending_callback_ = callback;
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_URLLoader_Impl::FinishStreamingToFile(
+ PP_CompletionCallback callback) {
+ if (!response_info_ || !response_info_->body())
+ return PP_ERROR_FAILED;
+ if (pending_callback_.func)
+ return PP_ERROR_INPROGRESS;
+
+ // We may have already reached EOF.
+ if (done_status_ != PP_ERROR_WOULDBLOCK)
+ return done_status_;
+
+ // Wait for didFinishLoading / didFail.
+ pending_callback_ = callback;
+ return PP_ERROR_WOULDBLOCK;
+}
+
+void PPB_URLLoader_Impl::Close() {
+ if (loader_.get()) {
+ loader_->cancel();
+ } else if (main_document_loader_) {
+ WebFrame* frame = instance_->container()->element().document().frame();
+ frame->stopLoading();
+ }
+}
+
+void PPB_URLLoader_Impl::GrantUniversalAccess() {
+ has_universal_access_ = true;
+}
+
+void PPB_URLLoader_Impl::SetStatusCallback(
+ PP_URLLoaderTrusted_StatusCallback cb) {
+ status_callback_ = cb;
+}
+
+void PPB_URLLoader_Impl::willSendRequest(
+ WebURLLoader* loader,
+ WebURLRequest& new_request,
+ const WebURLResponse& redirect_response) {
+ if (!request_info_->follow_redirects()) {
+ SaveResponse(redirect_response);
+ loader_->setDefersLoading(true);
+ RunCallback(PP_OK);
+ } else {
+ int32_t rv = CanRequest(GetFrame(instance_), new_request.url());
+ if (rv != PP_OK) {
+ loader_->setDefersLoading(true);
+ RunCallback(rv);
+ }
+ }
+}
+
+void PPB_URLLoader_Impl::didSendData(
+ WebURLLoader* loader,
+ unsigned long long bytes_sent,
+ unsigned long long total_bytes_to_be_sent) {
+ // TODO(darin): Bounds check input?
+ bytes_sent_ = static_cast<int64_t>(bytes_sent);
+ total_bytes_to_be_sent_ = static_cast<int64_t>(total_bytes_to_be_sent);
+ UpdateStatus();
+}
+
+void PPB_URLLoader_Impl::didReceiveResponse(WebURLLoader* loader,
+ const WebURLResponse& response) {
+ SaveResponse(response);
+
+ // Sets -1 if the content length is unknown.
+ total_bytes_to_be_received_ = response.expectedContentLength();
+ UpdateStatus();
+
+ RunCallback(PP_OK);
+}
+
+void PPB_URLLoader_Impl::didDownloadData(WebURLLoader* loader,
+ int data_length) {
+ bytes_received_ += data_length;
+ UpdateStatus();
+}
+
+void PPB_URLLoader_Impl::didReceiveData(WebURLLoader* loader,
+ const char* data,
+ int data_length) {
+ bytes_received_ += data_length;
+
+ buffer_.insert(buffer_.end(), data, data + data_length);
+ if (user_buffer_) {
+ RunCallback(FillUserBuffer());
+ } else {
+ DCHECK(!pending_callback_.func);
+ }
+}
+
+void PPB_URLLoader_Impl::didFinishLoading(WebURLLoader* loader,
+ double finish_time) {
+ done_status_ = PP_OK;
+ RunCallback(done_status_);
+}
+
+void PPB_URLLoader_Impl::didFail(WebURLLoader* loader,
+ const WebURLError& error) {
+ // TODO(darin): Provide more detailed error information.
+ done_status_ = PP_ERROR_FAILED;
+ RunCallback(done_status_);
+}
+
+void PPB_URLLoader_Impl::InstanceDestroyed(PluginInstance* instance) {
+ // When the instance is destroyed, we force delete any associated loads.
+ DCHECK(instance == instance_);
+ instance_ = NULL;
+
+ // Normally the only ref to this class will be from the plugin which
+ // ForceDeletePluginResourceRefs will free. We don't want our object to be
+ // deleted out from under us until the function completes.
+ scoped_refptr<PPB_URLLoader_Impl> death_grip(this);
+
+ // Force delete any plugin refs to us. If the instance is being deleted, we
+ // don't want to allow the requests to continue to use bandwidth and send us
+ // callbacks (for which we might have no plugin).
+ ResourceTracker *tracker = ResourceTracker::Get();
+ PP_Resource loader_resource = GetReferenceNoAddRef();
+ if (loader_resource)
+ tracker->ForceDeletePluginResourceRefs(loader_resource);
+
+ // Also force free the response from the plugin, both the plugin's ref(s)
+ // and ours.
+ if (response_info_.get()) {
+ PP_Resource response_info_resource = response_info_->GetReferenceNoAddRef();
+ if (response_info_resource)
+ tracker->ForceDeletePluginResourceRefs(response_info_resource);
+ response_info_ = NULL;
+ }
+
+ // Free the WebKit request.
+ loader_.reset();
+
+ // Often, |this| will be deleted at the end of this function when death_grip
+ // goes out of scope.
+}
+
+void PPB_URLLoader_Impl::RunCallback(int32_t result) {
+ if (!pending_callback_.func)
+ return;
+
+ PP_CompletionCallback callback = {0};
+ std::swap(callback, pending_callback_);
+ PP_RunCompletionCallback(&callback, result);
+}
+
+size_t PPB_URLLoader_Impl::FillUserBuffer() {
+ DCHECK(user_buffer_);
+ DCHECK(user_buffer_size_);
+
+ size_t bytes_to_copy = std::min(buffer_.size(), user_buffer_size_);
+ std::copy(buffer_.begin(), buffer_.begin() + bytes_to_copy, user_buffer_);
+ buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_copy);
+
+ // Reset for next time.
+ user_buffer_ = NULL;
+ user_buffer_size_ = 0;
+ return bytes_to_copy;
+}
+
+void PPB_URLLoader_Impl::SaveResponse(const WebKit::WebURLResponse& response) {
+ scoped_refptr<PPB_URLResponseInfo_Impl> response_info(
+ new PPB_URLResponseInfo_Impl(module()));
+ if (response_info->Initialize(response))
+ response_info_ = response_info;
+}
+
+// Checks that the client can request the URL. Returns a PPAPI error code.
+int32_t PPB_URLLoader_Impl::CanRequest(const WebKit::WebFrame* frame,
+ const WebKit::WebURL& url) {
+ if (!has_universal_access_ &&
+ !frame->securityOrigin().canRequest(url))
+ return PP_ERROR_NOACCESS;
+
+ return PP_OK;
+}
+
+void PPB_URLLoader_Impl::UpdateStatus() {
+ if (status_callback_ &&
+ (RecordDownloadProgress() || RecordUploadProgress())) {
+ PP_Resource pp_resource = GetReferenceNoAddRef();
+ if (pp_resource) {
+ // The PP_Resource on the plugin will be NULL if the plugin has no
+ // reference to this object. That's fine, because then we don't need to
+ // call UpdateStatus.
+ //
+ // Here we go through some effort to only send the exact information that
+ // the requestor wanted in the request flags. It would be just as
+ // efficient to send all of it, but we don't want people to rely on
+ // getting download progress when they happen to set the upload progress
+ // flag.
+ status_callback_(
+ instance_->pp_instance(), pp_resource,
+ RecordUploadProgress() ? bytes_sent_ : -1,
+ RecordUploadProgress() ? total_bytes_to_be_sent_ : -1,
+ RecordDownloadProgress() ? bytes_received_ : -1,
+ RecordDownloadProgress() ? total_bytes_to_be_received_ : -1);
+ }
+ }
+}
+
+bool PPB_URLLoader_Impl::RecordDownloadProgress() const {
+ return request_info_ && request_info_->record_download_progress();
+}
+
+bool PPB_URLLoader_Impl::RecordUploadProgress() const {
+ return request_info_ && request_info_->record_upload_progress();
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_url_loader_impl.h b/webkit/plugins/ppapi/ppb_url_loader_impl.h
new file mode 100644
index 0000000..6b05adc
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_loader_impl.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_URL_LOADER_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_URL_LOADER_IMPL_H_
+
+#include <deque>
+
+#include "base/scoped_ptr.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_URLLoader;
+struct PPB_URLLoaderTrusted;
+
+namespace WebKit {
+class WebFrame;
+class WebURL;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+class PPB_URLRequestInfo_Impl;
+class PPB_URLResponseInfo_Impl;
+
+class PPB_URLLoader_Impl : public Resource,
+ public WebKit::WebURLLoaderClient,
+ public PluginInstance::Observer {
+ public:
+ PPB_URLLoader_Impl(PluginInstance* instance, bool main_document_loader);
+ virtual ~PPB_URLLoader_Impl();
+
+ // Returns a pointer to the interface implementing PPB_URLLoader that is
+ // exposed to the plugin.
+ static const PPB_URLLoader* GetInterface();
+
+ // Returns a pointer to the interface implementing PPB_URLLoaderTrusted that
+ // is exposed to the plugin.
+ static const PPB_URLLoaderTrusted* GetTrustedInterface();
+
+ // Resource overrides.
+ virtual PPB_URLLoader_Impl* AsPPB_URLLoader_Impl();
+
+ // PPB_URLLoader implementation.
+ int32_t Open(PPB_URLRequestInfo_Impl* request,
+ PP_CompletionCallback callback);
+ int32_t FollowRedirect(PP_CompletionCallback callback);
+ bool GetUploadProgress(int64_t* bytes_sent,
+ int64_t* total_bytes_to_be_sent);
+ bool GetDownloadProgress(int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received);
+ int32_t ReadResponseBody(char* buffer, int32_t bytes_to_read,
+ PP_CompletionCallback callback);
+ int32_t FinishStreamingToFile(PP_CompletionCallback callback);
+ void Close();
+
+ // PPB_URLLoaderTrusted implementation.
+ void GrantUniversalAccess();
+ void SetStatusCallback(PP_URLLoaderTrusted_StatusCallback cb);
+
+ // WebKit::WebURLLoaderClient implementation.
+ virtual void willSendRequest(WebKit::WebURLLoader* loader,
+ WebKit::WebURLRequest& new_request,
+ const WebKit::WebURLResponse& redir_response);
+ virtual void didSendData(WebKit::WebURLLoader* loader,
+ unsigned long long bytes_sent,
+ unsigned long long total_bytes_to_be_sent);
+ virtual void didReceiveResponse(WebKit::WebURLLoader* loader,
+ const WebKit::WebURLResponse& response);
+ virtual void didDownloadData(WebKit::WebURLLoader* loader,
+ int data_length);
+ virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ const char* data,
+ int data_length);
+ virtual void didFinishLoading(WebKit::WebURLLoader* loader,
+ double finish_time);
+ virtual void didFail(WebKit::WebURLLoader* loader,
+ const WebKit::WebURLError& error);
+
+ // PluginInstance::Observer implementation.
+ virtual void InstanceDestroyed(PluginInstance* instance);
+
+ PPB_URLResponseInfo_Impl* response_info() const { return response_info_; }
+
+ private:
+ void RunCallback(int32_t result);
+ size_t FillUserBuffer();
+
+ // Converts a WebURLResponse to a URLResponseInfo and saves it.
+ void SaveResponse(const WebKit::WebURLResponse& response);
+
+ int32_t CanRequest(const WebKit::WebFrame* frame, const WebKit::WebURL& url);
+
+ // Calls the status_callback_ (if any) with the current upload and download
+ // progress. Call this function if you update any of these values to
+ // synchronize an out-of-process plugin's state.
+ void UpdateStatus();
+
+ // Returns true if the plugin has requested we record download or upload
+ // progress. When false, we don't need to update the counters. We go out of
+ // our way not to allow access to this information unless it's requested,
+ // even when it would be easier just to return it and not check, so that
+ // plugins don't depend on access without setting the flag.
+ bool RecordDownloadProgress() const;
+ bool RecordUploadProgress() const;
+
+ // This will be NULL if the instance has been deleted but this PPB_URLLoader_Impl was
+ // somehow leaked. In general, you should not need to check this for NULL.
+ // However, if you see a NULL pointer crash, that means somebody is holding
+ // a reference to this object longer than the PluginInstance's lifetime.
+ PluginInstance* instance_;
+
+ // If true, then the plugin instance is a full-frame plugin and we're just
+ // wrapping the main document's loader (i.e. loader_ is null).
+ bool main_document_loader_;
+ scoped_ptr<WebKit::WebURLLoader> loader_;
+ scoped_refptr<PPB_URLRequestInfo_Impl> request_info_;
+ scoped_refptr<PPB_URLResponseInfo_Impl> response_info_;
+ PP_CompletionCallback pending_callback_;
+ std::deque<char> buffer_;
+ int64_t bytes_sent_;
+ int64_t total_bytes_to_be_sent_;
+ int64_t bytes_received_;
+ int64_t total_bytes_to_be_received_;
+ char* user_buffer_;
+ size_t user_buffer_size_;
+ int32_t done_status_;
+
+ bool has_universal_access_;
+
+ PP_URLLoaderTrusted_StatusCallback status_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_URLLoader_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_URL_LOADER_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_url_request_info_impl.cc b/webkit/plugins/ppapi/ppb_url_request_info_impl.cc
new file mode 100644
index 0000000..1886af5
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_request_info_impl.cc
@@ -0,0 +1,287 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_url_request_info_impl.h"
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "googleurl/src/gurl.h"
+#include "net/http/http_util.h"
+#include "ppapi/c/pp_var.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/string.h"
+#include "webkit/plugins/ppapi/var.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebData;
+using WebKit::WebHTTPBody;
+using WebKit::WebString;
+using WebKit::WebFrame;
+using WebKit::WebURL;
+using WebKit::WebURLRequest;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// If any of these request headers are specified, they will not be sent.
+// TODO(darin): Add more based on security considerations?
+const char* const kIgnoredRequestHeaders[] = {
+ "content-length"
+};
+
+PP_Bool IsIgnoredRequestHeader(const std::string& name) {
+ for (size_t i = 0; i < arraysize(kIgnoredRequestHeaders); ++i) {
+ if (LowerCaseEqualsASCII(name, kIgnoredRequestHeaders[i]))
+ return PP_TRUE;
+ }
+ return PP_FALSE;
+}
+
+PP_Resource Create(PP_Module module_id) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return 0;
+
+ PPB_URLRequestInfo_Impl* request = new PPB_URLRequestInfo_Impl(module);
+
+ return request->GetReference();
+}
+
+PP_Bool IsURLRequestInfo(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_URLRequestInfo_Impl>(resource));
+}
+
+PP_Bool SetProperty(PP_Resource request_id,
+ PP_URLRequestProperty property,
+ PP_Var var) {
+ scoped_refptr<PPB_URLRequestInfo_Impl> request(
+ Resource::GetAs<PPB_URLRequestInfo_Impl>(request_id));
+ if (!request)
+ return PP_FALSE;
+
+ if (var.type == PP_VARTYPE_BOOL) {
+ return BoolToPPBool(
+ request->SetBooleanProperty(property,
+ PPBoolToBool(var.value.as_bool)));
+ }
+
+ if (var.type == PP_VARTYPE_STRING) {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
+ if (string) {
+ return BoolToPPBool(request->SetStringProperty(property,
+ string->value()));
+ }
+ }
+
+ return PP_FALSE;
+}
+
+PP_Bool AppendDataToBody(PP_Resource request_id,
+ const char* data,
+ uint32_t len) {
+ scoped_refptr<PPB_URLRequestInfo_Impl> request(
+ Resource::GetAs<PPB_URLRequestInfo_Impl>(request_id));
+ if (!request)
+ return PP_FALSE;
+
+ return BoolToPPBool(request->AppendDataToBody(std::string(data, len)));
+}
+
+PP_Bool AppendFileToBody(PP_Resource request_id,
+ PP_Resource file_ref_id,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time) {
+ scoped_refptr<PPB_URLRequestInfo_Impl> request(
+ Resource::GetAs<PPB_URLRequestInfo_Impl>(request_id));
+ if (!request)
+ return PP_FALSE;
+
+ scoped_refptr<PPB_FileRef_Impl> file_ref(
+ Resource::GetAs<PPB_FileRef_Impl>(file_ref_id));
+ if (!file_ref)
+ return PP_FALSE;
+
+ return BoolToPPBool(request->AppendFileToBody(file_ref,
+ start_offset,
+ number_of_bytes,
+ expected_last_modified_time));
+}
+
+const PPB_URLRequestInfo ppb_urlrequestinfo = {
+ &Create,
+ &IsURLRequestInfo,
+ &SetProperty,
+ &AppendDataToBody,
+ &AppendFileToBody
+};
+
+} // namespace
+
+struct PPB_URLRequestInfo_Impl::BodyItem {
+ BodyItem(const std::string& data)
+ : data(data),
+ start_offset(0),
+ number_of_bytes(-1),
+ expected_last_modified_time(0.0) {
+ }
+
+ BodyItem(PPB_FileRef_Impl* file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time)
+ : file_ref(file_ref),
+ start_offset(start_offset),
+ number_of_bytes(number_of_bytes),
+ expected_last_modified_time(expected_last_modified_time) {
+ }
+
+ std::string data;
+ scoped_refptr<PPB_FileRef_Impl> file_ref;
+ int64_t start_offset;
+ int64_t number_of_bytes;
+ PP_Time expected_last_modified_time;
+};
+
+PPB_URLRequestInfo_Impl::PPB_URLRequestInfo_Impl(PluginModule* module)
+ : Resource(module),
+ stream_to_file_(false),
+ follow_redirects_(true),
+ record_download_progress_(false),
+ record_upload_progress_(false) {
+}
+
+PPB_URLRequestInfo_Impl::~PPB_URLRequestInfo_Impl() {
+}
+
+// static
+const PPB_URLRequestInfo* PPB_URLRequestInfo_Impl::GetInterface() {
+ return &ppb_urlrequestinfo;
+}
+
+PPB_URLRequestInfo_Impl* PPB_URLRequestInfo_Impl::AsPPB_URLRequestInfo_Impl() {
+ return this;
+}
+
+bool PPB_URLRequestInfo_Impl::SetBooleanProperty(PP_URLRequestProperty property,
+ bool value) {
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_STREAMTOFILE:
+ stream_to_file_ = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS:
+ follow_redirects_ = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS:
+ record_download_progress_ = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS:
+ record_upload_progress_ = value;
+ return true;
+ default:
+ //NOTIMPLEMENTED(); // TODO(darin): Implement me!
+ return false;
+ }
+}
+
+bool PPB_URLRequestInfo_Impl::SetStringProperty(PP_URLRequestProperty property,
+ const std::string& value) {
+ // TODO(darin): Validate input. Perhaps at a different layer?
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_URL:
+ url_ = value; // NOTE: This may be a relative URL.
+ return true;
+ case PP_URLREQUESTPROPERTY_METHOD:
+ method_ = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_HEADERS:
+ headers_ = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool PPB_URLRequestInfo_Impl::AppendDataToBody(const std::string& data) {
+ if (!data.empty())
+ body_.push_back(BodyItem(data));
+ return true;
+}
+
+bool PPB_URLRequestInfo_Impl::AppendFileToBody(
+ PPB_FileRef_Impl* file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time) {
+ // Ignore a call to append nothing.
+ if (number_of_bytes == 0)
+ return true;
+
+ // Check for bad values. (-1 means read until end of file.)
+ if (start_offset < 0 || number_of_bytes < -1)
+ return false;
+
+ body_.push_back(BodyItem(file_ref,
+ start_offset,
+ number_of_bytes,
+ expected_last_modified_time));
+ return true;
+}
+
+WebURLRequest PPB_URLRequestInfo_Impl::ToWebURLRequest(WebFrame* frame) const {
+ WebURLRequest web_request;
+ web_request.initialize();
+ web_request.setURL(frame->document().completeURL(WebString::fromUTF8(url_)));
+ web_request.setDownloadToFile(stream_to_file_);
+
+ if (!method_.empty())
+ web_request.setHTTPMethod(WebString::fromUTF8(method_));
+
+ if (!headers_.empty()) {
+ net::HttpUtil::HeadersIterator it(headers_.begin(), headers_.end(), "\n");
+ while (it.GetNext()) {
+ if (!IsIgnoredRequestHeader(it.name())) {
+ web_request.addHTTPHeaderField(
+ WebString::fromUTF8(it.name()),
+ WebString::fromUTF8(it.values()));
+ }
+ }
+ }
+
+ if (!body_.empty()) {
+ WebHTTPBody http_body;
+ http_body.initialize();
+ for (size_t i = 0; i < body_.size(); ++i) {
+ if (body_[i].file_ref) {
+ http_body.appendFileRange(
+ webkit_glue::FilePathToWebString(
+ body_[i].file_ref->GetSystemPath()),
+ body_[i].start_offset,
+ body_[i].number_of_bytes,
+ body_[i].expected_last_modified_time);
+ } else {
+ DCHECK(!body_[i].data.empty());
+ http_body.appendData(WebData(body_[i].data));
+ }
+ }
+ web_request.setHTTPBody(http_body);
+ }
+
+ frame->setReferrerForRequest(web_request, WebURL()); // Use default.
+ return web_request;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_url_request_info_impl.h b/webkit/plugins/ppapi/ppb_url_request_info_impl.h
new file mode 100644
index 0000000..a55edfe
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_request_info_impl.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_URL_REQUEST_INFO_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_URL_REQUEST_INFO_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "ppapi/c/ppb_url_request_info.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace WebKit {
+class WebFrame;
+class WebURLRequest;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_FileRef_Impl;
+
+class PPB_URLRequestInfo_Impl : public Resource {
+ public:
+ explicit PPB_URLRequestInfo_Impl(PluginModule* module);
+ virtual ~PPB_URLRequestInfo_Impl();
+
+ // Returns a pointer to the interface implementing PPB_URLRequestInfo that is
+ // exposed to the plugin.
+ static const PPB_URLRequestInfo* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_URLRequestInfo_Impl* AsPPB_URLRequestInfo_Impl();
+
+ // PPB_URLRequestInfo implementation.
+ bool SetBooleanProperty(PP_URLRequestProperty property, bool value);
+ bool SetStringProperty(PP_URLRequestProperty property,
+ const std::string& value);
+ bool AppendDataToBody(const std::string& data);
+ bool AppendFileToBody(PPB_FileRef_Impl* file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time);
+
+ WebKit::WebURLRequest ToWebURLRequest(WebKit::WebFrame* frame) const;
+
+ bool follow_redirects() { return follow_redirects_; }
+
+ bool record_download_progress() const { return record_download_progress_; }
+ bool record_upload_progress() const { return record_upload_progress_; }
+
+ private:
+ struct BodyItem;
+ typedef std::vector<BodyItem> Body;
+
+ std::string url_;
+ std::string method_;
+ std::string headers_;
+ Body body_;
+
+ bool stream_to_file_;
+ bool follow_redirects_;
+ bool record_download_progress_;
+ bool record_upload_progress_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_URLRequestInfo_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_URL_REQUEST_INFO_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_url_response_info_impl.cc b/webkit/plugins/ppapi/ppb_url_response_info_impl.cc
new file mode 100644
index 0000000..43e3d9e
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_response_info_impl.cc
@@ -0,0 +1,146 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_url_response_info_impl.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_var.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/var.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebHTTPHeaderVisitor;
+using WebKit::WebString;
+using WebKit::WebURLResponse;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+class HeaderFlattener : public WebHTTPHeaderVisitor {
+ public:
+ const std::string& buffer() const { return buffer_; }
+
+ virtual void visitHeader(const WebString& name, const WebString& value) {
+ if (!buffer_.empty())
+ buffer_.append("\n");
+ buffer_.append(name.utf8());
+ buffer_.append(": ");
+ buffer_.append(value.utf8());
+ }
+
+ private:
+ std::string buffer_;
+};
+
+PP_Bool IsURLResponseInfo(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_URLResponseInfo_Impl>(resource));
+}
+
+PP_Var GetProperty(PP_Resource response_id,
+ PP_URLResponseProperty property) {
+ scoped_refptr<PPB_URLResponseInfo_Impl> response(
+ Resource::GetAs<PPB_URLResponseInfo_Impl>(response_id));
+ if (!response)
+ return PP_MakeUndefined();
+
+ return response->GetProperty(property);
+}
+
+PP_Resource GetBody(PP_Resource response_id) {
+ scoped_refptr<PPB_URLResponseInfo_Impl> response(
+ Resource::GetAs<PPB_URLResponseInfo_Impl>(response_id));
+ if (!response.get())
+ return 0;
+
+ PPB_FileRef_Impl* body = response->body();
+ if (!body)
+ return 0;
+ body->AddRef(); // AddRef for the caller.
+
+ return body->GetReference();
+}
+
+const PPB_URLResponseInfo ppb_urlresponseinfo = {
+ &IsURLResponseInfo,
+ &GetProperty,
+ &GetBody
+};
+
+bool IsRedirect(int32_t status) {
+ return status >= 300 && status <= 399;
+}
+
+} // namespace
+
+PPB_URLResponseInfo_Impl::PPB_URLResponseInfo_Impl(PluginModule* module)
+ : Resource(module),
+ status_code_(-1) {
+}
+
+PPB_URLResponseInfo_Impl::~PPB_URLResponseInfo_Impl() {
+}
+
+// static
+const PPB_URLResponseInfo* PPB_URLResponseInfo_Impl::GetInterface() {
+ return &ppb_urlresponseinfo;
+}
+
+PPB_URLResponseInfo_Impl*
+PPB_URLResponseInfo_Impl::AsPPB_URLResponseInfo_Impl() {
+ return this;
+}
+
+PP_Var PPB_URLResponseInfo_Impl::GetProperty(PP_URLResponseProperty property) {
+ switch (property) {
+ case PP_URLRESPONSEPROPERTY_URL:
+ return StringVar::StringToPPVar(module(), url_);
+ case PP_URLRESPONSEPROPERTY_REDIRECTURL:
+ if (IsRedirect(status_code_))
+ return StringVar::StringToPPVar(module(), redirect_url_);
+ break;
+ case PP_URLRESPONSEPROPERTY_REDIRECTMETHOD:
+ if (IsRedirect(status_code_))
+ return StringVar::StringToPPVar(module(), status_text_);
+ break;
+ case PP_URLRESPONSEPROPERTY_STATUSCODE:
+ return PP_MakeInt32(status_code_);
+ case PP_URLRESPONSEPROPERTY_STATUSLINE:
+ return StringVar::StringToPPVar(module(), status_text_);
+ case PP_URLRESPONSEPROPERTY_HEADERS:
+ return StringVar::StringToPPVar(module(), headers_);
+ }
+ // The default is to return an undefined PP_Var.
+ return PP_MakeUndefined();
+}
+
+bool PPB_URLResponseInfo_Impl::Initialize(const WebURLResponse& response) {
+ url_ = response.url().spec();
+ status_code_ = response.httpStatusCode();
+ status_text_ = response.httpStatusText().utf8();
+ if (IsRedirect(status_code_)) {
+ redirect_url_ = response.httpHeaderField(
+ WebString::fromUTF8("Location")).utf8();
+ }
+
+ HeaderFlattener flattener;
+ response.visitHTTPHeaderFields(&flattener);
+ headers_ = flattener.buffer();
+
+ WebString file_path = response.downloadFilePath();
+ if (!file_path.isEmpty())
+ body_ = new PPB_FileRef_Impl(module(),
+ webkit_glue::WebStringToFilePath(file_path));
+ return true;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_url_response_info_impl.h b/webkit/plugins/ppapi/ppb_url_response_info_impl.h
new file mode 100644
index 0000000..ee12d35c
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_response_info_impl.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_URL_RESPONSE_INFO_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_URL_RESPONSE_INFO_IMPL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/ppb_url_response_info.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace WebKit {
+class WebURLResponse;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_FileRef_Impl;
+
+class PPB_URLResponseInfo_Impl : public Resource {
+ public:
+ explicit PPB_URLResponseInfo_Impl(PluginModule* module);
+ virtual ~PPB_URLResponseInfo_Impl();
+
+ // Returns a pointer to the interface implementing PPB_URLResponseInfo that
+ // is exposed to the plugin.
+ static const PPB_URLResponseInfo* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_URLResponseInfo_Impl* AsPPB_URLResponseInfo_Impl();
+
+ // PPB_URLResponseInfo implementation.
+ PP_Var GetProperty(PP_URLResponseProperty property);
+
+ bool Initialize(const WebKit::WebURLResponse& response);
+
+ PPB_FileRef_Impl* body() { return body_; }
+
+ std::string redirect_url() { return redirect_url_; }
+
+ private:
+ std::string url_;
+ std::string headers_;
+ int32_t status_code_;
+ std::string status_text_;
+ std::string redirect_url_;
+ scoped_refptr<PPB_FileRef_Impl> body_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_URLResponseInfo_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_URL_RESPONSE_INFO_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_url_util_impl.cc b/webkit/plugins/ppapi/ppb_url_util_impl.cc
new file mode 100644
index 0000000..47980e4
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_util_impl.cc
@@ -0,0 +1,180 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_url_util_impl.h"
+
+#include "googleurl/src/gurl.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/string.h"
+#include "webkit/plugins/ppapi/var.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+void ConvertComponent(const url_parse::Component& input,
+ PP_UrlComponent_Dev* output) {
+ output->begin = input.begin;
+ output->len = input.len;
+}
+
+// Output can be NULL to specify "do nothing." This rule is followed by all the
+// url util functions, so we implement it once here.
+void ConvertComponents(const url_parse::Parsed& input,
+ PP_UrlComponents_Dev* output) {
+ if (!output)
+ return;
+
+ ConvertComponent(input.scheme, &output->scheme);
+ ConvertComponent(input.username, &output->username);
+ ConvertComponent(input.password, &output->password);
+ ConvertComponent(input.host, &output->host);
+ ConvertComponent(input.port, &output->port);
+ ConvertComponent(input.path, &output->path);
+ ConvertComponent(input.query, &output->query);
+ ConvertComponent(input.ref, &output->ref);
+}
+
+// Used for returning the given GURL from a PPAPI function, with an optional
+// out param indicating the components.
+PP_Var GenerateUrlReturn(PluginModule* module, const GURL& url,
+ PP_UrlComponents_Dev* components) {
+ if (!url.is_valid())
+ return PP_MakeNull();
+ ConvertComponents(url.parsed_for_possibly_invalid_spec(), components);
+ return StringVar::StringToPPVar(module, url.possibly_invalid_spec());
+}
+
+// Sets |*security_origin| to be the WebKit security origin associated with the
+// document containing the given plugin instance. On success, returns true. If
+// the instance is invalid, returns false and |*security_origin| will be
+// unchanged.
+bool SecurityOriginForInstance(PP_Instance instance_id,
+ WebKit::WebSecurityOrigin* security_origin) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return false;
+
+ WebKit::WebElement plugin_element = instance->container()->element();
+ WebKit::WebFrame* plugin_frame = plugin_element.document().frame();
+ if (!plugin_frame)
+ return false;
+
+ *security_origin = plugin_frame->securityOrigin();
+ return true;
+}
+
+PP_Var Canonicalize(PP_Var url, PP_UrlComponents_Dev* components) {
+ scoped_refptr<StringVar> url_string(StringVar::FromPPVar(url));
+ if (!url_string)
+ return PP_MakeNull();
+ return GenerateUrlReturn(url_string->module(),
+ GURL(url_string->value()), components);
+}
+
+PP_Var ResolveRelativeToUrl(PP_Var base_url,
+ PP_Var relative,
+ PP_UrlComponents_Dev* components) {
+ scoped_refptr<StringVar> base_url_string(StringVar::FromPPVar(base_url));
+ scoped_refptr<StringVar> relative_string(StringVar::FromPPVar(relative));
+ if (!base_url_string || !relative_string)
+ return PP_MakeNull();
+
+ GURL base_gurl(base_url_string->value());
+ if (!base_gurl.is_valid())
+ return PP_MakeNull();
+ return GenerateUrlReturn(base_url_string->module(),
+ base_gurl.Resolve(relative_string->value()),
+ components);
+}
+
+PP_Var ResolveRelativeToDocument(PP_Instance instance_id,
+ PP_Var relative,
+ PP_UrlComponents_Dev* components) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return PP_MakeNull();
+
+ scoped_refptr<StringVar> relative_string(StringVar::FromPPVar(relative));
+ if (!relative_string)
+ return PP_MakeNull();
+
+ WebKit::WebElement plugin_element = instance->container()->element();
+ GURL document_url = plugin_element.document().baseURL();
+ return GenerateUrlReturn(instance->module(),
+ document_url.Resolve(relative_string->value()),
+ components);
+}
+
+PP_Bool IsSameSecurityOrigin(PP_Var url_a, PP_Var url_b) {
+ scoped_refptr<StringVar> url_a_string(StringVar::FromPPVar(url_a));
+ scoped_refptr<StringVar> url_b_string(StringVar::FromPPVar(url_b));
+ if (!url_a_string || !url_b_string)
+ return PP_FALSE;
+
+ GURL gurl_a(url_a_string->value());
+ GURL gurl_b(url_b_string->value());
+ if (!gurl_a.is_valid() || !gurl_b.is_valid())
+ return PP_FALSE;
+
+ return BoolToPPBool(gurl_a.GetOrigin() == gurl_b.GetOrigin());
+}
+
+PP_Bool DocumentCanRequest(PP_Instance instance, PP_Var url) {
+ scoped_refptr<StringVar> url_string(StringVar::FromPPVar(url));
+ if (!url_string)
+ return PP_FALSE;
+
+ WebKit::WebSecurityOrigin security_origin;
+ if (!SecurityOriginForInstance(instance, &security_origin))
+ return PP_FALSE;
+
+ GURL gurl(url_string->value());
+ if (!gurl.is_valid())
+ return PP_FALSE;
+
+ return BoolToPPBool(security_origin.canRequest(gurl));
+}
+
+PP_Bool DocumentCanAccessDocument(PP_Instance active, PP_Instance target) {
+ WebKit::WebSecurityOrigin active_origin;
+ if (!SecurityOriginForInstance(active, &active_origin))
+ return PP_FALSE;
+
+ WebKit::WebSecurityOrigin target_origin;
+ if (!SecurityOriginForInstance(active, &target_origin))
+ return PP_FALSE;
+
+ return BoolToPPBool(active_origin.canAccess(target_origin));
+}
+
+} // namespace
+
+const PPB_UrlUtil_Dev ppb_url_util = {
+ &Canonicalize,
+ &ResolveRelativeToUrl,
+ &ResolveRelativeToDocument,
+ &IsSameSecurityOrigin,
+ &DocumentCanRequest,
+ &DocumentCanAccessDocument
+};
+
+// static
+const PPB_UrlUtil_Dev* PPB_UrlUtil_Impl::GetInterface() {
+ return &ppb_url_util;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_url_util_impl.h b/webkit/plugins/ppapi/ppb_url_util_impl.h
new file mode 100644
index 0000000..8cba6a9
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_url_util_impl.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_URL_UTIL_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_URL_UTIL_IMPL_H_
+
+struct PPB_UrlUtil_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_UrlUtil_Impl {
+ public:
+ static const PPB_UrlUtil_Dev* GetInterface();
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_URL_UTIL_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_video_decoder_impl.cc b/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
new file mode 100644
index 0000000..bd7f204
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_video_decoder_impl.h"
+
+#include "base/logging.h"
+#include "ppapi/c/dev/pp_video_dev.h"
+#include "ppapi/c/dev/ppb_video_decoder_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Bool GetConfig(PP_Instance instance_id,
+ PP_VideoCodecId_Dev codec,
+ PP_VideoConfig_Dev* configs,
+ int32_t config_size,
+ int32_t *num_config) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ *num_config = 0;
+ if (!instance)
+ return PP_FALSE;
+
+ // Get configs based on codec.
+
+ if (configs) {
+ // Fill in the array of configs.
+ }
+
+ // Update *num_config.
+
+ return PP_TRUE;
+}
+
+PP_Resource Create(PP_Instance instance_id,
+ const PP_VideoDecoderConfig_Dev* decoder_config) {
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ scoped_refptr<PPB_VideoDecoder_Impl> decoder(
+ new PPB_VideoDecoder_Impl(instance));
+
+ if (!decoder->Init(*decoder_config))
+ return 0;
+
+ return decoder->GetReference();
+}
+
+PP_Bool Decode(PP_Resource decoder_id,
+ PP_VideoCompressedDataBuffer_Dev* input_buffer) {
+ scoped_refptr<PPB_VideoDecoder_Impl> decoder(
+ Resource::GetAs<PPB_VideoDecoder_Impl>(decoder_id));
+ if (!decoder)
+ return PP_FALSE;
+
+ decoder->Decode(*input_buffer);
+ return PP_TRUE;
+}
+
+int32_t Flush(PP_Resource decoder_id, PP_CompletionCallback callback) {
+ scoped_refptr<PPB_VideoDecoder_Impl> decoder(
+ Resource::GetAs<PPB_VideoDecoder_Impl>(decoder_id));
+ if (!decoder)
+ return PP_ERROR_BADRESOURCE;
+
+ return decoder->Flush(callback);
+}
+
+PP_Bool ReturnUncompressedDataBuffer(
+ PP_Resource decoder_id,
+ PP_VideoUncompressedDataBuffer_Dev* buffer) {
+ scoped_refptr<PPB_VideoDecoder_Impl> decoder(
+ Resource::GetAs<PPB_VideoDecoder_Impl>(decoder_id));
+ if (!decoder)
+ return PP_FALSE;
+
+ return BoolToPPBool(decoder->ReturnUncompressedDataBuffer(*buffer));
+}
+
+const PPB_VideoDecoder_Dev ppb_videodecoder = {
+ &GetConfig,
+ &Create,
+ &Decode,
+ &Flush,
+ &ReturnUncompressedDataBuffer
+};
+
+} // namespace
+
+PPB_VideoDecoder_Impl::PPB_VideoDecoder_Impl(PluginInstance* instance)
+ : Resource(instance->module()),
+ instance_(instance) {
+}
+
+PPB_VideoDecoder_Impl::~PPB_VideoDecoder_Impl() {
+}
+
+// static
+const PPB_VideoDecoder_Dev* PPB_VideoDecoder_Impl::GetInterface() {
+ return &ppb_videodecoder;
+}
+
+PPB_VideoDecoder_Impl* PPB_VideoDecoder_Impl::AsPPB_VideoDecoder_Impl() {
+ return this;
+}
+
+bool PPB_VideoDecoder_Impl::Init(
+ const PP_VideoDecoderConfig_Dev& decoder_config) {
+ if (!instance())
+ return false;
+
+ platform_video_decoder_.reset(
+ instance()->delegate()->CreateVideoDecoder(decoder_config));
+
+ return platform_video_decoder_.get()? true : false;
+}
+
+bool PPB_VideoDecoder_Impl::Decode(
+ PP_VideoCompressedDataBuffer_Dev& input_buffer) {
+ if (!platform_video_decoder_.get())
+ return false;
+
+ return platform_video_decoder_->Decode(input_buffer);
+}
+
+int32_t PPB_VideoDecoder_Impl::Flush(PP_CompletionCallback& callback) {
+ if (!platform_video_decoder_.get())
+ return PP_ERROR_FAILED;
+
+ return platform_video_decoder_->Flush(callback);
+}
+
+bool PPB_VideoDecoder_Impl::ReturnUncompressedDataBuffer(
+ PP_VideoUncompressedDataBuffer_Dev& buffer) {
+ if (!platform_video_decoder_.get())
+ return false;
+
+ return platform_video_decoder_->ReturnUncompressedDataBuffer(buffer);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_video_decoder_impl.h b/webkit/plugins/ppapi/ppb_video_decoder_impl.h
new file mode 100644
index 0000000..169ebed
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_video_decoder_impl.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_VIDEO_DECODER_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_VIDEO_DECODER_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PP_VideoDecoderConfig_Dev;
+struct PP_VideoCompressedDataBuffer_Dev;
+struct PP_VideoUncompressedDataBuffer_Dev;
+struct PPB_VideoDecoder_Dev;
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+
+class PPB_VideoDecoder_Impl : public Resource {
+ public:
+ PPB_VideoDecoder_Impl(PluginInstance* instance);
+ virtual ~PPB_VideoDecoder_Impl();
+
+ // Returns a pointer to the interface implementing PPB_VideoDecoder that is
+ // exposed to the plugin.
+ static const PPB_VideoDecoder_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_VideoDecoder_Impl* AsPPB_VideoDecoder_Impl();
+
+ PluginInstance* instance() { return instance_.get(); }
+
+ // PPB_VideoDecoder implementation.
+ bool Init(const PP_VideoDecoderConfig_Dev& decoder_config);
+ bool Decode(PP_VideoCompressedDataBuffer_Dev& input_buffer);
+ int32_t Flush(PP_CompletionCallback& callback);
+ bool ReturnUncompressedDataBuffer(PP_VideoUncompressedDataBuffer_Dev& buffer);
+
+ private:
+ // This is NULL before initialization, and if this PPB_VideoDecoder_Impl is
+ // swapped with another.
+ scoped_ptr<PluginDelegate::PlatformVideoDecoder> platform_video_decoder_;
+ scoped_refptr<PluginInstance> instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_VideoDecoder_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_VIDEO_DECODER_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppb_widget_impl.cc b/webkit/plugins/ppapi/ppb_widget_impl.cc
new file mode 100644
index 0000000..57491b5
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_widget_impl.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppb_widget_impl.h"
+
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_widget_dev.h"
+#include "ppapi/c/dev/ppp_widget_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+PP_Bool IsWidget(PP_Resource resource) {
+ return BoolToPPBool(!!Resource::GetAs<PPB_Widget_Impl>(resource));
+}
+
+PP_Bool Paint(PP_Resource resource,
+ const PP_Rect* rect,
+ PP_Resource image_id) {
+ scoped_refptr<PPB_Widget_Impl> widget(
+ Resource::GetAs<PPB_Widget_Impl>(resource));
+ if (!widget)
+ return PP_FALSE;
+
+ scoped_refptr<PPB_ImageData_Impl> image(
+ Resource::GetAs<PPB_ImageData_Impl>(image_id));
+ if (!image)
+ return PP_FALSE;
+
+ return BoolToPPBool(widget->Paint(rect, image));
+}
+
+PP_Bool HandleEvent(PP_Resource resource, const PP_InputEvent* event) {
+ scoped_refptr<PPB_Widget_Impl> widget(
+ Resource::GetAs<PPB_Widget_Impl>(resource));
+ return BoolToPPBool(widget && widget->HandleEvent(event));
+}
+
+PP_Bool GetLocation(PP_Resource resource, PP_Rect* location) {
+ scoped_refptr<PPB_Widget_Impl> widget(
+ Resource::GetAs<PPB_Widget_Impl>(resource));
+ return BoolToPPBool(widget && widget->GetLocation(location));
+}
+
+void SetLocation(PP_Resource resource, const PP_Rect* location) {
+ scoped_refptr<PPB_Widget_Impl> widget(
+ Resource::GetAs<PPB_Widget_Impl>(resource));
+ if (widget)
+ widget->SetLocation(location);
+}
+
+const PPB_Widget_Dev ppb_widget = {
+ &IsWidget,
+ &Paint,
+ &HandleEvent,
+ &GetLocation,
+ &SetLocation,
+};
+
+} // namespace
+
+PPB_Widget_Impl::PPB_Widget_Impl(PluginInstance* instance)
+ : Resource(instance->module()),
+ instance_(instance) {
+}
+
+PPB_Widget_Impl::~PPB_Widget_Impl() {
+}
+
+// static
+const PPB_Widget_Dev* PPB_Widget_Impl::GetInterface() {
+ return &ppb_widget;
+}
+
+PPB_Widget_Impl* PPB_Widget_Impl::AsPPB_Widget_Impl() {
+ return this;
+}
+
+bool PPB_Widget_Impl::GetLocation(PP_Rect* location) {
+ *location = location_;
+ return true;
+}
+
+void PPB_Widget_Impl::SetLocation(const PP_Rect* location) {
+ location_ = *location;
+ SetLocationInternal(location);
+}
+
+void PPB_Widget_Impl::Invalidate(const PP_Rect* dirty) {
+ const PPP_Widget_Dev* widget = static_cast<const PPP_Widget_Dev*>(
+ module()->GetPluginInterface(PPP_WIDGET_DEV_INTERFACE));
+ if (!widget)
+ return;
+ ScopedResourceId resource(this);
+ widget->Invalidate(instance_->pp_instance(), resource.id, dirty);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/ppb_widget_impl.h b/webkit/plugins/ppapi/ppb_widget_impl.h
new file mode 100644
index 0000000..1cd9761
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_widget_impl.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPB_WIDGET_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_WIDGET_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ppapi/c/pp_rect.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PPB_Widget_Dev;
+struct PP_InputEvent;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_ImageData_Impla;
+class PluginInstance;
+
+class PPB_Widget_Impl : public Resource {
+ public:
+ explicit PPB_Widget_Impl(PluginInstance* instance);
+ virtual ~PPB_Widget_Impl();
+
+ // Returns a pointer to the interface implementing PPB_Widget that is
+ // exposed to the plugin.
+ static const PPB_Widget_Dev* GetInterface();
+
+ // Resource overrides.
+ virtual PPB_Widget_Impl* AsPPB_Widget_Impl();
+
+ // PPB_Widget implementation.
+ virtual bool Paint(const PP_Rect* rect, PPB_ImageData_Impl* image) = 0;
+ virtual bool HandleEvent(const PP_InputEvent* event) = 0;
+ bool GetLocation(PP_Rect* location);
+ void SetLocation(const PP_Rect* location);
+
+ // Notifies the plugin instance that the given rect needs to be repainted.
+ void Invalidate(const PP_Rect* dirty);
+ PluginInstance* instance() { return instance_; }
+
+ protected:
+ virtual void SetLocationInternal(const PP_Rect* location) = 0;
+ PP_Rect location() const { return location_; }
+
+ private:
+ scoped_refptr<PluginInstance> instance_;
+ PP_Rect location_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Widget_Impl);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_WIDGET_IMPL_H_
diff --git a/webkit/plugins/ppapi/ppp_pdf.h b/webkit/plugins/ppapi/ppp_pdf.h
new file mode 100644
index 0000000..6405225
--- /dev/null
+++ b/webkit/plugins/ppapi/ppp_pdf.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_PPP_PDF_H_
+#define WEBKIT_PLUGINS_PPAPI_PPP_PDF_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_var.h"
+
+#define PPP_PDF_INTERFACE "PPP_Pdf;1"
+
+struct PPP_Pdf {
+ // Returns an absolute URL if the position is over a link.
+ PP_Var (*GetLinkAtPosition)(PP_Instance instance,
+ PP_Point point);
+};
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPP_PDF_H_
diff --git a/webkit/plugins/ppapi/resource.cc b/webkit/plugins/ppapi/resource.cc
new file mode 100644
index 0000000..0f8fbf9
--- /dev/null
+++ b/webkit/plugins/ppapi/resource.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/resource.h"
+
+#include "base/logging.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+Resource::Resource(PluginModule* module)
+ : resource_id_(0), module_(module) {
+}
+
+Resource::~Resource() {
+}
+
+PP_Resource Resource::GetReference() {
+ ResourceTracker *tracker = ResourceTracker::Get();
+ if (resource_id_)
+ tracker->AddRefResource(resource_id_);
+ else
+ resource_id_ = tracker->AddResource(this);
+ return resource_id_;
+}
+
+PP_Resource Resource::GetReferenceNoAddRef() const {
+ return resource_id_;
+}
+
+void Resource::StoppedTracking() {
+ DCHECK(resource_id_ != 0);
+ resource_id_ = 0;
+}
+
+#define DEFINE_TYPE_GETTER(RESOURCE) \
+ RESOURCE* Resource::As##RESOURCE() { return NULL; }
+FOR_ALL_RESOURCES(DEFINE_TYPE_GETTER)
+#undef DEFINE_TYPE_GETTER
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/resource.h b/webkit/plugins/ppapi/resource.h
new file mode 100644
index 0000000..45f114c
--- /dev/null
+++ b/webkit/plugins/ppapi/resource.h
@@ -0,0 +1,141 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_RESOURCE_H_
+#define WEBKIT_PLUGINS_PPAPI_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "ppapi/c/pp_resource.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+// If you inherit from resource, make sure you add the class name here.
+#define FOR_ALL_RESOURCES(F) \
+ F(MockResource) \
+ F(ObjectVar) \
+ F(PPB_AudioConfig_Impl) \
+ F(PPB_Audio_Impl) \
+ F(PPB_Buffer_Impl) \
+ F(PPB_DirectoryReader_Impl) \
+ F(PPB_FileChooser_Impl) \
+ F(PPB_FileIO_Impl) \
+ F(PPB_FileRef_Impl) \
+ F(PPB_FileSystem_Impl) \
+ F(PPB_Font_Impl) \
+ F(PPB_Graphics2D_Impl) \
+ F(PPB_Graphics3D_Impl) \
+ F(PPB_ImageData_Impl) \
+ F(PPB_Scrollbar_Impl) \
+ F(PPB_Transport_Impl) \
+ F(PPB_URLLoader_Impl) \
+ F(PPB_URLRequestInfo_Impl) \
+ F(PPB_URLResponseInfo_Impl) \
+ F(PPB_VideoDecoder_Impl) \
+ F(PPB_Widget_Impl) \
+ F(PrivateFontFile) \
+ F(StringVar) \
+ F(Var) \
+ F(VarObjectClass)
+
+// Forward declaration of Resource classes.
+#define DECLARE_RESOURCE_CLASS(RESOURCE) class RESOURCE;
+FOR_ALL_RESOURCES(DECLARE_RESOURCE_CLASS)
+#undef DECLARE_RESOURCE_CLASS
+
+class Resource : public base::RefCountedThreadSafe<Resource> {
+ public:
+ explicit Resource(PluginModule* module);
+ virtual ~Resource();
+
+ // Returns NULL if the resource is invalid or is a different type.
+ template<typename T>
+ static scoped_refptr<T> GetAs(PP_Resource res) {
+ scoped_refptr<Resource> resource = ResourceTracker::Get()->GetResource(res);
+ return resource ? resource->Cast<T>() : NULL;
+ }
+
+ PluginModule* module() const { return module_; }
+
+ // Cast the resource into a specified type. This will return NULL if the
+ // resource does not match the specified type. Specializations of this
+ // template call into As* functions.
+ template <typename T> T* Cast() { return NULL; }
+
+ // Returns an resource id of this object. If the object doesn't have a
+ // resource id, new one is created with plugin refcount of 1. If it does,
+ // the refcount is incremented. Use this when you need to return a new
+ // reference to the plugin.
+ PP_Resource GetReference();
+
+ // Returns the resource ID of this object OR NULL IF THERE IS NONE ASSIGNED.
+ // This will happen if the plugin doesn't have a reference to the given
+ // resource. The resource will not be addref'ed.
+ //
+ // This should only be used as an input parameter to the plugin for status
+ // updates in the proxy layer, where if the plugin has no reference, it will
+ // just give up since nothing needs to be updated.
+ //
+ // Generally you should use GetReference instead. This is why it has this
+ // obscure name rather than pp_resource().
+ PP_Resource GetReferenceNoAddRef() const;
+
+ // When you need to ensure that a resource has a reference, but you do not
+ // want to increase the refcount (for example, if you need to call a plugin
+ // callback function with a reference), you can use this class. For example:
+ //
+ // plugin_callback(.., ScopedResourceId(resource).id, ...);
+ class ScopedResourceId {
+ public:
+ explicit ScopedResourceId(Resource* resource)
+ : id(resource->GetReference()) {}
+ ~ScopedResourceId() {
+ ResourceTracker::Get()->UnrefResource(id);
+ }
+ const PP_Resource id;
+ };
+
+ private:
+ // Type-specific getters for individual resource types. These will return
+ // NULL if the resource does not match the specified type. Used by the Cast()
+ // function.
+ #define DEFINE_TYPE_GETTER(RESOURCE) \
+ virtual RESOURCE* As##RESOURCE();
+ FOR_ALL_RESOURCES(DEFINE_TYPE_GETTER)
+ #undef DEFINE_TYPE_GETTER
+
+ // If referenced by a plugin, holds the id of this resource object. Do not
+ // access this member directly, because it is possible that the plugin holds
+ // no references to the object, and therefore the resource_id_ is zero. Use
+ // either GetReference() to obtain a new resource_id and increase the
+ // refcount, or TemporaryReference when you do not want to increase the
+ // refcount.
+ PP_Resource resource_id_;
+
+ // Non-owning pointer to our module.
+ PluginModule* module_;
+
+ // Called by the resource tracker when the last plugin reference has been
+ // dropped.
+ friend class ResourceTracker;
+ void StoppedTracking();
+
+ DISALLOW_COPY_AND_ASSIGN(Resource);
+};
+
+// Cast() specializations.
+#define DEFINE_RESOURCE_CAST(Type) \
+ template <> inline Type* Resource::Cast<Type>() { \
+ return As##Type(); \
+ }
+
+FOR_ALL_RESOURCES(DEFINE_RESOURCE_CAST)
+#undef DEFINE_RESOURCE_CAST
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_RESOURCE_H_
diff --git a/webkit/plugins/ppapi/resource_tracker.cc b/webkit/plugins/ppapi/resource_tracker.cc
new file mode 100644
index 0000000..7f66160
--- /dev/null
+++ b/webkit/plugins/ppapi/resource_tracker.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/resource_tracker.h"
+
+#include <limits>
+#include <set>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "ppapi/c/pp_resource.h"
+#include "webkit/plugins/ppapi/resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+static base::LazyInstance<ResourceTracker> g_resource_tracker(
+ base::LINKER_INITIALIZED);
+
+scoped_refptr<Resource> ResourceTracker::GetResource(PP_Resource res) const {
+ ResourceMap::const_iterator result = live_resources_.find(res);
+ if (result == live_resources_.end()) {
+ return scoped_refptr<Resource>();
+ }
+ return result->second.first;
+}
+
+// static
+ResourceTracker* ResourceTracker::singleton_override_ = NULL;
+
+ResourceTracker::ResourceTracker()
+ : last_id_(0) {
+}
+
+ResourceTracker::~ResourceTracker() {
+}
+
+// static
+ResourceTracker* ResourceTracker::Get() {
+ if (singleton_override_)
+ return singleton_override_;
+ return g_resource_tracker.Pointer();
+}
+
+PP_Resource ResourceTracker::AddResource(Resource* resource) {
+ // If the plugin manages to create 4B resources...
+ if (last_id_ == std::numeric_limits<PP_Resource>::max()) {
+ return 0;
+ }
+ // Add the resource with plugin use-count 1.
+ ++last_id_;
+ live_resources_.insert(std::make_pair(last_id_, std::make_pair(resource, 1)));
+ return last_id_;
+}
+
+bool ResourceTracker::AddRefResource(PP_Resource res) {
+ ResourceMap::iterator i = live_resources_.find(res);
+ if (i != live_resources_.end()) {
+ // We don't protect against overflow, since a plugin as malicious as to ref
+ // once per every byte in the address space could have just as well unrefed
+ // one time too many.
+ ++i->second.second;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool ResourceTracker::UnrefResource(PP_Resource res) {
+ ResourceMap::iterator i = live_resources_.find(res);
+ if (i != live_resources_.end()) {
+ if (!--i->second.second) {
+ i->second.first->StoppedTracking();
+ live_resources_.erase(i);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void ResourceTracker::ForceDeletePluginResourceRefs(PP_Resource res) {
+ ResourceMap::iterator i = live_resources_.find(res);
+ if (i == live_resources_.end())
+ return; // Nothing to do.
+
+ i->second.second = 0;
+ i->second.first->StoppedTracking();
+ live_resources_.erase(i);
+}
+
+uint32 ResourceTracker::GetLiveObjectsForModule(PluginModule* module) const {
+ // Since this is for testing only, we'll just go through all of them and
+ // count.
+ //
+ // TODO(brettw) we will eventually need to implement more efficient
+ // module->resource lookup to free resources when a module is unloaded. In
+ // this case, this function can be implemented using that system.
+ uint32 count = 0;
+ for (ResourceMap::const_iterator i = live_resources_.begin();
+ i != live_resources_.end(); ++i)
+ count++;
+ return count;
+}
+
+PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) {
+#ifndef NDEBUG
+ // Make sure we're not adding one more than once.
+ for (InstanceMap::const_iterator i = instance_map_.begin();
+ i != instance_map_.end(); ++i)
+ DCHECK(i->second != instance);
+#endif
+
+ // Use a random 64-bit number for the instance ID. This helps prevent some
+ // mischeif where you could misallocate resources if you gave a different
+ // instance ID.
+ //
+ // See also AddModule below.
+ //
+ // Need to make sure the random number isn't a duplicate or 0.
+ PP_Instance new_instance;
+ do {
+ new_instance = static_cast<PP_Instance>(base::RandUint64());
+ } while (!new_instance ||
+ instance_map_.find(new_instance) != instance_map_.end());
+ instance_map_[new_instance] = instance;
+ return new_instance;
+}
+
+void ResourceTracker::InstanceDeleted(PP_Instance instance) {
+ InstanceMap::iterator found = instance_map_.find(instance);
+ if (found == instance_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+ instance_map_.erase(found);
+}
+
+PluginInstance* ResourceTracker::GetInstance(PP_Instance instance) {
+ InstanceMap::iterator found = instance_map_.find(instance);
+ if (found == instance_map_.end())
+ return NULL;
+ return found->second;
+}
+
+PP_Module ResourceTracker::AddModule(PluginModule* module) {
+#ifndef NDEBUG
+ // Make sure we're not adding one more than once.
+ for (ModuleMap::const_iterator i = module_map_.begin();
+ i != module_map_.end(); ++i)
+ DCHECK(i->second != module);
+#endif
+
+ // See AddInstance above.
+ PP_Module new_module;
+ do {
+ new_module = static_cast<PP_Module>(base::RandUint64());
+ } while (!new_module ||
+ module_map_.find(new_module) != module_map_.end());
+ module_map_[new_module] = module;
+ return new_module;
+}
+
+void ResourceTracker::ModuleDeleted(PP_Module module) {
+ ModuleMap::iterator found = module_map_.find(module);
+ if (found == module_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+ module_map_.erase(found);
+}
+
+PluginModule* ResourceTracker::GetModule(PP_Module module) {
+ ModuleMap::iterator found = module_map_.find(module);
+ if (found == module_map_.end())
+ return NULL;
+ return found->second;
+}
+
+// static
+void ResourceTracker::SetSingletonOverride(ResourceTracker* tracker) {
+ DCHECK(!singleton_override_);
+ singleton_override_ = tracker;
+}
+
+// static
+void ResourceTracker::ClearSingletonOverride() {
+ DCHECK(singleton_override_);
+ singleton_override_ = NULL;
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/resource_tracker.h b/webkit/plugins/ppapi/resource_tracker.h
new file mode 100644
index 0000000..7a5e002
--- /dev/null
+++ b/webkit/plugins/ppapi/resource_tracker.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_RESOURCE_TRACKER_H_
+#define WEBKIT_PLUGINS_PPAPI_RESOURCE_TRACKER_H_
+
+#include <map>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/hash_tables.h"
+#include "base/ref_counted.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+
+namespace base {
+template <typename T> struct DefaultLazyInstanceTraits;
+}
+
+namespace webkit {
+namespace ppapi {
+
+class PluginInstance;
+class PluginModule;
+class Resource;
+class ResourceTrackerTest;
+
+// This class maintains a global list of all live pepper resources. It allows
+// us to check resource ID validity and to map them to a specific module.
+//
+// This object is threadsafe.
+class ResourceTracker {
+ public:
+ // Returns the pointer to the singleton object.
+ static ResourceTracker* Get();
+
+ // PP_Resources --------------------------------------------------------------
+
+ // The returned pointer will be NULL if there is no resource. Note that this
+ // return value is a scoped_refptr so that we ensure the resource is valid
+ // from the point of the lookup to the point that the calling code needs it.
+ // Otherwise, the plugin could Release() the resource on another thread and
+ // the object will get deleted out from under us.
+ scoped_refptr<Resource> GetResource(PP_Resource res) const;
+
+ // Increment resource's plugin refcount. See ResourceAndRefCount comments
+ // below.
+ bool AddRefResource(PP_Resource res);
+ bool UnrefResource(PP_Resource res);
+
+ // Forces the plugin refcount of the given resource to 0. This can be used to
+ // delete an object the plugin has leaked or whose lifetime is otherwise
+ // exceeded.
+ //
+ // Note that this may not necessarily delete the resource object since the
+ // regular refcount is maintained separately from the plugin refcount and
+ // random components in the Pepper implementation could still have
+ // references to it.
+ void ForceDeletePluginResourceRefs(PP_Resource res);
+
+ // Returns the number of resources associated with this module.
+ //
+ // This is slow, use only for testing.
+ uint32 GetLiveObjectsForModule(PluginModule* module) const;
+
+ // PP_Modules ----------------------------------------------------------------
+
+ // Adds a new plugin module to the list of tracked module, and returns a new
+ // module handle to identify it.
+ PP_Module AddModule(PluginModule* module);
+
+ // Called when a plugin modulde was deleted and should no longer be tracked.
+ // The given handle should be one generated by AddModule.
+ void ModuleDeleted(PP_Module module);
+
+ // Returns a pointer to the plugin modulde object associated with the given
+ // modulde handle. The return value will be NULL if the handle is invalid.
+ PluginModule* GetModule(PP_Module module);
+
+ // PP_Instances --------------------------------------------------------------
+
+ // Adds a new plugin instance to the list of tracked instances, and returns a
+ // new instance handle to identify it.
+ PP_Instance AddInstance(PluginInstance* instance);
+
+ // Called when a plugin instance was deleted and should no longer be tracked.
+ // The given handle should be one generated by AddInstance.
+ void InstanceDeleted(PP_Instance instance);
+
+ // Returns a pointer to the plugin instance object associated with the given
+ // instance handle. The return value will be NULL if the handle is invalid.
+ PluginInstance* GetInstance(PP_Instance instance);
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<ResourceTracker>;
+ friend class Resource;
+ friend class ResourceTrackerTest;
+
+ // Prohibit creation other then by the Singleton class.
+ ResourceTracker();
+ ~ResourceTracker();
+
+ // Adds the given resource to the tracker and assigns it a resource ID and
+ // refcount of 1. The assigned resource ID will be returned. Used only by the
+ // Resource class.
+ PP_Resource AddResource(Resource* resource);
+
+ // Overrides the singleton object. This is used for tests which want to
+ // specify their own tracker (otherwise, you can get cross-talk between
+ // tests since the data will live into the subsequent tests).
+ static void SetSingletonOverride(ResourceTracker* tracker);
+ static void ClearSingletonOverride();
+
+ // See SetSingletonOverride above.
+ static ResourceTracker* singleton_override_;
+
+ // Last assigned resource ID.
+ PP_Resource last_id_;
+
+ // For each PP_Resource, keep the Resource* (as refptr) and plugin use count.
+ // This use count is different then Resource's RefCount, and is manipulated
+ // using this RefResource/UnrefResource. When it drops to zero, we just remove
+ // the resource from this resource tracker, but the resource object will be
+ // alive so long as some scoped_refptr still holds it's reference. This
+ // prevents plugins from forcing destruction of Resource objects.
+ typedef std::pair<scoped_refptr<Resource>, size_t> ResourceAndRefCount;
+ typedef base::hash_map<PP_Resource, ResourceAndRefCount> ResourceMap;
+ ResourceMap live_resources_;
+
+ // Tracks all live instances. The pointers are non-owning, the PluginInstance
+ // destructor will notify us when the instance is deleted.
+ typedef std::map<PP_Instance, PluginInstance*> InstanceMap;
+ InstanceMap instance_map_;
+
+ // Tracks all live modules. The pointers are non-owning, the PluginModule
+ // destructor will notify us when the module is deleted.
+ typedef std::map<PP_Module, PluginModule*> ModuleMap;
+ ModuleMap module_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceTracker);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_RESOURCE_TRACKER_H_
diff --git a/webkit/plugins/ppapi/resource_tracker_unittest.cc b/webkit/plugins/ppapi/resource_tracker_unittest.cc
new file mode 100644
index 0000000..60910df
--- /dev/null
+++ b/webkit/plugins/ppapi/resource_tracker_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/ppapi_unittest.h"
+
+#include "webkit/plugins/ppapi/resource_tracker.h"
+#include "webkit/plugins/ppapi/mock_resource.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+class TrackedMockResource : public MockResource {
+ public:
+ static int tracked_objects_alive;
+
+ TrackedMockResource(PluginModule* module) : MockResource(module) {
+ tracked_objects_alive++;
+ }
+ ~TrackedMockResource() {
+ tracked_objects_alive--;
+ }
+};
+
+int TrackedMockResource::tracked_objects_alive = 0;
+
+} // namespace
+
+class ResourceTrackerTest : public PpapiUnittest {
+ public:
+ ResourceTrackerTest() {
+ }
+
+ virtual void SetUp() {
+ PpapiUnittest::SetUp();
+ ResourceTracker::SetSingletonOverride(&tracker_);
+ }
+ virtual void TearDown() {
+ ResourceTracker::ClearSingletonOverride();
+ PpapiUnittest::TearDown();
+ }
+
+ ResourceTracker& tracker() { return tracker_; }
+
+ private:
+ ResourceTracker tracker_;
+};
+
+TEST_F(ResourceTrackerTest, Ref) {
+ ASSERT_EQ(0, TrackedMockResource::tracked_objects_alive);
+ EXPECT_EQ(0u, tracker().GetLiveObjectsForModule(module()));
+ {
+ scoped_refptr<TrackedMockResource> new_resource(
+ new TrackedMockResource(module()));
+ ASSERT_EQ(1, TrackedMockResource::tracked_objects_alive);
+
+ // Since we haven't gotten a PP_Resource, it's not associated with the
+ // module.
+ EXPECT_EQ(0u, tracker().GetLiveObjectsForModule(module()));
+ }
+ ASSERT_EQ(0, TrackedMockResource::tracked_objects_alive);
+
+ // Make a new resource and get it as a PP_Resource.
+ PP_Resource resource_id = 0;
+ {
+ scoped_refptr<TrackedMockResource> new_resource(
+ new TrackedMockResource(module()));
+ ASSERT_EQ(1, TrackedMockResource::tracked_objects_alive);
+ resource_id = new_resource->GetReference();
+ EXPECT_EQ(1u, tracker().GetLiveObjectsForModule(module()));
+
+ // Resource IDs should be consistent.
+ PP_Resource resource_id_2 = new_resource->GetReference();
+ ASSERT_EQ(resource_id, resource_id_2);
+ }
+
+ // This time it should not have been deleted since the PP_Resource carries
+ // a ref.
+ ASSERT_EQ(1, TrackedMockResource::tracked_objects_alive);
+
+ // Now we have two refs, derefing twice should delete the object.
+ tracker().UnrefResource(resource_id);
+ ASSERT_EQ(1, TrackedMockResource::tracked_objects_alive);
+ tracker().UnrefResource(resource_id);
+ ASSERT_EQ(0, TrackedMockResource::tracked_objects_alive);
+}
+
+TEST_F(ResourceTrackerTest, ForceDelete) {
+ // Make two resources.
+ scoped_refptr<TrackedMockResource> resource1(
+ new TrackedMockResource(module()));
+ PP_Resource pp_resource1 = resource1->GetReference();
+ scoped_refptr<TrackedMockResource> resource2(
+ new TrackedMockResource(module()));
+ PP_Resource pp_resource2 = resource2->GetReference();
+
+ // Keep an "internal" ref to only the first (the PP_Resource also holds a
+ // ref to each resource on behalf of the plugin).
+ resource2 = NULL;
+
+ ASSERT_EQ(2, TrackedMockResource::tracked_objects_alive);
+ EXPECT_EQ(2u, tracker().GetLiveObjectsForModule(module()));
+
+ // Force delete both refs.
+ tracker().ForceDeletePluginResourceRefs(pp_resource1);
+ tracker().ForceDeletePluginResourceRefs(pp_resource2);
+ EXPECT_EQ(0u, tracker().GetLiveObjectsForModule(module()));
+
+ // The resource we have a scoped_refptr to should still be alive.
+ ASSERT_EQ(1, TrackedMockResource::tracked_objects_alive);
+ resource1 = NULL;
+ ASSERT_EQ(0, TrackedMockResource::tracked_objects_alive);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/string.cc b/webkit/plugins/ppapi/string.cc
new file mode 100644
index 0000000..d8b95de
--- /dev/null
+++ b/webkit/plugins/ppapi/string.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/string.h"
+
+namespace webkit {
+namespace ppapi {
+
+String::String(const char* str, uint32 len) : value_(str, len) {}
+
+String::~String() {}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/string.h b/webkit/plugins/ppapi/string.h
new file mode 100644
index 0000000..6880b3b
--- /dev/null
+++ b/webkit/plugins/ppapi/string.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 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 WEBKIT_GLUE_PLUGINS_PEPPER_STRING_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_STRING_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+
+namespace webkit {
+namespace ppapi {
+
+class String : public base::RefCountedThreadSafe<String> {
+ public:
+ String(const char* str, uint32 len);
+ virtual ~String();
+
+ const std::string& value() const { return value_; }
+
+ private:
+ std::string value_;
+
+ DISALLOW_COPY_AND_ASSIGN(String);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_STRING_H_
diff --git a/webkit/plugins/ppapi/var.cc b/webkit/plugins/ppapi/var.cc
new file mode 100644
index 0000000..132cdfb
--- /dev/null
+++ b/webkit/plugins/ppapi/var.cc
@@ -0,0 +1,872 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/var.h"
+
+#include <limits>
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/pp_var.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "webkit/plugins/ppapi/common.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/plugin_object.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "v8/include/v8.h"
+
+using WebKit::WebBindings;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+const char kInvalidObjectException[] = "Error: Invalid object";
+const char kInvalidPropertyException[] = "Error: Invalid property";
+const char kInvalidValueException[] = "Error: Invalid value";
+const char kUnableToGetPropertyException[] = "Error: Unable to get property";
+const char kUnableToSetPropertyException[] = "Error: Unable to set property";
+const char kUnableToRemovePropertyException[] =
+ "Error: Unable to remove property";
+const char kUnableToGetAllPropertiesException[] =
+ "Error: Unable to get all properties";
+const char kUnableToCallMethodException[] = "Error: Unable to call method";
+const char kUnableToConstructException[] = "Error: Unable to construct";
+
+// ---------------------------------------------------------------------------
+// Utilities
+
+// Converts the given PP_Var to an NPVariant, returning true on success.
+// False means that the given variant is invalid. In this case, the result
+// NPVariant will be set to a void one.
+//
+// The contents of the PP_Var will NOT be copied, so you need to ensure that
+// the PP_Var remains valid while the resultant NPVariant is in use.
+bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) {
+ switch (var.type) {
+ case PP_VARTYPE_UNDEFINED:
+ VOID_TO_NPVARIANT(*result);
+ break;
+ case PP_VARTYPE_NULL:
+ NULL_TO_NPVARIANT(*result);
+ break;
+ case PP_VARTYPE_BOOL:
+ BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
+ break;
+ case PP_VARTYPE_INT32:
+ INT32_TO_NPVARIANT(var.value.as_int, *result);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
+ break;
+ case PP_VARTYPE_STRING: {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
+ if (!string) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ const std::string& value = string->value();
+ STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result);
+ break;
+ }
+ case PP_VARTYPE_OBJECT: {
+ scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var));
+ if (!object) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ OBJECT_TO_NPVARIANT(object->np_object(), *result);
+ break;
+ }
+ default:
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ return true;
+}
+
+// ObjectAccessorTryCatch ------------------------------------------------------
+
+// Automatically sets up a TryCatch for accessing the object identified by the
+// given PP_Var. The module from the object will be used for the exception
+// strings generated by the TryCatch.
+//
+// This will automatically retrieve the ObjectVar from the object and throw
+// an exception if it's invalid. At the end of construction, if there is no
+// exception, you know that there is no previously set exception, that the
+// object passed in is valid and ready to use (via the object() getter), and
+// that the TryCatch's module() getter is also set up properly and ready to
+// use.
+class ObjectAccessorTryCatch : public TryCatch {
+ public:
+ ObjectAccessorTryCatch(PP_Var object, PP_Var* exception)
+ : TryCatch(NULL, exception),
+ object_(ObjectVar::FromPPVar(object)) {
+ if (!object_) {
+ // No object or an invalid object was given. This means we have no module
+ // to associated with the exception text, so use the magic invalid object
+ // exception.
+ SetInvalidObjectException();
+ } else {
+ // When the object is valid, we have a valid module to associate
+ set_module(object_->module());
+ }
+ }
+
+ ObjectVar* object() { return object_.get(); }
+
+ protected:
+ scoped_refptr<ObjectVar> object_;
+
+ DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch);
+};
+
+// ObjectAccessiorWithIdentifierTryCatch ---------------------------------------
+
+// Automatically sets up a TryCatch for accessing the identifier on the given
+// object. This just extends ObjectAccessorTryCatch to additionally convert
+// the given identifier to an NPIdentifier and validate it, throwing an
+// exception if it's invalid.
+//
+// At the end of construction, if there is no exception, you know that there is
+// no previously set exception, that the object passed in is valid and ready to
+// use (via the object() getter), that the identifier is valid and ready to
+// use (via the identifier() getter), and that the TryCatch's module() getter
+// is also set up properly and ready to use.
+class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch {
+ public:
+ ObjectAccessorWithIdentifierTryCatch(PP_Var object,
+ PP_Var identifier,
+ PP_Var* exception)
+ : ObjectAccessorTryCatch(object, exception),
+ identifier_(0) {
+ if (!has_exception()) {
+ identifier_ = Var::PPVarToNPIdentifier(identifier);
+ if (!identifier_)
+ SetException(kInvalidPropertyException);
+ }
+ }
+
+ NPIdentifier identifier() const { return identifier_; }
+
+ private:
+ NPIdentifier identifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch);
+};
+
+PP_Var RunJSFunction(PP_Var scope_var,
+ const char* function_script,
+ PP_Var* argv,
+ unsigned argc,
+ PP_Var* exception) {
+ TryCatch try_catch(NULL, exception);
+ if (try_catch.has_exception())
+ return PP_MakeUndefined();
+
+ scoped_refptr<ObjectVar> obj = ObjectVar::FromPPVar(scope_var);
+ if (!obj) {
+ try_catch.SetInvalidObjectException();
+ return PP_MakeUndefined();
+ }
+
+ try_catch.set_module(obj->module());
+
+ scoped_array<NPVariant> args;
+ if (argc) {
+ args.reset(new NPVariant[argc]);
+ for (uint32_t i = 0; i < argc; ++i) {
+ if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
+ // This argument was invalid, throw an exception & give up.
+ try_catch.SetException(kInvalidValueException);
+ return PP_MakeUndefined();
+ }
+ }
+ }
+
+ NPVariant function_var;
+ VOID_TO_NPVARIANT(function_var);
+ NPString function_string = { function_script, strlen(function_script) };
+ if (!WebBindings::evaluate(NULL, obj->np_object(), &function_string,
+ &function_var)) {
+ try_catch.SetException(kInvalidValueException);
+ return PP_MakeUndefined();
+ }
+ DCHECK(NPVARIANT_IS_OBJECT(function_var));
+ DCHECK(!try_catch.has_exception());
+
+ NPVariant result_var;
+ VOID_TO_NPVARIANT(result_var);
+ PP_Var result;
+
+ if (WebBindings::invokeDefault(NULL, NPVARIANT_TO_OBJECT(function_var),
+ args.get(), argc, &result_var)) {
+ result = Var::NPVariantToPPVar(obj->module(), &result_var);
+ } else {
+ DCHECK(try_catch.has_exception());
+ result = PP_MakeUndefined();
+ }
+
+ WebBindings::releaseVariantValue(&function_var);
+ WebBindings::releaseVariantValue(&result_var);
+ return result;
+}
+
+// PPB_Var methods -------------------------------------------------------------
+
+PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return PP_MakeNull();
+ return StringVar::StringToPPVar(module, data, len);
+}
+
+const char* VarToUtf8(PP_Var var, uint32_t* len) {
+ scoped_refptr<StringVar> str(StringVar::FromPPVar(var));
+ if (!str) {
+ *len = 0;
+ return NULL;
+ }
+ *len = static_cast<uint32_t>(str->value().size());
+ if (str->value().empty())
+ return ""; // Don't return NULL on success.
+ return str->value().data();
+}
+
+PP_Var ConvertType(PP_Instance instance,
+ struct PP_Var var,
+ PP_VarType new_type,
+ PP_Var* exception) {
+ TryCatch try_catch(NULL, exception);
+ if (try_catch.has_exception())
+ return PP_MakeUndefined();
+
+ if (var.type == new_type)
+ return var;
+
+ PluginInstance* plugin_instance =
+ ResourceTracker::Get()->GetInstance(instance);
+ if (!plugin_instance) {
+ try_catch.SetInvalidObjectException();
+ return PP_MakeUndefined();
+ }
+
+ try_catch.set_module(plugin_instance->module());
+ PP_Var object = plugin_instance->GetWindowObject();
+
+ PP_Var params[] = {
+ var,
+ PP_MakeInt32(new_type),
+ PP_MakeInt32(PP_VARTYPE_NULL),
+ PP_MakeInt32(PP_VARTYPE_BOOL),
+ PP_MakeInt32(PP_VARTYPE_INT32),
+ PP_MakeInt32(PP_VARTYPE_DOUBLE),
+ PP_MakeInt32(PP_VARTYPE_STRING),
+ PP_MakeInt32(PP_VARTYPE_OBJECT)
+ };
+ PP_Var result = RunJSFunction(object,
+ "(function(v, new_type, type_null, type_bool, type_int32, type_double,"
+ " type_string, type_object) {"
+ " switch(new_type) {"
+ " case type_null: return null;"
+ " case type_bool: return Boolean(v);"
+ " case type_int32: case type_double: return Number(v);"
+ " case type_string: return String(v);"
+ " case type_object: return Object(v);"
+ " default: return undefined;"
+ " }})",
+ params, sizeof(params) / sizeof(PP_Var), exception);
+
+ // Massage Number into the correct type.
+ if (new_type == PP_VARTYPE_INT32 && result.type == PP_VARTYPE_DOUBLE) {
+ double value = result.value.as_double;
+ // Exclusive test wouldn't deal with NaNs correctly.
+ if (value >= std::numeric_limits<int32_t>::max()
+ && value <= std::numeric_limits<int32_t>::min())
+ result = PP_MakeInt32(static_cast<int32_t>(value));
+ else
+ result = PP_MakeInt32(0);
+ } else if (new_type == PP_VARTYPE_DOUBLE && result.type == PP_VARTYPE_INT32) {
+ result = PP_MakeDouble(result.value.as_int);
+ }
+
+ Var::PluginReleasePPVar(object);
+ return result;
+}
+
+PP_Var BoolToPPVar(bool value) {
+ return PP_MakeBool(BoolToPPBool(value));
+}
+
+void DefineProperty(struct PP_Var object,
+ struct PP_ObjectProperty property,
+ PP_Var* exception) {
+ PP_Var params[] = {
+ object, property.name,
+ BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_HASVALUE)),
+ property.value,
+ BoolToPPVar(property.getter.type == PP_VARTYPE_OBJECT),
+ property.getter,
+ BoolToPPVar(property.setter.type == PP_VARTYPE_OBJECT),
+ property.setter,
+ BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)),
+ BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTDELETE)),
+ BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM))
+ };
+
+ RunJSFunction(object,
+ "(function(o, name,"
+ " has_value, value,"
+ " has_getter, getter,"
+ " has_setter, setter,"
+ " modifier_readonly, modifier_dontdelete, modifier_dontenum) {"
+ " prop = { 'enumerable': !modifier_dontenum,"
+ " 'configurable': !modifier_dontdelete };"
+ " if (has_value && !modifier_readonly) prop.writable = true;"
+ " if (has_value) prop.value = value;"
+ " if (has_getter) prop.get = getter;"
+ " if (has_setter) prop.set = setter;"
+ " return Object.defineProperty(o, name, prop); })",
+ params, sizeof(params) / sizeof(PP_Var), exception);
+}
+
+PP_Bool HasProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
+ if (accessor.has_exception())
+ return PP_FALSE;
+ return BoolToPPBool(WebBindings::hasProperty(NULL,
+ accessor.object()->np_object(),
+ accessor.identifier()));
+}
+
+bool HasPropertyDeprecated(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ return PPBoolToBool(HasProperty(var, name, exception));
+}
+
+bool HasMethodDeprecated(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
+ if (accessor.has_exception())
+ return false;
+ return WebBindings::hasMethod(NULL, accessor.object()->np_object(),
+ accessor.identifier());
+}
+
+PP_Var GetProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
+ if (accessor.has_exception())
+ return PP_MakeUndefined();
+
+ NPVariant result;
+ if (!WebBindings::getProperty(NULL, accessor.object()->np_object(),
+ accessor.identifier(), &result)) {
+ // An exception may have been raised.
+ accessor.SetException(kUnableToGetPropertyException);
+ return PP_MakeUndefined();
+ }
+
+ PP_Var ret = Var::NPVariantToPPVar(accessor.object()->module(), &result);
+ WebBindings::releaseVariantValue(&result);
+ return ret;
+}
+
+void EnumerateProperties(PP_Var var,
+ uint32_t* property_count,
+ PP_Var** properties,
+ PP_Var* exception) {
+ *properties = NULL;
+ *property_count = 0;
+
+ ObjectAccessorTryCatch accessor(var, exception);
+ if (accessor.has_exception())
+ return;
+
+ NPIdentifier* identifiers = NULL;
+ uint32_t count = 0;
+ if (!WebBindings::enumerate(NULL, accessor.object()->np_object(),
+ &identifiers, &count)) {
+ accessor.SetException(kUnableToGetAllPropertiesException);
+ return;
+ }
+
+ if (count == 0)
+ return;
+
+ *property_count = count;
+ *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count));
+ for (uint32_t i = 0; i < count; ++i) {
+ (*properties)[i] = Var::NPIdentifierToPPVar(accessor.object()->module(),
+ identifiers[i]);
+ }
+ free(identifiers);
+}
+
+void SetPropertyDeprecated(PP_Var var,
+ PP_Var name,
+ PP_Var value,
+ PP_Var* exception) {
+ ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
+ if (accessor.has_exception())
+ return;
+
+ NPVariant variant;
+ if (!PPVarToNPVariantNoCopy(value, &variant)) {
+ accessor.SetException(kInvalidValueException);
+ return;
+ }
+ if (!WebBindings::setProperty(NULL, accessor.object()->np_object(),
+ accessor.identifier(), &variant))
+ accessor.SetException(kUnableToSetPropertyException);
+}
+
+PP_Bool DeleteProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
+ if (accessor.has_exception())
+ return PP_FALSE;
+
+ return BoolToPPBool(
+ WebBindings::removeProperty(NULL,
+ accessor.object()->np_object(),
+ accessor.identifier()));
+}
+
+void DeletePropertyDeprecated(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
+ if (accessor.has_exception())
+ return;
+
+ if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(),
+ accessor.identifier()))
+ accessor.SetException(kUnableToRemovePropertyException);
+}
+
+PP_Bool IsCallable(struct PP_Var object) {
+ PP_Var result = RunJSFunction(object,
+ "(function() { return typeof(this) == 'function' })", NULL, 0, NULL);
+ if (result.type == PP_VARTYPE_BOOL)
+ return result.value.as_bool;
+ return PP_FALSE;
+}
+
+struct PP_Var Call(struct PP_Var object,
+ struct PP_Var this_object,
+ uint32_t argc,
+ struct PP_Var* argv,
+ struct PP_Var* exception) {
+ ObjectAccessorTryCatch accessor(object, exception);
+ if (accessor.has_exception())
+ return PP_MakeUndefined();
+
+ scoped_array<NPVariant> args;
+ if (argc) {
+ args.reset(new NPVariant[argc]);
+ for (uint32_t i = 0; i < argc; ++i) {
+ if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
+ // This argument was invalid, throw an exception & give up.
+ accessor.SetException(kInvalidValueException);
+ return PP_MakeUndefined();
+ }
+ }
+ }
+
+ NPVariant result;
+ if (!WebBindings::invokeDefault(NULL, accessor.object()->np_object(),
+ args.get(), argc, &result)) {
+ // An exception may have been raised.
+ accessor.SetException(kUnableToCallMethodException);
+ return PP_MakeUndefined();
+ }
+
+ PP_Var ret = Var::NPVariantToPPVar(accessor.module(), &result);
+ WebBindings::releaseVariantValue(&result);
+ return ret;
+}
+
+PP_Var CallDeprecated(PP_Var var,
+ PP_Var method_name,
+ uint32_t argc,
+ PP_Var* argv,
+ PP_Var* exception) {
+ ObjectAccessorTryCatch accessor(var, exception);
+ if (accessor.has_exception())
+ return PP_MakeUndefined();
+
+ NPIdentifier identifier;
+ if (method_name.type == PP_VARTYPE_UNDEFINED) {
+ identifier = NULL;
+ } else if (method_name.type == PP_VARTYPE_STRING) {
+ // Specifically allow only string functions to be called.
+ identifier = Var::PPVarToNPIdentifier(method_name);
+ if (!identifier) {
+ accessor.SetException(kInvalidPropertyException);
+ return PP_MakeUndefined();
+ }
+ } else {
+ accessor.SetException(kInvalidPropertyException);
+ return PP_MakeUndefined();
+ }
+
+ scoped_array<NPVariant> args;
+ if (argc) {
+ args.reset(new NPVariant[argc]);
+ for (uint32_t i = 0; i < argc; ++i) {
+ if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
+ // This argument was invalid, throw an exception & give up.
+ accessor.SetException(kInvalidValueException);
+ return PP_MakeUndefined();
+ }
+ }
+ }
+
+ bool ok;
+
+ NPVariant result;
+ if (identifier) {
+ ok = WebBindings::invoke(NULL, accessor.object()->np_object(),
+ identifier, args.get(), argc, &result);
+ } else {
+ ok = WebBindings::invokeDefault(NULL, accessor.object()->np_object(),
+ args.get(), argc, &result);
+ }
+
+ if (!ok) {
+ // An exception may have been raised.
+ accessor.SetException(kUnableToCallMethodException);
+ return PP_MakeUndefined();
+ }
+
+ PP_Var ret = Var::NPVariantToPPVar(accessor.module(), &result);
+ WebBindings::releaseVariantValue(&result);
+ return ret;
+}
+
+PP_Var Construct(PP_Var var,
+ uint32_t argc,
+ PP_Var* argv,
+ PP_Var* exception) {
+ ObjectAccessorTryCatch accessor(var, exception);
+ if (accessor.has_exception())
+ return PP_MakeUndefined();
+
+ scoped_array<NPVariant> args;
+ if (argc) {
+ args.reset(new NPVariant[argc]);
+ for (uint32_t i = 0; i < argc; ++i) {
+ if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
+ // This argument was invalid, throw an exception & give up.
+ accessor.SetException(kInvalidValueException);
+ return PP_MakeUndefined();
+ }
+ }
+ }
+
+ NPVariant result;
+ if (!WebBindings::construct(NULL, accessor.object()->np_object(),
+ args.get(), argc, &result)) {
+ // An exception may have been raised.
+ accessor.SetException(kUnableToConstructException);
+ return PP_MakeUndefined();
+ }
+
+ PP_Var ret = Var::NPVariantToPPVar(accessor.module(), &result);
+ WebBindings::releaseVariantValue(&result);
+ return ret;
+}
+
+bool IsInstanceOfDeprecated(PP_Var var,
+ const PPP_Class_Deprecated* ppp_class,
+ void** ppp_class_data) {
+ scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var));
+ if (!object)
+ return false; // Not an object at all.
+
+ return PluginObject::IsInstanceOf(object->np_object(),
+ ppp_class, ppp_class_data);
+}
+
+PP_Var CreateObjectDeprecated(PP_Module module_id,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data) {
+ PluginModule* module = ResourceTracker::Get()->GetModule(module_id);
+ if (!module)
+ return PP_MakeNull();
+ return PluginObject::Create(module, ppp_class, ppp_class_data);
+}
+
+const PPB_Var_Deprecated var_deprecated_interface = {
+ &Var::PluginAddRefPPVar,
+ &Var::PluginReleasePPVar,
+ &VarFromUtf8,
+ &VarToUtf8,
+ &HasPropertyDeprecated,
+ &HasMethodDeprecated,
+ &GetProperty,
+ &EnumerateProperties,
+ &SetPropertyDeprecated,
+ &DeletePropertyDeprecated,
+ &CallDeprecated,
+ &Construct,
+ &IsInstanceOfDeprecated,
+ &CreateObjectDeprecated
+};
+
+const PPB_Var var_interface = {
+ &Var::PluginAddRefPPVar,
+ &Var::PluginReleasePPVar,
+ &VarFromUtf8,
+ &VarToUtf8,
+ &ConvertType,
+ &DefineProperty,
+ &HasProperty,
+ &GetProperty,
+ &DeleteProperty,
+ &EnumerateProperties,
+ &IsCallable,
+ &Call,
+ &Construct,
+};
+
+
+} // namespace
+
+// Var -------------------------------------------------------------------------
+
+Var::Var(PluginModule* module) : Resource(module) {
+}
+
+Var::~Var() {
+}
+
+Var* Var::AsVar() {
+ return this;
+}
+
+// static
+PP_Var Var::NPVariantToPPVar(PluginModule* module, const NPVariant* variant) {
+ switch (variant->type) {
+ case NPVariantType_Void:
+ return PP_MakeUndefined();
+ case NPVariantType_Null:
+ return PP_MakeNull();
+ case NPVariantType_Bool:
+ return BoolToPPVar(NPVARIANT_TO_BOOLEAN(*variant));
+ case NPVariantType_Int32:
+ return PP_MakeInt32(NPVARIANT_TO_INT32(*variant));
+ case NPVariantType_Double:
+ return PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant));
+ case NPVariantType_String:
+ return StringVar::StringToPPVar(
+ module,
+ NPVARIANT_TO_STRING(*variant).UTF8Characters,
+ NPVARIANT_TO_STRING(*variant).UTF8Length);
+ case NPVariantType_Object:
+ return ObjectVar::NPObjectToPPVar(module, NPVARIANT_TO_OBJECT(*variant));
+ }
+ NOTREACHED();
+ return PP_MakeUndefined();
+}
+
+// static
+NPIdentifier Var::PPVarToNPIdentifier(PP_Var var) {
+ switch (var.type) {
+ case PP_VARTYPE_STRING: {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
+ if (!string)
+ return NULL;
+ return WebBindings::getStringIdentifier(string->value().c_str());
+ }
+ case PP_VARTYPE_INT32:
+ return WebBindings::getIntIdentifier(var.value.as_int);
+ default:
+ return NULL;
+ }
+}
+
+// static
+PP_Var Var::NPIdentifierToPPVar(PluginModule* module, NPIdentifier id) {
+ const NPUTF8* string_value = NULL;
+ int32_t int_value = 0;
+ bool is_string = false;
+ WebBindings::extractIdentifierData(id, string_value, int_value, is_string);
+ if (is_string)
+ return StringVar::StringToPPVar(module, string_value);
+
+ return PP_MakeInt32(int_value);
+}
+
+// static
+void Var::PluginAddRefPPVar(PP_Var var) {
+ if (var.type == PP_VARTYPE_STRING || var.type == PP_VARTYPE_OBJECT) {
+ // TODO(brettw) consider checking that the ID is actually a var ID rather
+ // than some random other resource ID.
+ PP_Resource resource = static_cast<PP_Resource>(var.value.as_id);
+ if (!ResourceTracker::Get()->AddRefResource(resource))
+ DLOG(WARNING) << "AddRefVar()ing a nonexistant string/object var.";
+ }
+}
+
+// static
+void Var::PluginReleasePPVar(PP_Var var) {
+ if (var.type == PP_VARTYPE_STRING || var.type == PP_VARTYPE_OBJECT) {
+ // TODO(brettw) consider checking that the ID is actually a var ID rather
+ // than some random other resource ID.
+ PP_Resource resource = static_cast<PP_Resource>(var.value.as_id);
+ if (!ResourceTracker::Get()->UnrefResource(resource))
+ DLOG(WARNING) << "ReleaseVar()ing a nonexistant string/object var.";
+ }
+}
+
+// static
+const PPB_Var_Deprecated* Var::GetDeprecatedInterface() {
+ return &var_deprecated_interface;
+}
+
+const PPB_Var* Var::GetInterface() {
+ return &var_interface;
+}
+
+// StringVar -------------------------------------------------------------------
+
+StringVar::StringVar(PluginModule* module, const char* str, uint32 len)
+ : Var(module),
+ value_(str, len) {
+}
+
+StringVar::~StringVar() {
+}
+
+StringVar* StringVar::AsStringVar() {
+ return this;
+}
+
+// static
+PP_Var StringVar::StringToPPVar(PluginModule* module, const std::string& var) {
+ return StringToPPVar(module, var.c_str(), var.size());
+}
+
+// static
+PP_Var StringVar::StringToPPVar(PluginModule* module,
+ const char* data, uint32 len) {
+ scoped_refptr<StringVar> str(new StringVar(module, data, len));
+ if (!str || !IsStringUTF8(str->value()))
+ return PP_MakeNull();
+
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+
+ // The caller takes ownership now.
+ ret.value.as_id = str->GetReference();
+ return ret;
+}
+
+// static
+scoped_refptr<StringVar> StringVar::FromPPVar(PP_Var var) {
+ if (var.type != PP_VARTYPE_STRING)
+ return scoped_refptr<StringVar>(NULL);
+ PP_Resource resource = static_cast<PP_Resource>(var.value.as_id);
+ return Resource::GetAs<StringVar>(resource);
+}
+
+// ObjectVar -------------------------------------------------------------
+
+ObjectVar::ObjectVar(PluginModule* module, NPObject* np_object)
+ : Var(module),
+ np_object_(np_object) {
+ WebBindings::retainObject(np_object_);
+ module->AddNPObjectVar(this);
+}
+
+ObjectVar::~ObjectVar() {
+ module()->RemoveNPObjectVar(this);
+ WebBindings::releaseObject(np_object_);
+}
+
+ObjectVar* ObjectVar::AsObjectVar() {
+ return this;
+}
+
+// static
+PP_Var ObjectVar::NPObjectToPPVar(PluginModule* module, NPObject* object) {
+ scoped_refptr<ObjectVar> object_var(module->ObjectVarForNPObject(object));
+ if (!object_var) // No object for this module yet, make a new one.
+ object_var = new ObjectVar(module, object);
+
+ if (!object_var)
+ return PP_MakeUndefined();
+
+ // Convert to a PP_Var, GetReference will AddRef for us.
+ PP_Var result;
+ result.type = PP_VARTYPE_OBJECT;
+ result.value.as_id = object_var->GetReference();
+ return result;
+}
+
+// static
+scoped_refptr<ObjectVar> ObjectVar::FromPPVar(PP_Var var) {
+ if (var.type != PP_VARTYPE_OBJECT)
+ return scoped_refptr<ObjectVar>(NULL);
+ PP_Resource resource = static_cast<PP_Resource>(var.value.as_id);
+ return Resource::GetAs<ObjectVar>(resource);
+}
+
+// TryCatch --------------------------------------------------------------------
+
+TryCatch::TryCatch(PluginModule* module, PP_Var* exception)
+ : module_(module),
+ has_exception_(exception && exception->type != PP_VARTYPE_UNDEFINED),
+ exception_(exception) {
+ WebBindings::pushExceptionHandler(&TryCatch::Catch, this);
+}
+
+TryCatch::~TryCatch() {
+ WebBindings::popExceptionHandler();
+}
+
+void TryCatch::SetException(const char* message) {
+ if (!module_) {
+ // Don't have a module to make the string.
+ SetInvalidObjectException();
+ return;
+ }
+
+ if (!has_exception()) {
+ has_exception_ = true;
+ if (exception_)
+ *exception_ = StringVar::StringToPPVar(module_, message, strlen(message));
+ }
+}
+
+void TryCatch::SetInvalidObjectException() {
+ if (!has_exception()) {
+ has_exception_ = true;
+ // TODO(brettw) bug 54504: Have a global singleton string that can hold
+ // a generic error message.
+ if (exception_)
+ *exception_ = PP_MakeInt32(1);
+ }
+}
+
+// static
+void TryCatch::Catch(void* self, const char* message) {
+ static_cast<TryCatch*>(self)->SetException(message);
+}
+
+} // namespace ppapi
+} // namespace webkit
+
diff --git a/webkit/plugins/ppapi/var.h b/webkit/plugins/ppapi/var.h
new file mode 100644
index 0000000..8f74733
--- /dev/null
+++ b/webkit/plugins/ppapi/var.h
@@ -0,0 +1,253 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_VAR_H_
+#define WEBKIT_PLUGINS_PPAPI_VAR_H_
+
+#include <string>
+
+#include "webkit/plugins/ppapi/resource.h"
+
+struct PP_Var;
+struct PPB_Var;
+struct PPB_Var_Deprecated;
+typedef struct NPObject NPObject;
+typedef struct _NPVariant NPVariant;
+typedef void* NPIdentifier;
+
+namespace webkit {
+namespace ppapi {
+
+// Var -------------------------------------------------------------------------
+
+// Represents a non-POD var. This is derived from a resource even though it
+// isn't a resource from the plugin's perspective. This allows us to re-use
+// the refcounting and the association with the module from the resource code.
+class Var : public Resource {
+ public:
+ virtual ~Var();
+
+ // Resource overrides.
+ virtual Var* AsVar();
+
+ // Returns a PP_Var that corresponds to the given NPVariant. The contents of
+ // the NPVariant will be copied unless the NPVariant corresponds to an
+ // object. This will handle all Variant types including POD, strings, and
+ // objects.
+ //
+ // The returned PP_Var will have a refcount of 1, this passing ownership of
+ // the reference to the caller. This is suitable for returning to a plugin.
+ static PP_Var NPVariantToPPVar(PluginModule* module,
+ const NPVariant* variant);
+
+ // Returns a NPIdentifier that corresponds to the given PP_Var. The contents
+ // of the PP_Var will be copied. Returns 0 if the given PP_Var is not a a
+ // string or integer type.
+ static NPIdentifier PPVarToNPIdentifier(PP_Var var);
+
+ // Returns a PP_Var corresponding to the given identifier. In the case of
+ // a string identifier, the string will be allocated associated with the
+ // given module. A returned string will have a reference count of 1.
+ static PP_Var NPIdentifierToPPVar(PluginModule* module, NPIdentifier id);
+
+ // Provides access to the manual refcounting of a PP_Var from the plugin's
+ // perspective. This is different than the AddRef/Release on this scoped
+ // object. This uses the ResourceTracker, which keeps a separate "plugin
+ // refcount" that prevents the plugin from messing up our refcounting or
+ // freeing something out from under us.
+ //
+ // You should not generally need to use these functions. However, if you
+ // call a plugin function that returns a var, it will transfer a ref to us
+ // (the caller) which in the case of a string or object var will need to
+ // be released.
+ //
+ // Example, assuming we're expecting the plugin to return a string:
+ // PP_Var rv = some_ppp_interface->DoSomething(a, b, c);
+ //
+ // // Get the string value. This will take a reference to the object which
+ // // will prevent it from being deleted out from under us when we call
+ // // PluginReleasePPVar().
+ // scoped_refptr<StringVar> string(StringVar::FromPPVar(rv));
+ //
+ // // Release the reference the plugin gave us when returning the value.
+ // // This is legal to do for all types of vars.
+ // Var::PluginReleasePPVar(rv);
+ //
+ // // Use the string.
+ // if (!string)
+ // return false; // It didn't return a proper string.
+ // UseTheString(string->value());
+ static void PluginAddRefPPVar(PP_Var var);
+ static void PluginReleasePPVar(PP_Var var);
+
+ // Returns the PPB_Var_Deprecated interface for the plugin to use.
+ static const PPB_Var_Deprecated* GetDeprecatedInterface();
+
+ // Returns the PPB_Var interface for the plugin to use.
+ static const PPB_Var* GetInterface();
+
+ protected:
+ // This can only be constructed as a StringVar or an ObjectVar.
+ explicit Var(PluginModule* module);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Var);
+};
+
+// StringVar -------------------------------------------------------------------
+
+// Represents a string-based Var.
+//
+// Returning a given string as a PP_Var:
+// return StringVar::StringToPPVar(module, my_string);
+//
+// Converting a PP_Var to a string:
+// scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
+// if (!string)
+// return false; // Not a string or an invalid var.
+// DoSomethingWithTheString(string->value());
+class StringVar : public Var {
+ public:
+ StringVar(PluginModule* module, const char* str, uint32 len);
+ virtual ~StringVar();
+
+ const std::string& value() const { return value_; }
+
+ // Resource overrides.
+ virtual StringVar* AsStringVar();
+
+ // Helper function to create a PP_Var of type string that contains a copy of
+ // the given string. The input data must be valid UTF-8 encoded text, if it
+ // is not valid UTF-8, a NULL var will be returned.
+ //
+ // The return value will have a reference count of 1. Internally, this will
+ // create a StringVar, associate it with a module, and return the reference
+ // to it in the var.
+ static PP_Var StringToPPVar(PluginModule* module, const std::string& str);
+ static PP_Var StringToPPVar(PluginModule* module,
+ const char* str, uint32 len);
+
+ // Helper function that converts a PP_Var to a string. This will return NULL
+ // if the PP_Var is not of string type or the string is invalid.
+ static scoped_refptr<StringVar> FromPPVar(PP_Var var);
+
+ private:
+ std::string value_;
+
+ DISALLOW_COPY_AND_ASSIGN(StringVar);
+};
+
+// ObjectVar -------------------------------------------------------------------
+
+// Represents a JavaScript object Var. By itself, this represents random
+// NPObjects that a given plugin (identified by the resource's module) wants to
+// reference. If two different modules reference the same NPObject (like the
+// "window" object), then there will be different ObjectVar's (and hence PP_Var
+// IDs) for each module. This allows us to track all references owned by a
+// given module and free them when the plugin exits independently of other
+// plugins that may be running at the same time.
+//
+// See StringVar for examples, except obviously using NPObjects instead of
+// strings.
+class ObjectVar : public Var {
+ public:
+ virtual ~ObjectVar();
+
+ // Resource overrides.
+ virtual ObjectVar* AsObjectVar();
+
+ // Returns the underlying NPObject corresponding to this ObjectVar.
+ // Guaranteed non-NULL.
+ NPObject* np_object() const { return np_object_; }
+
+ // Helper function to create a PP_Var of type object that contains the given
+ // NPObject for use byt he given module. Calling this function multiple times
+ // given the same module + NPObject results in the same PP_Var, assuming that
+ // there is still a PP_Var with a reference open to it from the previous
+ // call.
+ //
+ // The module is necessary because we can have different modules pointing to
+ // the same NPObject, and we want to keep their refs separate.
+ //
+ // If no ObjectVar currently exists corresponding to the NPObject, one is
+ // created associated with the given module.
+ static PP_Var NPObjectToPPVar(PluginModule* module, NPObject* object);
+
+ // Helper function that converts a PP_Var to an object. This will return NULL
+ // if the PP_Var is not of object type or the object is invalid.
+ static scoped_refptr<ObjectVar> FromPPVar(PP_Var var);
+
+ protected:
+ // You should always use FromNPObject to create an ObjectVar. This function
+ // guarantees that we maintain the 1:1 mapping between NPObject and
+ // ObjectVar.
+ ObjectVar(PluginModule* module, NPObject* np_object);
+
+ private:
+ // Guaranteed non-NULL, this is the underlying object used by WebKit. We
+ // hold a reference to this object.
+ NPObject* np_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(ObjectVar);
+};
+
+// TryCatch --------------------------------------------------------------------
+
+// Instantiate this object on the stack to catch V8 exceptions and pass them
+// to an optional out parameter supplied by the plugin.
+class TryCatch {
+ public:
+ // The given exception may be NULL if the consumer isn't interested in
+ // catching exceptions. If non-NULL, the given var will be updated if any
+ // exception is thrown (so it must outlive the TryCatch object).
+ //
+ // The module associated with the exception is passed so we know which module
+ // to associate any exception string with. It may be NULL if you don't know
+ // the module at construction time, in which case you should set it later
+ // by calling set_module().
+ //
+ // If an exception is thrown when the module is NULL, setting *any* exception
+ // will result in using the InvalidObjectException.
+ TryCatch(PluginModule* module, PP_Var* exception);
+ ~TryCatch();
+
+ // Get and set the module. This may be NULL (see the constructor).
+ PluginModule* module() { return module_; }
+ void set_module(PluginModule* module) { module_ = module; }
+
+ // Returns true is an exception has been thrown. This can be true immediately
+ // after construction if the var passed to the constructor is non-void.
+ bool has_exception() const { return has_exception_; }
+
+ // Sets the given exception. If no module has been set yet, the message will
+ // be ignored (since we have no module to associate the string with) and the
+ // SetInvalidObjectException() will be used instead.
+ //
+ // If an exception has been previously set, this function will do nothing
+ // (normally you want only the first exception).
+ void SetException(const char* message);
+
+ // Sets the exception to be a generic message contained in a magic string
+ // not associated with any module.
+ void SetInvalidObjectException();
+
+ private:
+ static void Catch(void* self, const char* message);
+
+ PluginModule* module_;
+
+ // True if an exception has been thrown. Since the exception itself may be
+ // NULL if the plugin isn't interested in getting the exception, this will
+ // always indicate if SetException has been called, regardless of whether
+ // the exception itself has been stored.
+ bool has_exception_;
+
+ // May be null if the consumer isn't interesting in catching exceptions.
+ PP_Var* exception_;
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_VAR_H_
diff --git a/webkit/plugins/ppapi/var_object_class.cc b/webkit/plugins/ppapi/var_object_class.cc
new file mode 100644
index 0000000..282ad72
--- /dev/null
+++ b/webkit/plugins/ppapi/var_object_class.cc
@@ -0,0 +1,286 @@
+// Copyright (c) 2010 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 "webkit/plugins/ppapi/var_object_class.h"
+
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "webkit/plugins/ppapi/npapi_glue.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+#include "webkit/plugins/ppapi/var.h"
+
+using WebKit::WebBindings;
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+// VarObjectAccessorWithIdentifier ---------------------------------------------
+
+// Helper class for the new (PPB_Class) NPObject wrapper. This converts a call
+// from WebKit where it gives us an NPObject and an NPIdentifier to an
+// easily-accessible InstanceData (corresponding to the NPObject) and
+// std::string and Property (corresponding to the NPIdentifier).
+class VarObjectAccessorWithIdentifier {
+ public:
+ VarObjectAccessorWithIdentifier(NPObject* object, NPIdentifier identifier)
+ : exists_(false),
+ instance_(static_cast<VarObjectClass::InstanceData*>(object)),
+ property_(NULL) {
+ if (instance_) {
+ const NPUTF8* string_value = NULL;
+ int32_t int_value = 0;
+ bool is_string = false;
+ WebBindings::extractIdentifierData(identifier, string_value, int_value,
+ is_string);
+ if (is_string) {
+ property_name_ = string_value;
+
+ const VarObjectClass::PropertyMap& properties =
+ instance_->object_class->properties();
+ VarObjectClass::PropertyMap::const_iterator it =
+ properties.find(property_name_);
+ if (it != properties.end()) {
+ property_ = &it->second;
+ exists_ = true;
+ }
+ }
+ }
+ }
+
+ // Return true if the object is valid, the identifier is valid, and the
+ // property with said name exists.
+ bool exists() const { return exists_; }
+ bool is_method() const { return exists() && property_->method; }
+ bool is_readable() const { return exists() && property_->getter; }
+ bool is_writable() const {
+ return exists() && property_->setter && property_->writable;
+ }
+ const VarObjectClass::InstanceData* instance() const { return instance_; }
+ const VarObjectClass::Property* property() const { return property_; }
+ PluginModule* module() const {
+ return instance_ ? instance_->object_class->module() : NULL;
+ }
+
+ private:
+ bool exists_;
+ const VarObjectClass::InstanceData* instance_;
+ std::string property_name_;
+ const VarObjectClass::Property* property_;
+
+ DISALLOW_COPY_AND_ASSIGN(VarObjectAccessorWithIdentifier);
+};
+
+NPObject* VarObjectClassAllocate(NPP npp, NPClass* the_class) {
+ return new VarObjectClass::InstanceData;
+}
+
+void VarObjectClassDeallocate(NPObject* object) {
+ VarObjectClass::InstanceData* instance =
+ static_cast<VarObjectClass::InstanceData*>(object);
+ if (instance->object_class->instance_native_destructor())
+ instance->object_class->instance_native_destructor()(instance->native_data);
+ delete instance;
+}
+
+bool VarObjectClassHasMethod(NPObject* np_obj, NPIdentifier name) {
+ VarObjectAccessorWithIdentifier accessor(np_obj, name);
+ return accessor.is_method();
+}
+
+bool VarObjectClassInvoke(NPObject* np_obj, NPIdentifier name,
+ const NPVariant* args, uint32 arg_count,
+ NPVariant* result) {
+ VarObjectAccessorWithIdentifier accessor(np_obj, name);
+ if (!accessor.is_method())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(np_obj, result);
+ PPVarArrayFromNPVariantArray arguments(accessor.module(), arg_count, args);
+ PPVarFromNPObject self(accessor.module(), np_obj);
+
+ return result_converter.SetResult(accessor.property()->method(
+ accessor.instance()->native_data, self.var(), arguments.array(), arg_count,
+ result_converter.exception()));
+}
+
+bool VarObjectClassInvokeDefault(NPObject* np_obj,
+ const NPVariant* args,
+ uint32 arg_count,
+ NPVariant* result) {
+ VarObjectClass::InstanceData* instance =
+ static_cast<VarObjectClass::InstanceData*>(np_obj);
+ if (!instance || !instance->object_class->instance_invoke())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(np_obj, result);
+ PPVarArrayFromNPVariantArray arguments(instance->object_class->module(),
+ arg_count, args);
+ PPVarFromNPObject self(instance->object_class->module(), np_obj);
+
+ return result_converter.SetResult(instance->object_class->instance_invoke()(
+ instance->native_data, self.var(), arguments.array(), arg_count,
+ result_converter.exception()));
+}
+
+bool VarObjectClassHasProperty(NPObject* np_obj, NPIdentifier name) {
+ VarObjectAccessorWithIdentifier accessor(np_obj, name);
+ return accessor.is_readable();
+}
+
+bool VarObjectClassGetProperty(NPObject* np_obj, NPIdentifier name,
+ NPVariant* result) {
+ VarObjectAccessorWithIdentifier accessor(np_obj, name);
+ if (!accessor.is_readable()) {
+ return false;
+ }
+
+ PPResultAndExceptionToNPResult result_converter(np_obj, result);
+ PPVarFromNPObject self(accessor.module(), np_obj);
+
+ return result_converter.SetResult(accessor.property()->getter(
+ accessor.instance()->native_data, self.var(), 0, 0,
+ result_converter.exception()));
+}
+
+bool VarObjectClassSetProperty(NPObject* np_obj, NPIdentifier name,
+ const NPVariant* variant) {
+ VarObjectAccessorWithIdentifier accessor(np_obj, name);
+ if (!accessor.is_writable()) {
+ return false;
+ }
+
+ PPResultAndExceptionToNPResult result_converter(np_obj, NULL);
+ PPVarArrayFromNPVariantArray arguments(accessor.module(), 1, variant);
+ PPVarFromNPObject self(accessor.module(), np_obj);
+
+ // Ignore return value.
+ Var::PluginReleasePPVar(accessor.property()->setter(
+ accessor.instance()->native_data, self.var(), arguments.array(), 1,
+ result_converter.exception()));
+
+ return result_converter.CheckExceptionForNoResult();
+}
+
+bool VarObjectClassEnumerate(NPObject *np_obj, NPIdentifier **value,
+ uint32_t *count) {
+ VarObjectClass::InstanceData* instance =
+ static_cast<VarObjectClass::InstanceData*>(np_obj);
+ *count = 0;
+ *value = NULL;
+ if (!instance)
+ return false;
+
+ const VarObjectClass::PropertyMap& properties =
+ instance->object_class->properties();
+
+ // Don't bother calculating the size of enumerable properties, just allocate
+ // enough for all and then fill it partially.
+ *value = static_cast<NPIdentifier*>(
+ malloc(sizeof(NPIdentifier) * properties.size()));
+
+ NPIdentifier* inserter = *value;
+ for (VarObjectClass::PropertyMap::const_iterator i = properties.begin();
+ i != properties.end(); ++i)
+ if (i->second.enumerable)
+ *inserter++ = WebBindings::getStringIdentifier(i->first.c_str());
+
+ *count = inserter - *value;
+ return true;
+}
+
+NPClass objectclassvar_class = {
+ NP_CLASS_STRUCT_VERSION,
+ &VarObjectClassAllocate,
+ &VarObjectClassDeallocate,
+ NULL,
+ &VarObjectClassHasMethod,
+ &VarObjectClassInvoke,
+ &VarObjectClassInvokeDefault,
+ &VarObjectClassHasProperty,
+ &VarObjectClassGetProperty,
+ &VarObjectClassSetProperty,
+ NULL,
+ &VarObjectClassEnumerate,
+};
+
+// PPB_Class -------------------------------------------------------------------
+
+PP_Resource Create(PP_Module module, PP_ClassDestructor destruct,
+ PP_ClassFunction invoke, PP_ClassProperty* properties) {
+ PluginModule* plugin_module = ResourceTracker::Get()->GetModule(module);
+ if (!properties || !plugin_module)
+ return 0;
+ scoped_refptr<VarObjectClass> cls = new VarObjectClass(plugin_module,
+ destruct,
+ invoke,
+ properties);
+ if (!cls)
+ return 0;
+ return cls->GetReference();
+}
+
+PP_Var Instantiate(PP_Resource class_object, void* native_data,
+ PP_Var* exception) {
+ scoped_refptr<VarObjectClass> object_class =
+ Resource::GetAs<VarObjectClass>(class_object);
+ if (!object_class)
+ return PP_MakeUndefined();
+ NPObject* obj = WebBindings::createObject(NULL, &objectclassvar_class);
+ VarObjectClass::InstanceData* instance_data =
+ static_cast<VarObjectClass::InstanceData*>(obj);
+ instance_data->object_class = object_class;
+ instance_data->native_data = native_data;
+ return ObjectVar::NPObjectToPPVar(object_class->module(), obj);
+}
+
+} // namespace
+
+// VarObjectClass --------------------------------------------------------------
+
+VarObjectClass::Property::Property(const PP_ClassProperty& prop)
+ : method(prop.method),
+ getter(prop.getter),
+ setter(prop.setter),
+ writable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)),
+ enumerable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) {
+}
+
+VarObjectClass::InstanceData::InstanceData() : native_data(NULL) {
+}
+
+VarObjectClass::VarObjectClass(PluginModule* module,
+ PP_ClassDestructor destruct,
+ PP_ClassFunction invoke,
+ PP_ClassProperty* properties)
+ : Resource(module),
+ instance_native_destructor_(destruct),
+ instance_invoke_(invoke) {
+ PP_ClassProperty* prop = properties;
+ while (prop->name) {
+ properties_.insert(std::make_pair(std::string(prop->name),
+ Property(*prop)));
+ ++prop;
+ }
+}
+
+// virtual
+VarObjectClass::~VarObjectClass() {
+}
+
+VarObjectClass* VarObjectClass::AsVarObjectClass() {
+ return this;
+}
+
+// static
+const PPB_Class* VarObjectClass::GetInterface() {
+ static PPB_Class interface = {
+ &Create,
+ &Instantiate
+ };
+ return &interface;
+}
+
+} // namespace ppapi
+} // namespace webkit
diff --git a/webkit/plugins/ppapi/var_object_class.h b/webkit/plugins/ppapi/var_object_class.h
new file mode 100644
index 0000000..7f9cb98
--- /dev/null
+++ b/webkit/plugins/ppapi/var_object_class.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2010 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 WEBKIT_PLUGINS_PPAPI_CLASS_H_
+#define WEBKIT_PLUGINS_PPAPI_CLASS_H_
+
+#include "webkit/plugins/ppapi/resource.h"
+
+#include <string>
+
+#include "base/hash_tables.h"
+#include "base/ref_counted.h"
+#include "ppapi/c/ppb_class.h"
+#include "third_party/npapi/bindings/npruntime.h"
+
+namespace webkit {
+namespace ppapi {
+
+class PluginModule;
+
+class VarObjectClass : public Resource {
+ public:
+ struct Property {
+ explicit Property(const PP_ClassProperty& prop);
+
+ const PP_ClassFunction method;
+ const PP_ClassFunction getter;
+ const PP_ClassFunction setter;
+ const bool writable;
+ const bool enumerable;
+ };
+
+ struct InstanceData : public NPObject {
+ InstanceData();
+
+ scoped_refptr<VarObjectClass> object_class;
+ void* native_data;
+ };
+
+ typedef base::hash_map<std::string, Property> PropertyMap;
+
+ VarObjectClass(PluginModule* module, PP_ClassDestructor destruct,
+ PP_ClassFunction invoke, PP_ClassProperty* properties);
+ virtual ~VarObjectClass();
+
+ // Resource override.
+ virtual VarObjectClass* AsVarObjectClass();
+
+ // Returns the PPB_Var interface for the plugin to use.
+ static const PPB_Class* GetInterface();
+
+ const PropertyMap &properties() const { return properties_; }
+
+ PP_ClassDestructor instance_native_destructor() {
+ return instance_native_destructor_;
+ }
+
+ PP_ClassFunction instance_invoke() {
+ return instance_invoke_;
+ }
+
+ private:
+ PropertyMap properties_;
+ PP_ClassDestructor instance_native_destructor_;
+ PP_ClassFunction instance_invoke_;
+
+ DISALLOW_COPY_AND_ASSIGN(VarObjectClass);
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_CLASS_H_
+