diff options
Diffstat (limited to 'chrome')
-rwxr-xr-x | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/renderer/DEPS | 1 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 4 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.cc | 423 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.h | 134 |
5 files changed, 562 insertions, 2 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 4b8d7e8..9b34464 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -3219,6 +3219,8 @@ 'renderer/visitedlink_slave.h', 'renderer/webplugin_delegate_proxy.cc', 'renderer/webplugin_delegate_proxy.h', + 'renderer/webplugin_delegate_pepper.cc', + 'renderer/webplugin_delegate_pepper.h', 'renderer/webworker_proxy.cc', 'renderer/webworker_proxy.h', ], diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS index f8b66fe..eba4b00 100644 --- a/chrome/renderer/DEPS +++ b/chrome/renderer/DEPS @@ -12,6 +12,7 @@ include_rules = [ "+webkit/glue", "+webkit/glue/plugins", "+v8/include", + "+third_party/npapi/bindings", "+third_party/sqlite/preprocessed", "+third_party/tcmalloc", diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 24b6850..490a1ee 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -50,6 +50,7 @@ #include "chrome/renderer/render_process.h" #include "chrome/renderer/user_script_slave.h" #include "chrome/renderer/visitedlink_slave.h" +#include "chrome/renderer/webplugin_delegate_pepper.h" #include "chrome/renderer/webplugin_delegate_proxy.h" #include "chrome/renderer/webworker_proxy.h" #include "grit/generated_resources.h" @@ -90,7 +91,6 @@ #include "webkit/glue/password_form.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/webplugin_delegate_impl.h" -#include "webkit/glue/plugins/webplugin_delegate_pepper_impl.h" #include "webkit/glue/searchable_form_data.h" #include "webkit/glue/webaccessibilitymanager_impl.h" #include "webkit/glue/webdropdata.h" @@ -2458,7 +2458,7 @@ webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate( #if defined(PEPPER_APIS_ENABLED) const char kPepperPrefix[] = "pepper-"; if (StartsWithASCII(*mime_type_to_use, kPepperPrefix, true)) { - return WebPluginDelegatePepperImpl::Create( + return WebPluginDelegatePepper::Create( path, *mime_type_to_use, gfx::NativeViewFromId(host_window_)); } #endif diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc new file mode 100644 index 0000000..42f3f53 --- /dev/null +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -0,0 +1,423 @@ +// Copyright (c) 2006-2008 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. + +#define PEPPER_APIS_ENABLED 1 + +#include "chrome/renderer/webplugin_delegate_pepper.h" + +#include <string> +#include <vector> + +#include "app/gfx/blit.h" +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/process_util.h" +#include "base/scoped_ptr.h" +#include "base/stats_counters.h" +#include "base/string_util.h" +#include "webkit/api/public/WebInputEvent.h" +#include "webkit/glue/glue_util.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/webkit_glue.h" + +using webkit_glue::WebPlugin; +using webkit_glue::WebPluginDelegate; +using webkit_glue::WebPluginResourceClient; +using WebKit::WebCursorInfo; +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; +using WebKit::WebMouseWheelEvent; + +namespace { + const uint32 kBytesPerPixel = 4; // Only 8888 RGBA for now. +} // namespace + +uint32 WebPluginDelegatePepper::next_buffer_id = 0; + +WebPluginDelegatePepper* WebPluginDelegatePepper::Create( + const FilePath& filename, + const std::string& mime_type, + gfx::PluginWindowHandle containing_view) { + scoped_refptr<NPAPI::PluginLib> plugin_lib = + NPAPI::PluginLib::CreatePluginLib(filename); + if (plugin_lib.get() == NULL) + return NULL; + + NPError err = plugin_lib->NP_Initialize(); + if (err != NPERR_NO_ERROR) + return NULL; + + scoped_refptr<NPAPI::PluginInstance> instance = + plugin_lib->CreateInstance(mime_type); + return new WebPluginDelegatePepper(containing_view, instance.get()); +} + +bool WebPluginDelegatePepper::Initialize( + const GURL& url, + const std::vector<std::string>& arg_names, + const std::vector<std::string>& arg_values, + WebPlugin* plugin, + bool load_manually) { + plugin_ = plugin; + + instance_->set_web_plugin(plugin_); + int argc = 0; + scoped_array<char*> argn(new char*[arg_names.size()]); + scoped_array<char*> argv(new char*[arg_names.size()]); + for (size_t i = 0; i < arg_names.size(); ++i) { + argn[argc] = const_cast<char*>(arg_names[i].c_str()); + argv[argc] = const_cast<char*>(arg_values[i].c_str()); + argc++; + } + + bool start_result = instance_->Start( + url, argn.get(), argv.get(), argc, load_manually); + if (!start_result) + return false; + + // For windowless plugins we should set the containing window handle + // as the instance window handle. This is what Safari does. Not having + // a valid window handle causes subtle bugs with plugins which retreive + // the window handle and validate the same. The window handle can be + // retreived via NPN_GetValue of NPNVnetscapeWindow. + instance_->set_window_handle(parent_); + + plugin_url_ = url.spec(); + + return true; +} + +void WebPluginDelegatePepper::DestroyInstance() { + if (instance_ && (instance_->npp()->ndata != NULL)) { + // Shutdown all streams before destroying so that + // no streams are left "in progress". Need to do + // this before calling set_web_plugin(NULL) because the + // instance uses the helper to do the download. + instance_->CloseStreams(); + + window_.window = NULL; + instance_->NPP_SetWindow(&window_); + + instance_->NPP_Destroy(); + + instance_->set_web_plugin(NULL); + + instance_ = 0; + } +} + +void WebPluginDelegatePepper::UpdateGeometry( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) { + // Only resend to the instance if the geometry has changed. + if (window_rect == window_rect_ && clip_rect == clip_rect_) + return; + + clip_rect_ = clip_rect; + cutout_rects_.clear(); + + if (window_rect_ == window_rect) + return; + window_rect_ = window_rect; + uint32 buffer_size = window_rect.height() * + window_rect.width() * + kBytesPerPixel; + if (buffer_size_ < buffer_size) { + buffer_size_ = buffer_size; + plugin_buffer_ = TransportDIB::Create(buffer_size, ++next_buffer_id); + } + + if (!instance()) + return; + + // TODO(sehr): do we need all this? + window_.clipRect.top = clip_rect_.y(); + window_.clipRect.left = clip_rect_.x(); + window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); + window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); + window_.height = window_rect_.height(); + window_.width = window_rect_.width(); + window_.x = window_rect_.x(); + window_.y = window_rect_.y(); + window_.type = NPWindowTypeDrawable; +} + +NPObject* WebPluginDelegatePepper::GetPluginScriptableObject() { + return instance_->GetPluginScriptableObject(); +} + +void WebPluginDelegatePepper::DidFinishLoadWithReason( + const GURL& url, + NPReason reason, + intptr_t notify_data) { + instance()->DidFinishLoadWithReason( + url, reason, reinterpret_cast<void*>(notify_data)); +} + +int WebPluginDelegatePepper::GetProcessId() { + // We are in process, so the plugin pid is this current process pid. + return base::GetCurrentProcId(); +} + +void WebPluginDelegatePepper::SendJavaScriptStream( + const GURL& url, + const std::string& result, + bool success, + bool notify_needed, + intptr_t notify_data) { + instance()->SendJavaScriptStream(url, result, success, notify_needed, + notify_data); +} + +void WebPluginDelegatePepper::DidReceiveManualResponse( + const GURL& url, const std::string& mime_type, + const std::string& headers, uint32 expected_length, uint32 last_modified) { + instance()->DidReceiveManualResponse(url, mime_type, headers, + expected_length, last_modified); +} + +void WebPluginDelegatePepper::DidReceiveManualData(const char* buffer, + int length) { + instance()->DidReceiveManualData(buffer, length); +} + +void WebPluginDelegatePepper::DidFinishManualLoading() { + instance()->DidFinishManualLoading(); +} + +void WebPluginDelegatePepper::DidManualLoadFail() { + instance()->DidManualLoadFail(); +} + +FilePath WebPluginDelegatePepper::GetPluginPath() { + return instance()->plugin_lib()->plugin_info().path; +} + +WebPluginResourceClient* WebPluginDelegatePepper::CreateResourceClient( + int resource_id, const GURL& url, bool notify_needed, + intptr_t notify_data, intptr_t existing_stream) { + // Stream already exists. This typically happens for range requests + // initiated via NPN_RequestRead. + if (existing_stream) { + NPAPI::PluginStream* plugin_stream = + reinterpret_cast<NPAPI::PluginStream*>(existing_stream); + + return plugin_stream->AsResourceClient(); + } + + std::string mime_type; + NPAPI::PluginStreamUrl *stream = instance()->CreateStream( + resource_id, url, mime_type, notify_needed, + reinterpret_cast<void*>(notify_data)); + return stream; +} + +bool WebPluginDelegatePepper::IsPluginDelegateWindow( + gfx::NativeWindow window) { + return false; +} + +bool WebPluginDelegatePepper::GetPluginNameFromWindow( + gfx::NativeWindow window, std::wstring *plugin_name) { + return false; +} + +bool WebPluginDelegatePepper::IsDummyActivationWindow( + gfx::NativeWindow window) { + return false; +} + +WebPluginDelegatePepper::WebPluginDelegatePepper( + gfx::PluginWindowHandle containing_view, + NPAPI::PluginInstance *instance) + : plugin_(NULL), + instance_(instance), + parent_(containing_view), + buffer_size_(0), + plugin_buffer_(0), + background_canvas_(0) { + memset(&window_, 0, sizeof(window_)); +} + +WebPluginDelegatePepper::~WebPluginDelegatePepper() { + DestroyInstance(); +} + +void WebPluginDelegatePepper::PluginDestroyed() { + delete this; +} + +void WebPluginDelegatePepper::Paint(gfx::NativeDrawingContext context, + const gfx::Rect& rect) { + static StatsRate plugin_paint("Plugin.Paint"); + StatsScope<StatsRate> scope(plugin_paint); + // Blit from background_context to context. + if (background_canvas_ != NULL) { + gfx::Point origin(window_rect_.origin().x(), window_rect_.origin().y()); + gfx::BlitCanvasToContext(context, rect, background_canvas_, origin); + } +} + +void WebPluginDelegatePepper::Print(gfx::NativeDrawingContext context) { + NOTIMPLEMENTED(); +} + +void WebPluginDelegatePepper::InstallMissingPlugin() { + NOTIMPLEMENTED(); +} + +void WebPluginDelegatePepper::SetFocus() { + NPEvent npevent; + + npevent.type = NPEventType_Focus; + npevent.size = sizeof(NPEvent); + // TODO(sehr): what timestamp should this have? + npevent.timeStampSeconds = 0.0; + // Currently this API only supports gaining focus. + npevent.u.focus.value = 1; + instance()->NPP_HandleEvent(&npevent); +} + +// Anonymous namespace for functions converting WebInputEvents to NPAPI types. +namespace { +NPEventTypes ConvertEventTypes(WebInputEvent::Type wetype) { + switch (wetype) { + case WebInputEvent::MouseDown: + return NPEventType_MouseDown; + case WebInputEvent::MouseUp: + return NPEventType_MouseUp; + case WebInputEvent::MouseMove: + return NPEventType_MouseMove; + case WebInputEvent::MouseEnter: + return NPEventType_MouseEnter; + case WebInputEvent::MouseLeave: + return NPEventType_MouseLeave; + case WebInputEvent::MouseWheel: + return NPEventType_MouseWheel; + case WebInputEvent::RawKeyDown: + return NPEventType_RawKeyDown; + case WebInputEvent::KeyDown: + return NPEventType_KeyDown; + case WebInputEvent::KeyUp: + return NPEventType_KeyUp; + case WebInputEvent::Char: + return NPEventType_Char; + case WebInputEvent::Undefined: + default: + return NPEventType_Undefined; + } +} + +void BuildKeyEvent(const WebInputEvent* event, NPEvent* npevent) { + const WebKeyboardEvent* key_event = + reinterpret_cast<const WebKeyboardEvent*>(event); + npevent->u.key.modifier = key_event->modifiers; + npevent->u.key.normalizedKeyCode = key_event->windowsKeyCode; +} + +void BuildCharEvent(const WebInputEvent* event, NPEvent* npevent) { + const WebKeyboardEvent* key_event = + reinterpret_cast<const WebKeyboardEvent*>(event); + npevent->u.character.modifier = key_event->modifiers; + // For consistency, check that the sizes of the texts agree. + DCHECK(sizeof(npevent->u.character.text) == sizeof(key_event->text)); + DCHECK(sizeof(npevent->u.character.unmodifiedText) == + sizeof(key_event->unmodifiedText)); + for (size_t i = 0; i < WebKeyboardEvent::textLengthCap; ++i) { + npevent->u.character.text[i] = key_event->text[i]; + npevent->u.character.unmodifiedText[i] = key_event->unmodifiedText[i]; + } +} + +void BuildMouseEvent(const WebInputEvent* event, NPEvent* npevent) { + const WebMouseEvent* mouse_event = + reinterpret_cast<const WebMouseEvent*>(event); + npevent->u.mouse.modifier = mouse_event->modifiers; + npevent->u.mouse.button = mouse_event->button; + npevent->u.mouse.x = mouse_event->x; + npevent->u.mouse.y = mouse_event->y; + npevent->u.mouse.clickCount = mouse_event->clickCount; +} + +void BuildMouseWheelEvent(const WebInputEvent* event, NPEvent* npevent) { + const WebMouseWheelEvent* mouse_wheel_event = + reinterpret_cast<const WebMouseWheelEvent*>(event); + npevent->u.wheel.modifier = mouse_wheel_event->modifiers; + npevent->u.wheel.deltaX = mouse_wheel_event->deltaX; + npevent->u.wheel.deltaY = mouse_wheel_event->deltaY; + npevent->u.wheel.wheelTicksX = mouse_wheel_event->wheelTicksX; + npevent->u.wheel.wheelTicksY = mouse_wheel_event->wheelTicksY; + npevent->u.wheel.scrollByPage = mouse_wheel_event->scrollByPage; +} +} // namespace + +bool WebPluginDelegatePepper::HandleInputEvent(const WebInputEvent& event, + WebCursorInfo* cursor_info) { + NPEvent npevent; + + npevent.type = ConvertEventTypes(event.type); + npevent.size = sizeof(NPEvent); + npevent.timeStampSeconds = event.timeStampSeconds; + switch (npevent.type) { + case NPEventType_Undefined: + return false; + case NPEventType_MouseDown: + case NPEventType_MouseUp: + case NPEventType_MouseMove: + case NPEventType_MouseEnter: + case NPEventType_MouseLeave: + BuildMouseEvent(&event, &npevent); + break; + case NPEventType_MouseWheel: + BuildMouseWheelEvent(&event, &npevent); + break; + case NPEventType_RawKeyDown: + case NPEventType_KeyDown: + case NPEventType_KeyUp: + BuildKeyEvent(&event, &npevent); + case NPEventType_Char: + BuildCharEvent(&event, &npevent); + break; + case NPEventType_Minimize: + case NPEventType_Focus: + case NPEventType_Device: + NOTIMPLEMENTED(); + break; + } + return instance()->NPP_HandleEvent(&npevent) != 0; +} + +NPError WebPluginDelegatePepper::InitializeRenderContext( + NPRenderType type, NPRenderContext* context) { + switch (type) { + case NPRenderGraphicsRGBA: { + int width = window_rect_.width(); + int height = window_rect_.height(); + background_canvas_ = new skia::PlatformCanvas(width, height, false); + plugin_canvas_ = plugin_buffer_->GetPlatformCanvas(width, height); + if (background_canvas_ == NULL || plugin_canvas_ == NULL) { + return NPERR_GENERIC_ERROR; + } + context->u.graphicsRgba.region = plugin_buffer_->memory(); + context->u.graphicsRgba.stride = width * kBytesPerPixel; + return NPERR_NO_ERROR; + } + default: + return NPERR_GENERIC_ERROR; + } +} + +NPError WebPluginDelegatePepper::FlushRenderContext( + NPRenderContext* context) { + gfx::BlitCanvasToCanvas(background_canvas_, + window_rect_, + plugin_canvas_, + window_rect_.origin()); + return NPERR_NO_ERROR; +} diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h new file mode 100644 index 0000000..bc59b2a --- /dev/null +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -0,0 +1,134 @@ +// Copyright (c) 2006-2008 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 CHROME_RENDERER_WEBPLUGIN_DELEGATE_PEPPER_H_ +#define CHROME_RENDERER_WEBPLUGIN_DELEGATE_PEPPER_H_ + +#include "build/build_config.h" + +#include <list> +#include <string> +#include <vector> + +#include "app/gfx/native_widget_types.h" +#include "base/file_path.h" +#include "base/gfx/rect.h" +#include "base/ref_counted.h" +#include "base/task.h" +#include "chrome/common/transport_dib.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/npapi/bindings/npapi.h" +#include "webkit/glue/webcursor.h" +#include "webkit/glue/webplugin_delegate.h" + +namespace NPAPI { +class PluginInstance; +} + +// An implementation of WebPluginDelegate for Pepper in-process plugins. +class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { + public: + static WebPluginDelegatePepper* Create(const FilePath& filename, + const std::string& mime_type, gfx::PluginWindowHandle containing_view); + + static bool IsPluginDelegateWindow(gfx::NativeWindow window); + static bool GetPluginNameFromWindow(gfx::NativeWindow window, + std::wstring *plugin_name); + + // Returns true if the window handle passed in is that of the dummy + // activation window for windowless plugins. + static bool IsDummyActivationWindow(gfx::NativeWindow window); + + // WebPluginDelegate implementation + virtual bool Initialize(const GURL& url, + const std::vector<std::string>& arg_names, + const std::vector<std::string>& arg_values, + webkit_glue::WebPlugin* plugin, + bool load_manually); + virtual void PluginDestroyed(); + virtual void UpdateGeometry(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect); + virtual void Paint(gfx::NativeDrawingContext context, const gfx::Rect& rect); + virtual void Print(gfx::NativeDrawingContext context); + virtual void SetFocus(); + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebKit::WebCursorInfo* cursor); + virtual NPObject* GetPluginScriptableObject(); + virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason, + intptr_t notify_data); + virtual int GetProcessId(); + virtual void SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, bool notify_needed, + intptr_t notify_data); + virtual void DidReceiveManualResponse(const GURL& url, + const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified); + virtual void DidReceiveManualData(const char* buffer, int length); + virtual void DidFinishManualLoading(); + virtual void DidManualLoadFail(); + virtual void InstallMissingPlugin(); + virtual webkit_glue::WebPluginResourceClient* CreateResourceClient( + int resource_id, + const GURL& url, + bool notify_needed, + intptr_t notify_data, + intptr_t stream); + // End of WebPluginDelegate implementation. + + bool IsWindowless() const { return true; } + gfx::Rect GetRect() const { return window_rect_; } + gfx::Rect GetClipRect() const { return clip_rect_; } + + // Returns the path for the library implementing this plugin. + FilePath GetPluginPath(); + + private: + WebPluginDelegatePepper(gfx::PluginWindowHandle containing_view, + NPAPI::PluginInstance *instance); + ~WebPluginDelegatePepper(); + + //---------------------------- + // used for windowless plugins + virtual NPError InitializeRenderContext(NPRenderType type, + NPRenderContext* context); + virtual NPError FlushRenderContext(NPRenderContext* context); + + // Tells the plugin about the current state of the window. + // See NPAPI NPP_SetWindow for more information. + void WindowlessSetWindow(bool force_set_window); + + //----------------------------------------- + // used for windowed and windowless plugins + + NPAPI::PluginInstance* instance() { return instance_.get(); } + + // Closes down and destroys our plugin instance. + void DestroyInstance(); + + webkit_glue::WebPlugin* plugin_; + scoped_refptr<NPAPI::PluginInstance> instance_; + + gfx::PluginWindowHandle parent_; + NPWindow window_; + gfx::Rect window_rect_; + gfx::Rect clip_rect_; + std::vector<gfx::Rect> cutout_rects_; + + // Plugin graphics context implementation + size_t buffer_size_; + TransportDIB* plugin_buffer_; + static uint32 next_buffer_id; + skia::PlatformCanvas* plugin_canvas_; + skia::PlatformCanvas* background_canvas_; + + // The url with which the plugin was instantiated. + std::string plugin_url_; + + DISALLOW_COPY_AND_ASSIGN(WebPluginDelegatePepper); +}; + +#endif // CHROME_RENDERER_WEBPLUGIN_DELEGATE_PEPPER_H_ |