diff options
author | sehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-17 22:32:29 +0000 |
---|---|---|
committer | sehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-17 22:32:29 +0000 |
commit | d439ba076792f1aa83a04ca562382a9af3c0de9d (patch) | |
tree | 7d5ab9d4d5c3c56d50eb5b79af3ab660ef0b9f53 /chrome | |
parent | 0877e3db672aa26d89549f545e6e6c64904fec4c (diff) | |
download | chromium_src-d439ba076792f1aa83a04ca562382a9af3c0de9d.zip chromium_src-d439ba076792f1aa83a04ca562382a9af3c0de9d.tar.gz chromium_src-d439ba076792f1aa83a04ca562382a9af3c0de9d.tar.bz2 |
Moved Pepper delegate definition to chrome\renderer to allow it to use
code from chrome\common.
Also added canvas support and hooked up NPAPI interface functions.
No tests have been added yet, so this is probably not fully ready.
Review URL: http://codereview.chromium.org/291001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29380 0039d316-1c4b-4281-b951-d872f2087c98
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_ |