Commit a0233591 authored by marshall@chromium.org's avatar marshall@chromium.org

Windowless Flash plugins on Mac do not currently draw in single-process...

Windowless Flash plugins on Mac do not currently draw in single-process applications using the Chromium WebKit API because the current design assumes a multi-process implementation and requires a buffer context. Add a new flag to indicate no buffer context will be used and change WebPluginDelegateImpl::WindowlessPaint() to paint directly to the window context when this flag is set. Also change test_shell to force Flash plugins to run in windowless mode by setting the wmode="opaque" attribute.

BUG=94395
TEST=load Flash plugin in test_shell

Review URL: http://codereview.chromium.org/7746009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98571 0039d316-1c4b-4281-b951-d872f2087c98
parent 666900e1
......@@ -176,6 +176,10 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Informs the delegate that the plugin set a Cocoa NSCursor.
void SetNSCursor(NSCursor* cursor);
// Indicates that the windowless plugins will draw directly to the window
// context instead of a buffer context.
void SetNoBufferContext();
#ifndef NP_NO_CARBON
// Indicates that it's time to send the plugin a null event.
void FireIdleEvent();
......@@ -428,6 +432,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
void UpdateIdleEventRate();
#endif // !NP_NO_CARBON
bool use_buffer_context_;
CGContextRef buffer_context_; // Weak ref.
#ifndef NP_NO_CARBON
......
......@@ -262,6 +262,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
instance_(instance),
parent_(containing_view),
quirks_(0),
use_buffer_context_(true),
buffer_context_(NULL),
layer_(nil),
surface_(NULL),
......@@ -692,18 +693,24 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
const gfx::Rect& damage_rect) {
// If we get a paint event before we are completely set up (e.g., a nested
// call while the plugin is still in NPP_SetWindow), bail.
if (!have_called_set_window_ || !buffer_context_)
if (!have_called_set_window_ || (use_buffer_context_ && !buffer_context_))
return;
DCHECK(buffer_context_ == context);
DCHECK(!use_buffer_context_ || buffer_context_ == context);
static base::StatsRate plugin_paint("Plugin.Paint");
base::StatsScope<base::StatsRate> scope(plugin_paint);
// Plugin invalidates trigger asynchronous paints with the original
// invalidation rect; the plugin may be resized before the paint is handled,
// so we need to ensure that the damage rect is still sane.
const gfx::Rect paint_rect(damage_rect.Intersect(
gfx::Rect(0, 0, window_rect_.width(), window_rect_.height())));
gfx::Rect paint_rect;
if (use_buffer_context_) {
// Plugin invalidates trigger asynchronous paints with the original
// invalidation rect; the plugin may be resized before the paint is handled,
// so we need to ensure that the damage rect is still sane.
paint_rect = damage_rect.Intersect(
gfx::Rect(0, 0, window_rect_.width(), window_rect_.height()));
} else {
// Use the actual window region when drawing directly to the window context.
paint_rect = damage_rect.Intersect(window_rect_);
}
ScopedActiveDelegate active_delegate(this);
......@@ -714,6 +721,13 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
CGContextSaveGState(context);
if (!use_buffer_context_) {
// Reposition the context origin so that plugins will draw at the correct
// location in the window.
CGContextClipToRect(context, paint_rect.ToCGRect());
CGContextTranslateCTM(context, window_rect_.x(), window_rect_.y());
}
switch (instance()->event_model()) {
#ifndef NP_NO_CARBON
case NPEventModelCarbon: {
......@@ -739,10 +753,15 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
}
}
// The backing buffer can change during the call to NPP_HandleEvent, in which
// case the old context is (or is about to be) invalid.
if (context == buffer_context_)
if (use_buffer_context_) {
// The backing buffer can change during the call to NPP_HandleEvent, in
// which case the old context is (or is about to be) invalid.
if (context == buffer_context_)
CGContextRestoreGState(context);
} else {
// Always restore the context to the saved state.
CGContextRestoreGState(context);
}
}
void WebPluginDelegateImpl::WindowlessSetWindow() {
......@@ -1115,6 +1134,10 @@ void WebPluginDelegateImpl::UpdateIdleEventRate() {
plugin_visible);
}
void WebPluginDelegateImpl::SetNoBufferContext() {
use_buffer_context_ = false;
}
void WebPluginDelegateImpl::FireIdleEvent() {
// Avoid a race condition between IO and UI threads during plugin shutdown
if (!instance())
......
// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 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.
......@@ -16,6 +16,7 @@
#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
#include "webkit/tools/test_shell/test_shell.h"
using webkit::npapi::WebPluginDelegateImpl;
using WebKit::WebCursorInfo;
using WebKit::WebNavigationPolicy;
using WebKit::WebPopupMenu;
......@@ -176,8 +177,11 @@ webkit::npapi::WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
return NULL;
gfx::PluginWindowHandle containing_view = NULL;
return webkit::npapi::WebPluginDelegateImpl::Create(
path, mime_type, containing_view);
WebPluginDelegateImpl* delegate =
WebPluginDelegateImpl::Create(path, mime_type, containing_view);
if (delegate)
delegate->SetNoBufferContext();
return delegate;
}
void TestWebViewDelegate::CreatedPluginWindow(
......
......@@ -53,6 +53,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
#include "ui/gfx/native_widget_types.h"
......@@ -127,6 +128,7 @@ using WebKit::WebWidget;
using WebKit::WebWindowFeatures;
using WebKit::WebWorker;
using WebKit::WebWorkerClient;
using WebKit::WebVector;
using WebKit::WebView;
namespace {
......@@ -601,6 +603,37 @@ WebPlugin* TestWebViewDelegate::createPlugin(WebFrame* frame,
if (plugins.empty())
return NULL;
#if defined(OS_MACOSX)
if (!shell_->layout_test_mode()) {
bool flash = LowerCaseEqualsASCII(params.mimeType.utf8(),
"application/x-shockwave-flash");
if (flash) {
// Mac does not support windowed plugins. Force Flash plugins to use
// windowless mode by setting the wmode="opaque" attribute.
DCHECK(params.attributeNames.size() == params.attributeValues.size());
size_t size = params.attributeNames.size();
WebVector<WebString> new_names(size+1), new_values(size+1);
for (size_t i = 0; i < size; ++i) {
new_names[i] = params.attributeNames[i];
new_values[i] = params.attributeValues[i];
}
new_names[size] = "wmode";
new_values[size] = "opaque";
WebPluginParams new_params = params;
new_params.attributeNames.swap(new_names);
new_params.attributeValues.swap(new_values);
return new webkit::npapi::WebPluginImpl(
frame, new_params, plugins.front().path, mime_types.front(),
AsWeakPtr());
}
}
#endif // defined (OS_MACOSX)
return new webkit::npapi::WebPluginImpl(
frame, params, plugins.front().path, mime_types.front(), AsWeakPtr());
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment