diff options
author | Iain Merrick <husky@google.com> | 2010-10-19 14:37:37 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-10-19 14:37:37 +0100 |
commit | 3345a6884c488ff3a535c2c9acdd33d74b37e311 (patch) | |
tree | 7784b988ef1698cb6967ea1bdf07616237716c6c /webkit/glue/plugins | |
parent | efc8475837ec58186051f23bb03542620424f6ce (diff) | |
download | external_chromium-3345a6884c488ff3a535c2c9acdd33d74b37e311.zip external_chromium-3345a6884c488ff3a535c2c9acdd33d74b37e311.tar.gz external_chromium-3345a6884c488ff3a535c2c9acdd33d74b37e311.tar.bz2 |
Merge Chromium at 7.0.540.0 : Initial merge by git
Not including third_party/icu as it contains huge data files that break Gerrit, and aren't actually used.
Change-Id: I428a386e70f3b58cacd28677b8cfda282e891e15
Diffstat (limited to 'webkit/glue/plugins')
83 files changed, 3376 insertions, 2134 deletions
diff --git a/webkit/glue/plugins/gtk_plugin_container_manager.cc b/webkit/glue/plugins/gtk_plugin_container_manager.cc index 9d9ee4b..f26b44c 100644 --- a/webkit/glue/plugins/gtk_plugin_container_manager.cc +++ b/webkit/glue/plugins/gtk_plugin_container_manager.cc @@ -65,17 +65,21 @@ void GtkPluginContainerManager::MovePluginContainer( return; } - DCHECK(GTK_WIDGET_REALIZED(widget)); gtk_widget_show(widget); if (!move.rects_valid) return; - GdkRectangle clip_rect = move.clip_rect.ToGdkRectangle(); - GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); - gfx::SubtractRectanglesFromRegion(clip_region, move.cutout_rects); - gdk_window_shape_combine_region(widget->window, clip_region, 0, 0); - gdk_region_destroy(clip_region); + // TODO(piman): if the widget hasn't been realized (e.g. the tab has been + // torn off and the parent gtk widget has been detached from the hierarchy), + // we lose the cutout information. + if (GTK_WIDGET_REALIZED(widget)) { + GdkRectangle clip_rect = move.clip_rect.ToGdkRectangle(); + GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); + gfx::SubtractRectanglesFromRegion(clip_region, move.cutout_rects); + gdk_window_shape_combine_region(widget->window, clip_region, 0, 0); + gdk_region_destroy(clip_region); + } // Update the window position. Resizing is handled by WebPluginDelegate. // TODO(deanm): Verify that we only need to move and not resize. diff --git a/webkit/glue/plugins/pepper_buffer.cc b/webkit/glue/plugins/pepper_buffer.cc index 1c0bdd8..c3acef8 100644 --- a/webkit/glue/plugins/pepper_buffer.cc +++ b/webkit/glue/plugins/pepper_buffer.cc @@ -8,10 +8,10 @@ #include "base/logging.h" #include "base/scoped_ptr.h" +#include "third_party/ppapi/c/dev/ppb_buffer_dev.h" #include "third_party/ppapi/c/pp_instance.h" #include "third_party/ppapi/c/pp_module.h" #include "third_party/ppapi/c/pp_resource.h" -#include "third_party/ppapi/c/ppb_buffer.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_plugin_module.h" @@ -22,11 +22,11 @@ namespace { PP_Resource Create(PP_Module module_id, int32_t size) { PluginModule* module = PluginModule::FromPPModule(module_id); if (!module) - return NULL; + return 0; scoped_refptr<Buffer> buffer(new Buffer(module)); if (!buffer->Init(size)) - return NULL; + return 0; return buffer->GetReference(); } @@ -57,7 +57,7 @@ void Unmap(PP_Resource resource) { return buffer->Unmap(); } -const PPB_Buffer ppb_buffer = { +const PPB_Buffer_Dev ppb_buffer = { &Create, &IsBuffer, &Describe, @@ -76,7 +76,7 @@ Buffer::~Buffer() { } // static -const PPB_Buffer* Buffer::GetInterface() { +const PPB_Buffer_Dev* Buffer::GetInterface() { return &ppb_buffer; } diff --git a/webkit/glue/plugins/pepper_buffer.h b/webkit/glue/plugins/pepper_buffer.h index 5d750ec..2f20e55 100644 --- a/webkit/glue/plugins/pepper_buffer.h +++ b/webkit/glue/plugins/pepper_buffer.h @@ -7,9 +7,10 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" -#include "third_party/ppapi/c/ppb_buffer.h" #include "webkit/glue/plugins/pepper_resource.h" +struct PPB_Buffer_Dev; + namespace pepper { class PluginInstance; @@ -28,7 +29,7 @@ class Buffer : public Resource { // Returns a pointer to the interface implementing PPB_Buffer that is // exposed to the plugin. - static const PPB_Buffer* GetInterface(); + static const PPB_Buffer_Dev* GetInterface(); // Resource overrides. Buffer* AsBuffer() { return this; } diff --git a/webkit/glue/plugins/pepper_device_context_2d.cc b/webkit/glue/plugins/pepper_device_context_2d.cc deleted file mode 100644 index 45ed9ee..0000000 --- a/webkit/glue/plugins/pepper_device_context_2d.cc +++ /dev/null @@ -1,553 +0,0 @@ -// 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/glue/plugins/pepper_device_context_2d.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 "third_party/ppapi/c/pp_errors.h" -#include "third_party/ppapi/c/pp_module.h" -#include "third_party/ppapi/c/pp_rect.h" -#include "third_party/ppapi/c/pp_resource.h" -#include "third_party/ppapi/c/ppb_device_context_2d.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "webkit/glue/plugins/pepper_image_data.h" -#include "webkit/glue/plugins/pepper_plugin_instance.h" -#include "webkit/glue/plugins/pepper_plugin_module.h" - -#if defined(OS_MACOSX) -#include "base/mac_util.h" -#include "base/scoped_cftyperef.h" -#endif - -namespace pepper { - -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; -} - -PP_Resource Create(PP_Module module_id, - const PP_Size* size, - bool is_always_opaque) { - PluginModule* module = PluginModule::FromPPModule(module_id); - if (!module) - return NULL; - - scoped_refptr<DeviceContext2D> context(new DeviceContext2D(module)); - if (!context->Init(size->width, size->height, is_always_opaque)) - return NULL; - return context->GetReference(); -} - -bool IsDeviceContext2D(PP_Resource resource) { - return !!Resource::GetAs<DeviceContext2D>(resource); -} - -bool Describe(PP_Resource device_context, - PP_Size* size, - bool* is_always_opaque) { - scoped_refptr<DeviceContext2D> context( - Resource::GetAs<DeviceContext2D>(device_context)); - if (!context) - return false; - return context->Describe(size, is_always_opaque); -} - -bool PaintImageData(PP_Resource device_context, - PP_Resource image, - const PP_Point* top_left, - const PP_Rect* src_rect) { - scoped_refptr<DeviceContext2D> context( - Resource::GetAs<DeviceContext2D>(device_context)); - if (!context) - return false; - return context->PaintImageData(image, top_left, src_rect); -} - -bool Scroll(PP_Resource device_context, - const PP_Rect* clip_rect, - const PP_Point* amount) { - scoped_refptr<DeviceContext2D> context( - Resource::GetAs<DeviceContext2D>(device_context)); - if (!context) - return false; - return context->Scroll(clip_rect, amount); -} - -bool ReplaceContents(PP_Resource device_context, PP_Resource image) { - scoped_refptr<DeviceContext2D> context( - Resource::GetAs<DeviceContext2D>(device_context)); - if (!context) - return false; - return context->ReplaceContents(image); -} - -int32_t Flush(PP_Resource device_context, - PP_CompletionCallback callback) { - scoped_refptr<DeviceContext2D> context( - Resource::GetAs<DeviceContext2D>(device_context)); - if (!context) - return PP_ERROR_BADRESOURCE; - return context->Flush(callback); -} - -const PPB_DeviceContext2D ppb_devicecontext2d = { - &Create, - &IsDeviceContext2D, - &Describe, - &PaintImageData, - &Scroll, - &ReplaceContents, - &Flush -}; - -} // namespace - -struct DeviceContext2D::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<ImageData> 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<ImageData> replace_image; -}; - -DeviceContext2D::DeviceContext2D(PluginModule* module) - : Resource(module), - bound_instance_(NULL), - flushed_any_data_(false), - offscreen_flush_pending_(false) { -} - -DeviceContext2D::~DeviceContext2D() { -} - -// static -const PPB_DeviceContext2D* DeviceContext2D::GetInterface() { - return &ppb_devicecontext2d; -} - -bool DeviceContext2D::Init(int width, int height, bool is_always_opaque) { - // The underlying ImageData will validate the dimensions. - image_data_ = new ImageData(module()); - if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) || - !image_data_->Map()) { - image_data_ = NULL; - return false; - } - - return true; -} - -bool DeviceContext2D::Describe(PP_Size* size, bool* is_always_opaque) { - size->width = image_data_->width(); - size->height = image_data_->height(); - *is_always_opaque = false; // TODO(brettw) implement this. - return true; -} - -bool DeviceContext2D::PaintImageData(PP_Resource image, - const PP_Point* top_left, - const PP_Rect* src_rect) { - if (!top_left) - return false; - - scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image)); - if (!image_resource) - return false; - - QueuedOperation operation(QueuedOperation::PAINT); - operation.paint_image = image_resource; - if (!ValidateAndConvertRect(src_rect, image_resource->width(), - image_resource->height(), - &operation.paint_src_rect)) - return false; - - // 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 false; - if (y64 + static_cast<int64>(operation.paint_src_rect.y()) < 0 || - y64 + static_cast<int64>(operation.paint_src_rect.bottom()) > - image_data_->height()) - return false; - operation.paint_x = top_left->x; - operation.paint_y = top_left->y; - - queued_operations_.push_back(operation); - return true; -} - -bool DeviceContext2D::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 false; - - // 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() || - dx <= -image_data_->height() || dy >= image_data_->height()) - return true; - - operation.scroll_dx = dx; - operation.scroll_dy = dy; - - queued_operations_.push_back(operation); - return false; -} - -bool DeviceContext2D::ReplaceContents(PP_Resource image) { - scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image)); - if (!image_resource) - return false; - if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL) - return false; - - if (image_resource->width() != image_data_->width() || - image_resource->height() != image_data_->height()) - return false; - - QueuedOperation operation(QueuedOperation::REPLACE); - operation.replace_image = image_resource; - queued_operations_.push_back(operation); - - return true; -} - -int32_t DeviceContext2D::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; - - gfx::Rect changed_rect; - 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; - } - changed_rect = changed_rect.Union(op_rect); - } - queued_operations_.clear(); - flushed_any_data_ = true; - - // 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_ && !changed_rect.IsEmpty()) - visible_changed_rect = bound_instance_->clip().Intersect(changed_rect); - - if (bound_instance_ && !visible_changed_rect.IsEmpty()) { - unpainted_flush_callback_.Set(callback); - bound_instance_->InvalidateRect(visible_changed_rect); - } else { - // There's nothing visible to invalidate so just schedule the callback to - // execute in the next round of the message loop. - ScheduleOffscreenCallback(FlushCallbackData(callback)); - } - return PP_ERROR_WOULDBLOCK; -} - -bool DeviceContext2D::ReadImageData(PP_Resource image, - const PP_Point* top_left) { - // Get and validate the image object to paint into. - scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image)); - if (!image_resource) - return false; - if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL) - 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; - skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas(); - - 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()) }; - - // 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 DeviceContext2D::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 DeviceContext2D::Paint(WebKit::WebCanvas* canvas, - const gfx::Rect& plugin_rect, - const gfx::Rect& paint_rect) { - // We're guaranteed to have a mapped canvas since we mapped it in Init(). - const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap(); - -#if defined(OS_MACOSX) - SkAutoLockPixels lock(backing_bitmap); - - scoped_cftyperef<CGDataProviderRef> data_provider( - CGDataProviderCreateWithData( - NULL, backing_bitmap.getAddr32(0, 0), - backing_bitmap.rowBytes() * backing_bitmap.height(), NULL)); - scoped_cftyperef<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(); - - CGContextDrawImage(canvas, bounds, image); - CGContextRestoreGState(canvas); -#else - 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())); -#endif -} - -void DeviceContext2D::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 DeviceContext2D::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 DeviceContext2D::ExecutePaintImageData(ImageData* 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()) }; - - // 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 DeviceContext2D::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 DeviceContext2D::ExecuteReplaceContents(ImageData* image, - gfx::Rect* invalidated_rect) { - image_data_->Swap(image); - *invalidated_rect = gfx::Rect(0, 0, - image_data_->width(), image_data_->height()); -} - -void DeviceContext2D::ScheduleOffscreenCallback( - const FlushCallbackData& callback) { - DCHECK(!HasPendingFlush()); - offscreen_flush_pending_ = true; - MessageLoop::current()->PostTask( - FROM_HERE, - NewRunnableMethod(this, - &DeviceContext2D::ExecuteOffscreenCallback, - callback)); -} - -void DeviceContext2D::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 DeviceContext2D::HasPendingFlush() const { - return !unpainted_flush_callback_.is_null() || - !painted_flush_callback_.is_null() || - offscreen_flush_pending_; -} - -} // namespace pepper diff --git a/webkit/glue/plugins/pepper_device_context_2d.h b/webkit/glue/plugins/pepper_device_context_2d.h deleted file mode 100644 index 603bd52..0000000 --- a/webkit/glue/plugins/pepper_device_context_2d.h +++ /dev/null @@ -1,175 +0,0 @@ -// 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_DEVICE_CONTEXT_2D_H_ -#define WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_2D_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "third_party/ppapi/c/pp_completion_callback.h" -#include "third_party/ppapi/c/ppb_device_context_2d.h" -#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h" -#include "webkit/glue/plugins/pepper_resource.h" - -typedef struct _ppb_DeviceContext2D PPB_DeviceContext2D; - -namespace gfx { -class Rect; -} - -namespace pepper { - -class ImageData; -class PluginInstance; -class PluginModule; - -class DeviceContext2D : public Resource { - public: - DeviceContext2D(PluginModule* module); - virtual ~DeviceContext2D(); - - // Returns a pointer to the interface implementing PPB_ImageData that is - // exposed to the plugin. - static const PPB_DeviceContext2D* GetInterface(); - - bool Init(int width, int height, bool is_always_opaque); - - // Resource override. - virtual DeviceContext2D* AsDeviceContext2D() { return this; } - - // PPB_DeviceContext2D functions. - bool Describe(PP_Size* size, bool* is_always_opaque); - bool PaintImageData(PP_Resource image, - const PP_Point* top_left, - const PP_Rect* src_rect); - bool Scroll(const PP_Rect* clip_rect, const PP_Point* amount); - bool ReplaceContents(PP_Resource image); - 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(); - - ImageData* 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(ImageData* 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(ImageData* 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<ImageData> image_data_; - - // Non-owning pointer to the plugin instance this device context is currently - // bound to, if any. If the device 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_; - - DISALLOW_COPY_AND_ASSIGN(DeviceContext2D); -}; - -} // namespace pepper - -#endif // WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_2D_H_ diff --git a/webkit/glue/plugins/pepper_directory_reader.cc b/webkit/glue/plugins/pepper_directory_reader.cc index 93f19ee..bcf2533 100644 --- a/webkit/glue/plugins/pepper_directory_reader.cc +++ b/webkit/glue/plugins/pepper_directory_reader.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "third_party/ppapi/c/pp_completion_callback.h" +#include "third_party/ppapi/c/dev/ppb_directory_reader_dev.h" #include "third_party/ppapi/c/pp_errors.h" #include "webkit/glue/plugins/pepper_file_ref.h" #include "webkit/glue/plugins/pepper_resource_tracker.h" @@ -29,7 +30,7 @@ bool IsDirectoryReader(PP_Resource resource) { } int32_t GetNextEntry(PP_Resource reader_id, - PP_DirectoryEntry* entry, + PP_DirectoryEntry_Dev* entry, PP_CompletionCallback callback) { scoped_refptr<DirectoryReader> reader( Resource::GetAs<DirectoryReader>(reader_id)); @@ -39,7 +40,7 @@ int32_t GetNextEntry(PP_Resource reader_id, return reader->GetNextEntry(entry, callback); } -const PPB_DirectoryReader ppb_directoryreader = { +const PPB_DirectoryReader_Dev ppb_directoryreader = { &Create, &IsDirectoryReader, &GetNextEntry @@ -55,11 +56,11 @@ DirectoryReader::DirectoryReader(FileRef* directory_ref) DirectoryReader::~DirectoryReader() { } -const PPB_DirectoryReader* DirectoryReader::GetInterface() { +const PPB_DirectoryReader_Dev* DirectoryReader::GetInterface() { return &ppb_directoryreader; } -int32_t DirectoryReader::GetNextEntry(PP_DirectoryEntry* entry, +int32_t DirectoryReader::GetNextEntry(PP_DirectoryEntry_Dev* entry, PP_CompletionCallback callback) { NOTIMPLEMENTED(); // TODO(darin): Implement me! return PP_ERROR_FAILED; diff --git a/webkit/glue/plugins/pepper_directory_reader.h b/webkit/glue/plugins/pepper_directory_reader.h index c477a3e..a56d546 100644 --- a/webkit/glue/plugins/pepper_directory_reader.h +++ b/webkit/glue/plugins/pepper_directory_reader.h @@ -5,9 +5,12 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_DIRECTORY_READER_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_DIRECTORY_READER_H_ -#include "third_party/ppapi/c/ppb_directory_reader.h" #include "webkit/glue/plugins/pepper_resource.h" +struct PP_CompletionCallback; +struct PP_DirectoryEntry_Dev; +struct PPB_DirectoryReader_Dev; + namespace pepper { class FileRef; @@ -19,13 +22,13 @@ class DirectoryReader : public Resource { // Returns a pointer to the interface implementing PPB_DirectoryReader that // is exposed to the plugin. - static const PPB_DirectoryReader* GetInterface(); + static const PPB_DirectoryReader_Dev* GetInterface(); // Resource overrides. DirectoryReader* AsDirectoryReader() { return this; } // PPB_DirectoryReader implementation. - int32_t GetNextEntry(PP_DirectoryEntry* entry, + int32_t GetNextEntry(PP_DirectoryEntry_Dev* entry, PP_CompletionCallback callback); private: diff --git a/webkit/glue/plugins/pepper_event_conversion.cc b/webkit/glue/plugins/pepper_event_conversion.cc index 033ac93..b88041e 100644 --- a/webkit/glue/plugins/pepper_event_conversion.cc +++ b/webkit/glue/plugins/pepper_event_conversion.cc @@ -4,9 +4,13 @@ #include "webkit/glue/plugins/pepper_event_conversion.h" +#include "base/i18n/char_iterator.h" #include "base/logging.h" #include "base/scoped_ptr.h" -#include "third_party/ppapi/c/pp_event.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "base/utf_string_conversion_utils.h" +#include "third_party/ppapi/c/pp_input_event.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" using WebKit::WebInputEvent; @@ -15,153 +19,216 @@ using WebKit::WebMouseEvent; using WebKit::WebMouseWheelEvent; namespace { -// Anonymous namespace for functions converting WebInputEvent to PP_Event and -// back. -PP_Event_Type ConvertEventTypes(WebInputEvent::Type wetype) { + +PP_InputEvent_Type ConvertEventTypes(WebInputEvent::Type wetype) { switch (wetype) { case WebInputEvent::MouseDown: - return PP_EVENT_TYPE_MOUSEDOWN; + return PP_INPUTEVENT_TYPE_MOUSEDOWN; case WebInputEvent::MouseUp: - return PP_EVENT_TYPE_MOUSEUP; + return PP_INPUTEVENT_TYPE_MOUSEUP; case WebInputEvent::MouseMove: - return PP_EVENT_TYPE_MOUSEMOVE; + return PP_INPUTEVENT_TYPE_MOUSEMOVE; case WebInputEvent::MouseEnter: - return PP_EVENT_TYPE_MOUSEENTER; + return PP_INPUTEVENT_TYPE_MOUSEENTER; case WebInputEvent::MouseLeave: - return PP_EVENT_TYPE_MOUSELEAVE; + return PP_INPUTEVENT_TYPE_MOUSELEAVE; case WebInputEvent::MouseWheel: - return PP_EVENT_TYPE_MOUSEWHEEL; + return PP_INPUTEVENT_TYPE_MOUSEWHEEL; case WebInputEvent::RawKeyDown: - return PP_EVENT_TYPE_RAWKEYDOWN; + return PP_INPUTEVENT_TYPE_RAWKEYDOWN; case WebInputEvent::KeyDown: - return PP_EVENT_TYPE_KEYDOWN; + return PP_INPUTEVENT_TYPE_KEYDOWN; case WebInputEvent::KeyUp: - return PP_EVENT_TYPE_KEYUP; + return PP_INPUTEVENT_TYPE_KEYUP; case WebInputEvent::Char: - return PP_EVENT_TYPE_CHAR; + return PP_INPUTEVENT_TYPE_CHAR; case WebInputEvent::Undefined: default: - return PP_EVENT_TYPE_UNDEFINED; + return PP_INPUTEVENT_TYPE_UNDEFINED; } } -void BuildKeyEvent(const WebInputEvent* event, PP_Event* pp_event) { - const WebKeyboardEvent* key_event = - reinterpret_cast<const WebKeyboardEvent*>(event); - pp_event->u.key.modifier = key_event->modifiers; - pp_event->u.key.normalizedKeyCode = key_event->windowsKeyCode; +// 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); + result.time_stamp_seconds = 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 BuildCharEvent(const WebInputEvent* event, PP_Event* pp_event) { - const WebKeyboardEvent* key_event = - reinterpret_cast<const WebKeyboardEvent*>(event); - pp_event->u.character.modifier = key_event->modifiers; - // For consistency, check that the sizes of the texts agree. - DCHECK(sizeof(pp_event->u.character.text) == sizeof(key_event->text)); - DCHECK(sizeof(pp_event->u.character.unmodifiedText) == - sizeof(key_event->unmodifiedText)); - for (size_t i = 0; i < WebKeyboardEvent::textLengthCap; ++i) { - pp_event->u.character.text[i] = key_event->text[i]; - pp_event->u.character.unmodifiedText[i] = key_event->unmodifiedText[i]; +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 BuildMouseEvent(const WebInputEvent* event, PP_Event* pp_event) { - const WebMouseEvent* mouse_event = - reinterpret_cast<const WebMouseEvent*>(event); - pp_event->u.mouse.modifier = mouse_event->modifiers; - pp_event->u.mouse.button = mouse_event->button; - pp_event->u.mouse.x = mouse_event->x; - pp_event->u.mouse.y = mouse_event->y; - pp_event->u.mouse.clickCount = mouse_event->clickCount; +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 BuildMouseWheelEvent(const WebInputEvent* event, PP_Event* pp_event) { - const WebMouseWheelEvent* mouse_wheel_event = - reinterpret_cast<const WebMouseWheelEvent*>(event); - pp_event->u.wheel.modifier = mouse_wheel_event->modifiers; - pp_event->u.wheel.deltaX = mouse_wheel_event->deltaX; - pp_event->u.wheel.deltaY = mouse_wheel_event->deltaY; - pp_event->u.wheel.wheelTicksX = mouse_wheel_event->wheelTicksX; - pp_event->u.wheel.wheelTicksY = mouse_wheel_event->wheelTicksY; - pp_event->u.wheel.scrollByPage = mouse_wheel_event->scrollByPage; +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 = !!mouse_wheel_event.scrollByPage; + pp_events->push_back(result); } -WebKeyboardEvent* BuildKeyEvent(const PP_Event& event) { +WebKeyboardEvent* BuildKeyEvent(const PP_InputEvent& event) { WebKeyboardEvent* key_event = new WebKeyboardEvent(); switch (event.type) { - case PP_EVENT_TYPE_RAWKEYDOWN: + case PP_INPUTEVENT_TYPE_RAWKEYDOWN: key_event->type = WebInputEvent::RawKeyDown; break; - case PP_EVENT_TYPE_KEYDOWN: + case PP_INPUTEVENT_TYPE_KEYDOWN: key_event->type = WebInputEvent::KeyDown; break; - case PP_EVENT_TYPE_KEYUP: + case PP_INPUTEVENT_TYPE_KEYUP: key_event->type = WebInputEvent::KeyUp; break; + default: + NOTREACHED(); } key_event->timeStampSeconds = event.time_stamp_seconds; key_event->modifiers = event.u.key.modifier; - key_event->windowsKeyCode = event.u.key.normalizedKeyCode; + key_event->windowsKeyCode = event.u.key.key_code; return key_event; } -WebKeyboardEvent* BuildCharEvent(const PP_Event& event) { +WebKeyboardEvent* BuildCharEvent(const PP_InputEvent& event) { WebKeyboardEvent* key_event = new WebKeyboardEvent(); key_event->type = WebInputEvent::Char; key_event->timeStampSeconds = event.time_stamp_seconds; key_event->modifiers = event.u.character.modifier; - // For consistency, check that the sizes of the texts agree. - DCHECK(sizeof(event.u.character.text) == sizeof(key_event->text)); - DCHECK(sizeof(event.u.character.unmodifiedText) == - sizeof(key_event->unmodifiedText)); - for (size_t i = 0; i < WebKeyboardEvent::textLengthCap; ++i) { - key_event->text[i] = event.u.character.text[i]; - key_event->unmodifiedText[i] = event.u.character.unmodifiedText[i]; - } + + // 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_Event& event) { +WebMouseEvent* BuildMouseEvent(const PP_InputEvent& event) { WebMouseEvent* mouse_event = new WebMouseEvent(); switch (event.type) { - case PP_EVENT_TYPE_MOUSEDOWN: + case PP_INPUTEVENT_TYPE_MOUSEDOWN: mouse_event->type = WebInputEvent::MouseDown; break; - case PP_EVENT_TYPE_MOUSEUP: + case PP_INPUTEVENT_TYPE_MOUSEUP: mouse_event->type = WebInputEvent::MouseUp; break; - case PP_EVENT_TYPE_MOUSEMOVE: + case PP_INPUTEVENT_TYPE_MOUSEMOVE: mouse_event->type = WebInputEvent::MouseMove; break; - case PP_EVENT_TYPE_MOUSEENTER: + case PP_INPUTEVENT_TYPE_MOUSEENTER: mouse_event->type = WebInputEvent::MouseEnter; break; - case PP_EVENT_TYPE_MOUSELEAVE: + case PP_INPUTEVENT_TYPE_MOUSELEAVE: mouse_event->type = WebInputEvent::MouseLeave; break; + default: + NOTREACHED(); } mouse_event->timeStampSeconds = event.time_stamp_seconds; mouse_event->modifiers = event.u.mouse.modifier; mouse_event->button = static_cast<WebMouseEvent::Button>(event.u.mouse.button); - mouse_event->x = event.u.mouse.x; - mouse_event->y = event.u.mouse.y; - mouse_event->clickCount = event.u.mouse.clickCount; + 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_Event& 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_seconds; mouse_wheel_event->modifiers = event.u.wheel.modifier; - mouse_wheel_event->deltaX = event.u.wheel.deltaX; - mouse_wheel_event->deltaY = event.u.wheel.deltaY; - mouse_wheel_event->wheelTicksX = event.u.wheel.wheelTicksX; - mouse_wheel_event->wheelTicksY = event.u.wheel.wheelTicksY; - mouse_wheel_event->scrollByPage = event.u.wheel.scrollByPage; + 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; } @@ -169,64 +236,58 @@ WebMouseWheelEvent* BuildMouseWheelEvent(const PP_Event& event) { namespace pepper { -PP_Event* CreatePP_Event(const WebInputEvent& event) { - scoped_ptr<PP_Event> pp_event(new PP_Event); +void CreatePPEvent(const WebInputEvent& event, + std::vector<PP_InputEvent>* pp_events) { + pp_events->clear(); - pp_event->type = ConvertEventTypes(event.type); - pp_event->size = sizeof(pp_event); - pp_event->time_stamp_seconds = event.timeStampSeconds; - switch (pp_event->type) { - case PP_EVENT_TYPE_UNDEFINED: - return NULL; - case PP_EVENT_TYPE_MOUSEDOWN: - case PP_EVENT_TYPE_MOUSEUP: - case PP_EVENT_TYPE_MOUSEMOVE: - case PP_EVENT_TYPE_MOUSEENTER: - case PP_EVENT_TYPE_MOUSELEAVE: - BuildMouseEvent(&event, pp_event.get()); + switch (event.type) { + case WebInputEvent::MouseDown: + case WebInputEvent::MouseUp: + case WebInputEvent::MouseMove: + case WebInputEvent::MouseEnter: + case WebInputEvent::MouseLeave: + AppendMouseEvent(event, pp_events); break; - case PP_EVENT_TYPE_MOUSEWHEEL: - BuildMouseWheelEvent(&event, pp_event.get()); + case WebInputEvent::MouseWheel: + AppendMouseWheelEvent(event, pp_events); break; - case PP_EVENT_TYPE_RAWKEYDOWN: - case PP_EVENT_TYPE_KEYDOWN: - case PP_EVENT_TYPE_KEYUP: - BuildKeyEvent(&event, pp_event.get()); + case WebInputEvent::RawKeyDown: + case WebInputEvent::KeyDown: + case WebInputEvent::KeyUp: + AppendKeyEvent(event, pp_events); break; - case PP_EVENT_TYPE_CHAR: - BuildCharEvent(&event, pp_event.get()); + case WebInputEvent::Char: + AppendCharEvent(event, pp_events); + break; + case WebInputEvent::Undefined: + default: break; } - - return pp_event.release(); } -WebInputEvent* CreateWebInputEvent(const PP_Event& event) { +WebInputEvent* CreateWebInputEvent(const PP_InputEvent& event) { scoped_ptr<WebInputEvent> web_input_event; switch (event.type) { - case PP_EVENT_TYPE_UNDEFINED: + case PP_INPUTEVENT_TYPE_UNDEFINED: return NULL; - case PP_EVENT_TYPE_MOUSEDOWN: - case PP_EVENT_TYPE_MOUSEUP: - case PP_EVENT_TYPE_MOUSEMOVE: - case PP_EVENT_TYPE_MOUSEENTER: - case PP_EVENT_TYPE_MOUSELEAVE: + 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_EVENT_TYPE_MOUSEWHEEL: + case PP_INPUTEVENT_TYPE_MOUSEWHEEL: web_input_event.reset(BuildMouseWheelEvent(event)); break; - case PP_EVENT_TYPE_RAWKEYDOWN: - case PP_EVENT_TYPE_KEYDOWN: - case PP_EVENT_TYPE_KEYUP: + case PP_INPUTEVENT_TYPE_RAWKEYDOWN: + case PP_INPUTEVENT_TYPE_KEYDOWN: + case PP_INPUTEVENT_TYPE_KEYUP: web_input_event.reset(BuildKeyEvent(event)); break; - case PP_EVENT_TYPE_CHAR: + case PP_INPUTEVENT_TYPE_CHAR: web_input_event.reset(BuildCharEvent(event)); break; - case PP_EVENT_TYPE_FOCUS: - // NOTIMPLEMENTED(); - return NULL; } return web_input_event.release(); diff --git a/webkit/glue/plugins/pepper_event_conversion.h b/webkit/glue/plugins/pepper_event_conversion.h index 2d699cd..9eab3e4 100644 --- a/webkit/glue/plugins/pepper_event_conversion.h +++ b/webkit/glue/plugins/pepper_event_conversion.h @@ -5,7 +5,9 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_EVENT_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_EVENT_H_ -typedef struct _pp_Event PP_Event; +#include <vector> + +struct PP_InputEvent; namespace WebKit { class WebInputEvent; @@ -13,13 +15,15 @@ class WebInputEvent; namespace pepper { -// Creates a PP_Event from the given WebInputEvent. If it fails, returns NULL. -// The caller owns the created object on success. -PP_Event* CreatePP_Event(const WebKit::WebInputEvent& event); +// 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_Event. If it fails, returns NULL. -// The caller owns the created object on success. -WebKit::WebInputEvent* CreateWebInputEvent(const PP_Event& event); +// 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 pepper diff --git a/webkit/glue/plugins/pepper_file_chooser.cc b/webkit/glue/plugins/pepper_file_chooser.cc index 5e45600..138efd7 100644 --- a/webkit/glue/plugins/pepper_file_chooser.cc +++ b/webkit/glue/plugins/pepper_file_chooser.cc @@ -4,19 +4,35 @@ #include "webkit/glue/plugins/pepper_file_chooser.h" +#include <string> +#include <vector> + #include "base/logging.h" #include "third_party/ppapi/c/pp_completion_callback.h" #include "third_party/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/glue/plugins/pepper_file_ref.h" +#include "webkit/glue/plugins/pepper_plugin_delegate.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_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 pepper { namespace { PP_Resource Create(PP_Instance instance_id, - const PP_FileChooserOptions* options) { + const PP_FileChooserOptions_Dev* options) { PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); if (!instance) return 0; @@ -51,38 +67,89 @@ PP_Resource GetNextChosenFile(PP_Resource chooser_id) { return file_ref->GetReference(); } -const PPB_FileChooser ppb_filechooser = { +const PPB_FileChooser_Dev ppb_filechooser = { &Create, &IsFileChooser, &Show, &GetNextChosenFile }; +class FileChooserCompletionImpl : public WebFileChooserCompletion { + public: + FileChooserCompletionImpl(pepper::FileChooser* 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: + FileChooser* file_chooser_; +}; + } // namespace FileChooser::FileChooser(PluginInstance* instance, - const PP_FileChooserOptions* options) + const PP_FileChooserOptions_Dev* options) : Resource(instance->module()), + delegate_(instance->delegate()), mode_(options->mode), - accept_mime_types_(options->accept_mime_types) { + accept_mime_types_(options->accept_mime_types), + completion_callback_() { } FileChooser::~FileChooser() { } // static -const PPB_FileChooser* FileChooser::GetInterface() { +const PPB_FileChooser_Dev* FileChooser::GetInterface() { return &ppb_filechooser; } +void FileChooser::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( + new FileRef(module(), PP_FILESYSTEMTYPE_LOCALPERSISTENT, *it, "")); + + if (!completion_callback_.func) + return; + + PP_CompletionCallback callback = {0}; + std::swap(callback, completion_callback_); + PP_RunCompletionCallback(&callback, 0); +} + int32_t FileChooser::Show(PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + 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<FileRef> FileChooser::GetNextChosenFile() { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return NULL; + if (next_chosen_file_index_ >= chosen_files_.size()) + return NULL; + + return chosen_files_[next_chosen_file_index_++]; } } // namespace pepper diff --git a/webkit/glue/plugins/pepper_file_chooser.h b/webkit/glue/plugins/pepper_file_chooser.h index 8474188..eafdd0e 100644 --- a/webkit/glue/plugins/pepper_file_chooser.h +++ b/webkit/glue/plugins/pepper_file_chooser.h @@ -6,33 +6,45 @@ #define WEBKIT_GLUE_PLUGINS_PEPPER_FILE_CHOOSER_H_ #include <string> +#include <vector> -#include "third_party/ppapi/c/ppb_file_chooser.h" +#include "base/scoped_ptr.h" +#include "third_party/ppapi/c/dev/ppb_file_chooser_dev.h" +#include "third_party/ppapi/c/pp_completion_callback.h" #include "webkit/glue/plugins/pepper_resource.h" namespace pepper { +class PluginDelegate; class PluginInstance; class FileChooser : public Resource { public: - FileChooser(PluginInstance* instance, const PP_FileChooserOptions* options); + FileChooser(PluginInstance* instance, + const PP_FileChooserOptions_Dev* options); virtual ~FileChooser(); // Returns a pointer to the interface implementing PPB_FileChooser that is // exposed to the plugin. - static const PPB_FileChooser* GetInterface(); + static const PPB_FileChooser_Dev* GetInterface(); // Resource overrides. FileChooser* AsFileChooser() { return this; } + // 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<FileRef> GetNextChosenFile(); private: - PP_FileChooserMode mode_; + PluginDelegate* delegate_; + PP_FileChooserMode_Dev mode_; std::string accept_mime_types_; + PP_CompletionCallback completion_callback_; + std::vector< scoped_refptr<FileRef> > chosen_files_; + size_t next_chosen_file_index_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_file_io.cc b/webkit/glue/plugins/pepper_file_io.cc index 46f7276..9090f88 100644 --- a/webkit/glue/plugins/pepper_file_io.cc +++ b/webkit/glue/plugins/pepper_file_io.cc @@ -4,12 +4,19 @@ #include "webkit/glue/plugins/pepper_file_io.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 "third_party/ppapi/c/dev/ppb_file_io_dev.h" +#include "third_party/ppapi/c/dev/ppb_file_io_trusted_dev.h" #include "third_party/ppapi/c/pp_completion_callback.h" #include "third_party/ppapi/c/pp_errors.h" -#include "third_party/ppapi/c/ppb_file_io.h" -#include "third_party/ppapi/c/ppb_file_io_trusted.h" #include "webkit/glue/plugins/pepper_file_ref.h" +#include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_plugin_module.h" #include "webkit/glue/plugins/pepper_resource_tracker.h" @@ -46,12 +53,11 @@ int32_t Open(PP_Resource file_io_id, } int32_t Query(PP_Resource file_io_id, - PP_FileInfo* info, + PP_FileInfo_Dev* info, PP_CompletionCallback callback) { scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->Query(info, callback); } @@ -62,7 +68,6 @@ int32_t Touch(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->Touch(last_access_time, last_modified_time, callback); } @@ -74,7 +79,6 @@ int32_t Read(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->Read(offset, buffer, bytes_to_read, callback); } @@ -86,7 +90,6 @@ int32_t Write(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->Write(offset, buffer, bytes_to_write, callback); } @@ -96,7 +99,6 @@ int32_t SetLength(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->SetLength(length, callback); } @@ -105,7 +107,6 @@ int32_t Flush(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->Flush(callback); } @@ -113,11 +114,10 @@ void Close(PP_Resource file_io_id) { scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return; - file_io->Close(); } -const PPB_FileIO ppb_fileio = { +const PPB_FileIO_Dev ppb_fileio = { &Create, &IsFileIO, &Open, @@ -134,7 +134,6 @@ int32_t GetOSFileDescriptor(PP_Resource file_io_id) { scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->GetOSFileDescriptor(); } @@ -145,7 +144,6 @@ int32_t WillWrite(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->WillWrite(offset, bytes_to_write, callback); } @@ -155,101 +153,281 @@ int32_t WillSetLength(PP_Resource file_io_id, scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); if (!file_io) return PP_ERROR_BADRESOURCE; - return file_io->WillSetLength(length, callback); } -const PPB_FileIOTrusted ppb_fileiotrusted = { +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 -FileIO::FileIO(PluginModule* module) : Resource(module) { +FileIO::FileIO(PluginModule* module) + : Resource(module), + delegate_(module->GetSomeInstance()->delegate()), + ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), + file_(base::kInvalidPlatformFileValue), + callback_(), + info_(NULL) { } FileIO::~FileIO() { + Close(); } // static -const PPB_FileIO* FileIO::GetInterface() { +const PPB_FileIO_Dev* FileIO::GetInterface() { return &ppb_fileio; } // static -const PPB_FileIOTrusted* FileIO::GetTrustedInterface() { +const PPB_FileIOTrusted_Dev* FileIO::GetTrustedInterface() { return &ppb_fileiotrusted; } int32_t FileIO::Open(FileRef* file_ref, int32_t open_flags, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + 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(flags & PP_FILEOPENFLAG_WRITE); + flags |= base::PLATFORM_FILE_TRUNCATE; + } + + 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->file_system_type(); + if (!delegate_->AsyncOpenFile( + file_ref->system_path(), flags, + callback_factory_.NewCallback(&FileIO::AsyncOpenFileCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } -int32_t FileIO::Query(PP_FileInfo* info, +int32_t FileIO::Query(PP_FileInfo_Dev* info, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + 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(&FileIO::QueryInfoCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } int32_t FileIO::Touch(PP_Time last_access_time, PP_Time last_modified_time, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + 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(&FileIO::StatusCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } int32_t FileIO::Read(int64_t offset, char* buffer, int32_t bytes_to_read, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + 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(&FileIO::ReadWriteCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } int32_t FileIO::Write(int64_t offset, const char* buffer, int32_t bytes_to_write, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + 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(&FileIO::ReadWriteCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } int32_t FileIO::SetLength(int64_t length, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + if (file_ == base::kInvalidPlatformFileValue) + return PP_ERROR_FAILED; + + DCHECK(!callback_.func); + callback_ = callback; + + if (!base::FileUtilProxy::Truncate( + delegate_->GetFileThreadMessageLoopProxy(), + file_, length, + callback_factory_.NewCallback(&FileIO::StatusCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } int32_t FileIO::Flush(PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + if (file_ == base::kInvalidPlatformFileValue) + return PP_ERROR_FAILED; + + DCHECK(!callback_.func); + callback_ = callback; + + if (!base::FileUtilProxy::Flush( + delegate_->GetFileThreadMessageLoopProxy(), file_, + callback_factory_.NewCallback(&FileIO::StatusCallback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } void FileIO::Close() { - NOTIMPLEMENTED(); // TODO(darin): Implement me! + if (file_ != base::kInvalidPlatformFileValue) + base::FileUtilProxy::Close( + delegate_->GetFileThreadMessageLoopProxy(), file_, NULL); } int32_t FileIO::GetOSFileDescriptor() { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; +#if defined(OS_POSIX) + return file_; +#elif defined(OS_WIN) + return reinterpret_cast<uintptr_t>(file_); +#else +#error "Platform not supported." +#endif } int32_t FileIO::WillWrite(int64_t offset, int32_t bytes_to_write, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + // TODO(dumi): implement me + return PP_OK; } int32_t FileIO::WillSetLength(int64_t length, PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_ERROR_FAILED; + // TODO(dumi): implement me + return PP_OK; +} + +void FileIO::RunPendingCallback(int result) { + if (!callback_.func) + return; + + PP_CompletionCallback callback = {0}; + std::swap(callback, callback_); + PP_RunCompletionCallback(&callback, result); +} + +void FileIO::StatusCallback(base::PlatformFileError error_code) { + RunPendingCallback(PlatformFileErrorToPepperError(error_code)); +} + +void FileIO::AsyncOpenFileCallback(base::PlatformFileError error_code, + base::PlatformFile file) { + DCHECK(file_ == base::kInvalidPlatformFileValue); + file_ = file; + RunPendingCallback(PlatformFileErrorToPepperError(error_code)); +} + +void FileIO::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 FileIO::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 pepper diff --git a/webkit/glue/plugins/pepper_file_io.h b/webkit/glue/plugins/pepper_file_io.h index 4af6f2b..bda8ed6 100644 --- a/webkit/glue/plugins/pepper_file_io.h +++ b/webkit/glue/plugins/pepper_file_io.h @@ -5,13 +5,20 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_FILE_IO_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_FILE_IO_H_ +#include "base/file_path.h" +#include "base/platform_file.h" +#include "base/scoped_callback_factory.h" +#include "base/scoped_ptr.h" +#include "third_party/ppapi/c/dev/pp_file_info_dev.h" +#include "third_party/ppapi/c/pp_completion_callback.h" #include "third_party/ppapi/c/pp_time.h" +#include "webkit/glue/plugins/pepper_plugin_delegate.h" #include "webkit/glue/plugins/pepper_resource.h" -typedef struct _pp_CompletionCallback PP_CompletionCallback; -typedef struct _pp_FileInfo PP_FileInfo; -typedef struct _ppb_FileIO PPB_FileIO; -typedef struct _ppb_FileIOTrusted PPB_FileIOTrusted; +struct PP_CompletionCallback; +struct PP_FileInfo_Dev; +struct PPB_FileIO_Dev; +struct PPB_FileIOTrusted_Dev; namespace pepper { @@ -24,11 +31,11 @@ class FileIO : public Resource { // Returns a pointer to the interface implementing PPB_FileIO that is exposed // to the plugin. - static const PPB_FileIO* GetInterface(); + 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* GetTrustedInterface(); + static const PPB_FileIOTrusted_Dev* GetTrustedInterface(); // Resource overrides. FileIO* AsFileIO() { return this; } @@ -37,7 +44,7 @@ class FileIO : public Resource { int32_t Open(FileRef* file_ref, int32_t open_flags, PP_CompletionCallback callback); - int32_t Query(PP_FileInfo* info, + int32_t Query(PP_FileInfo_Dev* info, PP_CompletionCallback callback); int32_t Touch(PP_Time last_access_time, PP_Time last_modified_time, @@ -62,6 +69,25 @@ class FileIO : public Resource { 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<FileIO> callback_factory_; + + base::PlatformFile file_; + PP_FileSystemType_Dev file_system_type_; + + PP_CompletionCallback callback_; + PP_FileInfo_Dev* info_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_file_ref.cc b/webkit/glue/plugins/pepper_file_ref.cc index 9b42cff..7cb65a4 100644 --- a/webkit/glue/plugins/pepper_file_ref.cc +++ b/webkit/glue/plugins/pepper_file_ref.cc @@ -4,6 +4,8 @@ #include "webkit/glue/plugins/pepper_file_ref.h" +#include "base/base_paths.h" +#include "base/path_service.h" #include "base/string_util.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_var.h" @@ -33,7 +35,7 @@ void TrimTrailingSlash(std::string* path) { } PP_Resource CreateFileRef(PP_Instance instance_id, - PP_FileSystemType fs_type, + PP_FileSystemType_Dev fs_type, const char* path) { PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); if (!instance) @@ -65,11 +67,10 @@ bool IsFileRef(PP_Resource resource) { return !!Resource::GetAs<FileRef>(resource); } -PP_FileSystemType GetFileSystemType(PP_Resource file_ref_id) { +PP_FileSystemType_Dev GetFileSystemType(PP_Resource file_ref_id) { scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); if (!file_ref) return PP_FILESYSTEMTYPE_EXTERNAL; - return file_ref->file_system_type(); } @@ -77,8 +78,7 @@ PP_Var GetName(PP_Resource file_ref_id) { scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); if (!file_ref) return PP_MakeVoid(); - - return StringToPPVar(file_ref->GetName()); + return StringVar::StringToPPVar(file_ref->module(), file_ref->GetName()); } PP_Var GetPath(PP_Resource file_ref_id) { @@ -89,7 +89,7 @@ PP_Var GetPath(PP_Resource file_ref_id) { if (file_ref->file_system_type() == PP_FILESYSTEMTYPE_EXTERNAL) return PP_MakeVoid(); - return StringToPPVar(file_ref->path()); + return StringVar::StringToPPVar(file_ref->module(), file_ref->path()); } PP_Resource GetParent(PP_Resource file_ref_id) { @@ -107,7 +107,7 @@ PP_Resource GetParent(PP_Resource file_ref_id) { return parent_ref->GetReference(); } -const PPB_FileRef ppb_fileref = { +const PPB_FileRef_Dev ppb_fileref = { &CreatePersistentFileRef, &CreateTemporaryFileRef, &IsFileRef, @@ -120,7 +120,7 @@ const PPB_FileRef ppb_fileref = { } // namespace FileRef::FileRef(PluginModule* module, - PP_FileSystemType file_system_type, + PP_FileSystemType_Dev file_system_type, const std::string& validated_path, const std::string& origin) : Resource(module), @@ -130,11 +130,18 @@ FileRef::FileRef(PluginModule* module, // TODO(darin): Need to initialize system_path_. } +FileRef::FileRef(PluginModule* module, + const FilePath& external_file_path) + : Resource(module), + system_path_(external_file_path), + fs_type_(PP_FILESYSTEMTYPE_EXTERNAL) { +} + FileRef::~FileRef() { } // static -const PPB_FileRef* FileRef::GetInterface() { +const PPB_FileRef_Dev* FileRef::GetInterface() { return &ppb_fileref; } @@ -166,4 +173,21 @@ scoped_refptr<FileRef> FileRef::GetParent() { return parent_ref; } +// static +FileRef* FileRef::GetInaccessibleFileRef(PluginModule* module) { + FilePath inaccessible_path; + if (!PathService::Get(base::FILE_MODULE, &inaccessible_path)) + return NULL; + return new FileRef(module, inaccessible_path); +} + +// static +FileRef* FileRef::GetNonexistentFileRef(PluginModule* module) { + FilePath dir_module_path; + if (!PathService::Get(base::DIR_MODULE, &dir_module_path)) + return NULL; + return new FileRef(module, dir_module_path.Append( + FILE_PATH_LITERAL("nonexistent_file"))); +} + } // namespace pepper diff --git a/webkit/glue/plugins/pepper_file_ref.h b/webkit/glue/plugins/pepper_file_ref.h index 34e4c3e..0ab0e65 100644 --- a/webkit/glue/plugins/pepper_file_ref.h +++ b/webkit/glue/plugins/pepper_file_ref.h @@ -8,7 +8,7 @@ #include <string> #include "base/file_path.h" -#include "third_party/ppapi/c/ppb_file_ref.h" +#include "third_party/ppapi/c/dev/ppb_file_ref_dev.h" #include "webkit/glue/plugins/pepper_resource.h" namespace pepper { @@ -18,14 +18,16 @@ class PluginModule; class FileRef : public Resource { public: FileRef(PluginModule* module, - PP_FileSystemType file_system_type, + PP_FileSystemType_Dev file_system_type, const std::string& validated_path, const std::string& origin); + FileRef(PluginModule* module, + const FilePath& external_file_path); virtual ~FileRef(); // Returns a pointer to the interface implementing PPB_FileRef that is // exposed to the plugin. - static const PPB_FileRef* GetInterface(); + static const PPB_FileRef_Dev* GetInterface(); // Resource overrides. FileRef* AsFileRef() { return this; } @@ -34,7 +36,7 @@ class FileRef : public Resource { std::string GetName() const; scoped_refptr<FileRef> GetParent(); - PP_FileSystemType file_system_type() const { return fs_type_; } + PP_FileSystemType_Dev file_system_type() const { return fs_type_; } // Returns the virtual path (i.e., the path that the pepper plugin sees) // corresponding to this file. @@ -43,9 +45,17 @@ class FileRef : public Resource { // Returns the system path corresponding to this file. const FilePath& system_path() const { return system_path_; } + // Returns a FileRef instance pointing to a file that should not be + // accessible by the plugin. Should be used for testing only. + static FileRef* GetInaccessibleFileRef(PluginModule* module); + + // Returns a FileRef instance pointing to a nonexistent file. + // Should be used for testing only. + static FileRef* GetNonexistentFileRef(PluginModule* module); + private: FilePath system_path_; - PP_FileSystemType fs_type_; + PP_FileSystemType_Dev fs_type_; std::string path_; // UTF-8 encoded. std::string origin_; }; diff --git a/webkit/glue/plugins/pepper_file_system.cc b/webkit/glue/plugins/pepper_file_system.cc index 678399e..82a2fc8 100644 --- a/webkit/glue/plugins/pepper_file_system.cc +++ b/webkit/glue/plugins/pepper_file_system.cc @@ -4,45 +4,235 @@ #include "webkit/glue/plugins/pepper_file_system.h" +#include "base/logging.h" +#include "base/ref_counted.h" +#include "base/weak_ptr.h" +#include "third_party/ppapi/c/dev/ppb_file_system_dev.h" #include "third_party/ppapi/c/pp_completion_callback.h" -#include "third_party/ppapi/c/pp_errors.h" -#include "third_party/ppapi/c/ppb_file_system.h" +#include "third_party/ppapi/c/pp_time.h" +#include "webkit/fileapi/file_system_callback_dispatcher.h" +#include "webkit/glue/plugins/pepper_resource.h" +#include "webkit/glue/plugins/pepper_error_util.h" +#include "webkit/glue/plugins/pepper_file_ref.h" +#include "webkit/glue/plugins/pepper_plugin_delegate.h" +#include "webkit/glue/plugins/pepper_plugin_instance.h" +#include "webkit/glue/plugins/pepper_plugin_module.h" +#include "webkit/glue/plugins/pepper_resource.h" namespace pepper { namespace { -int32_t MakeDirectory(PP_Resource directory_ref, +// Instances of this class are deleted when RunCallback() is called. +class StatusCallback : public fileapi::FileSystemCallbackDispatcher { + public: + StatusCallback(base::WeakPtr<pepper::PluginModule> module, + PP_CompletionCallback callback) + : module_(module), + callback_(callback) { + } + + // FileSystemCallbackDispatcher implementation. + virtual void DidSucceed() { + RunCallback(base::PLATFORM_FILE_OK); + } + + virtual void DidReadMetadata(const base::PlatformFileInfo&) { + NOTREACHED(); + } + + virtual void DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>&, bool) { + NOTREACHED(); + } + + virtual void DidOpenFileSystem(const std::string&, const FilePath&) { + NOTREACHED(); + } + + virtual void DidFail(base::PlatformFileError error_code) { + RunCallback(error_code); + } + + private: + void RunCallback(base::PlatformFileError error_code) { + if (!module_.get() || !callback_.func) + return; + + PP_RunCompletionCallback( + &callback_, pepper::PlatformFileErrorToPepperError(error_code)); + + delete this; + } + + base::WeakPtr<pepper::PluginModule> module_; + PP_CompletionCallback callback_; +}; + +// Instances of this class are deleted when RunCallback() is called. +class QueryInfoCallback : public fileapi::FileSystemCallbackDispatcher { + public: + QueryInfoCallback(base::WeakPtr<pepper::PluginModule> module, + PP_CompletionCallback callback, + PP_FileInfo_Dev* info, + PP_FileSystemType_Dev file_system_type) + : module_(module), + callback_(callback), + info_(info), + file_system_type_(file_system_type) { + DCHECK(info_); + } + + // FileSystemCallbackDispatcher implementation. + virtual void DidSucceed() { + NOTREACHED(); + } + + virtual void DidReadMetadata(const base::PlatformFileInfo& file_info) { + RunCallback(base::PLATFORM_FILE_OK, file_info); + } + + virtual void DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>&, bool) { + NOTREACHED(); + } + + virtual void DidOpenFileSystem(const std::string&, const FilePath&) { + NOTREACHED(); + } + + virtual void DidFail(base::PlatformFileError error_code) { + RunCallback(error_code, base::PlatformFileInfo()); + } + + private: + void RunCallback(base::PlatformFileError error_code, + const base::PlatformFileInfo& file_info) { + if (!module_.get() || !callback_.func) + return; + + 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; + } + PP_RunCompletionCallback( + &callback_, pepper::PlatformFileErrorToPepperError(error_code)); + + delete this; + } + + base::WeakPtr<pepper::PluginModule> module_; + PP_CompletionCallback callback_; + PP_FileInfo_Dev* info_; + PP_FileSystemType_Dev file_system_type_; +}; + +int32_t MakeDirectory(PP_Resource directory_ref_id, bool make_ancestors, PP_CompletionCallback callback) { - return PP_ERROR_FAILED; // TODO(darin): Implement me! + scoped_refptr<FileRef> directory_ref( + Resource::GetAs<FileRef>(directory_ref_id)); + if (!directory_ref) + return PP_ERROR_BADRESOURCE; + + if (directory_ref->file_system_type() == PP_FILESYSTEMTYPE_EXTERNAL) + return PP_ERROR_FAILED; + + PluginModule* module = directory_ref->module(); + if (!module->GetSomeInstance()->delegate()->MakeDirectory( + directory_ref->system_path(), make_ancestors, + new StatusCallback(module->AsWeakPtr(), callback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } -int32_t Query(PP_Resource file_ref, - PP_FileInfo* info, +int32_t Query(PP_Resource file_ref_id, + PP_FileInfo_Dev* info, PP_CompletionCallback callback) { - return PP_ERROR_FAILED; // TODO(darin): Implement me! + scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); + if (!file_ref) + return PP_ERROR_BADRESOURCE; + + PluginModule* module = file_ref->module(); + if (!module->GetSomeInstance()->delegate()->Query( + file_ref->system_path(), + new QueryInfoCallback(module->AsWeakPtr(), callback, + info, file_ref->file_system_type()))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } -int32_t Touch(PP_Resource file_ref, +int32_t Touch(PP_Resource file_ref_id, PP_Time last_access_time, PP_Time last_modified_time, PP_CompletionCallback callback) { - return PP_ERROR_FAILED; // TODO(darin): Implement me! + scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); + if (!file_ref) + return PP_ERROR_BADRESOURCE; + + PluginModule* module = file_ref->module(); + if (!module->GetSomeInstance()->delegate()->Touch( + file_ref->system_path(), base::Time::FromDoubleT(last_access_time), + base::Time::FromDoubleT(last_modified_time), + new StatusCallback(module->AsWeakPtr(), callback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } -int32_t Delete(PP_Resource file_ref, +int32_t Delete(PP_Resource file_ref_id, PP_CompletionCallback callback) { - return PP_ERROR_FAILED; // TODO(darin): Implement me! + scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); + if (!file_ref) + return PP_ERROR_BADRESOURCE; + + if (file_ref->file_system_type() == PP_FILESYSTEMTYPE_EXTERNAL) + return PP_ERROR_FAILED; + + PluginModule* module = file_ref->module(); + if (!module->GetSomeInstance()->delegate()->Delete( + file_ref->system_path(), + new StatusCallback(module->AsWeakPtr(), callback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } -int32_t Rename(PP_Resource file_ref, - PP_Resource new_file_ref, +int32_t Rename(PP_Resource file_ref_id, + PP_Resource new_file_ref_id, PP_CompletionCallback callback) { - return PP_ERROR_FAILED; // TODO(darin): Implement me! + scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); + if (!file_ref) + return PP_ERROR_BADRESOURCE; + + scoped_refptr<FileRef> new_file_ref( + Resource::GetAs<FileRef>(new_file_ref_id)); + if (!new_file_ref) + return PP_ERROR_BADRESOURCE; + + if ((file_ref->file_system_type() == PP_FILESYSTEMTYPE_EXTERNAL) || + (file_ref->file_system_type() != new_file_ref->file_system_type())) + return PP_ERROR_FAILED; + + PluginModule* module = file_ref->module(); + if (!module->GetSomeInstance()->delegate()->Rename( + file_ref->system_path(), new_file_ref->system_path(), + new StatusCallback(module->AsWeakPtr(), callback))) + return PP_ERROR_FAILED; + + return PP_ERROR_WOULDBLOCK; } -const PPB_FileSystem ppb_filesystem = { +const PPB_FileSystem_Dev ppb_filesystem = { &MakeDirectory, &Query, &Touch, @@ -52,7 +242,7 @@ const PPB_FileSystem ppb_filesystem = { } // namespace -const PPB_FileSystem* FileSystem::GetInterface() { +const PPB_FileSystem_Dev* FileSystem::GetInterface() { return &ppb_filesystem; } diff --git a/webkit/glue/plugins/pepper_file_system.h b/webkit/glue/plugins/pepper_file_system.h index b8ad01a..1abfc52 100644 --- a/webkit/glue/plugins/pepper_file_system.h +++ b/webkit/glue/plugins/pepper_file_system.h @@ -5,7 +5,9 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_FILE_SYSTEM_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_FILE_SYSTEM_H_ -typedef struct _ppb_FileSystem PPB_FileSystem; +#include "base/basictypes.h" + +struct PPB_FileSystem_Dev; namespace pepper { @@ -13,7 +15,10 @@ class FileSystem { public: // Returns a pointer to the interface implementing PPB_FileSystem that is // exposed to the plugin. - static const PPB_FileSystem* GetInterface(); + static const PPB_FileSystem_Dev* GetInterface(); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystem); }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_font.cc b/webkit/glue/plugins/pepper_font.cc index af4cb81..82bf369 100644 --- a/webkit/glue/plugins/pepper_font.cc +++ b/webkit/glue/plugins/pepper_font.cc @@ -2,98 +2,290 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" - #include "webkit/glue/plugins/pepper_font.h" -#if defined(OS_LINUX) -#include <unistd.h> -#endif - #include "base/logging.h" -#include "third_party/ppapi/c/ppb_font.h" +#include "base/utf_string_conversions.h" +#include "third_party/ppapi/c/dev/ppb_font_dev.h" +#include "third_party/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/glue/plugins/pepper_image_data.h" #include "webkit/glue/plugins/pepper_plugin_module.h" +#include "webkit/glue/plugins/pepper_string.h" +#include "webkit/glue/plugins/pepper_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 pepper { namespace { -PP_Resource MatchFontWithFallback(PP_Module module_id, - const PP_FontDescription* description) { -#if defined(OS_LINUX) +bool IsPPFontDescriptionValid(const PP_FontDescription_Dev& desc) { + // Check validity of UTF-8. + if (desc.face.type != PP_VARTYPE_STRING && desc.face.type != PP_VARTYPE_VOID) + 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 = font.italic; + result.smallCaps = 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()), + run->rtl, run->override_direction); + return true; +} + +PP_Resource Create(PP_Module module_id, + const PP_FontDescription_Dev* description) { PluginModule* module = PluginModule::FromPPModule(module_id); if (!module) - return NULL; + return 0; - int fd = webkit_glue::MatchFontWithFallback(description->face, - description->weight >= 700, - description->italic, - description->charset); - if (fd == -1) - return NULL; - - scoped_refptr<Font> font(new Font(module, fd)); + if (!IsPPFontDescriptionValid(*description)) + return 0; + scoped_refptr<Font> font(new Font(module, *description)); return font->GetReference(); -#else - // For trusted pepper plugins, this is only needed in Linux since font loading - // on Windows and Mac works through the renderer sandbox. - return false; -#endif } bool IsFont(PP_Resource resource) { - return !!Resource::GetAs<Font>(resource); + return !!Resource::GetAs<Font>(resource).get(); } -bool GetFontTable(PP_Resource font_id, - uint32_t table, - void* output, - uint32_t* output_length) { +bool Describe(PP_Resource font_id, + PP_FontDescription_Dev* description, + PP_FontMetrics_Dev* metrics) { scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); if (!font.get()) return false; + return font->Describe(description, metrics); +} - return font->GetFontTable(table, output, output_length); +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, + bool image_data_is_opaque) { + scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); + if (!font.get()) + return false; + return font->DrawTextAt(image_data, text, position, color, clip, + image_data_is_opaque); } -const PPB_Font ppb_font = { - &MatchFontWithFallback, +int32_t MeasureText(PP_Resource font_id, const PP_TextRun_Dev* text) { + scoped_refptr<Font> font(Resource::GetAs<Font>(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<Font> font(Resource::GetAs<Font>(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<Font> font(Resource::GetAs<Font>(font_id)); + if (!font.get()) + return false; + return font->PixelOffsetForCharacter(text, char_offset); +} + +const PPB_Font_Dev ppb_font = { + &Create, &IsFont, - &GetFontTable, + &Describe, + &DrawTextAt, + &MeasureText, + &CharacterOffsetForPixel, + &PixelOffsetForCharacter }; } // namespace -Font::Font(PluginModule* module, int fd) - : Resource(module), - fd_(fd) { +Font::Font(PluginModule* module, const PP_FontDescription_Dev& desc) + : Resource(module) { + WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc); + font_.reset(WebFont::create(web_font_desc)); } Font::~Font() { -#if defined (OS_LINUX) - close(fd_); -#endif } // static -const PPB_Font* Font::GetInterface() { +const PPB_Font_Dev* Font::GetInterface() { return &ppb_font; } -bool Font::GetFontTable(uint32_t table, - void* output, - uint32_t* output_length) { -#if defined(OS_LINUX) - 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; -#else - return false; -#endif +bool Font::Describe(PP_FontDescription_Dev* description, + PP_FontMetrics_Dev* metrics) { + if (description->face.type != PP_VARTYPE_VOID) + 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 = web_desc.italic; + description->small_caps = 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 Font::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<ImageData> image_resource( + Resource::GetAs<ImageData>(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 Font::MeasureText(const PP_TextRun_Dev* text) { + WebTextRun run; + if (!PPTextRunToWebTextRun(text, &run)) + return -1; + return font_->calculateWidth(run); +} + +uint32_t Font::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 Font::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 pepper diff --git a/webkit/glue/plugins/pepper_font.h b/webkit/glue/plugins/pepper_font.h index ad1abba..34fe521 100644 --- a/webkit/glue/plugins/pepper_font.h +++ b/webkit/glue/plugins/pepper_font.h @@ -5,9 +5,13 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_FONT_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_FONT_H_ +#include "base/scoped_ptr.h" +#include "third_party/ppapi/c/dev/ppb_font_dev.h" #include "webkit/glue/plugins/pepper_resource.h" -typedef struct _ppb_Font PPB_Font; +namespace WebKit { +class WebFont; +} namespace pepper { @@ -15,23 +19,33 @@ class PluginInstance; class Font : public Resource { public: - Font(PluginModule* module, int fd); + Font(PluginModule* module, const PP_FontDescription_Dev& desc); virtual ~Font(); // Returns a pointer to the interface implementing PPB_Font that is exposed to // the plugin. - static const PPB_Font* GetInterface(); + static const PPB_Font_Dev* GetInterface(); // Resource overrides. Font* AsFont() { return this; } // PPB_Font implementation. - bool GetFontTable(uint32_t table, - void* output, - uint32_t* output_length); + 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: - int fd_; + scoped_ptr<WebKit::WebFont> font_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_image_data.cc b/webkit/glue/plugins/pepper_image_data.cc index 8288fe2..aeb2c88 100644 --- a/webkit/glue/plugins/pepper_image_data.cc +++ b/webkit/glue/plugins/pepper_image_data.cc @@ -14,6 +14,7 @@ #include "third_party/ppapi/c/pp_module.h" #include "third_party/ppapi/c/pp_resource.h" #include "third_party/ppapi/c/ppb_image_data.h" +#include "third_party/ppapi/c/trusted/ppb_image_data_trusted.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_plugin_module.h" @@ -31,11 +32,11 @@ PP_Resource Create(PP_Module module_id, bool init_to_zero) { PluginModule* module = PluginModule::FromPPModule(module_id); if (!module) - return NULL; + return 0; scoped_refptr<ImageData> data(new ImageData(module)); if (!data->Init(format, size->width, size->height, init_to_zero)) - return NULL; + return 0; return data->GetReference(); } @@ -68,6 +69,13 @@ void Unmap(PP_Resource resource) { image_data->Unmap(); } +uint64_t GetNativeMemoryHandle2(PP_Resource resource) { + scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); + if (image_data) + return image_data->GetNativeMemoryHandle(); + return 0; +} + const PPB_ImageData ppb_imagedata = { &GetNativeImageDataFormat, &Create, @@ -77,6 +85,10 @@ const PPB_ImageData ppb_imagedata = { &Unmap, }; +const PPB_ImageDataTrusted ppb_imagedata_trusted = { + &GetNativeMemoryHandle2, +}; + } // namespace ImageData::ImageData(PluginModule* module) @@ -93,6 +105,11 @@ const PPB_ImageData* ImageData::GetInterface() { return &ppb_imagedata; } +// static +const PPB_ImageDataTrusted* ImageData::GetTrustedInterface() { + return &ppb_imagedata_trusted; +} + bool ImageData::Init(PP_ImageDataFormat format, int width, int height, bool init_to_zero) { @@ -143,6 +160,10 @@ void ImageData::Unmap() { // in the future to save some memory. } +uint64 ImageData::GetNativeMemoryHandle() const { + return platform_image_->GetSharedMemoryHandle(); +} + const SkBitmap* ImageData::GetMappedBitmap() const { if (!mapped_canvas_.get()) return NULL; diff --git a/webkit/glue/plugins/pepper_image_data.h b/webkit/glue/plugins/pepper_image_data.h index 7652b80..f2a110b 100644 --- a/webkit/glue/plugins/pepper_image_data.h +++ b/webkit/glue/plugins/pepper_image_data.h @@ -15,6 +15,7 @@ namespace skia { class PlatformCanvas; } +struct PPB_ImageDataTrusted; class SkBitmap; namespace pepper { @@ -37,12 +38,17 @@ class ImageData : public Resource { // 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(); // Resource overrides. - ImageData* AsImageData() { return this; } + virtual ImageData* AsImageData() { return this; } // PPB_ImageData implementation. bool Init(PP_ImageDataFormat format, @@ -52,6 +58,9 @@ class ImageData : public Resource { void* Map(); void Unmap(); + // PPB_ImageDataTrusted implementation. + uint64 GetNativeMemoryHandle() 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; diff --git a/webkit/glue/plugins/pepper_plugin_delegate.h b/webkit/glue/plugins/pepper_plugin_delegate.h index ffc9d52..1bb4bed 100644 --- a/webkit/glue/plugins/pepper_plugin_delegate.h +++ b/webkit/glue/plugins/pepper_plugin_delegate.h @@ -5,15 +5,57 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_DELEGATE_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_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 "base/task.h" +#include "third_party/ppapi/c/pp_completion_callback.h" +#include "third_party/ppapi/c/pp_errors.h" #include "third_party/ppapi/c/pp_stdint.h" +class AudioMessageFilter; + +namespace base { +class MessageLoopProxy; +class Time; +} + +namespace fileapi { +class FileSystemCallbackDispatcher; +} + +namespace gfx { +class Rect; +} + +namespace gpu { +class CommandBuffer; +} + 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 pepper { +class FileIO; class PluginInstance; +class FullscreenContainer; // Virtual interface that the browser implements to implement features for // Pepper plugins. @@ -32,6 +74,62 @@ class PluginDelegate { // this image. This is used by NativeClient to send the image to the // out-of-process plugin. Returns 0 on failure. virtual intptr_t GetSharedMemoryHandle() const = 0; + + virtual TransportDIB* GetTransportDIB() const = 0; + }; + + class PlatformContext3D { + public: + virtual ~PlatformContext3D() {} + + // Initialize the context. + virtual bool Init(const gfx::Rect& position, const gfx::Rect& clip) = 0; + + // This call will return the address of the command buffer object that is + // constructed in Initialize() and is valid until this context is destroyed. + virtual gpu::CommandBuffer* GetCommandBuffer() = 0; + + // Sets the function to be called on repaint. + virtual void SetNotifyRepaintTask(Task* task) = 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; + }; + + virtual ~PlatformAudio() {} + + // 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; + }; + + 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. @@ -45,13 +143,65 @@ class PluginDelegate { // 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 DidChangeNumberOfFindResults(int identifier, - int total, - bool final_result) = 0; + int total, + bool final_result) = 0; // Notifies that the index of the currently selected item has been updated. virtual void DidChangeSelectedFindResult(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 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; + + // 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; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_plugin_instance.cc b/webkit/glue/plugins/pepper_plugin_instance.cc index 6a7bf54..b4ccd89 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.cc +++ b/webkit/glue/plugins/pepper_plugin_instance.cc @@ -22,17 +22,19 @@ #include "printing/units.h" #include "skia/ext/vector_platform_device.h" #include "skia/ext/platform_canvas.h" +#include "third_party/ppapi/c/dev/ppb_find_dev.h" +#include "third_party/ppapi/c/dev/ppb_fullscreen_dev.h" +#include "third_party/ppapi/c/dev/ppp_find_dev.h" +#include "third_party/ppapi/c/dev/ppp_zoom_dev.h" +#include "third_party/ppapi/c/pp_input_event.h" #include "third_party/ppapi/c/pp_instance.h" -#include "third_party/ppapi/c/pp_event.h" #include "third_party/ppapi/c/pp_rect.h" #include "third_party/ppapi/c/pp_resource.h" #include "third_party/ppapi/c/pp_var.h" #include "third_party/ppapi/c/ppb_core.h" -#include "third_party/ppapi/c/ppb_find.h" #include "third_party/ppapi/c/ppb_instance.h" -#include "third_party/ppapi/c/ppp_find.h" #include "third_party/ppapi/c/ppp_instance.h" -#include "third_party/ppapi/c/ppp_zoom.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" @@ -41,8 +43,9 @@ #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" #include "webkit/glue/plugins/pepper_buffer.h" -#include "webkit/glue/plugins/pepper_device_context_2d.h" +#include "webkit/glue/plugins/pepper_graphics_2d.h" #include "webkit/glue/plugins/pepper_event_conversion.h" +#include "webkit/glue/plugins/pepper_fullscreen_container.h" #include "webkit/glue/plugins/pepper_image_data.h" #include "webkit/glue/plugins/pepper_plugin_delegate.h" #include "webkit/glue/plugins/pepper_plugin_module.h" @@ -50,6 +53,7 @@ #include "webkit/glue/plugins/pepper_url_loader.h" #include "webkit/glue/plugins/pepper_var.h" +using WebKit::WebBindings; using WebKit::WebCanvas; using WebKit::WebCursorInfo; using WebKit::WebFrame; @@ -146,11 +150,11 @@ PP_Var GetOwnerElementObject(PP_Instance instance_id) { return instance->GetOwnerElementObject(); } -bool BindGraphicsDeviceContext(PP_Instance instance_id, PP_Resource device_id) { +bool BindGraphics(PP_Instance instance_id, PP_Resource device_id) { PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); if (!instance) return false; - return instance->BindGraphicsDeviceContext(device_id); + return instance->BindGraphics(device_id); } bool IsFullFrame(PP_Instance instance_id) { @@ -160,31 +164,21 @@ bool IsFullFrame(PP_Instance instance_id) { return instance->full_frame(); } -bool SetCursor(PP_Instance instance_id, - PP_CursorType type, - PP_Resource custom_image_id, - const PP_Point* hot_spot) { +PP_Var ExecuteScript(PP_Instance instance_id, + PP_Var script, + PP_Var* exception) { PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); if (!instance) - return false; - - scoped_refptr<ImageData> custom_image( - Resource::GetAs<ImageData>(custom_image_id)); - if (custom_image.get()) { - // TODO: implement custom cursors. - NOTIMPLEMENTED(); - return false; - } - - return instance->SetCursor(type); + return PP_MakeVoid(); + return instance->ExecuteScript(script, exception); } const PPB_Instance ppb_instance = { &GetWindowObject, &GetOwnerElementObject, - &BindGraphicsDeviceContext, + &BindGraphics, &IsFullFrame, - &SetCursor, + &ExecuteScript, }; void NumberOfFindResultsChanged(PP_Instance instance_id, @@ -210,11 +204,30 @@ void SelectedFindResultChanged(PP_Instance instance_id, instance->find_identifier(), index); } -const PPB_Find ppb_find = { +const PPB_Find_Dev ppb_find = { &NumberOfFindResultsChanged, &SelectedFindResultChanged, }; +bool IsFullscreen(PP_Instance instance_id) { + PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); + if (!instance) + return false; + return instance->IsFullscreen(); +} + +bool SetFullscreen(PP_Instance instance_id, bool fullscreen) { + PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); + if (!instance) + return false; + return instance->SetFullscreen(fullscreen); +} + +const PPB_Fullscreen_Dev ppb_fullscreen = { + &IsFullscreen, + &SetFullscreen, +}; + } // namespace PluginInstance::PluginInstance(PluginDelegate* delegate, @@ -225,6 +238,8 @@ PluginInstance::PluginInstance(PluginDelegate* delegate, instance_interface_(instance_interface), container_(NULL), full_frame_(false), + has_webkit_focus_(false), + has_content_area_focus_(false), find_identifier_(-1), plugin_find_interface_(NULL), plugin_zoom_interface_(NULL), @@ -232,7 +247,10 @@ PluginInstance::PluginInstance(PluginDelegate* delegate, num_pages_(0), pdf_output_done_(false), #endif // defined (OS_LINUX) - plugin_print_interface_(NULL) { + plugin_print_interface_(NULL), + plugin_graphics_3d_interface_(NULL), + always_on_top_(false), + fullscreen_container_(NULL) { memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); DCHECK(delegate); module_->InstanceCreated(this); @@ -255,10 +273,15 @@ PluginInstance* PluginInstance::FromPPInstance(PP_Instance instance) { } // static -const PPB_Find* PluginInstance::GetFindInterface() { +const PPB_Find_Dev* PluginInstance::GetFindInterface() { return &ppb_find; } +// static +const PPB_Fullscreen_Dev* PluginInstance::GetFullscreenInterface() { + return &ppb_fullscreen; +} + PP_Instance PluginInstance::GetPPInstance() { return reinterpret_cast<intptr_t>(this); } @@ -266,17 +289,24 @@ PP_Instance PluginInstance::GetPPInstance() { void PluginInstance::Paint(WebCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect) { - if (device_context_2d_) - device_context_2d_->Paint(canvas, plugin_rect, paint_rect); + if (bound_graphics_2d_) + bound_graphics_2d_->Paint(canvas, plugin_rect, paint_rect); } void PluginInstance::InvalidateRect(const gfx::Rect& rect) { - if (!container_ || position_.IsEmpty()) - return; // Nothing to do. - if (rect.IsEmpty()) - container_->invalidate(); - else - container_->invalidateRect(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); + } } PP_Var PluginInstance::GetWindowObject() { @@ -287,29 +317,28 @@ PP_Var PluginInstance::GetWindowObject() { if (!frame) return PP_MakeVoid(); - return NPObjectToPPVar(frame->windowObject()); + return ObjectVar::NPObjectToPPVar(module(), frame->windowObject()); } PP_Var PluginInstance::GetOwnerElementObject() { if (!container_) return PP_MakeVoid(); - - return NPObjectToPPVar(container_->scriptableObjectForElement()); + return ObjectVar::NPObjectToPPVar(module(), + container_->scriptableObjectForElement()); } -bool PluginInstance::BindGraphicsDeviceContext(PP_Resource device_id) { +bool PluginInstance::BindGraphics(PP_Resource device_id) { if (!device_id) { // Special-case clearing the current device. - if (device_context_2d_) { - device_context_2d_->BindToInstance(NULL); - device_context_2d_ = NULL; + if (bound_graphics_2d_) { + bound_graphics_2d_->BindToInstance(NULL); + bound_graphics_2d_ = NULL; InvalidateRect(gfx::Rect()); } return true; } - scoped_refptr<DeviceContext2D> device_2d = - Resource::GetAs<DeviceContext2D>(device_id); + scoped_refptr<Graphics2D> device_2d = Resource::GetAs<Graphics2D>(device_id); if (device_2d) { if (!device_2d->BindToInstance(this)) @@ -317,11 +346,11 @@ bool PluginInstance::BindGraphicsDeviceContext(PP_Resource device_id) { // See http://crbug.com/49403: this can be further optimized by keeping the // old device around and painting from it. - if (device_context_2d_.get()) { + if (bound_graphics_2d_.get()) { // Start the new image with the content of the old image until the plugin // repaints. const SkBitmap* old_backing_bitmap = - device_context_2d_->image_data()->GetMappedBitmap(); + 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()))); @@ -334,21 +363,63 @@ bool PluginInstance::BindGraphicsDeviceContext(PP_Resource device_id) { canvas.drawARGB(255, 255, 255, 255); } - device_context_2d_ = device_2d; + bound_graphics_2d_ = device_2d; // BindToInstance will have invalidated the plugin if necessary. } return true; } -bool PluginInstance::SetCursor(PP_CursorType type) { +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_MakeVoid(); + + // 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_MakeVoid(); + } + 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_MakeVoid(); + } + + 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_MakeVoid(); + } + + PP_Var ret = Var::NPVariantToPPVar(module_, &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + void PluginInstance::Delete() { instance_interface_->Delete(GetPPInstance()); + if (fullscreen_container_) { + fullscreen_container_->Destroy(); + fullscreen_container_ = NULL; + } container_ = NULL; } @@ -382,11 +453,14 @@ bool PluginInstance::HandleDocumentLoad(URLLoader* loader) { bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event, WebCursorInfo* cursor_info) { - scoped_ptr<PP_Event> pp_event(CreatePP_Event(event)); - if (!pp_event.get()) - return false; + 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 |= instance_interface_->HandleInputEvent(GetPPInstance(), &pp_events[i]); - bool rv = instance_interface_->HandleEvent(GetPPInstance(), pp_event.get()); if (cursor_.get()) *cursor_info = *cursor_; return rv; @@ -415,19 +489,67 @@ void PluginInstance::ViewChanged(const gfx::Rect& position, instance_interface_->ViewChanged(GetPPInstance(), &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_->FocusChanged(GetPPInstance(), 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_->FocusChanged(GetPPInstance(), PluginHasFocus()); +} + void PluginInstance::ViewInitiatedPaint() { - if (device_context_2d_) - device_context_2d_->ViewInitiatedPaint(); + if (bound_graphics_2d_) + bound_graphics_2d_->ViewInitiatedPaint(); } void PluginInstance::ViewFlushedPaint() { - if (device_context_2d_) - device_context_2d_->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. + ImageData* 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 plugin_paint_rect = plugin_backing_store_rect.Intersect(clip_); + if (!plugin_paint_rect.Contains(paint_bounds)) + return false; + + *dib = image_data->platform_image()->GetTransportDIB(); + *location = plugin_backing_store_rect; + *clip = clip_; + return true; } string16 PluginInstance::GetSelectedText(bool html) { PP_Var rv = instance_interface_->GetSelectedText(GetPPInstance(), html); - String* string = GetString(rv); + 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()); @@ -466,8 +588,8 @@ void PluginInstance::StopFind() { bool PluginInstance::LoadFindInterface() { if (!plugin_find_interface_) { plugin_find_interface_ = - reinterpret_cast<const PPP_Find*>(module_->GetPluginInterface( - PPP_FIND_INTERFACE)); + reinterpret_cast<const PPP_Find_Dev*>(module_->GetPluginInterface( + PPP_FIND_DEV_INTERFACE)); } return !!plugin_find_interface_; @@ -476,24 +598,28 @@ bool PluginInstance::LoadFindInterface() { bool PluginInstance::LoadZoomInterface() { if (!plugin_zoom_interface_) { plugin_zoom_interface_ = - reinterpret_cast<const PPP_Zoom*>(module_->GetPluginInterface( - PPP_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* format) { + PP_PrintOutputFormat_Dev* format) { if (!plugin_print_interface_) { plugin_print_interface_ = - reinterpret_cast<const PPP_Printing*>(module_->GetPluginInterface( - PPP_PRINTING_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* supported_formats = + PP_PrintOutputFormat_Dev* supported_formats = plugin_print_interface_->QuerySupportedFormats(GetPPInstance(), &format_count); if (!supported_formats) @@ -517,13 +643,13 @@ bool PluginInstance::GetPreferredPrintOutputFormat( } bool PluginInstance::SupportsPrintInterface() { - PP_PrintOutputFormat format; + PP_PrintOutputFormat_Dev format; return GetPreferredPrintOutputFormat(&format); } int PluginInstance::PrintBegin(const gfx::Rect& printable_area, int printer_dpi) { - PP_PrintOutputFormat format; + PP_PrintOutputFormat_Dev format; if (!GetPreferredPrintOutputFormat(&format)) { // PrintBegin should not have been called since SupportsPrintInterface // would have returned false; @@ -531,7 +657,7 @@ int PluginInstance::PrintBegin(const gfx::Rect& printable_area, return 0; } - PP_PrintSettings print_settings; + PP_PrintSettings_Dev print_settings; RectToPPRect(printable_area, &print_settings.printable_area); print_settings.dpi = printer_dpi; print_settings.orientation = PP_PRINTORIENTATION_NORMAL; @@ -551,7 +677,7 @@ int PluginInstance::PrintBegin(const gfx::Rect& printable_area, bool PluginInstance::PrintPage(int page_number, WebKit::WebCanvas* canvas) { DCHECK(plugin_print_interface_); - PP_PrintPageNumberRange page_range; + 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 @@ -592,13 +718,48 @@ void PluginInstance::PrintEnd() { plugin_print_interface_->End(GetPPInstance()); memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); #if defined(OS_MACOSX) - last_printed_page_ = SkBitmap(); + last_printed_page_ = NULL; #elif defined(OS_LINUX) num_pages_ = 0; pdf_output_done_ = false; #endif // defined(OS_LINUX) } +void PluginInstance::Graphics3DContextLost() { + if (!plugin_graphics_3d_interface_) { + plugin_graphics_3d_interface_ = + reinterpret_cast<const PPP_Graphics3D_Dev*>(module_->GetPluginInterface( + PPP_GRAPHICS_3D_DEV_INTERFACE)); + } + if (plugin_graphics_3d_interface_) + plugin_graphics_3d_interface_->Graphics3DContextLost(GetPPInstance()); +} + +bool PluginInstance::IsFullscreen() { + return fullscreen_container_ != NULL; +} + +bool PluginInstance::SetFullscreen(bool fullscreen) { + bool is_fullscreen = (fullscreen_container_ != NULL); + if (fullscreen == is_fullscreen) + return true; + LOG(INFO) << "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::PrintPDFOutput(PP_Resource print_output, WebKit::WebCanvas* canvas) { scoped_refptr<Buffer> buffer(Resource::GetAs<Buffer>(print_output)); @@ -730,7 +891,7 @@ bool PluginInstance::PrintRasterOutput(PP_Resource print_output, DrawSkBitmapToCanvas(*bitmap, canvas, dest_rect_gfx, current_print_settings_.printable_area.size.height); // See comments in the header file. - last_printed_page_ = *bitmap; + last_printed_page_ = image; #else // defined(OS_MACOSX) if (draw_to_canvas) canvas->drawBitmapRect(*bitmap, &src_rect, dest_rect); diff --git a/webkit/glue/plugins/pepper_plugin_instance.h b/webkit/glue/plugins/pepper_plugin_instance.h index 4528a99..4eb956f 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.h +++ b/webkit/glue/plugins/pepper_plugin_instance.h @@ -13,21 +13,24 @@ #include "base/scoped_ptr.h" #include "base/string16.h" #include "gfx/rect.h" -#include "third_party/ppapi/c/pp_cursor_type.h" +#include "third_party/ppapi/c/dev/pp_cursor_type_dev.h" +#include "third_party/ppapi/c/dev/ppp_graphics_3d_dev.h" +#include "third_party/ppapi/c/dev/ppp_printing_dev.h" #include "third_party/ppapi/c/pp_instance.h" #include "third_party/ppapi/c/pp_resource.h" -#include "third_party/ppapi/c/ppp_printing.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h" -typedef struct _pp_Var PP_Var; -typedef struct _ppb_Instance PPB_Instance; -typedef struct _ppb_Find PPB_Find; -typedef struct _ppp_Find PPP_Find; -typedef struct _ppp_Instance PPP_Instance; -typedef struct _ppp_Zoom PPP_Zoom; +struct PP_Var; +struct PPB_Instance; +struct PPB_Find_Dev; +struct PPB_Fullscreen_Dev; +struct PPP_Find_Dev; +struct PPP_Instance; +struct PPP_Zoom_Dev; class SkBitmap; +class TransportDIB; namespace gfx { class Rect; @@ -41,10 +44,12 @@ class WebPluginContainer; namespace pepper { -class DeviceContext2D; +class Graphics2D; +class ImageData; class PluginDelegate; class PluginModule; class URLLoader; +class FullscreenContainer; class PluginInstance : public base::RefCounted<PluginInstance> { public: @@ -60,7 +65,8 @@ class PluginInstance : public base::RefCounted<PluginInstance> { // Returns a pointer to the interface implementing PPB_Find that is // exposed to the plugin. - static const PPB_Find* GetFindInterface(); + static const PPB_Find_Dev* GetFindInterface(); + static const PPB_Fullscreen_Dev* GetFullscreenInterface(); PluginDelegate* delegate() const { return delegate_; } PluginModule* module() const { return module_.get(); } @@ -72,6 +78,8 @@ class PluginInstance : public base::RefCounted<PluginInstance> { int find_identifier() const { return find_identifier_; } + void set_always_on_top(bool on_top) { always_on_top_ = on_top; } + PP_Instance GetPPInstance(); // Paints the current backing store to the web page. @@ -88,9 +96,10 @@ class PluginInstance : public base::RefCounted<PluginInstance> { // PPB_Instance implementation. PP_Var GetWindowObject(); PP_Var GetOwnerElementObject(); - bool BindGraphicsDeviceContext(PP_Resource device_id); + bool BindGraphics(PP_Resource device_id); bool full_frame() const { return full_frame_; } - bool SetCursor(PP_CursorType type); + bool SetCursor(PP_CursorType_Dev type); + PP_Var ExecuteScript(PP_Var script, PP_Var* exception); // PPP_Instance pass-through. void Delete(); @@ -104,12 +113,26 @@ class PluginInstance : public base::RefCounted<PluginInstance> { 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); void Zoom(float factor, bool text_only); bool StartFind(const string16& search_text, @@ -123,14 +146,24 @@ class PluginInstance : public base::RefCounted<PluginInstance> { bool PrintPage(int page_number, WebKit::WebCanvas* canvas); void PrintEnd(); + void Graphics3DContextLost(); + + // Implementation of PPB_Fullscreen_Dev. + bool IsFullscreen(); + bool SetFullscreen(bool fullscreen); + private: bool LoadFindInterface(); 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* format); + 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) @@ -165,24 +198,31 @@ class PluginInstance : public base::RefCounted<PluginInstance> { // be (0, 0, w, h) regardless of scroll position. gfx::Rect clip_; + // 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 current device context for painting in 2D. - scoped_refptr<DeviceContext2D> device_context_2d_; + scoped_refptr<Graphics2D> bound_graphics_2d_; // The id of the current find operation, or -1 if none is in process. int find_identifier_; // The plugin find and zoom interfaces. - const PPP_Find* plugin_find_interface_; - const PPP_Zoom* plugin_zoom_interface_; + const PPP_Find_Dev* plugin_find_interface_; + const PPP_Zoom_Dev* plugin_zoom_interface_; // This is only valid between a successful PrintBegin call and a PrintEnd // call. - PP_PrintSettings current_print_settings_; + 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. - SkBitmap last_printed_page_; + scoped_refptr<ImageData> 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 @@ -197,11 +237,21 @@ class PluginInstance : public base::RefCounted<PluginInstance> { #endif // defined(OS_LINUX) // The plugin print interface. - const PPP_Printing* 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_; + DISALLOW_COPY_AND_ASSIGN(PluginInstance); }; diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc index 8ffd78b..251023f 100644 --- a/webkit/glue/plugins/pepper_plugin_module.cc +++ b/webkit/glue/plugins/pepper_plugin_module.cc @@ -12,46 +12,71 @@ #include "base/logging.h" #include "base/scoped_ptr.h" #include "base/time.h" -#include "third_party/ppapi/c/ppb_buffer.h" +#include "third_party/ppapi/c/dev/ppb_buffer_dev.h" +#include "third_party/ppapi/c/dev/ppb_char_set_dev.h" +#include "third_party/ppapi/c/dev/ppb_cursor_control_dev.h" +#include "third_party/ppapi/c/dev/ppb_directory_reader_dev.h" +#include "third_party/ppapi/c/dev/ppb_file_io_dev.h" +#include "third_party/ppapi/c/dev/ppb_file_io_trusted_dev.h" +#include "third_party/ppapi/c/dev/ppb_file_system_dev.h" +#include "third_party/ppapi/c/dev/ppb_find_dev.h" +#include "third_party/ppapi/c/dev/ppb_font_dev.h" +#include "third_party/ppapi/c/dev/ppb_fullscreen_dev.h" +#include "third_party/ppapi/c/dev/ppb_graphics_3d_dev.h" +#include "third_party/ppapi/c/dev/ppb_opengles_dev.h" +#include "third_party/ppapi/c/dev/ppb_scrollbar_dev.h" +#include "third_party/ppapi/c/dev/ppb_testing_dev.h" +#include "third_party/ppapi/c/dev/ppb_transport_dev.h" +#include "third_party/ppapi/c/dev/ppb_url_loader_dev.h" +#include "third_party/ppapi/c/dev/ppb_url_loader_trusted_dev.h" +#include "third_party/ppapi/c/dev/ppb_url_request_info_dev.h" +#include "third_party/ppapi/c/dev/ppb_url_response_info_dev.h" +#include "third_party/ppapi/c/dev/ppb_url_util_dev.h" +#include "third_party/ppapi/c/dev/ppb_video_decoder_dev.h" +#include "third_party/ppapi/c/dev/ppb_widget_dev.h" +#include "third_party/ppapi/c/trusted/ppb_image_data_trusted.h" +#include "third_party/ppapi/c/pp_module.h" +#include "third_party/ppapi/c/pp_resource.h" +#include "third_party/ppapi/c/pp_var.h" #include "third_party/ppapi/c/ppb_core.h" -#include "third_party/ppapi/c/ppb_device_context_2d.h" -#include "third_party/ppapi/c/ppb_file_io.h" -#include "third_party/ppapi/c/ppb_file_io_trusted.h" -#include "third_party/ppapi/c/ppb_file_system.h" +#include "third_party/ppapi/c/ppb_graphics_2d.h" #include "third_party/ppapi/c/ppb_image_data.h" #include "third_party/ppapi/c/ppb_instance.h" -#include "third_party/ppapi/c/ppb_find.h" -#include "third_party/ppapi/c/ppb_font.h" -#include "third_party/ppapi/c/ppb_scrollbar.h" -#include "third_party/ppapi/c/ppb_testing.h" -#include "third_party/ppapi/c/ppb_url_loader.h" -#include "third_party/ppapi/c/ppb_url_request_info.h" -#include "third_party/ppapi/c/ppb_url_response_info.h" #include "third_party/ppapi/c/ppb_var.h" -#include "third_party/ppapi/c/ppb_widget.h" #include "third_party/ppapi/c/ppp.h" #include "third_party/ppapi/c/ppp_instance.h" -#include "third_party/ppapi/c/pp_module.h" -#include "third_party/ppapi/c/pp_resource.h" -#include "third_party/ppapi/c/pp_var.h" +#include "webkit/glue/plugins/pepper_audio.h" #include "webkit/glue/plugins/pepper_buffer.h" -#include "webkit/glue/plugins/pepper_device_context_2d.h" +#include "webkit/glue/plugins/pepper_char_set.h" +#include "webkit/glue/plugins/pepper_cursor_control.h" #include "webkit/glue/plugins/pepper_directory_reader.h" +#include "webkit/glue/plugins/pepper_file_chooser.h" #include "webkit/glue/plugins/pepper_file_io.h" #include "webkit/glue/plugins/pepper_file_ref.h" #include "webkit/glue/plugins/pepper_file_system.h" #include "webkit/glue/plugins/pepper_font.h" +#include "webkit/glue/plugins/pepper_graphics_2d.h" #include "webkit/glue/plugins/pepper_image_data.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" +#include "webkit/glue/plugins/pepper_plugin_object.h" #include "webkit/glue/plugins/pepper_private.h" +#include "webkit/glue/plugins/pepper_private2.h" #include "webkit/glue/plugins/pepper_resource_tracker.h" #include "webkit/glue/plugins/pepper_scrollbar.h" +#include "webkit/glue/plugins/pepper_transport.h" #include "webkit/glue/plugins/pepper_url_loader.h" #include "webkit/glue/plugins/pepper_url_request_info.h" #include "webkit/glue/plugins/pepper_url_response_info.h" +#include "webkit/glue/plugins/pepper_url_util.h" #include "webkit/glue/plugins/pepper_var.h" +#include "webkit/glue/plugins/pepper_video_decoder.h" #include "webkit/glue/plugins/pepper_widget.h" #include "webkit/glue/plugins/ppb_private.h" +#include "webkit/glue/plugins/ppb_private2.h" + +#ifdef ENABLE_GPU +#include "webkit/glue/plugins/pepper_graphics_3d.h" +#endif // ENABLE_GPU namespace pepper { @@ -107,13 +132,18 @@ void CallOnMainThread(int delay_in_msec, delay_in_msec); } +bool IsMainThread() { + return GetMainThreadMessageLoop()->BelongsToCurrentThread(); +} + const PPB_Core core_interface = { &AddRefResource, &ReleaseResource, &MemAlloc, &MemFree, &GetTime, - &CallOnMainThread + &CallOnMainThread, + &IsMainThread }; // PPB_Testing ----------------------------------------------------------------- @@ -121,8 +151,8 @@ const PPB_Core core_interface = { bool ReadImageData(PP_Resource device_context_2d, PP_Resource image, const PP_Point* top_left) { - scoped_refptr<DeviceContext2D> context( - Resource::GetAs<DeviceContext2D>(device_context_2d)); + scoped_refptr<Graphics2D> context( + Resource::GetAs<Graphics2D>(device_context_2d)); if (!context.get()) return false; return context->ReadImageData(image, top_left); @@ -136,13 +166,37 @@ void RunMessageLoop() { } void QuitMessageLoop() { - MessageLoop::current()->Quit(); + MessageLoop::current()->QuitNow(); +} + +uint32_t GetLiveObjectCount(PP_Module module_id) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return static_cast<uint32_t>(-1); + return ResourceTracker::Get()->GetLiveObjectsForModule(module); +} + +PP_Resource GetInaccessibleFileRef(PP_Module module_id) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return static_cast<uint32_t>(-1); + return FileRef::GetInaccessibleFileRef(module)->GetReference(); +} + +PP_Resource GetNonexistentFileRef(PP_Module module_id) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return static_cast<uint32_t>(-1); + return FileRef::GetNonexistentFileRef(module)->GetReference(); } -const PPB_Testing testing_interface = { +const PPB_Testing_Dev testing_interface = { &ReadImageData, &RunMessageLoop, &QuitMessageLoop, + &GetLiveObjectCount, + &GetInaccessibleFileRef, + &GetNonexistentFileRef }; // GetInterface ---------------------------------------------------------------- @@ -151,46 +205,78 @@ const void* GetInterface(const char* name) { if (strcmp(name, PPB_CORE_INTERFACE) == 0) return &core_interface; if (strcmp(name, PPB_VAR_INTERFACE) == 0) - return GetVarInterface(); + return Var::GetInterface(); if (strcmp(name, PPB_INSTANCE_INTERFACE) == 0) return PluginInstance::GetInterface(); if (strcmp(name, PPB_IMAGEDATA_INTERFACE) == 0) return ImageData::GetInterface(); - if (strcmp(name, PPB_DEVICECONTEXT2D_INTERFACE) == 0) - return DeviceContext2D::GetInterface(); - if (strcmp(name, PPB_URLLOADER_INTERFACE) == 0) + if (strcmp(name, PPB_IMAGEDATA_TRUSTED_INTERFACE) == 0) + return ImageData::GetTrustedInterface(); + if (strcmp(name, PPB_AUDIO_CONFIG_DEV_INTERFACE) == 0) + return AudioConfig::GetInterface(); + if (strcmp(name, PPB_AUDIO_DEV_INTERFACE) == 0) + return Audio::GetInterface(); + if (strcmp(name, PPB_AUDIO_TRUSTED_DEV_INTERFACE) == 0) + return Audio::GetTrustedInterface(); + if (strcmp(name, PPB_GRAPHICS_2D_INTERFACE) == 0) + return Graphics2D::GetInterface(); +#ifdef ENABLE_GPU + if (strcmp(name, PPB_GRAPHICS_3D_DEV_INTERFACE) == 0) + return Graphics3D::GetInterface(); + if (strcmp(name, PPB_OPENGLES_DEV_INTERFACE) == 0) + return Graphics3D::GetOpenGLESInterface(); +#endif // ENABLE_GPU + if (strcmp(name, PPB_TRANSPORT_DEV_INTERFACE) == 0) + return Transport::GetInterface(); + if (strcmp(name, PPB_URLLOADER_DEV_INTERFACE) == 0) return URLLoader::GetInterface(); - if (strcmp(name, PPB_URLREQUESTINFO_INTERFACE) == 0) + if (strcmp(name, PPB_URLLOADERTRUSTED_DEV_INTERFACE) == 0) + return URLLoader::GetTrustedInterface(); + if (strcmp(name, PPB_URLREQUESTINFO_DEV_INTERFACE) == 0) return URLRequestInfo::GetInterface(); - if (strcmp(name, PPB_URLRESPONSEINFO_INTERFACE) == 0) + if (strcmp(name, PPB_URLRESPONSEINFO_DEV_INTERFACE) == 0) return URLResponseInfo::GetInterface(); - if (strcmp(name, PPB_BUFFER_INTERFACE) == 0) + if (strcmp(name, PPB_BUFFER_DEV_INTERFACE) == 0) return Buffer::GetInterface(); - if (strcmp(name, PPB_FILEREF_INTERFACE) == 0) + if (strcmp(name, PPB_FILEREF_DEV_INTERFACE) == 0) return FileRef::GetInterface(); - if (strcmp(name, PPB_FILEIO_INTERFACE) == 0) + if (strcmp(name, PPB_FILEIO_DEV_INTERFACE) == 0) return FileIO::GetInterface(); - if (strcmp(name, PPB_FILEIOTRUSTED_INTERFACE) == 0) + if (strcmp(name, PPB_FILEIOTRUSTED_DEV_INTERFACE) == 0) return FileIO::GetTrustedInterface(); - if (strcmp(name, PPB_FILESYSTEM_INTERFACE) == 0) + if (strcmp(name, PPB_FILESYSTEM_DEV_INTERFACE) == 0) return FileSystem::GetInterface(); - if (strcmp(name, PPB_DIRECTORYREADER_INTERFACE) == 0) + if (strcmp(name, PPB_DIRECTORYREADER_DEV_INTERFACE) == 0) return DirectoryReader::GetInterface(); - if (strcmp(name, PPB_WIDGET_INTERFACE) == 0) + if (strcmp(name, PPB_WIDGET_DEV_INTERFACE) == 0) return Widget::GetInterface(); - if (strcmp(name, PPB_SCROLLBAR_INTERFACE) == 0) + if (strcmp(name, PPB_SCROLLBAR_DEV_INTERFACE) == 0) return Scrollbar::GetInterface(); - if (strcmp(name, PPB_FONT_INTERFACE) == 0) + if (strcmp(name, PPB_FONT_DEV_INTERFACE) == 0) return Font::GetInterface(); - if (strcmp(name, PPB_FIND_INTERFACE) == 0) + if (strcmp(name, PPB_FIND_DEV_INTERFACE) == 0) return PluginInstance::GetFindInterface(); + if (strcmp(name, PPB_FULLSCREEN_DEV_INTERFACE) == 0) + return PluginInstance::GetFullscreenInterface(); + if (strcmp(name, PPB_URLUTIL_DEV_INTERFACE) == 0) + return UrlUtil::GetInterface(); if (strcmp(name, PPB_PRIVATE_INTERFACE) == 0) return Private::GetInterface(); + if (strcmp(name, PPB_PRIVATE2_INTERFACE) == 0) + return Private2::GetInterface(); + if (strcmp(name, PPB_FILECHOOSER_DEV_INTERFACE) == 0) + return FileChooser::GetInterface(); + if (strcmp(name, PPB_VIDEODECODER_DEV_INTERFACE) == 0) + return VideoDecoder::GetInterface(); + if (strcmp(name, PPB_CHAR_SET_DEV_INTERFACE) == 0) + return CharSet::GetInterface(); + if (strcmp(name, PPB_CURSOR_CONTROL_DEV_INTERFACE) == 0) + return GetCursorControlInterface(); // 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_INTERFACE) == 0) { + if (strcmp(name, PPB_TESTING_DEV_INTERFACE) == 0) { if (CommandLine::ForCurrentProcess()->HasSwitch("enable-pepper-testing")) return &testing_interface; } @@ -207,6 +293,17 @@ PluginModule::PluginModule() } 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()); @@ -359,4 +456,44 @@ void PluginModule::InstanceDeleted(PluginInstance* 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); +} + } // namespace pepper diff --git a/webkit/glue/plugins/pepper_plugin_module.h b/webkit/glue/plugins/pepper_plugin_module.h index 6bfeccf..a560c56 100644 --- a/webkit/glue/plugins/pepper_plugin_module.h +++ b/webkit/glue/plugins/pepper_plugin_module.h @@ -5,23 +5,30 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_MODULE_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_MODULE_H_ +#include <map> #include <set> #include "base/basictypes.h" -#include "base/file_path.h" #include "base/native_library.h" #include "base/ref_counted.h" +#include "base/weak_ptr.h" #include "third_party/ppapi/c/pp_module.h" #include "third_party/ppapi/c/ppb.h" -typedef struct _ppb_Core PPB_Core; +class FilePath; +typedef struct NPObject NPObject; +struct PPB_Core; +typedef void* NPIdentifier; namespace pepper { +class ObjectVar; class PluginDelegate; class PluginInstance; +class PluginObject; -class PluginModule : public base::RefCounted<PluginModule> { +class PluginModule : public base::RefCounted<PluginModule>, + public base::SupportsWeakPtr<PluginModule> { public: typedef const void* (*PPP_GetInterfaceFunc)(const char*); typedef int (*PPP_InitializeModuleFunc)(PP_Module, PPB_GetInterface); @@ -69,6 +76,22 @@ class PluginModule : public base::RefCounted<PluginModule> { 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: PluginModule(); @@ -94,6 +117,14 @@ class PluginModule : public base::RefCounted<PluginModule> { 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); }; diff --git a/webkit/glue/plugins/pepper_private.cc b/webkit/glue/plugins/pepper_private.cc index 8d5182f..e35006b 100644 --- a/webkit/glue/plugins/pepper_private.cc +++ b/webkit/glue/plugins/pepper_private.cc @@ -6,26 +6,167 @@ #include "webkit/glue/plugins/pepper_private.h" +#include "app/resource_bundle.h" #include "base/utf_string_conversions.h" +#include "grit/webkit_resources.h" #include "grit/webkit_strings.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "webkit/glue/webkit_glue.h" +#include "webkit/glue/plugins/pepper_image_data.h" +#include "webkit/glue/plugins/pepper_plugin_module.h" #include "webkit/glue/plugins/pepper_var.h" #include "webkit/glue/plugins/ppb_private.h" namespace pepper { +#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 { -PP_Var GetLocalizedString(PP_ResourceString string_id) { +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 = PluginModule::FromPPModule(module_id); + if (!module) + return PP_MakeVoid(); + std::string rv; if (string_id == PP_RESOURCESTRING_PDFGETPASSWORD) rv = UTF16ToUTF8(webkit_glue::GetLocalizedString(IDS_PDF_NEED_PASSWORD)); - return StringToPPVar(rv); + 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 = PluginModule::FromPPModule(module_id); + if (!module) + return 0; + scoped_refptr<pepper::ImageData> image_data(new pepper::ImageData(module)); + if (!image_data->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, + 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_PrivateFontFileDescription* description) { +#if defined(OS_LINUX) + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return 0; + + int fd = webkit_glue::MatchFontWithFallback(description->face, + description->weight >= 700, + description->italic, + description->charset); + if (fd == -1) + return 0; + + scoped_refptr<PrivateFontFile> font(new PrivateFontFile(module, fd)); + + return font->GetReference(); +#else + // For trusted pepper 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 } const PPB_Private ppb_private = { &GetLocalizedString, + &GetResourceImage, + &GetFontFileWithFallback, + &GetFontTableForPrivateFontFile, }; } // namespace @@ -35,4 +176,16 @@ const PPB_Private* Private::GetInterface() { return &ppb_private; } +#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 pepper diff --git a/webkit/glue/plugins/pepper_private.h b/webkit/glue/plugins/pepper_private.h index fda75a7..06016f0 100644 --- a/webkit/glue/plugins/pepper_private.h +++ b/webkit/glue/plugins/pepper_private.h @@ -7,7 +7,7 @@ #include "webkit/glue/plugins/pepper_resource.h" -typedef struct _ppb_Private PPB_Private; +struct PPB_Private; namespace pepper { diff --git a/webkit/glue/plugins/pepper_resource.cc b/webkit/glue/plugins/pepper_resource.cc index c568183..cf7a7fe 100644 --- a/webkit/glue/plugins/pepper_resource.cc +++ b/webkit/glue/plugins/pepper_resource.cc @@ -4,10 +4,18 @@ #include "webkit/glue/plugins/pepper_resource.h" +#include "base/logging.h" #include "webkit/glue/plugins/pepper_resource_tracker.h" namespace pepper { +Resource::Resource(PluginModule* module) + : resource_id_(0), module_(module) { +} + +Resource::~Resource() { +} + PP_Resource Resource::GetReference() { ResourceTracker *tracker = ResourceTracker::Get(); if (resource_id_) @@ -16,4 +24,10 @@ PP_Resource Resource::GetReference() { resource_id_ = tracker->AddResource(this); return resource_id_; } + +void Resource::StoppedTracking() { + DCHECK(resource_id_ != 0); + resource_id_ = 0; +} + } // namespace pepper diff --git a/webkit/glue/plugins/pepper_resource.h b/webkit/glue/plugins/pepper_resource.h index 417a06b..cab6f32 100644 --- a/webkit/glue/plugins/pepper_resource.h +++ b/webkit/glue/plugins/pepper_resource.h @@ -5,7 +5,6 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_RESOURCE_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_RESOURCE_H_ -#include "base/logging.h" #include "base/basictypes.h" #include "base/ref_counted.h" #include "third_party/ppapi/c/pp_resource.h" @@ -14,24 +13,33 @@ namespace pepper { class Buffer; -class DeviceContext2D; +class Audio; +class AudioConfig; class DirectoryReader; class FileChooser; class FileIO; class FileRef; class Font; +class Graphics2D; +class Graphics3D; class ImageData; +class ObjectVar; class PluginModule; +class PrivateFontFile; class Scrollbar; +class StringVar; +class Transport; class URLLoader; class URLRequestInfo; class URLResponseInfo; +class Var; +class VideoDecoder; class Widget; class Resource : public base::RefCountedThreadSafe<Resource> { public: - explicit Resource(PluginModule* module) : resource_id_(0), module_(module) {} - virtual ~Resource() {} + explicit Resource(PluginModule* module); + virtual ~Resource(); // Returns NULL if the resource is invalid or is a different type. template<typename T> @@ -72,18 +80,27 @@ class Resource : public base::RefCountedThreadSafe<Resource> { // 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. + virtual Audio* AsAudio() { return NULL; } + virtual AudioConfig* AsAudioConfig() { return NULL; } virtual Buffer* AsBuffer() { return NULL; } - virtual DeviceContext2D* AsDeviceContext2D() { return NULL; } virtual DirectoryReader* AsDirectoryReader() { return NULL; } virtual FileChooser* AsFileChooser() { return NULL; } virtual FileIO* AsFileIO() { return NULL; } virtual FileRef* AsFileRef() { return NULL; } virtual Font* AsFont() { return NULL; } + virtual Graphics2D* AsGraphics2D() { return NULL; } + virtual Graphics3D* AsGraphics3D() { return NULL; } virtual ImageData* AsImageData() { return NULL; } + virtual ObjectVar* AsObjectVar() { return NULL; } + virtual PrivateFontFile* AsPrivateFontFile() { return NULL; } virtual Scrollbar* AsScrollbar() { return NULL; } + virtual StringVar* AsStringVar() { return NULL; } + virtual Transport* AsTransport() { return NULL; } virtual URLLoader* AsURLLoader() { return NULL; } virtual URLRequestInfo* AsURLRequestInfo() { return NULL; } virtual URLResponseInfo* AsURLResponseInfo() { return NULL; } + virtual Var* AsVar() { return NULL; } + virtual VideoDecoder* AsVideoDecoder() { return NULL; } virtual Widget* AsWidget() { return NULL; } private: @@ -101,10 +118,7 @@ class Resource : public base::RefCountedThreadSafe<Resource> { // Called by the resource tracker when the last plugin reference has been // dropped. friend class ResourceTracker; - void StoppedTracking() { - DCHECK(resource_id_ != 0); - resource_id_ = 0; - } + void StoppedTracking(); DISALLOW_COPY_AND_ASSIGN(Resource); }; @@ -115,18 +129,27 @@ class Resource : public base::RefCountedThreadSafe<Resource> { return As##Type(); \ } +DEFINE_RESOURCE_CAST(Audio) +DEFINE_RESOURCE_CAST(AudioConfig) DEFINE_RESOURCE_CAST(Buffer) -DEFINE_RESOURCE_CAST(DeviceContext2D) DEFINE_RESOURCE_CAST(DirectoryReader) DEFINE_RESOURCE_CAST(FileChooser) DEFINE_RESOURCE_CAST(FileIO) DEFINE_RESOURCE_CAST(FileRef) DEFINE_RESOURCE_CAST(Font) +DEFINE_RESOURCE_CAST(Graphics2D) +DEFINE_RESOURCE_CAST(Graphics3D) DEFINE_RESOURCE_CAST(ImageData) +DEFINE_RESOURCE_CAST(ObjectVar) +DEFINE_RESOURCE_CAST(PrivateFontFile) DEFINE_RESOURCE_CAST(Scrollbar) +DEFINE_RESOURCE_CAST(StringVar); +DEFINE_RESOURCE_CAST(Transport) DEFINE_RESOURCE_CAST(URLLoader) DEFINE_RESOURCE_CAST(URLRequestInfo) DEFINE_RESOURCE_CAST(URLResponseInfo) +DEFINE_RESOURCE_CAST(Var) +DEFINE_RESOURCE_CAST(VideoDecoder) DEFINE_RESOURCE_CAST(Widget) #undef DEFINE_RESOURCE_CAST diff --git a/webkit/glue/plugins/pepper_resource_tracker.cc b/webkit/glue/plugins/pepper_resource_tracker.cc index 8aa94d2..9ee54f8 100644 --- a/webkit/glue/plugins/pepper_resource_tracker.cc +++ b/webkit/glue/plugins/pepper_resource_tracker.cc @@ -21,6 +21,13 @@ scoped_refptr<Resource> ResourceTracker::GetResource(PP_Resource res) const { return result->second.first; } +ResourceTracker::ResourceTracker() + : last_id_(0) { +} + +ResourceTracker::~ResourceTracker() { +} + PP_Resource ResourceTracker::AddResource(Resource* resource) { // If the plugin manages to create 4B resources... if (last_id_ == std::numeric_limits<PP_Resource>::max()) { @@ -58,4 +65,18 @@ bool ResourceTracker::UnrefResource(PP_Resource res) { } } +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; +} + } // namespace pepper diff --git a/webkit/glue/plugins/pepper_resource_tracker.h b/webkit/glue/plugins/pepper_resource_tracker.h index d06c9ba..59f02d2 100644 --- a/webkit/glue/plugins/pepper_resource_tracker.h +++ b/webkit/glue/plugins/pepper_resource_tracker.h @@ -5,17 +5,19 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_RESOURCE_TRACKER_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_RESOURCE_TRACKER_H_ -#include <set> +#include <utility> -#include "base/atomic_sequence_num.h" #include "base/basictypes.h" #include "base/hash_tables.h" #include "base/ref_counted.h" #include "base/singleton.h" #include "third_party/ppapi/c/pp_resource.h" +typedef struct NPObject NPObject; + namespace pepper { +class PluginModule; class Resource; // This class maintains a global list of all live pepper resources. It allows @@ -41,13 +43,18 @@ class ResourceTracker { bool AddRefResource(PP_Resource res); bool UnrefResource(PP_Resource res); + // Returns the number of resources associated with this module. + // + // This is slow, use only for testing. + uint32 GetLiveObjectsForModule(PluginModule* module) const; + private: friend struct DefaultSingletonTraits<ResourceTracker>; friend class Resource; // Prohibit creation other then by the Singleton class. - ResourceTracker() : last_id_(0) {} - ~ResourceTracker() {} + 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 diff --git a/webkit/glue/plugins/pepper_scrollbar.cc b/webkit/glue/plugins/pepper_scrollbar.cc index 48db8d4..a8943d2 100644 --- a/webkit/glue/plugins/pepper_scrollbar.cc +++ b/webkit/glue/plugins/pepper_scrollbar.cc @@ -6,7 +6,8 @@ #include "base/logging.h" #include "base/message_loop.h" -#include "third_party/ppapi/c/ppp_scrollbar.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/ppapi/c/dev/ppp_scrollbar_dev.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" @@ -17,6 +18,10 @@ #include "webkit/glue/plugins/pepper_plugin_module.h" #include "webkit/glue/webkit_glue.h" +#if defined(OS_WIN) +#include "base/win_util.h" +#endif + using WebKit::WebInputEvent; using WebKit::WebRect; using WebKit::WebScrollbar; @@ -28,7 +33,7 @@ namespace { PP_Resource Create(PP_Instance instance_id, bool vertical) { PluginInstance* instance = PluginInstance::FromPPInstance(instance_id); if (!instance) - return NULL; + return 0; scoped_refptr<Scrollbar> scrollbar(new Scrollbar(instance, vertical)); return scrollbar->GetReference(); @@ -69,15 +74,13 @@ void SetTickMarks(PP_Resource resource, scrollbar->SetTickMarks(tick_marks, count); } -void ScrollBy(PP_Resource resource, - PP_ScrollBy unit, - int32_t multiplier) { +void ScrollBy(PP_Resource resource, PP_ScrollBy_Dev unit, int32_t multiplier) { scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource)); if (scrollbar) scrollbar->ScrollBy(unit, multiplier); } -const PPB_Scrollbar ppb_scrollbar = { +const PPB_Scrollbar_Dev ppb_scrollbar = { &Create, &IsScrollbar, &GetThickness, @@ -101,7 +104,7 @@ Scrollbar::~Scrollbar() { } // static -const PPB_Scrollbar* Scrollbar::GetInterface() { +const PPB_Scrollbar_Dev* Scrollbar::GetInterface() { return &ppb_scrollbar; } @@ -129,7 +132,7 @@ void Scrollbar::SetTickMarks(const PP_Rect* tick_marks, uint32_t count) { Invalidate(&rect); } -void Scrollbar::ScrollBy(PP_ScrollBy unit, int32_t multiplier) { +void Scrollbar::ScrollBy(PP_ScrollBy_Dev unit, int32_t multiplier) { WebScrollbar::ScrollDirection direction = multiplier >= 0 ? WebScrollbar::ScrollForward : WebScrollbar::ScrollBackward; float fmultiplier = 1.0; @@ -159,10 +162,18 @@ bool Scrollbar::Paint(const PP_Rect* rect, ImageData* image) { if (!canvas) return false; scrollbar_->paint(webkit_glue::ToWebCanvas(canvas), gfx_rect); + +#if defined(OS_WIN) + if (win_util::GetWinVersion() == win_util::WINVERSION_XP) { + canvas->getTopPlatformDevice().makeOpaque( + gfx_rect.x(), gfx_rect.y(), gfx_rect.width(), gfx_rect.height()); + } +#endif + return true; } -bool Scrollbar::HandleEvent(const PP_Event* event) { +bool Scrollbar::HandleEvent(const PP_InputEvent* event) { scoped_ptr<WebInputEvent> web_input_event(CreateWebInputEvent(*event)); if (!web_input_event.get()) return false; @@ -178,8 +189,9 @@ void Scrollbar::SetLocationInternal(const PP_Rect* location) { } void Scrollbar::valueChanged(WebKit::WebScrollbar* scrollbar) { - const PPP_Scrollbar* ppp_scrollbar = static_cast<const PPP_Scrollbar*>( - module()->GetPluginInterface(PPP_SCROLLBAR_INTERFACE)); + 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); diff --git a/webkit/glue/plugins/pepper_scrollbar.h b/webkit/glue/plugins/pepper_scrollbar.h index bf25136..e8ac480 100644 --- a/webkit/glue/plugins/pepper_scrollbar.h +++ b/webkit/glue/plugins/pepper_scrollbar.h @@ -8,13 +8,11 @@ #include <vector> #include "gfx/rect.h" -#include "third_party/ppapi/c/ppb_scrollbar.h" +#include "third_party/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/glue/plugins/pepper_widget.h" -typedef struct _ppb_Scrollbar PPB_Scrollbar; - namespace pepper { class PluginInstance; @@ -26,7 +24,7 @@ class Scrollbar : public Widget, public WebKit::WebScrollbarClient { // Returns a pointer to the interface implementing PPB_Scrollbar that is // exposed to the plugin. - static const PPB_Scrollbar* GetInterface(); + static const PPB_Scrollbar_Dev* GetInterface(); // Resource overrides. Scrollbar* AsScrollbar() { return this; } @@ -36,11 +34,11 @@ class Scrollbar : public Widget, public WebKit::WebScrollbarClient { void SetValue(uint32_t value); void SetDocumentSize(uint32_t size); void SetTickMarks(const PP_Rect* tick_marks, uint32_t count); - void ScrollBy(PP_ScrollBy unit, int32_t multiplier); + void ScrollBy(PP_ScrollBy_Dev unit, int32_t multiplier); // PPB_Widget implementation. virtual bool Paint(const PP_Rect* rect, ImageData* image); - virtual bool HandleEvent(const PP_Event* event); + virtual bool HandleEvent(const PP_InputEvent* event); virtual void SetLocationInternal(const PP_Rect* location); private: diff --git a/webkit/glue/plugins/pepper_url_loader.cc b/webkit/glue/plugins/pepper_url_loader.cc index aa09686..4169c00 100644 --- a/webkit/glue/plugins/pepper_url_loader.cc +++ b/webkit/glue/plugins/pepper_url_loader.cc @@ -7,14 +7,17 @@ #include "base/logging.h" #include "third_party/ppapi/c/pp_completion_callback.h" #include "third_party/ppapi/c/pp_errors.h" -#include "third_party/ppapi/c/ppb_url_loader.h" +#include "third_party/ppapi/c/dev/ppb_url_loader_dev.h" +#include "third_party/ppapi/c/dev/ppb_url_loader_trusted_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/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/WebURLRequest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_url_request_info.h" #include "webkit/glue/plugins/pepper_url_response_info.h" @@ -121,6 +124,15 @@ int32_t ReadResponseBody(PP_Resource loader_id, return loader->ReadResponseBody(buffer, bytes_to_read, callback); } +int32_t FinishStreamingToFile(PP_Resource loader_id, + PP_CompletionCallback callback) { + scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); + if (!loader) + return PP_ERROR_BADRESOURCE; + + return loader->FinishStreamingToFile(callback); +} + void Close(PP_Resource loader_id) { scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); if (!loader) @@ -129,7 +141,7 @@ void Close(PP_Resource loader_id) { loader->Close(); } -const PPB_URLLoader ppb_urlloader = { +const PPB_URLLoader_Dev ppb_urlloader = { &Create, &IsURLLoader, &Open, @@ -138,9 +150,22 @@ const PPB_URLLoader ppb_urlloader = { &GetDownloadProgress, &GetResponseInfo, &ReadResponseBody, + &FinishStreamingToFile, &Close }; +void GrantUniversalAccess(PP_Resource loader_id) { + scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); + if (!loader) + return; + + loader->GrantUniversalAccess(); +} + +const PPB_URLLoaderTrusted_Dev ppb_urlloadertrusted = { + &GrantUniversalAccess +}; + } // namespace URLLoader::URLLoader(PluginInstance* instance) @@ -148,22 +173,28 @@ URLLoader::URLLoader(PluginInstance* instance) instance_(instance), pending_callback_(), bytes_sent_(0), - total_bytes_to_be_sent_(0), + total_bytes_to_be_sent_(-1), bytes_received_(0), - total_bytes_to_be_received_(0), + total_bytes_to_be_received_(-1), user_buffer_(NULL), user_buffer_size_(0), - done_(false) { + done_status_(PP_ERROR_WOULDBLOCK), + has_universal_access_(false) { } URLLoader::~URLLoader() { } // static -const PPB_URLLoader* URLLoader::GetInterface() { +const PPB_URLLoader_Dev* URLLoader::GetInterface() { return &ppb_urlloader; } +// static +const PPB_URLLoaderTrusted_Dev* URLLoader::GetTrustedInterface() { + return &ppb_urlloadertrusted; +} + int32_t URLLoader::Open(URLRequestInfo* request, PP_CompletionCallback callback) { if (loader_.get()) @@ -177,6 +208,12 @@ int32_t URLLoader::Open(URLRequestInfo* request, if (!frame) return PP_ERROR_FAILED; WebURLRequest web_request(request->ToWebURLRequest(frame)); + + // Check if we are allowed to access this URL. + if (!has_universal_access_ && + !frame->securityOrigin().canRequest(web_request.url())) + return PP_ERROR_NOACCESS; + frame->dispatchWillSendRequest(web_request); loader_.reset(WebKit::webKitClient()->createURLLoader()); @@ -199,6 +236,8 @@ int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { int32_t URLLoader::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) @@ -214,20 +253,40 @@ int32_t URLLoader::ReadResponseBody(char* buffer, int32_t bytes_to_read, if (!buffer_.empty()) return FillUserBuffer(); - if (done_) { + // We may have already reached EOF. + if (done_status_ != PP_ERROR_WOULDBLOCK) { user_buffer_ = NULL; user_buffer_size_ = 0; - return 0; + return done_status_; } pending_callback_ = callback; return PP_ERROR_WOULDBLOCK; } +int32_t URLLoader::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 URLLoader::Close() { NOTIMPLEMENTED(); // TODO(darin): Implement me. } +void URLLoader::GrantUniversalAccess() { + has_universal_access_ = true; +} + void URLLoader::willSendRequest(WebURLLoader* loader, WebURLRequest& new_request, const WebURLResponse& redirect_response) { @@ -248,12 +307,22 @@ void URLLoader::didReceiveResponse(WebURLLoader* loader, if (response_info->Initialize(response)) response_info_ = response_info; + // Sets -1 if the content length is unknown. + total_bytes_to_be_received_ = response.expectedContentLength(); + RunCallback(PP_OK); } +void URLLoader::didDownloadData(WebURLLoader* loader, + int data_length) { + bytes_received_ += data_length; +} + void URLLoader::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()); @@ -262,15 +331,15 @@ void URLLoader::didReceiveData(WebURLLoader* loader, } } -void URLLoader::didFinishLoading(WebURLLoader* loader) { - done_ = true; - RunCallback(PP_OK); +void URLLoader::didFinishLoading(WebURLLoader* loader, double finish_time) { + done_status_ = PP_OK; + RunCallback(done_status_); } void URLLoader::didFail(WebURLLoader* loader, const WebURLError& error) { - done_ = true; // TODO(darin): Provide more detailed error information. - RunCallback(PP_ERROR_FAILED); + done_status_ = PP_ERROR_FAILED; + RunCallback(done_status_); } void URLLoader::RunCallback(int32_t result) { diff --git a/webkit/glue/plugins/pepper_url_loader.h b/webkit/glue/plugins/pepper_url_loader.h index 088f220..4919de7 100644 --- a/webkit/glue/plugins/pepper_url_loader.h +++ b/webkit/glue/plugins/pepper_url_loader.h @@ -13,7 +13,8 @@ #include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" #include "webkit/glue/plugins/pepper_resource.h" -typedef struct _ppb_URLLoader PPB_URLLoader; +struct PPB_URLLoader_Dev; +struct PPB_URLLoaderTrusted_Dev; namespace pepper { @@ -28,7 +29,11 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { // Returns a pointer to the interface implementing PPB_URLLoader that is // exposed to the plugin. - static const PPB_URLLoader* GetInterface(); + static const PPB_URLLoader_Dev* GetInterface(); + + // Returns a pointer to the interface implementing PPB_URLLoaderTrusted that + // is exposed to the plugin. + static const PPB_URLLoaderTrusted_Dev* GetTrustedInterface(); // Resource overrides. URLLoader* AsURLLoader() { return this; } @@ -38,8 +43,12 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { int32_t FollowRedirect(PP_CompletionCallback callback); 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(); + // WebKit::WebURLLoaderClient implementation. virtual void willSendRequest(WebKit::WebURLLoader* loader, WebKit::WebURLRequest& new_request, @@ -49,10 +58,13 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { 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); + virtual void didFinishLoading(WebKit::WebURLLoader* loader, + double finish_time); virtual void didFail(WebKit::WebURLLoader* loader, const WebKit::WebURLError& error); @@ -81,7 +93,8 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { int64_t total_bytes_to_be_received_; char* user_buffer_; size_t user_buffer_size_; - bool done_; + int32_t done_status_; + bool has_universal_access_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_url_request_info.cc b/webkit/glue/plugins/pepper_url_request_info.cc index d230f20..4edbe83 100644 --- a/webkit/glue/plugins/pepper_url_request_info.cc +++ b/webkit/glue/plugins/pepper_url_request_info.cc @@ -22,7 +22,6 @@ #include "webkit/glue/webkit_glue.h" using WebKit::WebData; -using WebKit::WebFileInfo; using WebKit::WebHTTPBody; using WebKit::WebString; using WebKit::WebFrame; @@ -62,7 +61,7 @@ bool IsURLRequestInfo(PP_Resource resource) { } bool SetProperty(PP_Resource request_id, - PP_URLRequestProperty property, + PP_URLRequestProperty_Dev property, PP_Var var) { scoped_refptr<URLRequestInfo> request( Resource::GetAs<URLRequestInfo>(request_id)); @@ -72,8 +71,11 @@ bool SetProperty(PP_Resource request_id, if (var.type == PP_VARTYPE_BOOL) return request->SetBooleanProperty(property, var.value.as_bool); - if (var.type == PP_VARTYPE_STRING) - return request->SetStringProperty(property, GetString(var)->value()); + if (var.type == PP_VARTYPE_STRING) { + scoped_refptr<StringVar> string(StringVar::FromPPVar(var)); + if (string) + return request->SetStringProperty(property, string->value()); + } return false; } @@ -84,7 +86,7 @@ bool AppendDataToBody(PP_Resource request_id, PP_Var var) { if (!request) return false; - String* data = GetString(var); + scoped_refptr<StringVar> data(StringVar::FromPPVar(var)); if (!data) return false; @@ -111,7 +113,7 @@ bool AppendFileToBody(PP_Resource request_id, expected_last_modified_time); } -const PPB_URLRequestInfo ppb_urlrequestinfo = { +const PPB_URLRequestInfo_Dev ppb_urlrequestinfo = { &Create, &IsURLRequestInfo, &SetProperty, @@ -122,24 +124,31 @@ const PPB_URLRequestInfo ppb_urlrequestinfo = { } // namespace URLRequestInfo::URLRequestInfo(PluginModule* module) - : Resource(module) { + : Resource(module), + stream_to_file_(false) { } URLRequestInfo::~URLRequestInfo() { } // static -const PPB_URLRequestInfo* URLRequestInfo::GetInterface() { +const PPB_URLRequestInfo_Dev* URLRequestInfo::GetInterface() { return &ppb_urlrequestinfo; } -bool URLRequestInfo::SetBooleanProperty(PP_URLRequestProperty property, +bool URLRequestInfo::SetBooleanProperty(PP_URLRequestProperty_Dev property, bool value) { - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return false; + switch (property) { + case PP_URLREQUESTPROPERTY_STREAMTOFILE: + stream_to_file_ = value; + return true; + default: + NOTIMPLEMENTED(); // TODO(darin): Implement me! + return false; + } } -bool URLRequestInfo::SetStringProperty(PP_URLRequestProperty property, +bool URLRequestInfo::SetStringProperty(PP_URLRequestProperty_Dev property, const std::string& value) { // TODO(darin): Validate input. Perhaps at a different layer? switch (property) { @@ -167,6 +176,14 @@ bool URLRequestInfo::AppendFileToBody(FileRef* 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, @@ -178,6 +195,7 @@ WebURLRequest URLRequestInfo::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_)); @@ -198,13 +216,11 @@ WebURLRequest URLRequestInfo::ToWebURLRequest(WebFrame* frame) const { http_body.initialize(); for (size_t i = 0; i < body_.size(); ++i) { if (body_[i].file_ref) { - WebFileInfo file_info; - file_info.modificationTime = body_[i].expected_last_modified_time; http_body.appendFileRange( webkit_glue::FilePathToWebString(body_[i].file_ref->system_path()), body_[i].start_offset, body_[i].number_of_bytes, - file_info); + body_[i].expected_last_modified_time); } else { DCHECK(!body_[i].data.empty()); http_body.appendData(WebData(body_[i].data)); diff --git a/webkit/glue/plugins/pepper_url_request_info.h b/webkit/glue/plugins/pepper_url_request_info.h index ef1452c..7220531 100644 --- a/webkit/glue/plugins/pepper_url_request_info.h +++ b/webkit/glue/plugins/pepper_url_request_info.h @@ -9,7 +9,7 @@ #include <vector> #include "base/ref_counted.h" -#include "third_party/ppapi/c/ppb_url_request_info.h" +#include "third_party/ppapi/c/dev/ppb_url_request_info_dev.h" #include "webkit/glue/plugins/pepper_file_ref.h" #include "webkit/glue/plugins/pepper_resource.h" @@ -27,14 +27,14 @@ class URLRequestInfo : public Resource { // Returns a pointer to the interface implementing PPB_URLRequestInfo that is // exposed to the plugin. - static const PPB_URLRequestInfo* GetInterface(); + static const PPB_URLRequestInfo_Dev* GetInterface(); // Resource overrides. URLRequestInfo* AsURLRequestInfo() { return this; } // PPB_URLRequestInfo implementation. - bool SetBooleanProperty(PP_URLRequestProperty property, bool value); - bool SetStringProperty(PP_URLRequestProperty property, + bool SetBooleanProperty(PP_URLRequestProperty_Dev property, bool value); + bool SetStringProperty(PP_URLRequestProperty_Dev property, const std::string& value); bool AppendDataToBody(const std::string& data); bool AppendFileToBody(FileRef* file_ref, @@ -76,6 +76,7 @@ class URLRequestInfo : public Resource { std::string method_; std::string headers_; Body body_; + bool stream_to_file_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_url_response_info.cc b/webkit/glue/plugins/pepper_url_response_info.cc index bff92aa..79042ba 100644 --- a/webkit/glue/plugins/pepper_url_response_info.cc +++ b/webkit/glue/plugins/pepper_url_response_info.cc @@ -12,6 +12,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" #include "webkit/glue/plugins/pepper_file_ref.h" #include "webkit/glue/plugins/pepper_var.h" +#include "webkit/glue/webkit_glue.h" using WebKit::WebHTTPHeaderVisitor; using WebKit::WebString; @@ -42,7 +43,7 @@ bool IsURLResponseInfo(PP_Resource resource) { } PP_Var GetProperty(PP_Resource response_id, - PP_URLResponseProperty property) { + PP_URLResponseProperty_Dev property) { scoped_refptr<URLResponseInfo> response( Resource::GetAs<URLResponseInfo>(response_id)); if (!response) @@ -65,7 +66,7 @@ PP_Resource GetBody(PP_Resource response_id) { return body->GetReference(); } -const PPB_URLResponseInfo ppb_urlresponseinfo = { +const PPB_URLResponseInfo_Dev ppb_urlresponseinfo = { &IsURLResponseInfo, &GetProperty, &GetBody @@ -82,18 +83,18 @@ URLResponseInfo::~URLResponseInfo() { } // static -const PPB_URLResponseInfo* URLResponseInfo::GetInterface() { +const PPB_URLResponseInfo_Dev* URLResponseInfo::GetInterface() { return &ppb_urlresponseinfo; } -PP_Var URLResponseInfo::GetProperty(PP_URLResponseProperty property) { +PP_Var URLResponseInfo::GetProperty(PP_URLResponseProperty_Dev property) { switch (property) { case PP_URLRESPONSEPROPERTY_URL: - return StringToPPVar(url_); + return StringVar::StringToPPVar(module(), url_); case PP_URLRESPONSEPROPERTY_STATUSCODE: return PP_MakeInt32(status_code_); case PP_URLRESPONSEPROPERTY_HEADERS: - return StringToPPVar(headers_); + return StringVar::StringToPPVar(module(), headers_); default: NOTIMPLEMENTED(); // TODO(darin): Implement me! return PP_MakeVoid(); @@ -107,6 +108,10 @@ bool URLResponseInfo::Initialize(const WebURLResponse& response) { HeaderFlattener flattener; response.visitHTTPHeaderFields(&flattener); headers_ = flattener.buffer(); + + WebString file_path = response.downloadFilePath(); + if (!file_path.isEmpty()) + body_ = new FileRef(module(), webkit_glue::WebStringToFilePath(file_path)); return true; } diff --git a/webkit/glue/plugins/pepper_url_response_info.h b/webkit/glue/plugins/pepper_url_response_info.h index 8874919..d8e1321 100644 --- a/webkit/glue/plugins/pepper_url_response_info.h +++ b/webkit/glue/plugins/pepper_url_response_info.h @@ -7,7 +7,7 @@ #include <string> -#include "third_party/ppapi/c/ppb_url_response_info.h" +#include "third_party/ppapi/c/dev/ppb_url_response_info_dev.h" #include "webkit/glue/plugins/pepper_resource.h" namespace WebKit { @@ -23,13 +23,13 @@ class URLResponseInfo : public Resource { // Returns a pointer to the interface implementing PPB_URLResponseInfo that // is exposed to the plugin. - static const PPB_URLResponseInfo* GetInterface(); + static const PPB_URLResponseInfo_Dev* GetInterface(); // Resource overrides. URLResponseInfo* AsURLResponseInfo() { return this; } // PPB_URLResponseInfo implementation. - PP_Var GetProperty(PP_URLResponseProperty property); + PP_Var GetProperty(PP_URLResponseProperty_Dev property); bool Initialize(const WebKit::WebURLResponse& response); diff --git a/webkit/glue/plugins/pepper_var.cc b/webkit/glue/plugins/pepper_var.cc index 414df7b..b4ba014 100644 --- a/webkit/glue/plugins/pepper_var.cc +++ b/webkit/glue/plugins/pepper_var.cc @@ -9,9 +9,9 @@ #include "base/string_util.h" #include "third_party/ppapi/c/pp_var.h" #include "third_party/ppapi/c/ppb_var.h" -#include "third_party/ppapi/c/ppp_class.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" -#include "webkit/glue/plugins/pepper_string.h" +#include "webkit/glue/plugins/pepper_plugin_module.h" +#include "webkit/glue/plugins/pepper_plugin_object.h" #include "v8/include/v8.h" using WebKit::WebBindings; @@ -20,43 +20,9 @@ namespace pepper { namespace { -void Release(PP_Var var); -PP_Var VarFromUtf8(const char* data, uint32_t len); - -// --------------------------------------------------------------------------- -// Exceptions - -class TryCatch { - public: - TryCatch(PP_Var* exception) : exception_(exception) { - WebBindings::pushExceptionHandler(&TryCatch::Catch, this); - } - - ~TryCatch() { - WebBindings::popExceptionHandler(); - } - - bool HasException() const { - return exception_ && exception_->type != PP_VARTYPE_VOID; - } - - void SetException(const char* message) { - DCHECK(!HasException()); - if (exception_) - *exception_ = VarFromUtf8(message, strlen(message)); - } - - private: - static void Catch(void* self, const NPUTF8* message) { - static_cast<TryCatch*>(self)->SetException(message); - } - - // May be null if the consumer isn't interesting in catching exceptions. - PP_Var* exception_; -}; - 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[] = @@ -69,531 +35,182 @@ const char kUnableToConstructException[] = "Error: Unable to construct"; // --------------------------------------------------------------------------- // Utilities -String* GetStringUnchecked(PP_Var var) { - return reinterpret_cast<String*>(var.value.as_id); -} - -NPObject* GetNPObjectUnchecked(PP_Var var) { - return reinterpret_cast<NPObject*>(var.value.as_id); -} - -// 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. -PP_Var NPVariantToPPVar(const NPVariant* variant) { - switch (variant->type) { - case NPVariantType_Void: - return PP_MakeVoid(); - case NPVariantType_Null: - return PP_MakeNull(); - case NPVariantType_Bool: - return PP_MakeBool(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 VarFromUtf8(NPVARIANT_TO_STRING(*variant).UTF8Characters, - NPVARIANT_TO_STRING(*variant).UTF8Length); - case NPVariantType_Object: - return NPObjectToPPVar(NPVARIANT_TO_OBJECT(*variant)); - } - NOTREACHED(); - return PP_MakeVoid(); -} - -// Returns a NPVariant that corresponds to the given PP_Var. The contents of -// the PP_Var will be copied unless the PP_Var corresponds to an object. -NPVariant PPVarToNPVariant(PP_Var var) { - NPVariant ret; +// 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_VOID: - VOID_TO_NPVARIANT(ret); + VOID_TO_NPVARIANT(*result); break; case PP_VARTYPE_NULL: - NULL_TO_NPVARIANT(ret); + NULL_TO_NPVARIANT(*result); break; case PP_VARTYPE_BOOL: - BOOLEAN_TO_NPVARIANT(var.value.as_bool, ret); + BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result); break; case PP_VARTYPE_INT32: - INT32_TO_NPVARIANT(var.value.as_int, ret); + INT32_TO_NPVARIANT(var.value.as_int, *result); break; case PP_VARTYPE_DOUBLE: - DOUBLE_TO_NPVARIANT(var.value.as_double, ret); + DOUBLE_TO_NPVARIANT(var.value.as_double, *result); break; case PP_VARTYPE_STRING: { - const std::string& value = GetStringUnchecked(var)->value(); - STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), ret); + 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: { - NPObject* object = GetNPObjectUnchecked(var); - OBJECT_TO_NPVARIANT(WebBindings::retainObject(object), ret); + scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); + if (!object) { + VOID_TO_NPVARIANT(*result); + return false; + } + OBJECT_TO_NPVARIANT(object->np_object(), *result); break; } - } - return ret; -} - -// Returns a NPVariant that corresponds to the given PP_Var. 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. -NPVariant PPVarToNPVariantNoCopy(PP_Var var) { - NPVariant ret; - switch (var.type) { - case PP_VARTYPE_VOID: - VOID_TO_NPVARIANT(ret); - break; - case PP_VARTYPE_NULL: - NULL_TO_NPVARIANT(ret); - break; - case PP_VARTYPE_BOOL: - BOOLEAN_TO_NPVARIANT(var.value.as_bool, ret); - break; - case PP_VARTYPE_INT32: - INT32_TO_NPVARIANT(var.value.as_int, ret); - break; - case PP_VARTYPE_DOUBLE: - DOUBLE_TO_NPVARIANT(var.value.as_double, ret); - break; - case PP_VARTYPE_STRING: { - const std::string& value = GetStringUnchecked(var)->value(); - STRINGN_TO_NPVARIANT(value.c_str(), value.size(), ret); - break; - } - case PP_VARTYPE_OBJECT: { - OBJECT_TO_NPVARIANT(GetNPObjectUnchecked(var), ret); - break; - } - } - return ret; -} - -// Returns a NPIdentifier that corresponds to the given PP_Var. The contents -// of the PP_Var will be copied. Returns NULL if the given PP_Var is not a a -// string or integer type. -NPIdentifier PPVarToNPIdentifier(PP_Var var) { - switch (var.type) { - case PP_VARTYPE_STRING: - return WebBindings::getStringIdentifier( - GetStringUnchecked(var)->value().c_str()); - case PP_VARTYPE_INT32: - return WebBindings::getIntIdentifier(var.value.as_int); default: - return NULL; + VOID_TO_NPVARIANT(*result); + return false; } + return true; } -PP_Var NPIdentifierToPPVar(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 VarFromUtf8(string_value, strlen(string_value)); - - return PP_MakeInt32(int_value); -} - -PP_Var NPIdentifierToPPVarString(NPIdentifier id) { - PP_Var var = NPIdentifierToPPVar(id); - if (var.type == PP_VARTYPE_STRING) - return var; - DCHECK(var.type == PP_VARTYPE_INT32); - const std::string& str = IntToString(var.value.as_int); - return VarFromUtf8(str.data(), str.size()); -} - -void ThrowException(NPObject* object, PP_Var exception) { - String* str = GetString(exception); - if (str) - WebBindings::setException(object, str->value().c_str()); -} - -// --------------------------------------------------------------------------- -// NPObject implementation in terms of PPP_Class - -struct WrapperObject : NPObject { - const PPP_Class* ppp_class; - void* ppp_class_data; -}; - -static WrapperObject* ToWrapper(NPObject* object) { - return static_cast<WrapperObject*>(object); -} - -NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) { - return new WrapperObject; -} - -void WrapperClass_Deallocate(NPObject* object) { - WrapperObject* wrapper = ToWrapper(object); - wrapper->ppp_class->Deallocate(wrapper->ppp_class_data); - delete object; -} - -void WrapperClass_Invalidate(NPObject* object) { - // TODO(darin): Do I need to do something here? -} - -bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) { - WrapperObject* wrapper = ToWrapper(object); - - PP_Var method_name_var = NPIdentifierToPPVarString(method_name); - PP_Var exception = PP_MakeVoid(); - bool rv = wrapper->ppp_class->HasMethod(wrapper->ppp_class_data, - method_name_var, - &exception); - Release(method_name_var); - - if (exception.type != PP_VARTYPE_VOID) { - ThrowException(object, exception); - Release(exception); - return false; - } - return rv; -} - -bool WrapperClass_Invoke(NPObject* object, NPIdentifier method_name, - const NPVariant* argv, uint32_t argc, - NPVariant* result) { - WrapperObject* wrapper = ToWrapper(object); - - scoped_array<PP_Var> args; - if (argc) { - args.reset(new PP_Var[argc]); - for (uint32_t i = 0; i < argc; ++i) - args[i] = NPVariantToPPVar(&argv[i]); - } - PP_Var method_name_var = NPIdentifierToPPVarString(method_name); - PP_Var exception = PP_MakeVoid(); - PP_Var result_var = wrapper->ppp_class->Call(wrapper->ppp_class_data, - method_name_var, argc, - args.get(), &exception); - Release(method_name_var); - for (uint32_t i = 0; i < argc; ++i) - Release(args[i]); - - bool rv; - if (exception.type == PP_VARTYPE_VOID) { - rv = true; - *result = PPVarToNPVariant(result_var); - } else { - rv = false; - ThrowException(object, exception); - Release(exception); - } - Release(result_var); - return rv; -} - -bool WrapperClass_InvokeDefault(NPObject* object, const NPVariant* argv, - uint32_t argc, NPVariant* result) { - WrapperObject* wrapper = ToWrapper(object); - - scoped_array<PP_Var> args; - if (argc) { - args.reset(new PP_Var[argc]); - for (uint32_t i = 0; i < argc; ++i) - args[i] = NPVariantToPPVar(&argv[i]); - } - PP_Var exception = PP_MakeVoid(); - PP_Var result_var = wrapper->ppp_class->Call(wrapper->ppp_class_data, - PP_MakeVoid(), argc, args.get(), - &exception); - for (uint32_t i = 0; i < argc; ++i) - Release(args[i]); - - bool rv; - if (exception.type == PP_VARTYPE_VOID) { - rv = true; - *result = PPVarToNPVariant(result_var); - } else { - rv = false; - ThrowException(object, exception); - Release(exception); - } - Release(result_var); - return rv; -} - -bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) { - WrapperObject* wrapper = ToWrapper(object); - - PP_Var property_name_var = NPIdentifierToPPVar(property_name); - PP_Var exception = PP_MakeVoid(); - bool rv = wrapper->ppp_class->HasProperty(wrapper->ppp_class_data, - property_name_var, - &exception); - Release(property_name_var); - - if (exception.type != PP_VARTYPE_VOID) { - ThrowException(object, exception); - Release(exception); - return false; - } - return rv; -} - -bool WrapperClass_GetProperty(NPObject* object, NPIdentifier property_name, - NPVariant* result) { - WrapperObject* wrapper = ToWrapper(object); - - PP_Var property_name_var = NPIdentifierToPPVar(property_name); - PP_Var exception = PP_MakeVoid(); - PP_Var result_var = wrapper->ppp_class->GetProperty(wrapper->ppp_class_data, - property_name_var, - &exception); - Release(property_name_var); - - bool rv; - if (exception.type == PP_VARTYPE_VOID) { - rv = true; - *result = PPVarToNPVariant(result_var); - } else { - rv = false; - ThrowException(object, exception); - Release(exception); - } - Release(result_var); - return rv; -} - -bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name, - const NPVariant* value) { - WrapperObject* wrapper = ToWrapper(object); +// ObjectAccessorTryCatch ------------------------------------------------------ - PP_Var property_name_var = NPIdentifierToPPVar(property_name); - PP_Var value_var = NPVariantToPPVar(value); - PP_Var exception = PP_MakeVoid(); - wrapper->ppp_class->SetProperty(wrapper->ppp_class_data, property_name_var, - value_var, &exception); - Release(value_var); - Release(property_name_var); - - if (exception.type != PP_VARTYPE_VOID) { - ThrowException(object, exception); - Release(exception); - return false; +// 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()); + } } - return true; -} -bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) { - WrapperObject* wrapper = ToWrapper(object); + ObjectVar* object() { return object_.get(); } - PP_Var property_name_var = NPIdentifierToPPVar(property_name); - PP_Var exception = PP_MakeVoid(); - wrapper->ppp_class->RemoveProperty(wrapper->ppp_class_data, property_name_var, - &exception); - Release(property_name_var); + protected: + scoped_refptr<ObjectVar> object_; - if (exception.type != PP_VARTYPE_VOID) { - ThrowException(object, exception); - Release(exception); - return false; - } - return true; -} + DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch); +}; -bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values, - uint32_t* count) { - WrapperObject* wrapper = ToWrapper(object); - - uint32_t property_count = 0; - PP_Var* properties = NULL; - PP_Var exception = PP_MakeVoid(); - wrapper->ppp_class->GetAllPropertyNames(wrapper->ppp_class_data, - &property_count, - &properties, - &exception); - - bool rv; - if (exception.type == PP_VARTYPE_VOID) { - rv = true; - if (property_count == 0) { - *values = NULL; - *count = 0; - } else { - *values = static_cast<NPIdentifier*>( - malloc(sizeof(NPIdentifier) * property_count)); - *count = property_count; - for (uint32_t i = 0; i < property_count; ++i) - (*values)[i] = PPVarToNPIdentifier(properties[i]); +// 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); } - } else { - rv = false; - ThrowException(object, exception); - Release(exception); } - for (uint32_t i = 0; i < property_count; ++i) - Release(properties[i]); - free(properties); - return rv; -} + NPIdentifier identifier() const { return identifier_; } -bool WrapperClass_Construct(NPObject* object, const NPVariant* argv, - uint32_t argc, NPVariant* result) { - WrapperObject* wrapper = ToWrapper(object); - - scoped_array<PP_Var> args; - if (argc) { - args.reset(new PP_Var[argc]); - for (uint32_t i = 0; i < argc; ++i) - args[i] = NPVariantToPPVar(&argv[i]); - } + private: + NPIdentifier identifier_; - PP_Var exception = PP_MakeVoid(); - PP_Var result_var = wrapper->ppp_class->Construct(wrapper->ppp_class_data, - argc, args.get(), - &exception); - for (uint32_t i = 0; i < argc; ++i) - Release(args[i]); - - bool rv; - if (exception.type == PP_VARTYPE_VOID) { - rv = true; - *result = PPVarToNPVariant(result_var); - } else { - rv = false; - ThrowException(object, exception); - Release(exception); - } - Release(result_var); - return rv; -} - -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 + DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); }; -// --------------------------------------------------------------------------- -// PPB_Var methods - -void AddRef(PP_Var var) { - if (var.type == PP_VARTYPE_STRING) { - GetStringUnchecked(var)->AddRef(); - } else if (var.type == PP_VARTYPE_OBJECT) { - // TODO(darin): Add thread safety check - WebBindings::retainObject(GetNPObjectUnchecked(var)); - } -} - -void Release(PP_Var var) { - if (var.type == PP_VARTYPE_STRING) { - GetStringUnchecked(var)->Release(); - } else if (var.type == PP_VARTYPE_OBJECT) { - // TODO(darin): Add thread safety check - WebBindings::releaseObject(GetNPObjectUnchecked(var)); - } -} +// PPB_Var methods ------------------------------------------------------------- -PP_Var VarFromUtf8(const char* data, uint32_t len) { - String* str = new String(data, len); - str->AddRef(); // This is for the caller, we return w/ a refcount of 1. - PP_Var ret; - ret.type = PP_VARTYPE_STRING; - ret.value.as_id = reinterpret_cast<intptr_t>(str); - return ret; +PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return PP_MakeNull(); + return StringVar::StringToPPVar(module, data, len); } const char* VarToUtf8(PP_Var var, uint32_t* len) { - if (var.type != PP_VARTYPE_STRING) { + scoped_refptr<StringVar> str(StringVar::FromPPVar(var)); + if (!str) { *len = 0; return NULL; } - const std::string& str = GetStringUnchecked(var)->value(); - *len = static_cast<uint32_t>(str.size()); - if (str.empty()) + *len = static_cast<uint32_t>(str->value().size()); + if (str->value().empty()) return ""; // Don't return NULL on success. - return str.data(); + return str->value().data(); } bool HasProperty(PP_Var var, PP_Var name, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) return false; - - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); - return false; - } - - NPIdentifier identifier = PPVarToNPIdentifier(name); - if (!identifier) { - try_catch.SetException(kInvalidPropertyException); - return false; - } - - return WebBindings::hasProperty(NULL, object, identifier); + return WebBindings::hasProperty(NULL, accessor.object()->np_object(), + accessor.identifier()); } bool HasMethod(PP_Var var, PP_Var name, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) - return false; - - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) return false; - } - - NPIdentifier identifier = PPVarToNPIdentifier(name); - if (!identifier) { - try_catch.SetException(kInvalidPropertyException); - return false; - } - - return WebBindings::hasMethod(NULL, object, identifier); + return WebBindings::hasMethod(NULL, accessor.object()->np_object(), + accessor.identifier()); } PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) - return PP_MakeVoid(); - - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); - return PP_MakeVoid(); - } - - NPIdentifier identifier = PPVarToNPIdentifier(name); - if (!identifier) { - try_catch.SetException(kInvalidPropertyException); + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) return PP_MakeVoid(); - } NPVariant result; - if (!WebBindings::getProperty(NULL, object, identifier, &result)) { + if (!WebBindings::getProperty(NULL, accessor.object()->np_object(), + accessor.identifier(), &result)) { // An exception may have been raised. - if (!try_catch.HasException()) - try_catch.SetException(kUnableToGetPropertyException); + accessor.SetException(kUnableToGetPropertyException); return PP_MakeVoid(); } - PP_Var ret = NPVariantToPPVar(&result); + PP_Var ret = Var::NPVariantToPPVar(accessor.object()->module(), &result); WebBindings::releaseVariantValue(&result); return ret; } @@ -605,21 +222,15 @@ void GetAllPropertyNames(PP_Var var, *properties = NULL; *property_count = 0; - TryCatch try_catch(exception); - if (try_catch.HasException()) + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) return; - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); - return; - } - NPIdentifier* identifiers = NULL; uint32_t count = 0; - if (!WebBindings::enumerate(NULL, object, &identifiers, &count)) { - if (!try_catch.HasException()) - try_catch.SetException(kUnableToGetAllPropertiesException); + if (!WebBindings::enumerate(NULL, accessor.object()->np_object(), + &identifiers, &count)) { + accessor.SetException(kUnableToGetAllPropertiesException); return; } @@ -628,8 +239,10 @@ void GetAllPropertyNames(PP_Var var, *property_count = count; *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count)); - for (uint32_t i = 0; i < count; ++i) - (*properties)[i] = NPIdentifierToPPVar(identifiers[i]); + for (uint32_t i = 0; i < count; ++i) { + (*properties)[i] = Var::NPIdentifierToPPVar(accessor.object()->module(), + identifiers[i]); + } free(identifiers); } @@ -637,52 +250,30 @@ void SetProperty(PP_Var var, PP_Var name, PP_Var value, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) return; - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); + NPVariant variant; + if (!PPVarToNPVariantNoCopy(value, &variant)) { + accessor.SetException(kInvalidValueException); return; } - - NPIdentifier identifier = PPVarToNPIdentifier(name); - if (!identifier) { - try_catch.SetException(kInvalidPropertyException); - return; - } - - NPVariant variant = PPVarToNPVariantNoCopy(value); - if (!WebBindings::setProperty(NULL, object, identifier, &variant)) { - if (!try_catch.HasException()) - try_catch.SetException(kUnableToSetPropertyException); - } + if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), + accessor.identifier(), &variant)) + accessor.SetException(kUnableToSetPropertyException); } void RemoveProperty(PP_Var var, PP_Var name, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) - return; - - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); - return; - } - - NPIdentifier identifier = PPVarToNPIdentifier(name); - if (!identifier) { - try_catch.SetException(kInvalidPropertyException); + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) return; - } - if (!WebBindings::removeProperty(NULL, object, identifier)) { - if (!try_catch.HasException()) - try_catch.SetException(kUnableToRemovePropertyException); - } + if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), + accessor.identifier())) + accessor.SetException(kUnableToRemovePropertyException); } PP_Var Call(PP_Var var, @@ -690,56 +281,55 @@ PP_Var Call(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) return PP_MakeVoid(); - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); - return PP_MakeVoid(); - } - NPIdentifier identifier; if (method_name.type == PP_VARTYPE_VOID) { identifier = NULL; } else if (method_name.type == PP_VARTYPE_STRING) { // Specifically allow only string functions to be called. - identifier = PPVarToNPIdentifier(method_name); + identifier = Var::PPVarToNPIdentifier(method_name); if (!identifier) { - try_catch.SetException(kInvalidPropertyException); + accessor.SetException(kInvalidPropertyException); return PP_MakeVoid(); } } else { - try_catch.SetException(kInvalidPropertyException); + accessor.SetException(kInvalidPropertyException); return PP_MakeVoid(); } scoped_array<NPVariant> args; if (argc) { args.reset(new NPVariant[argc]); - for (uint32_t i = 0; i < argc; ++i) - args[i] = PPVarToNPVariantNoCopy(argv[i]); + 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_MakeVoid(); + } + } } bool ok; NPVariant result; if (identifier) { - ok = WebBindings::invoke(NULL, object, identifier, args.get(), argc, - &result); + ok = WebBindings::invoke(NULL, accessor.object()->np_object(), + identifier, args.get(), argc, &result); } else { - ok = WebBindings::invokeDefault(NULL, object, args.get(), argc, &result); + ok = WebBindings::invokeDefault(NULL, accessor.object()->np_object(), + args.get(), argc, &result); } if (!ok) { // An exception may have been raised. - if (!try_catch.HasException()) - try_catch.SetException(kUnableToCallMethodException); + accessor.SetException(kUnableToCallMethodException); return PP_MakeVoid(); } - PP_Var ret = NPVariantToPPVar(&result); + PP_Var ret = Var::NPVariantToPPVar(accessor.module(), &result); WebBindings::releaseVariantValue(&result); return ret; } @@ -748,67 +338,58 @@ PP_Var Construct(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) { - TryCatch try_catch(exception); - if (try_catch.HasException()) + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) return PP_MakeVoid(); - NPObject* object = GetNPObject(var); - if (!object) { - try_catch.SetException(kInvalidObjectException); - return PP_MakeVoid(); - } - scoped_array<NPVariant> args; if (argc) { args.reset(new NPVariant[argc]); - for (uint32_t i = 0; i < argc; ++i) - args[i] = PPVarToNPVariantNoCopy(argv[i]); + 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_MakeVoid(); + } + } } NPVariant result; - if (!WebBindings::construct(NULL, object, args.get(), argc, &result)) { + if (!WebBindings::construct(NULL, accessor.object()->np_object(), + args.get(), argc, &result)) { // An exception may have been raised. - if (!try_catch.HasException()) - try_catch.SetException(kUnableToConstructException); + accessor.SetException(kUnableToConstructException); return PP_MakeVoid(); } - PP_Var ret = NPVariantToPPVar(&result); + PP_Var ret = Var::NPVariantToPPVar(accessor.module(), &result); WebBindings::releaseVariantValue(&result); return ret; } -bool IsInstanceOf(PP_Var var, const PPP_Class* ppp_class, +bool IsInstanceOf(PP_Var var, + const PPP_Class* ppp_class, void** ppp_class_data) { - NPObject* object = GetNPObject(var); + scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); if (!object) - return false; - - if (object->_class != &wrapper_class) - return false; + return false; // Not an object at all. - WrapperObject* wrapper = ToWrapper(object); - if (wrapper->ppp_class != ppp_class) - return false; - - if (ppp_class_data) - *ppp_class_data = wrapper->ppp_class_data; - return true; + return PluginObject::IsInstanceOf(object->np_object(), + ppp_class, ppp_class_data); } -PP_Var CreateObject(const PPP_Class* ppp_class, void* ppp_class_data) { - NPObject* object = - WebBindings::createObject(NULL, const_cast<NPClass*>(&wrapper_class)); - static_cast<WrapperObject*>(object)->ppp_class = ppp_class; - static_cast<WrapperObject*>(object)->ppp_class_data = ppp_class_data; - PP_Var ret = NPObjectToPPVar(object); - WebBindings::releaseObject(object); // Release reference from createObject - return ret; +PP_Var CreateObject(PP_Module module_id, + const PPP_Class* ppp_class, + void* ppp_class_data) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return PP_MakeNull(); + return PluginObject::Create(module, ppp_class, ppp_class_data); } const PPB_Var var_interface = { - &AddRef, - &Release, + &Var::PluginAddRefPPVar, + &Var::PluginReleasePPVar, &VarFromUtf8, &VarToUtf8, &HasProperty, @@ -825,33 +406,206 @@ const PPB_Var var_interface = { } // namespace -const PPB_Var* GetVarInterface() { +// Var ------------------------------------------------------------------------- + +Var::Var(PluginModule* module) : Resource(module) { +} + +Var::~Var() { +} + +// static +PP_Var Var::NPVariantToPPVar(PluginModule* module, const NPVariant* variant) { + switch (variant->type) { + case NPVariantType_Void: + return PP_MakeVoid(); + case NPVariantType_Null: + return PP_MakeNull(); + case NPVariantType_Bool: + return PP_MakeBool(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_MakeVoid(); +} + +// 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. + if (!ResourceTracker::Get()->AddRefResource(var.value.as_id)) + 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. + if (!ResourceTracker::Get()->UnrefResource(var.value.as_id)) + DLOG(WARNING) << "ReleaseVar()ing a nonexistant string/object var."; + } +} + +// static +const PPB_Var* Var::GetInterface() { return &var_interface; } -PP_Var NPObjectToPPVar(NPObject* object) { +// StringVar ------------------------------------------------------------------- + +StringVar::StringVar(PluginModule* module, const char* str, uint32 len) + : Var(module), + value_(str, len) { +} + +StringVar::~StringVar() { +} + +// 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_OBJECT; - ret.value.as_id = reinterpret_cast<intptr_t>(object); - WebBindings::retainObject(object); + ret.type = PP_VARTYPE_STRING; + + // The caller takes ownership now. + ret.value.as_id = str->GetReference(); return ret; } -NPObject* GetNPObject(PP_Var var) { +// static +scoped_refptr<StringVar> StringVar::FromPPVar(PP_Var var) { + if (var.type != PP_VARTYPE_STRING) + return scoped_refptr<StringVar>(NULL); + return Resource::GetAs<StringVar>(var.value.as_id); +} + +// 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_); +} + +// 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_MakeVoid(); + + // 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 NULL; - return GetNPObjectUnchecked(var); + return scoped_refptr<ObjectVar>(NULL); + return Resource::GetAs<ObjectVar>(var.value.as_id); } -PP_Var StringToPPVar(const std::string& str) { - DCHECK(IsStringUTF8(str)); - return VarFromUtf8(str.data(), str.size()); +// TryCatch -------------------------------------------------------------------- + +TryCatch::TryCatch(PluginModule* module, PP_Var* exception) + : module_(module), + has_exception_(exception && exception->type != PP_VARTYPE_VOID), + exception_(exception) { + WebBindings::pushExceptionHandler(&TryCatch::Catch, this); } -String* GetString(PP_Var var) { - if (var.type != PP_VARTYPE_STRING) - return NULL; - return GetStringUnchecked(var); +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 pepper diff --git a/webkit/glue/plugins/pepper_var.h b/webkit/glue/plugins/pepper_var.h index b8c31cc..b618029 100644 --- a/webkit/glue/plugins/pepper_var.h +++ b/webkit/glue/plugins/pepper_var.h @@ -7,39 +7,240 @@ #include <string> -typedef struct _pp_Var PP_Var; -typedef struct _ppb_Var PPB_Var; +#include "webkit/glue/plugins/pepper_resource.h" + +struct PP_Var; +struct PPB_Var; typedef struct NPObject NPObject; typedef struct _NPVariant NPVariant; typedef void* NPIdentifier; namespace pepper { -class String; +// 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() { return this; } + + // 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 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() { return this; } + + // 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() { return this; } + + // 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); -// There's no class implementing Var since it could represent a number of -// objects. Instead, we just expose a getter for the interface implemented in -// the .cc file here. -const PPB_Var* GetVarInterface(); + // Sets the exception to be a generic message contained in a magic string + // not associated with any module. + void SetInvalidObjectException(); -// Returns a PP_Var of type object that wraps the given NPObject. Calling this -// function multiple times given the same NPObject results in the same PP_Var. -PP_Var NPObjectToPPVar(NPObject* object); + private: + static void Catch(void* self, const char* message); -// Returns the NPObject corresponding to the PP_Var. This pointer has not been -// retained, so you should not call WebBindings::releaseObject unless you first -// call WebBindings::retainObject. Returns NULL if the PP_Var is not an object -// type. -NPObject* GetNPObject(PP_Var var); + PluginModule* module_; -// Returns a PP_Var of type string that contains a copy of the given string. -// The input data must be valid UTF-8 encoded text. -PP_Var StringToPPVar(const std::string& str); + // 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_; -// Returns the String corresponding to the PP_Var. This pointer has not been -// AddRef'd, so you should not call Release! Returns NULL if the PP_Var is not -// a string type. -String* GetString(PP_Var var); + // May be null if the consumer isn't interesting in catching exceptions. + PP_Var* exception_; +}; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_webplugin_impl.cc b/webkit/glue/plugins/pepper_webplugin_impl.cc index df8aae0..32903b0 100644 --- a/webkit/glue/plugins/pepper_webplugin_impl.cc +++ b/webkit/glue/plugins/pepper_webplugin_impl.cc @@ -4,7 +4,6 @@ #include "webkit/glue/plugins/pepper_webplugin_impl.h" -#include "base/file_path.h" #include "base/message_loop.h" #include "third_party/ppapi/c/pp_var.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h" @@ -74,11 +73,16 @@ void WebPluginImpl::destroy() { } NPObject* WebPluginImpl::scriptableObject() { - return GetNPObject(instance_->GetInstanceObject()); + scoped_refptr<ObjectVar> object( + ObjectVar::FromPPVar(instance_->GetInstanceObject())); + if (object) + return object->np_object(); + return NULL; } void WebPluginImpl::paint(WebCanvas* canvas, const WebRect& rect) { - instance_->Paint(canvas, plugin_rect_, rect); + if (!instance_->IsFullscreen()) + instance_->Paint(canvas, plugin_rect_, rect); } void WebPluginImpl::updateGeometry( @@ -87,10 +91,12 @@ void WebPluginImpl::updateGeometry( const WebVector<WebRect>& cut_outs_rects, bool is_visible) { plugin_rect_ = window_rect; - instance_->ViewChanged(plugin_rect_, clip_rect); + if (!instance_->IsFullscreen()) + instance_->ViewChanged(plugin_rect_, clip_rect); } void WebPluginImpl::updateFocus(bool focused) { + instance_->SetWebKitFocus(focused); } void WebPluginImpl::updateVisibility(bool visible) { @@ -102,6 +108,8 @@ bool WebPluginImpl::acceptsInputEvents() { bool WebPluginImpl::handleInputEvent(const WebKit::WebInputEvent& event, WebKit::WebCursorInfo& cursor_info) { + if (instance_->IsFullscreen()) + return false; return instance_->HandleInputEvent(event, &cursor_info); } @@ -123,7 +131,7 @@ void WebPluginImpl::didReceiveData(const char* data, int data_length) { void WebPluginImpl::didFinishLoading() { if (document_loader_) { - document_loader_->didFinishLoading(NULL); + document_loader_->didFinishLoading(NULL, 0); document_loader_ = NULL; } } diff --git a/webkit/glue/plugins/pepper_widget.cc b/webkit/glue/plugins/pepper_widget.cc index 74b0e40..1ba5280 100644 --- a/webkit/glue/plugins/pepper_widget.cc +++ b/webkit/glue/plugins/pepper_widget.cc @@ -5,10 +5,10 @@ #include "webkit/glue/plugins/pepper_widget.h" #include "base/logging.h" +#include "third_party/ppapi/c/dev/ppb_widget_dev.h" +#include "third_party/ppapi/c/dev/ppp_widget_dev.h" #include "third_party/ppapi/c/pp_completion_callback.h" #include "third_party/ppapi/c/pp_errors.h" -#include "third_party/ppapi/c/ppb_widget.h" -#include "third_party/ppapi/c/ppp_widget.h" #include "webkit/glue/plugins/pepper_image_data.h" #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_plugin_module.h" @@ -27,10 +27,13 @@ bool Paint(PP_Resource resource, const PP_Rect* rect, PP_Resource image_id) { return false; scoped_refptr<ImageData> image(Resource::GetAs<ImageData>(image_id)); - return widget && widget->Paint(rect, image); + if (!image) + return false; + + return widget->Paint(rect, image); } -bool HandleEvent(PP_Resource resource, const PP_Event* event) { +bool HandleEvent(PP_Resource resource, const PP_InputEvent* event) { scoped_refptr<Widget> widget(Resource::GetAs<Widget>(resource)); return widget && widget->HandleEvent(event); } @@ -46,7 +49,7 @@ void SetLocation(PP_Resource resource, const PP_Rect* location) { widget->SetLocation(location); } -const PPB_Widget ppb_widget = { +const PPB_Widget_Dev ppb_widget = { &IsWidget, &Paint, &HandleEvent, @@ -65,7 +68,7 @@ Widget::~Widget() { } // static -const PPB_Widget* Widget::GetInterface() { +const PPB_Widget_Dev* Widget::GetInterface() { return &ppb_widget; } @@ -80,8 +83,8 @@ void Widget::SetLocation(const PP_Rect* location) { } void Widget::Invalidate(const PP_Rect* dirty) { - const PPP_Widget* widget = static_cast<const PPP_Widget*>( - module()->GetPluginInterface(PPP_WIDGET_INTERFACE)); + const PPP_Widget_Dev* widget = static_cast<const PPP_Widget_Dev*>( + module()->GetPluginInterface(PPP_WIDGET_DEV_INTERFACE)); if (!widget) return; ScopedResourceId resource(this); diff --git a/webkit/glue/plugins/pepper_widget.h b/webkit/glue/plugins/pepper_widget.h index 048a718..47826e3 100644 --- a/webkit/glue/plugins/pepper_widget.h +++ b/webkit/glue/plugins/pepper_widget.h @@ -9,8 +9,8 @@ #include "third_party/ppapi/c/pp_rect.h" #include "webkit/glue/plugins/pepper_resource.h" -typedef struct _ppb_Widget PPB_Widget; -typedef struct _pp_Event PP_Event; +struct PPB_Widget_Dev; +struct PP_InputEvent; namespace pepper { @@ -24,14 +24,14 @@ class Widget : public Resource { // Returns a pointer to the interface implementing PPB_Widget that is // exposed to the plugin. - static const PPB_Widget* GetInterface(); + static const PPB_Widget_Dev* GetInterface(); // Resource overrides. Widget* AsWidget() { return this; } // PPB_Widget implementation. virtual bool Paint(const PP_Rect* rect, ImageData* image) = 0; - virtual bool HandleEvent(const PP_Event* event) = 0; + virtual bool HandleEvent(const PP_InputEvent* event) = 0; bool GetLocation(PP_Rect* location); void SetLocation(const PP_Rect* location); diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc index fe1d7ef..a1a6d5f 100644 --- a/webkit/glue/plugins/plugin_host.cc +++ b/webkit/glue/plugins/plugin_host.cc @@ -13,6 +13,7 @@ #include "base/sys_info.h" #endif #include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" #include "net/base/net_util.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" #include "webkit/glue/webkit_glue.h" @@ -449,7 +450,7 @@ static NPError PostURLNotify(NPP id, base::SysNativeMBToWide(file_path_ascii)); } - file_util::FileInfo post_file_info = {0}; + base::PlatformFileInfo post_file_info = {0}; if (!file_util::GetFileInfo(file_path, &post_file_info) || post_file_info.is_directory) return NPERR_FILE_NOT_FOUND; diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc index 8506623..f7b3bf7 100644 --- a/webkit/glue/plugins/plugin_instance.cc +++ b/webkit/glue/plugins/plugin_instance.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -8,7 +8,7 @@ #include "base/file_util.h" #include "base/message_loop.h" -#include "base/string_util.h" +#include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/plugins/plugin_host.h" @@ -489,13 +489,13 @@ void PluginInstance::RequestRead(NPStream* stream, NPByteRange* range_list) { std::string range_info = "bytes="; while (range_list) { - range_info += IntToString(range_list->offset); - range_info += "-"; - range_info += IntToString(range_list->offset + range_list->length - 1); + range_info += base::IntToString(range_list->offset); + range_info.push_back('-'); + range_info += + base::IntToString(range_list->offset + range_list->length - 1); range_list = range_list->next; - if (range_list) { - range_info += ","; - } + if (range_list) + range_info.push_back(','); } if (plugin_data_stream_) { diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h index 36bf601..0dd3ee4 100644 --- a/webkit/glue/plugins/plugin_instance.h +++ b/webkit/glue/plugins/plugin_instance.h @@ -9,7 +9,6 @@ #define WEBKIT_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ #include <map> -#include <set> #include <stack> #include <string> #include <vector> diff --git a/webkit/glue/plugins/plugin_lib.cc b/webkit/glue/plugins/plugin_lib.cc index 877548e..9a0770e 100644 --- a/webkit/glue/plugins/plugin_lib.cc +++ b/webkit/glue/plugins/plugin_lib.cc @@ -98,8 +98,9 @@ NPPluginFuncs* PluginLib::functions() { } NPError PluginLib::NP_Initialize() { - LOG(INFO) << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() << - "): initialized=" << initialized_; + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() + << "): initialized=" << initialized_; if (initialized_) return NPERR_NO_ERROR; @@ -123,8 +124,9 @@ NPError PluginLib::NP_Initialize() { } #endif // OS_MACOSX #endif - LOG(INFO) << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() << - "): result=" << rv; + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() + << "): result=" << rv; initialized_ = (rv == NPERR_NO_ERROR); return rv; } @@ -165,7 +167,7 @@ bool PluginLib::Load() { if (!internal_) { library = base::LoadNativeLibrary(web_plugin_info_.path); if (library == 0) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Couldn't load plugin " << web_plugin_info_.path.value(); return rv; } @@ -215,12 +217,12 @@ bool PluginLib::Load() { if (!internal_) { if (rv) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Plugin " << web_plugin_info_.path.value() << " loaded successfully."; library_ = library; } else { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Plugin " << web_plugin_info_.path.value() << " failed to load, unloading."; base::UnloadNativeLibrary(library); @@ -277,14 +279,14 @@ void PluginLib::Unload() { FreePluginLibraryTask* free_library_task = new FreePluginLibraryTask(skip_unload_ ? NULL : library_, entry_points_.np_shutdown); - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Scheduling delayed unload for plugin " << web_plugin_info_.path.value(); MessageLoop::current()->PostTask(FROM_HERE, free_library_task); } else { Shutdown(); if (!skip_unload_) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Unloading plugin " << web_plugin_info_.path.value(); base::UnloadNativeLibrary(library_); } diff --git a/webkit/glue/plugins/plugin_lib.h b/webkit/glue/plugins/plugin_lib.h index 647916e..ca46e41 100644 --- a/webkit/glue/plugins/plugin_lib.h +++ b/webkit/glue/plugins/plugin_lib.h @@ -9,13 +9,13 @@ #include <vector> #include "base/basictypes.h" -#include "base/file_path.h" #include "base/native_library.h" #include "base/ref_counted.h" #include "build/build_config.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/webplugin.h" +class FilePath; struct WebPluginInfo; namespace NPAPI { diff --git a/webkit/glue/plugins/plugin_lib_mac.mm b/webkit/glue/plugins/plugin_lib_mac.mm index 263b3b4..07da77c 100644 --- a/webkit/glue/plugins/plugin_lib_mac.mm +++ b/webkit/glue/plugins/plugin_lib_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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. @@ -9,6 +9,7 @@ #include "base/native_library.h" #include "base/scoped_cftyperef.h" #include "base/scoped_ptr.h" +#include "base/string_split.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" diff --git a/webkit/glue/plugins/plugin_lib_posix.cc b/webkit/glue/plugins/plugin_lib_posix.cc index dbc64ed..fb813b6 100644 --- a/webkit/glue/plugins/plugin_lib_posix.cc +++ b/webkit/glue/plugins/plugin_lib_posix.cc @@ -17,6 +17,7 @@ #include "base/eintr_wrapper.h" #include "base/file_util.h" +#include "base/string_split.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" @@ -118,14 +119,14 @@ void UnwrapNSPluginWrapper(void **dl, FilePath* unwrapped_path) { if (!newdl) { // We couldn't load the unwrapped plugin for some reason, despite // being able to load the wrapped one. Just use the wrapped one. - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Could not use unwrapped nspluginwrapper plugin " << unwrapped_path->value() << ", using the wrapped one."; return; } // Unload the wrapped plugin, and use the wrapped plugin instead. - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Using unwrapped version " << unwrapped_path->value() << " of nspluginwrapper-wrapped plugin."; base::UnloadNativeLibrary(*dl); @@ -144,7 +145,7 @@ bool PluginLib::ReadWebPluginInfo(const FilePath& filename, // Skip files that aren't appropriate for our architecture. if (!ELFMatchesCurrentArchitecture(filename)) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Skipping plugin " << filename.value() << " because it doesn't match the current architecture."; return false; @@ -152,7 +153,7 @@ bool PluginLib::ReadWebPluginInfo(const FilePath& filename, void* dl = base::LoadNativeLibrary(filename); if (!dl) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "While reading plugin info, unable to load library " << filename.value() << ", skipping."; return false; @@ -193,12 +194,12 @@ bool PluginLib::ReadWebPluginInfo(const FilePath& filename, if (description) info->desc = UTF8ToUTF16(description); - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Got info for plugin " << filename.value() << " Name = \"" << UTF16ToUTF8(info->name) << "\", Description = \"" << UTF16ToUTF8(info->desc) << "\"."; } else { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Plugin " << filename.value() << " has no GetValue() and probably won't work."; } diff --git a/webkit/glue/plugins/plugin_lib_unittest.cc b/webkit/glue/plugins/plugin_lib_unittest.cc index a52510b..5ac6bdc 100644 --- a/webkit/glue/plugins/plugin_lib_unittest.cc +++ b/webkit/glue/plugins/plugin_lib_unittest.cc @@ -5,6 +5,7 @@ #include "webkit/glue/plugins/plugin_lib.h" #include "base/string_util.h" +#include "base/utf_string_conversions.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/webkit/glue/plugins/plugin_lib_win.cc b/webkit/glue/plugins/plugin_lib_win.cc index 00f6243..382c2c8 100644 --- a/webkit/glue/plugins/plugin_lib_win.cc +++ b/webkit/glue/plugins/plugin_lib_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -6,12 +6,13 @@ #include "base/file_version_info.h" #include "base/file_version_info_win.h" +#include "base/logging.h" #include "base/path_service.h" #include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_list.h" -namespace NPAPI -{ +namespace NPAPI { + bool PluginLib::ReadWebPluginInfo(const FilePath &filename, WebPluginInfo* info) { // On windows, the way we get the mime types for the library is @@ -21,8 +22,12 @@ bool PluginLib::ReadWebPluginInfo(const FilePath &filename, // video/quicktime|audio/aiff|image/jpeg scoped_ptr<FileVersionInfo> version_info( FileVersionInfo::CreateFileVersionInfo(filename.value())); - if (!version_info.get()) + if (!version_info.get()) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Could not get version info for plugin " + << filename.value(); return false; + } FileVersionInfoWin* version_info_win = static_cast<FileVersionInfoWin*>(version_info.get()); diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc index a3412d7..b2a7634 100644 --- a/webkit/glue/plugins/plugin_list.cc +++ b/webkit/glue/plugins/plugin_list.cc @@ -9,9 +9,9 @@ #include "base/command_line.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/string_split.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "base/time.h" #include "googleurl/src/gurl.h" #include "net/base/mime_util.h" #include "webkit/glue/plugins/plugin_constants_win.h" @@ -45,8 +45,11 @@ void PluginList::RefreshPlugins() { } void PluginList::AddExtraPluginPath(const FilePath& plugin_path) { + // Chrome OS only loads plugins from /opt/google/chrome/plugins. +#if !defined(OS_CHROMEOS) AutoLock lock(lock_); extra_plugin_paths_.push_back(plugin_path); +#endif } void PluginList::RemoveExtraPluginPath(const FilePath& plugin_path) { @@ -59,8 +62,11 @@ void PluginList::RemoveExtraPluginPath(const FilePath& plugin_path) { } void PluginList::AddExtraPluginDir(const FilePath& plugin_dir) { + // Chrome OS only loads plugins from /opt/google/chrome/plugins. +#if !defined(OS_CHROMEOS) AutoLock lock(lock_); extra_plugin_dirs_.push_back(plugin_dir); +#endif } void PluginList::RegisterInternalPlugin(const PluginVersionInfo& info) { @@ -108,8 +114,11 @@ bool PluginList::CreateWebPluginInfo(const PluginVersionInfo& pvi, info->mime_types.clear(); - if (mime_types.empty()) + if (mime_types.empty()) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Plugin " << pvi.product_name << " has no MIME types, skipping"; return false; + } info->name = WideToUTF16(pvi.product_name); info->desc = WideToUTF16(pvi.file_description); @@ -168,8 +177,6 @@ void PluginList::LoadPlugins(bool refresh) { internal_plugins = internal_plugins_; } - base::TimeTicks start_time = base::TimeTicks::Now(); - std::vector<WebPluginInfo> new_plugins; std::set<FilePath> visited_plugins; @@ -209,10 +216,6 @@ void PluginList::LoadPlugins(bool refresh) { if (webkit_glue::IsDefaultPluginEnabled()) LoadPlugin(FilePath(kDefaultPluginLibraryName), &new_plugins); - base::TimeTicks end_time = base::TimeTicks::Now(); - base::TimeDelta elapsed = end_time - start_time; - DLOG(INFO) << "Loaded plugin list in " << elapsed.InMilliseconds() << " ms."; - // Only update the data now since loading plugins can take a while. AutoLock lock(lock_); @@ -230,6 +233,9 @@ void PluginList::LoadPlugins(bool refresh) { void PluginList::LoadPlugin(const FilePath& path, std::vector<WebPluginInfo>* plugins) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Loading plugin " << path.value(); + WebPluginInfo plugin_info; const PluginEntryPoints* entry_points; diff --git a/webkit/glue/plugins/plugin_list_mac.mm b/webkit/glue/plugins/plugin_list_mac.mm index 16bde9d..ee6c6ad 100644 --- a/webkit/glue/plugins/plugin_list_mac.mm +++ b/webkit/glue/plugins/plugin_list_mac.mm @@ -92,6 +92,14 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, if (IsBlacklistedPlugin(info)) return false; + // Flip4Mac has a reproducible hang during a synchronous call from the render + // with certain content types (as well as a common crash). Disable by default + // to minimize those issues, but don't blacklist it so that users can choose + // to enable it. + if (StartsWith(info.name, ASCIIToUTF16("Flip4Mac Windows Media Plugin"), + false)) + DisablePlugin(info.path); + // Hierarchy check // (we're loading plugins hierarchically from Library folders, so plugins we // encounter earlier must override plugins we encounter later) diff --git a/webkit/glue/plugins/plugin_list_posix.cc b/webkit/glue/plugins/plugin_list_posix.cc index 1fbd76f..b23909b 100644 --- a/webkit/glue/plugins/plugin_list_posix.cc +++ b/webkit/glue/plugins/plugin_list_posix.cc @@ -7,6 +7,7 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/sha1.h" +#include "base/string_split.h" #include "base/string_util.h" #include "build/build_config.h" @@ -121,6 +122,8 @@ void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) { PathService::Get(base::DIR_EXE, &dir); plugin_dirs->push_back(dir.Append("plugins")); + // Chrome OS only loads plugins from /opt/google/chrome/plugins. +#if !defined(OS_CHROMEOS) // Mozilla code to reference: // http://mxr.mozilla.org/firefox/ident?i=NS_APP_PLUGINS_DIR_LIST // and tens of accompanying files (mxr is very helpful). @@ -156,7 +159,8 @@ void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) { plugin_dirs->push_back(FilePath("/usr/lib64/mozilla/plugins")); plugin_dirs->push_back(FilePath("/usr/lib64/firefox/plugins")); plugin_dirs->push_back(FilePath("/usr/lib64/xulrunner-addons/plugins")); -#endif +#endif // defined(ARCH_CPU_64_BITS) +#endif // !defined(OS_CHROMEOS) } void PluginList::LoadPluginsFromDir(const FilePath& dir_path, @@ -183,18 +187,18 @@ void PluginList::LoadPluginsFromDir(const FilePath& dir_path, // symlinks. FilePath orig_path = path; file_util::AbsolutePath(&path); - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Resolved " << orig_path.value() << " -> " << path.value(); if (visited_plugins->find(path) != visited_plugins->end()) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Skipping duplicate instance of " << path.value(); continue; } visited_plugins->insert(path); if (IsBlacklistedPlugin(path)) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Skipping blacklisted plugin " << path.value(); continue; } @@ -209,14 +213,15 @@ void PluginList::LoadPluginsFromDir(const FilePath& dir_path, // Go back to the old path. path = orig_path; } else { - LOG(ERROR) << "Flash misbehaves when used from a directory containing " - << kNetscapeInPath << ", so skipping " << orig_path.value(); + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Flash misbehaves when used from a directory containing " + << kNetscapeInPath << ", so skipping " << orig_path.value(); continue; } } // Get mtime. - file_util::FileInfo info; + base::PlatformFileInfo info; if (!file_util::GetFileInfo(path, &info)) continue; @@ -232,14 +237,13 @@ void PluginList::LoadPluginsFromDir(const FilePath& dir_path, } } - bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, std::vector<WebPluginInfo>* plugins) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Considering " << info.path.value() << " (" << info.name << ")"; if (IsUndesirablePlugin(info)) { - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << info.path.value() << " is undesirable."; // See if we have a better version of this plugin. @@ -248,7 +252,7 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, !IsUndesirablePlugin(plugins->at(i))) { // Skip the current undesirable one so we can use the better one // we just found. - LOG_IF(INFO, PluginList::DebugPluginLoading()) + LOG_IF(ERROR, PluginList::DebugPluginLoading()) << "Skipping " << info.path.value() << ", preferring " << plugins->at(i).path.value(); return false; diff --git a/webkit/glue/plugins/plugin_list_win.cc b/webkit/glue/plugins/plugin_list_win.cc index 1c91916..b5ded9e 100644 --- a/webkit/glue/plugins/plugin_list_win.cc +++ b/webkit/glue/plugins/plugin_list_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -14,6 +14,8 @@ #include "base/path_service.h" #include "base/registry.h" #include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" +#include "base/string_split.h" #include "base/string_util.h" #include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_lib.h" @@ -65,7 +67,7 @@ bool GetInstalledPath(const TCHAR* app, FilePath* out) { reg_path.append(L"\\"); reg_path.append(app); - RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str()); + RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ); std::wstring path; if (key.ReadValue(kRegistryPath, &path)) { *out = FilePath(path); @@ -86,7 +88,7 @@ void GetPluginsInRegistryDirectory( std::wstring reg_path = registry_folder; reg_path.append(L"\\"); reg_path.append(iter.Name()); - RegKey key(root_key, reg_path.c_str()); + RegKey key(root_key, reg_path.c_str(), KEY_READ); std::wstring path; if (key.ReadValue(kRegistryPath, &path)) @@ -313,8 +315,10 @@ bool IsNewerVersion(const std::wstring& a, const std::wstring& b) { if (a_ver.size() != b_ver.size()) return false; for (size_t i = 0; i < a_ver.size(); i++) { - int cur_a = StringToInt(a_ver[i]); - int cur_b = StringToInt(b_ver[i]); + int cur_a, cur_b; + base::StringToInt(a_ver[i], &cur_a); + base::StringToInt(b_ver[i], &cur_b); + if (cur_a > cur_b) return false; if (cur_a < cur_b) @@ -370,9 +374,9 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, SplitString(info.version, '.', &ver); int major, minor, update; if (ver.size() == 4 && - StringToInt(ver[0], &major) && - StringToInt(ver[1], &minor) && - StringToInt(ver[2], &update)) { + base::StringToInt(ver[0], &major) && + base::StringToInt(ver[1], &minor) && + base::StringToInt(ver[2], &update)) { if (major == 6 && minor == 0 && update < 120) return false; // Java SE6 Update 11 or older. } diff --git a/webkit/glue/plugins/plugin_stream.h b/webkit/glue/plugins/plugin_stream.h index f15ea66..c17faaf 100644 --- a/webkit/glue/plugins/plugin_stream.h +++ b/webkit/glue/plugins/plugin_stream.h @@ -2,13 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_H__ -#define WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_H__ +#ifndef WEBKIT_GLUE_PLUGINS_PLUGIN_STREAM_H_ +#define WEBKIT_GLUE_PLUGINS_PLUGIN_STREAM_H_ + +#include "build/build_config.h" #include <string> #include <vector> +#if defined(OS_POSIX) #include "base/file_path.h" +#endif #include "base/ref_counted.h" #include "third_party/npapi/bindings/npapi.h" @@ -110,7 +114,8 @@ class PluginStream : public base::RefCounted<PluginStream> { // Send the data to the plugin, returning how many bytes it accepted, or -1 // if an error occurred. - int TryWriteToPlugin(const char *buf, const int length, const int data_offset); + int TryWriteToPlugin(const char *buf, const int length, + const int data_offset); // The callback which calls TryWriteToPlugin. void OnDelayDelivery(); @@ -141,6 +146,6 @@ class PluginStream : public base::RefCounted<PluginStream> { DISALLOW_COPY_AND_ASSIGN(PluginStream); }; -} // namespace NPAPI +} // namespace NPAPI -#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_H__ +#endif // WEBKIT_GLUE_PLUGINS_PLUGIN_STREAM_H_ diff --git a/webkit/glue/plugins/ppb_private.h b/webkit/glue/plugins/ppb_private.h index a0956f0..218f73a 100644 --- a/webkit/glue/plugins/ppb_private.h +++ b/webkit/glue/plugins/ppb_private.h @@ -5,17 +5,103 @@ #ifndef WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_ #define WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_ +#include "third_party/ppapi/c/pp_module.h" #include "third_party/ppapi/c/pp_var.h" #define PPB_PRIVATE_INTERFACE "PPB_Private;1" -typedef enum _pp_ResourceString { +typedef enum { PP_RESOURCESTRING_PDFGETPASSWORD = 0, } PP_ResourceString; -typedef struct _ppb_Private { +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_PRIVATEFONTPITCH_DEFAULT = 0, + PP_PRIVATEFONTPITCH_FIXED = 1 +} PP_PrivateFontPitch; + +typedef enum { + PP_PRIVATEFONTFAMILY_DEFAULT = 0, + PP_PRIVATEFONTFAMILY_ROMAN = 1, + PP_PRIVATEFONTFAMILY_SCRIPT = 2 +} PP_PrivateFontFamily; + +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; + PP_PrivateFontPitch pitch; + PP_PrivateFontFamily family; + PP_PrivateFontCharset charset; +}; + +struct PPB_Private { // Returns a localized string. - PP_Var (*GetLocalizedString)(PP_ResourceString string_id); -} PPB_Private; + 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. Linux only. + PP_Resource (*GetFontFileWithFallback)( + PP_Module module, + const PP_PrivateFontFileDescription* description); + + // 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); +}; #endif // WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_ diff --git a/webkit/glue/plugins/test/npapi_test.cc b/webkit/glue/plugins/test/npapi_test.cc index d7c4fa7..895a842 100644 --- a/webkit/glue/plugins/test/npapi_test.cc +++ b/webkit/glue/plugins/test/npapi_test.cc @@ -66,13 +66,55 @@ EXPORT NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* pFuncs) { return NPAPIClient::PluginClient::GetEntryPoints(pFuncs); } -EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* pFuncs) { - return NPAPIClient::PluginClient::Initialize(pFuncs); -} - EXPORT NPError API_CALL NP_Shutdown() { return NPAPIClient::PluginClient::Shutdown(); } + +#if defined(OS_WIN) || defined(OS_MACOSX) +EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* npnFuncs) { + return NPAPIClient::PluginClient::Initialize(npnFuncs); +} +#elif defined(OS_POSIX) +EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* npnFuncs, + NPPluginFuncs* nppFuncs) { + NPError error = NPAPIClient::PluginClient::Initialize(npnFuncs); + if (error == NPERR_NO_ERROR) { + error = NP_GetEntryPoints(nppFuncs); + } + return error; +} + +EXPORT NPError API_CALL NP_GetValue(NPP instance, NPPVariable variable, + void* value) { + NPError err = NPERR_NO_ERROR; + + switch (variable) { + case NPPVpluginNameString: + *(static_cast<const char**>(value)) = "NPAPI Test Plugin"; + break; + case NPPVpluginDescriptionString: + *(static_cast<const char**>(value)) = + "Simple NPAPI plug-in for Chromium unit tests"; + break; + case NPPVpluginNeedsXEmbed: + *(static_cast<NPBool*>(value)) = true; + break; + default: + err = NPERR_GENERIC_ERROR; + break; + } + + return err; +} + +EXPORT const char* API_CALL NP_GetMIMEDescription(void) { + // The layout test LayoutTests/fast/js/navigator-mimeTypes-length.html + // asserts that the number of mimetypes handled by plugins should be + // greater than the number of plugins. We specify a mimetype here so + // this plugin has at least one. + return "application/vnd.npapi-test:npapitest:test npapi"; +} +#endif // OS_POSIX } // extern "C" namespace WebCore { diff --git a/webkit/glue/plugins/test/plugin_arguments_test.cc b/webkit/glue/plugins/test/plugin_arguments_test.cc index ee6d2c0..46ccf43 100644 --- a/webkit/glue/plugins/test/plugin_arguments_test.cc +++ b/webkit/glue/plugins/test/plugin_arguments_test.cc @@ -1,9 +1,10 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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 "base/basictypes.h" #include "base/string_util.h" +#include "base/stringprintf.h" #include "webkit/glue/plugins/test/plugin_arguments_test.h" @@ -45,7 +46,7 @@ NPError PluginArgumentsTest::New(uint16 mode, int16 argc, int size = atoi(size_string); for (int index = 1; index <= max_args; index++) { - std::string arg_name = StringPrintf("%s%d", "val", index); + std::string arg_name = base::StringPrintf("%s%d", "val", index); const char *val_string = GetArgValue(arg_name.c_str(), argc, argn, argv); ExpectAsciiStringNotEqual(val_string, (const char*)NULL); diff --git a/webkit/glue/plugins/test/plugin_geturl_test.cc b/webkit/glue/plugins/test/plugin_geturl_test.cc index f321b4b..aedf582 100644 --- a/webkit/glue/plugins/test/plugin_geturl_test.cc +++ b/webkit/glue/plugins/test/plugin_geturl_test.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -8,6 +8,8 @@ #include "base/basictypes.h" #include "base/file_util.h" +#include "base/string_number_conversions.h" +#include "base/utf_string_conversions.h" // url for "self". The %22%22 is to make a statement for javascript to // evaluate and return. @@ -357,7 +359,7 @@ void PluginGetURLTest::URLNotify(const char* url, NPReason reason, void* data) { case BOGUS_URL_STREAM_ID: if (reason != NPRES_NETWORK_ERR) { std::string err = "BOGUS_URL received unexpected URLNotify status: "; - err.append(IntToString(reason)); + err.append(base::IntToString(reason)); SetError(err); } tests_in_progress_--; diff --git a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc index b62a764..10b3239 100644 --- a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc +++ b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc @@ -17,7 +17,8 @@ NPObjectDeletePluginInNPN_Evaluate* NPObjectLifetimeTest::NPObjectLifetimeTest(NPP id, NPNetscapeFuncs *host_functions) : PluginTest(id, host_functions), - other_plugin_instance_object_(NULL) { + other_plugin_instance_object_(NULL), + timer_id_(0) { } NPError NPObjectLifetimeTest::SetWindow(NPWindow* pNPWindow) { @@ -30,8 +31,8 @@ NPError NPObjectLifetimeTest::SetWindow(NPWindow* pNPWindow) { // We attempt to retreive the NPObject for the plugin instance identified // by the NPObjectLifetimeTestInstance2 class as it may not have been // instantiated yet. - SetTimer(window_handle, kNPObjectLifetimeTimer, kNPObjectLifetimeTimerElapse, - TimerProc); + timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer, + kNPObjectLifetimeTimerElapse, TimerProc); } return NPERR_NO_ERROR; } @@ -40,10 +41,11 @@ void CALLBACK NPObjectLifetimeTest::TimerProc( HWND window, UINT message, UINT timer_id, unsigned long elapsed_milli_seconds) { - KillTimer(window, kNPObjectLifetimeTimer); NPObjectLifetimeTest* this_instance = reinterpret_cast<NPObjectLifetimeTest*> (::GetProp(window, L"Plugin_Instance")); + KillTimer(window, this_instance->timer_id_); + this_instance->timer_id_ = 0; this_instance->other_plugin_instance_object_ = NPObjectLifetimeTestInstance2::plugin_instance_object_; @@ -107,7 +109,7 @@ NPObjectDeletePluginInNPN_Evaluate::NPObjectDeletePluginInNPN_Evaluate( NPP id, NPNetscapeFuncs *host_functions) : PluginTest(id, host_functions), plugin_instance_object_(NULL), - npn_evaluate_timer_proc_set_(false) { + timer_id_(0) { g_npn_evaluate_test_instance_ = this; } @@ -128,12 +130,10 @@ NPError NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow* np_window) { // while it is being used in webkit as this leads to crashes and is a // more accurate representation of the renderer crash as described in // http://b/issue?id=1134683. - if (!npn_evaluate_timer_proc_set_) { - npn_evaluate_timer_proc_set_ = true; - SetTimer(window_handle, kNPObjectLifetimeTimer, kNPObjectLifetimeTimerElapse, - TimerProc); + if (!timer_id_) { + timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer, + kNPObjectLifetimeTimerElapse, TimerProc); } - return NPERR_NO_ERROR; } @@ -141,7 +141,8 @@ void CALLBACK NPObjectDeletePluginInNPN_Evaluate::TimerProc( HWND window, UINT message, UINT timer_id, unsigned long elapsed_milli_seconds) { - KillTimer(window, kNPObjectLifetimeTimer); + KillTimer(window, g_npn_evaluate_test_instance_->timer_id_); + g_npn_evaluate_test_instance_->timer_id_ = 0; NPObject *window_obj = NULL; g_npn_evaluate_test_instance_->HostFunctions()->getvalue( g_npn_evaluate_test_instance_->id(), NPNVWindowNPObject, diff --git a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h index 4303d99..60d0314 100644 --- a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h +++ b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h @@ -30,6 +30,7 @@ class NPObjectLifetimeTest : public PluginTest { #if defined(OS_WIN) static void CALLBACK TimerProc(HWND window, UINT message, UINT timer_id, unsigned long elapsed_milli_seconds); + UINT_PTR timer_id_; #endif DISALLOW_IMPLICIT_CONSTRUCTORS(NPObjectLifetimeTest); }; @@ -67,10 +68,10 @@ class NPObjectDeletePluginInNPN_Evaluate : public PluginTest { #if defined(OS_WIN) static void CALLBACK TimerProc(HWND window, UINT message, UINT timer_id, unsigned long elapsed_milli_seconds); + UINT_PTR timer_id_; #endif private: - bool npn_evaluate_timer_proc_set_; static NPObjectDeletePluginInNPN_Evaluate* g_npn_evaluate_test_instance_; DISALLOW_IMPLICIT_CONSTRUCTORS(NPObjectDeletePluginInNPN_Evaluate); diff --git a/webkit/glue/plugins/test/plugin_schedule_timer_test.h b/webkit/glue/plugins/test/plugin_schedule_timer_test.h index 9ca947f..e3e6505 100644 --- a/webkit/glue/plugins/test/plugin_schedule_timer_test.h +++ b/webkit/glue/plugins/test/plugin_schedule_timer_test.h @@ -1,12 +1,10 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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_TEST_PLUGIN_SCHEDULE_TIMER_TEST_H #define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SCHEDULE_TIMER_TEST_H -#include <vector> - #include "base/at_exit.h" #include "base/time.h" #include "webkit/glue/plugins/test/plugin_test.h" diff --git a/webkit/glue/plugins/test/plugin_test.h b/webkit/glue/plugins/test/plugin_test.h index f06307e..eed6e3f 100644 --- a/webkit/glue/plugins/test/plugin_test.h +++ b/webkit/glue/plugins/test/plugin_test.h @@ -1,12 +1,13 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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_PORT_PLUGINS_TEST_PLUGIN_TEST_H__ -#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H__ +#ifndef WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H_ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H_ #include <string> +#include "base/string_number_conversions.h" #include "base/string_util.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/nphostapi.h" @@ -82,9 +83,9 @@ class PluginTest { if (val1 != val2) { std::string err; err = "Expected Equal for '"; - err.append(IntToString(val1)); + err.append(base::IntToString(val1)); err.append("' and '"); - err.append(IntToString(val2)); + err.append(base::IntToString(val2)); err.append("'"); SetError(err); } @@ -128,4 +129,4 @@ class PluginTest { } // namespace NPAPIClient -#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H__ +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H_ diff --git a/webkit/glue/plugins/test/plugin_test_factory.cc b/webkit/glue/plugins/test/plugin_test_factory.cc index e2b42b3..62a3977 100644 --- a/webkit/glue/plugins/test/plugin_test_factory.cc +++ b/webkit/glue/plugins/test/plugin_test_factory.cc @@ -66,7 +66,8 @@ PluginTest* CreatePluginTest(const std::string& test_name, new_test = new NPObjectLifetimeTestInstance2(instance, host_functions); } else if (test_name == "new_fails") { new_test = new NewFailsTest(instance, host_functions); - } else if (test_name == "npobject_delete_plugin_in_evaluate") { + } else if (test_name == "npobject_delete_plugin_in_evaluate" || + test_name == "npobject_delete_create_plugin_in_evaluate") { new_test = new NPObjectDeletePluginInNPN_Evaluate(instance, host_functions); #endif } else if (test_name == "plugin_javascript_open_popup_with_plugin") { @@ -86,7 +87,8 @@ PluginTest* CreatePluginTest(const std::string& test_name, } else if (test_name == "hidden_plugin" || test_name == "create_instance_in_paint" || test_name == "alert_in_window_message" || - test_name == "ensure_scripting_works_in_destroy") { + test_name == "ensure_scripting_works_in_destroy" || + test_name == "invoke_js_function_on_create") { new_test = new WindowedPluginTest(instance, host_functions); #endif } diff --git a/webkit/glue/plugins/test/plugin_thread_async_call_test.cc b/webkit/glue/plugins/test/plugin_thread_async_call_test.cc index 2e9f9e9..c01a49e 100644 --- a/webkit/glue/plugins/test/plugin_thread_async_call_test.cc +++ b/webkit/glue/plugins/test/plugin_thread_async_call_test.cc @@ -4,6 +4,7 @@ #include "webkit/glue/plugins/test/plugin_thread_async_call_test.h" +#include "base/at_exit.h" #include "base/message_loop.h" #include "base/thread.h" #include "webkit/glue/plugins/test/plugin_client.h" diff --git a/webkit/glue/plugins/test/plugin_thread_async_call_test.h b/webkit/glue/plugins/test/plugin_thread_async_call_test.h index 020e5e1..78e4e8d 100644 --- a/webkit/glue/plugins/test/plugin_thread_async_call_test.h +++ b/webkit/glue/plugins/test/plugin_thread_async_call_test.h @@ -1,16 +1,17 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H -#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H +#ifndef WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H_ +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H_ -#include <vector> - -#include "base/at_exit.h" #include "base/scoped_ptr.h" #include "webkit/glue/plugins/test/plugin_test.h" +namespace base { +class AtExitManager; +} + namespace NPAPIClient { // This class tests scheduling and unscheduling of async callbacks using @@ -35,4 +36,4 @@ class PluginThreadAsyncCallTest : public PluginTest { } // namespace NPAPIClient -#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H_ diff --git a/webkit/glue/plugins/test/plugin_windowed_test.cc b/webkit/glue/plugins/test/plugin_windowed_test.cc index 5ae8e30..461fc20 100644 --- a/webkit/glue/plugins/test/plugin_windowed_test.cc +++ b/webkit/glue/plugins/test/plugin_windowed_test.cc @@ -36,7 +36,8 @@ NPError WindowedPluginTest::SetWindow(NPWindow* pNPWindow) { } if ((test_name() == "create_instance_in_paint" && test_id() == "1") || - test_name() == "alert_in_window_message") { + test_name() == "alert_in_window_message" || + test_name() == "invoke_js_function_on_create") { static ATOM window_class = 0; if (!window_class) { WNDCLASSEX wcex; @@ -130,6 +131,11 @@ LRESULT CALLBACK WindowedPluginTest::WindowProc( // and verify that we don't hang the browser. CallJSFunction(this_ptr, "CallAlert"); CallJSFunction(this_ptr, "CallAlert"); + } else if (this_ptr->test_name() == + "invoke_js_function_on_create" && + message == WM_PAINT) { + this_ptr->done_ = true; + CallJSFunction(this_ptr, "PluginCreated"); } } diff --git a/webkit/glue/plugins/test/plugin_windowless_test.cc b/webkit/glue/plugins/test/plugin_windowless_test.cc index c47c1d7..aa6a9d7 100644 --- a/webkit/glue/plugins/test/plugin_windowless_test.cc +++ b/webkit/glue/plugins/test/plugin_windowless_test.cc @@ -1,8 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. #define STRSAFE_NO_DEPRECATE +#include "base/string_number_conversions.h" #include "base/string_util.h" #include "webkit/glue/plugins/test/plugin_windowless_test.h" #include "webkit/glue/plugins/test/plugin_client.h" @@ -151,9 +152,9 @@ void WindowlessPluginTest::MultipleInstanceSyncCalls(NPNetscapeFuncs* browser) { #if defined(OS_MACOSX) std::string StringForPoint(int x, int y) { std::string point_string("("); - point_string.append(IntToString(x)); + point_string.append(base::IntToString(x)); point_string.append(", "); - point_string.append(IntToString(y)); + point_string.append(base::IntToString(y)); point_string.append(")"); return point_string; } diff --git a/webkit/glue/plugins/webplugin.cc b/webkit/glue/plugins/webplugin.cc index 6443318..18f722b 100644 --- a/webkit/glue/plugins/webplugin.cc +++ b/webkit/glue/plugins/webplugin.cc @@ -12,6 +12,9 @@ WebPluginGeometry::WebPluginGeometry() visible(false) { } +WebPluginGeometry::~WebPluginGeometry() { +} + bool WebPluginGeometry::Equals(const WebPluginGeometry& rhs) const { return window == rhs.window && window_rect == rhs.window_rect && diff --git a/webkit/glue/plugins/webplugin.h b/webkit/glue/plugins/webplugin.h index 1813842..19c6cb0 100644 --- a/webkit/glue/plugins/webplugin.h +++ b/webkit/glue/plugins/webplugin.h @@ -33,6 +33,7 @@ class WebPluginResourceClient; // Describes the new location for a plugin window. struct WebPluginGeometry { WebPluginGeometry(); + ~WebPluginGeometry(); bool Equals(const WebPluginGeometry& rhs) const; diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc index b73b5ae..5374546 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -156,6 +156,42 @@ void WebPluginDelegateImpl::UpdateGeometry( } } +void WebPluginDelegateImpl::SetFocus(bool focused) { + DCHECK(windowless_); + // This is called when internal WebKit focus (the focused element on the page) + // changes, but plugins need to know about OS-level focus, so we have an extra + // layer of focus tracking. + // + // On Windows, historically browsers did not set focus events to windowless + // plugins when the toplevel window focus changes. Sending such focus events + // breaks full screen mode in Flash because it will come out of full screen + // mode when it loses focus, and its full screen window causes the browser to + // lose focus. + has_webkit_focus_ = focused; +#ifndef OS_WIN + if (containing_view_has_focus_) + SetPluginHasFocus(focused); +#else + SetPluginHasFocus(focused); +#endif +} + +void WebPluginDelegateImpl::SetPluginHasFocus(bool focused) { + if (focused == plugin_has_focus_) + return; + if (PlatformSetPluginHasFocus(focused)) + plugin_has_focus_ = focused; +} + +void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) { + containing_view_has_focus_ = has_focus; + if (!windowless_) + return; +#ifndef OS_WIN // See SetFocus above. + SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_); +#endif +} + NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() { return instance_->GetPluginScriptableObject(); } diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index ebf5d3e..650d398 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H_ -#define WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H_ +#ifndef WEBKIT_GLUE_PLUGINS_WEBPLUGIN_DELEGATE_IMPL_H_ +#define WEBKIT_GLUE_PLUGINS_WEBPLUGIN_DELEGATE_IMPL_H_ #include "build/build_config.h" #include <string> #include <list> -#include <set> -#include "base/file_path.h" #include "base/ref_counted.h" #include "base/task.h" #include "base/time.h" @@ -27,9 +25,13 @@ #endif #if defined(USE_X11) +#include "app/x11_util.h" + typedef struct _GdkDrawable GdkPixmap; #endif +class FilePath; + namespace NPAPI { class PluginInstance; } @@ -135,6 +137,9 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // Returns a combination of PluginQuirks. int GetQuirks() const { return quirks_; } + // Informs the plugin that the view it is in has gained or lost focus. + void SetContentAreaHasFocus(bool has_focus); + #if defined(OS_MACOSX) // Informs the plugin that the geometry has changed, as with UpdateGeometry, // but also includes the new buffer context for that new geometry. @@ -148,16 +153,14 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { static WebPluginDelegateImpl* GetActiveDelegate(); // Informs the plugin that the window it is in has gained or lost focus. void SetWindowHasFocus(bool has_focus); - // Informs the plugin that the view it is in has gained or lost first - // responder status. - void SetContentAreaHasFocus(bool has_focus); // Returns whether or not the window the plugin is in has focus. bool GetWindowHasFocus() const { return containing_window_has_focus_; } // Informs the plugin that its tab or window has been hidden or shown. void SetContainerVisibility(bool is_visible); // Informs the plugin that its containing window's frame has changed. // Frames are in screen coordinates. - void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame); + void WindowFrameChanged(const gfx::Rect& window_frame, + const gfx::Rect& view_frame); // Informs the delegate that the plugin set a Carbon ThemeCursor. void SetThemeCursor(ThemeCursor cursor); // Informs the delegate that the plugin set a Carbon Cursor. @@ -181,6 +184,12 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { void set_windowed_handle(gfx::PluginWindowHandle handle); #endif +#if defined(USE_X11) + void SetWindowlessShmPixmap(XID shm_pixmap) { + windowless_shm_pixmap_ = shm_pixmap; + } +#endif + private: friend class DeleteTask<WebPluginDelegateImpl>; friend class webkit_glue::WebPluginDelegate; @@ -246,6 +255,14 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // See NPAPI NPP_SetWindow for more information. void WindowlessSetWindow(); + // Informs the plugin that it has gained or lost keyboard focus (on the Mac, + // this just means window first responder status). + void SetPluginHasFocus(bool focused); + + // Handles the platform specific details of setting plugin focus. Returns + // false if the platform cancelled the focus tranfer. + bool PlatformSetPluginHasFocus(bool focused); + //----------------------------------------- // used for windowed and windowless plugins @@ -289,9 +306,12 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // layout of this process with the one of the browser process. HKL keyboard_layout_; int parent_thread_id_; -#endif // OS_WIN +#endif // defined(OS_WIN) #if defined(USE_X11) + // The SHM pixmap for a windowless plugin. + XID windowless_shm_pixmap_; + // The pixmap we're drawing into, for a windowless plugin. GdkPixmap* pixmap_; double first_event_time_; @@ -366,10 +386,6 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // Updates everything that depends on the plugin's absolute screen location. void PluginScreenLocationChanged(); - // Informs the plugin that it has gained or lost keyboard focus (i.e., window - // first responder status). - void SetPluginHasFocus(bool has_focus); - // Returns the apparent zoom ratio for the given event, as inferred from our // current knowledge about about where on screen the plugin is. // This is a temporary workaround for <http://crbug.com/9996>; once that is @@ -424,14 +440,6 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // relative to an upper-left (0,0). gfx::Point content_area_origin_; - // True if the plugin thinks it has keyboard focus - bool plugin_has_focus_; - // True if the plugin element has focus within the page, regardless of whether - // its containing view is currently the first responder for the window. - bool has_webkit_focus_; - // True if the containing view is the window's first responder. - bool containing_view_has_focus_; - bool containing_window_has_focus_; bool initial_window_focus_; bool container_is_visible_; @@ -484,7 +492,18 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // call received by the plugin. bool first_set_window_call_; + // True if the plugin thinks it has keyboard focus + bool plugin_has_focus_; + // True if the plugin element has focus within the web content, regardless of + // whether its containing view currently has focus. + bool has_webkit_focus_; + // True if the containing view currently has focus. + // Initially set to true so that plugin focus still works in environments + // where SetContentAreaHasFocus is never called. See + // https://bugs.webkit.org/show_bug.cgi?id=46013 for details. + bool containing_view_has_focus_; + DISALLOW_COPY_AND_ASSIGN(WebPluginDelegateImpl); }; -#endif // WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H_ +#endif // WEBKIT_GLUE_PLUGINS_WEBPLUGIN_DELEGATE_IMPL_H_ diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index 18b1504..3d112fa 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -44,6 +44,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( windowless_(false), plugin_(NULL), instance_(instance), + windowless_shm_pixmap_(None), pixmap_(NULL), first_event_time_(-1.0), plug_(NULL), @@ -51,7 +52,10 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( parent_(containing_view), quirks_(0), handle_event_depth_(0), - first_set_window_call_(true) { + first_set_window_call_(true), + plugin_has_focus_(false), + has_webkit_focus_(false), + containing_view_has_focus_(true) { memset(&window_, 0, sizeof(window_)); if (instance_->mime_type() == "application/x-shockwave-flash") { // Flash is tied to Firefox's whacky behavior with windowless plugins. See @@ -399,47 +403,99 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_t* context, pixmap_draw_rect.right(), pixmap_draw_rect.bottom()); - EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); - - // Copy the current image into the pixmap, so the plugin can draw over - // this background. - cairo_t* cairo = gdk_cairo_create(pixmap_); - BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); - cairo_destroy(cairo); - // Construct the paint message, targeting the pixmap. NPEvent np_event = {0}; XGraphicsExposeEvent &event = np_event.xgraphicsexpose; event.type = GraphicsExpose; - event.display = GDK_DISPLAY(); - event.drawable = GDK_PIXMAP_XID(pixmap_); event.x = pixmap_draw_rect.x(); event.y = pixmap_draw_rect.y(); event.width = pixmap_draw_rect.width(); event.height = pixmap_draw_rect.height(); + event.display = GDK_DISPLAY(); - // Tell the plugin to paint into the pixmap. - static StatsRate plugin_paint("Plugin.Paint"); - StatsScope<StatsRate> scope(plugin_paint); - NPError err = instance()->NPP_HandleEvent(&np_event); - DCHECK_EQ(err, NPERR_NO_ERROR); + if (windowless_shm_pixmap_ != None) { + Pixmap pixmap = None; + GC xgc = NULL; + Display* display = event.display; + gfx::Rect plugin_draw_rect = draw_rect; + + // Make plugin_draw_rect relative to the plugin window. + plugin_draw_rect.Offset(-window_rect_.x(), -window_rect_.y()); + + // In case the drawing area does not start with the plugin window origin, + // we can not let the plugin directly draw over the shared memory pixmap. + if (plugin_draw_rect.x() != pixmap_draw_rect.x() || + plugin_draw_rect.y() != pixmap_draw_rect.y()) { + pixmap = XCreatePixmap(display, windowless_shm_pixmap_, + std::max(1, pixmap_rect.width()), + std::max(1, pixmap_rect.height()), + DefaultDepth(display, 0)); + xgc = XCreateGC(display, windowless_shm_pixmap_, 0, NULL); + // Copy the current image into the pixmap, so the plugin can draw over it. + XCopyArea(display, windowless_shm_pixmap_, pixmap, xgc, + plugin_draw_rect.x(), plugin_draw_rect.y(), + pixmap_draw_rect.width(), pixmap_draw_rect.height(), + pixmap_draw_rect.x(), pixmap_draw_rect.y()); + + event.drawable = pixmap; + } else { + event.drawable = windowless_shm_pixmap_; + } + + // Tell the plugin to paint into the pixmap. + static StatsRate plugin_paint("Plugin.Paint"); + StatsScope<StatsRate> scope(plugin_paint); + NPError err = instance()->NPP_HandleEvent(&np_event); + DCHECK_EQ(err, NPERR_NO_ERROR); - cairo_save(context); - // Now copy the rendered image pixmap back into the drawing buffer. - gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); - cairo_rectangle(context, draw_rect.x(), draw_rect.y(), - draw_rect.width(), draw_rect.height()); - cairo_clip(context); - cairo_paint(context); + if (pixmap != None) { + // Copy the rendered image pixmap back into the shm pixmap + // and thus the drawing buffer. + XCopyArea(display, pixmap, windowless_shm_pixmap_, xgc, + pixmap_draw_rect.x(), pixmap_draw_rect.y(), + pixmap_draw_rect.width(), pixmap_draw_rect.height(), + plugin_draw_rect.x(), plugin_draw_rect.y()); + XSync(display, FALSE); + if (xgc) + XFreeGC(display, xgc); + XFreePixmap(display, pixmap); + } else { + XSync(display, FALSE); + } + } else { + EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); + + // Copy the current image into the pixmap, so the plugin can draw over + // this background. + cairo_t* cairo = gdk_cairo_create(pixmap_); + BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); + cairo_destroy(cairo); + + event.drawable = GDK_PIXMAP_XID(pixmap_); + + // Tell the plugin to paint into the pixmap. + static StatsRate plugin_paint("Plugin.Paint"); + StatsScope<StatsRate> scope(plugin_paint); + NPError err = instance()->NPP_HandleEvent(&np_event); + DCHECK_EQ(err, NPERR_NO_ERROR); + + cairo_save(context); + // Now copy the rendered image pixmap back into the drawing buffer. + gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); + cairo_rectangle(context, draw_rect.x(), draw_rect.y(), + draw_rect.width(), draw_rect.height()); + cairo_clip(context); + cairo_paint(context); #ifdef DEBUG_RECTANGLES - // Draw some debugging rectangles. - // Pixmap rect = blue. - DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); - // Drawing rect = red. - DrawDebugRectangle(context, draw_rect, 1, 0, 0); + // Draw some debugging rectangles. + // Pixmap rect = blue. + DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); + // Drawing rect = red. + DrawDebugRectangle(context, draw_rect, 1, 0, 0); #endif - cairo_restore(context); + cairo_restore(context); + } } void WebPluginDelegateImpl::WindowlessSetWindow() { @@ -485,7 +541,7 @@ void WebPluginDelegateImpl::WindowlessSetWindow() { } } -void WebPluginDelegateImpl::SetFocus(bool focused) { +bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { DCHECK(instance()->windowless()); NPEvent np_event = {0}; @@ -496,6 +552,7 @@ void WebPluginDelegateImpl::SetFocus(bool focused) { event.mode = -1; event.detail = NotifyDetailNone; instance()->NPP_HandleEvent(&np_event); + return true; } // Converts a WebInputEvent::Modifiers bitfield into a diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index efa6bdd..614f1d2 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -12,11 +12,11 @@ #include <set> #include "base/file_util.h" -#include "base/lazy_instance.h" #include "base/message_loop.h" #include "base/scoped_ptr.h" #include "base/stats_counters.h" #include "base/string_util.h" +#include "base/utf_string_conversions.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/plugins/plugin_lib.h" @@ -258,16 +258,16 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( layer_(nil), surface_(NULL), renderer_(nil), - plugin_has_focus_(false), - has_webkit_focus_(false), - containing_view_has_focus_(false), containing_window_has_focus_(false), initial_window_focus_(false), container_is_visible_(false), have_called_set_window_(false), external_drag_tracker_(new ExternalDragTracker()), handle_event_depth_(0), - first_set_window_call_(true) { + first_set_window_call_(true), + plugin_has_focus_(false), + has_webkit_focus_(false), + containing_view_has_focus_(true) { memset(&window_, 0, sizeof(window_)); #ifndef NP_NO_CARBON memset(&np_cg_context_, 0, sizeof(np_cg_context_)); @@ -385,12 +385,6 @@ bool WebPluginDelegateImpl::PlatformInitialize() { break; } - // TODO(stuartmorgan): We need real plugin container visibility information - // when the plugin is initialized; for now, assume it's visible. - // None of the calls SetContainerVisibility would make are useful at this - // point, so we just set the initial state directly. - container_is_visible_ = true; - // Let the WebPlugin know that we are windowless (unless this is a // Core Animation plugin, in which case BindFakePluginWindowHandle will take // care of setting up the appropriate window handle). @@ -472,15 +466,6 @@ void WebPluginDelegateImpl::Print(CGContextRef context) { NOTIMPLEMENTED(); } -void WebPluginDelegateImpl::SetFocus(bool focused) { - // This is called when internal WebKit focus (the focused element on the page) - // changes, but plugins need to know about actual first responder status, so - // we have an extra layer of focus tracking. - has_webkit_focus_ = focused; - if (containing_view_has_focus_) - SetPluginHasFocus(focused); -} - bool WebPluginDelegateImpl::PlatformHandleInputEvent( const WebInputEvent& event, WebCursorInfo* cursor_info) { DCHECK(cursor_info != NULL); @@ -497,12 +482,6 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( if (WebInputEvent::isMouseEventType(event.type) || event.type == WebInputEvent::MouseWheel) { - // Ideally we would compute the content origin from the web event using the - // code below as a safety net for missed content area location changes. - // Because of <http://crbug.com/9996>, however, only globalX/Y are right if - // the page has been zoomed, so for now the coordinates we get aren't - // trustworthy enough to use for corrections. -#if PLUGIN_SCALING_FIXED // Check our plugin location before we send the event to the plugin, just // in case we somehow missed a plugin frame change. const WebMouseEvent* mouse_event = @@ -517,7 +496,6 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( << content_origin; SetContentAreaOrigin(content_origin); } -#endif current_windowless_cursor_.GetCursorInfo(cursor_info); } @@ -593,25 +571,6 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( } } -#ifndef PLUGIN_SCALING_FIXED - // Because of <http://crbug.com/9996>, the non-global coordinates we get for - // zoomed pages are wrong. As a temporary hack around that bug, override the - // coordinates we are given with ones computed based on our knowledge of where - // the plugin is on screen. We only need to do this for Cocoa, since Carbon - // only uses the global coordinates. - if (instance()->event_model() == NPEventModelCocoa && - (WebInputEvent::isMouseEventType(event.type) || - event.type == WebInputEvent::MouseWheel)) { - const WebMouseEvent* mouse_event = - static_cast<const WebMouseEvent*>(&event); - NPCocoaEvent* cocoa_event = static_cast<NPCocoaEvent*>(plugin_event); - cocoa_event->data.mouse.pluginX = - mouse_event->globalX - content_area_origin_.x() - window_rect_.x(); - cocoa_event->data.mouse.pluginY = - mouse_event->globalY - content_area_origin_.y() - window_rect_.y(); - } -#endif - // Send the plugin the event. scoped_ptr<NPAPI::ScopedCurrentPluginEvent> event_scope(NULL); if (instance()->event_model() == NPEventModelCocoa) { @@ -855,13 +814,9 @@ void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) { } } -void WebPluginDelegateImpl::SetPluginHasFocus(bool has_focus) { +bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { if (!have_called_set_window_) - return; - - if (has_focus == plugin_has_focus_) - return; - plugin_has_focus_ = has_focus; + return false; ScopedActiveDelegate active_delegate(this); @@ -869,7 +824,7 @@ void WebPluginDelegateImpl::SetPluginHasFocus(bool has_focus) { #ifndef NP_NO_CARBON case NPEventModelCarbon: { NPEvent focus_event = { 0 }; - if (plugin_has_focus_) + if (focused) focus_event.what = NPEventType_GetFocusEvent; else focus_event.what = NPEventType_LoseFocusEvent; @@ -882,16 +837,12 @@ void WebPluginDelegateImpl::SetPluginHasFocus(bool has_focus) { NPCocoaEvent focus_event; memset(&focus_event, 0, sizeof(focus_event)); focus_event.type = NPCocoaEventFocusChanged; - focus_event.data.focus.hasFocus = plugin_has_focus_; + focus_event.data.focus.hasFocus = focused; instance()->NPP_HandleEvent(&focus_event); break; } } -} - -void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) { - containing_view_has_focus_ = has_focus; - SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_); + return true; } void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { @@ -925,8 +876,8 @@ void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { instance()->webplugin()->InvalidateRect(gfx::Rect()); } -void WebPluginDelegateImpl::WindowFrameChanged(gfx::Rect window_frame, - gfx::Rect view_frame) { +void WebPluginDelegateImpl::WindowFrameChanged(const gfx::Rect& window_frame, + const gfx::Rect& view_frame) { instance()->set_window_frame(window_frame); SetContentAreaOrigin(gfx::Point(view_frame.x(), view_frame.y())); } diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc index 09184ab..9cdc7db 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -15,7 +15,10 @@ #include "base/registry.h" #include "base/scoped_ptr.h" #include "base/stats_counters.h" +#include "base/string_number_conversions.h" +#include "base/string_split.h" #include "base/string_util.h" +#include "base/stringprintf.h" #include "base/win_util.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" @@ -264,7 +267,10 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( user_gesture_msg_factory_(this), handle_event_depth_(0), mouse_hook_(NULL), - first_set_window_call_(true) { + first_set_window_call_(true), + plugin_has_focus_(false), + has_webkit_focus_(false), + containing_view_has_focus_(true) { memset(&window_, 0, sizeof(window_)); const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); @@ -285,7 +291,8 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( std::vector<std::wstring> version; SplitString(plugin_info.version, L'.', &version); if (version.size() > 0) { - int major = static_cast<int>(StringToInt64(version[0])); + int major; + base::StringToInt(version[0], &major); if (major >= 9) { quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; @@ -410,7 +417,8 @@ bool WebPluginDelegateImpl::PlatformInitialize() { if ((quirks_ & PLUGIN_QUIRK_PATCH_REGENUMKEYEXW) && win_util::GetWinVersion() == win_util::WINVERSION_XP && !RegKey().Open(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe") && + L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", + KEY_READ) && !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", @@ -1048,7 +1056,7 @@ void WebPluginDelegateImpl::WindowlessSetWindow() { DCHECK(err == NPERR_NO_ERROR); } -void WebPluginDelegateImpl::SetFocus(bool focused) { +bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { DCHECK(instance()->windowless()); NPEvent focus_event; @@ -1057,6 +1065,7 @@ void WebPluginDelegateImpl::SetFocus(bool focused) { focus_event.lParam = 0; instance()->NPP_HandleEvent(&focus_event); + return true; } static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, @@ -1187,7 +1196,7 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( parent_thread_id_ = GetWindowThreadProcessId(parent_, NULL); HKL parent_layout = GetKeyboardLayout(parent_thread_id_); if (keyboard_layout_ != parent_layout) { - std::wstring layout_name(StringPrintf(L"%08x", parent_layout)); + std::wstring layout_name(base::StringPrintf(L"%08x", parent_layout)); LoadKeyboardLayout(layout_name.c_str(), KLF_ACTIVATE); keyboard_layout_ = parent_layout; } diff --git a/webkit/glue/plugins/webplugin_impl.cc b/webkit/glue/plugins/webplugin_impl.cc index 1660ede..80bc197 100644 --- a/webkit/glue/plugins/webplugin_impl.cc +++ b/webkit/glue/plugins/webplugin_impl.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/string_util.h" +#include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "gfx/rect.h" #include "googleurl/src/gurl.h" @@ -113,7 +114,7 @@ class MultiPartResponseClient : public WebURLLoaderClient { byte_range_lower_bound_ += data_size; } - virtual void didFinishLoading(WebURLLoader*) {} + virtual void didFinishLoading(WebURLLoader*, double finishTime) {} virtual void didFail(WebURLLoader*, const WebURLError&) {} void Clear() { @@ -160,7 +161,7 @@ std::string GetAllHeaders(const WebURLResponse& response) { return result; // TODO(darin): Shouldn't we also report HTTP version numbers? - result = StringPrintf("HTTP %d ", response.httpStatusCode()); + result = base::StringPrintf("HTTP %d ", response.httpStatusCode()); result.append(status.utf8()); result.append("\n"); @@ -340,6 +341,10 @@ bool WebPluginImpl::acceptsInputEvents() { bool WebPluginImpl::handleInputEvent( const WebInputEvent& event, WebCursorInfo& cursor_info) { + // Swallow context menu events in order to suppress the default context menu. + if (event.type == WebInputEvent::ContextMenu) + return true; + return delegate_->HandleInputEvent(event, &cursor_info); } @@ -913,7 +918,7 @@ void WebPluginImpl::didReceiveData(WebURLLoader* loader, } } -void WebPluginImpl::didFinishLoading(WebURLLoader* loader) { +void WebPluginImpl::didFinishLoading(WebURLLoader* loader, double finishTime) { ClientInfo* client_info = GetClientInfoFromLoader(loader); if (client_info && client_info->client) { MultiPartResponseHandlerMap::iterator index = diff --git a/webkit/glue/plugins/webplugin_impl.h b/webkit/glue/plugins/webplugin_impl.h index 9b75e6e..5fe96d2 100644 --- a/webkit/glue/plugins/webplugin_impl.h +++ b/webkit/glue/plugins/webplugin_impl.h @@ -204,7 +204,8 @@ class WebPluginImpl : public WebPlugin, const WebKit::WebURLResponse& response); virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer, int length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader); + virtual void didFinishLoading(WebKit::WebURLLoader* loader, + double finishTime); virtual void didFail(WebKit::WebURLLoader* loader, const WebKit::WebURLError& error); diff --git a/webkit/glue/plugins/webview_plugin.cc b/webkit/glue/plugins/webview_plugin.cc index 413ae10..231bd37 100644 --- a/webkit/glue/plugins/webview_plugin.cc +++ b/webkit/glue/plugins/webview_plugin.cc @@ -4,6 +4,7 @@ #include "webkit/glue/plugins/webview_plugin.h" +#include "base/histogram.h" #include "base/message_loop.h" #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" @@ -12,6 +13,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" #include "third_party/WebKit/WebKit/chromium/public/WebURL.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" #if WEBKIT_USING_CG @@ -27,18 +29,21 @@ using WebKit::WebDragOperationsMask; using WebKit::WebFrame; using WebKit::WebImage; using WebKit::WebInputEvent; +using WebKit::WebPlugin; using WebKit::WebPluginContainer; using WebKit::WebPoint; using WebKit::WebRect; using WebKit::WebSize; using WebKit::WebURLError; using WebKit::WebURLRequest; +using WebKit::WebURLResponse; using WebKit::WebVector; using WebKit::WebView; WebViewPlugin::WebViewPlugin(WebViewPlugin::Delegate* delegate) : delegate_(delegate), - container_(NULL) { + container_(NULL), + finished_loading_(false) { web_view_ = WebView::create(this, NULL); web_view_->initializeMainFrame(this); } @@ -47,6 +52,26 @@ WebViewPlugin::~WebViewPlugin() { web_view_->close(); } +void WebViewPlugin::ReplayReceivedData(WebPlugin* plugin) { + if (!response_.isNull()) { + plugin->didReceiveResponse(response_); + size_t total_bytes = 0; + for (std::list<std::string>::iterator it = data_.begin(); + it != data_.end(); ++it) { + plugin->didReceiveData(it->c_str(), it->length()); + total_bytes += it->length(); + } + UMA_HISTOGRAM_MEMORY_KB("PluginDocument.Memory", (total_bytes / 1024)); + UMA_HISTOGRAM_COUNTS("PluginDocument.NumChunks", data_.size()); + } + if (finished_loading_) { + plugin->didFinishLoading(); + } + if (error_.get()) { + plugin->didFailLoading(*error_); + } +} + bool WebViewPlugin::initialize(WebPluginContainer* container) { container_ = container; return true; @@ -55,6 +80,7 @@ bool WebViewPlugin::initialize(WebPluginContainer* container) { void WebViewPlugin::destroy() { delegate_->WillDestroyPlugin(); delegate_ = NULL; + container_ = NULL; MessageLoop::current()->DeleteSoon(FROM_HERE, this); } @@ -104,6 +130,25 @@ bool WebViewPlugin::handleInputEvent(const WebInputEvent& event, return handled; } +void WebViewPlugin::didReceiveResponse(const WebURLResponse& response) { + DCHECK(response_.isNull()); + response_ = response; +} + +void WebViewPlugin::didReceiveData(const char* data, int data_length) { + data_.push_back(std::string(data, data_length)); +} + +void WebViewPlugin::didFinishLoading() { + DCHECK(!finished_loading_); + finished_loading_ = true; +} + +void WebViewPlugin::didFailLoading(const WebURLError& error) { + DCHECK(!error_.get()); + error_.reset(new WebURLError(error)); +} + void WebViewPlugin::startDragging(const WebDragData&, WebDragOperationsMask, const WebImage&, @@ -114,7 +159,7 @@ void WebViewPlugin::startDragging(const WebDragData&, void WebViewPlugin::didInvalidateRect(const WebRect& rect) { if (container_) - container_->invalidateRect(WebRect(rect)); + container_->invalidateRect(rect); } void WebViewPlugin::didChangeCursor(const WebCursorInfo& cursor) { @@ -122,7 +167,8 @@ void WebViewPlugin::didChangeCursor(const WebCursorInfo& cursor) { } void WebViewPlugin::didClearWindowObject(WebFrame* frame) { - delegate_->BindWebFrame(frame); + if (delegate_) + delegate_->BindWebFrame(frame); } bool WebViewPlugin::canHandleRequest(WebFrame* frame, diff --git a/webkit/glue/plugins/webview_plugin.h b/webkit/glue/plugins/webview_plugin.h index 2e41218..757a012 100644 --- a/webkit/glue/plugins/webview_plugin.h +++ b/webkit/glue/plugins/webview_plugin.h @@ -5,11 +5,14 @@ #ifndef WEBKIT_GLUE_PLUGINS_WEBVIEW_PLUGIN_H_ #define WEBKIT_GLUE_PLUGINS_WEBVIEW_PLUGIN_H_ +#include <list> + #include "base/scoped_ptr.h" #include "base/task.h" #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" -#include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrameClient.h" +#include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" #include "third_party/WebKit/WebKit/chromium/public/WebViewClient.h" // This class implements the WebPlugin interface by forwarding drawing and @@ -36,9 +39,14 @@ class WebViewPlugin: public WebKit::WebPlugin, public WebKit::WebViewClient, explicit WebViewPlugin(Delegate* delegate); - virtual WebKit::WebView* web_view() { return web_view_; } + WebKit::WebView* web_view() { return web_view_; } - virtual WebKit::WebPluginContainer* container() { return container_; } + WebKit::WebPluginContainer* container() { return container_; } + + // When loading a plug-in document (i.e. a full page plug-in not embedded in + // another page), we save all data that has been received, and replay it with + // this method on the actual plug-in. + void ReplayReceivedData(WebKit::WebPlugin* plugin); // WebPlugin methods: virtual bool initialize(WebKit::WebPluginContainer*); @@ -60,10 +68,10 @@ class WebViewPlugin: public WebKit::WebPlugin, public WebKit::WebViewClient, 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& error) { } + 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& error); // Called in response to WebPluginContainer::loadFrameRequest virtual void didFinishLoadingFrameRequest( @@ -102,6 +110,11 @@ class WebViewPlugin: public WebKit::WebPlugin, public WebKit::WebViewClient, WebKit::WebPluginContainer* container_; WebKit::WebView* web_view_; gfx::Rect rect_; + + WebKit::WebURLResponse response_; + std::list<std::string> data_; + bool finished_loading_; + scoped_ptr<WebKit::WebURLError> error_; }; #endif // WEBKIT_GLUE_PLUGINS_WEBVIEW_PLUGIN_H_ |