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 { ...@@ -176,6 +176,10 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Informs the delegate that the plugin set a Cocoa NSCursor. // Informs the delegate that the plugin set a Cocoa NSCursor.
void SetNSCursor(NSCursor* cursor); 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 #ifndef NP_NO_CARBON
// Indicates that it's time to send the plugin a null event. // Indicates that it's time to send the plugin a null event.
void FireIdleEvent(); void FireIdleEvent();
...@@ -428,6 +432,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { ...@@ -428,6 +432,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
void UpdateIdleEventRate(); void UpdateIdleEventRate();
#endif // !NP_NO_CARBON #endif // !NP_NO_CARBON
bool use_buffer_context_;
CGContextRef buffer_context_; // Weak ref. CGContextRef buffer_context_; // Weak ref.
#ifndef NP_NO_CARBON #ifndef NP_NO_CARBON
......
...@@ -262,6 +262,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( ...@@ -262,6 +262,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
instance_(instance), instance_(instance),
parent_(containing_view), parent_(containing_view),
quirks_(0), quirks_(0),
use_buffer_context_(true),
buffer_context_(NULL), buffer_context_(NULL),
layer_(nil), layer_(nil),
surface_(NULL), surface_(NULL),
...@@ -692,18 +693,24 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context, ...@@ -692,18 +693,24 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
const gfx::Rect& damage_rect) { const gfx::Rect& damage_rect) {
// If we get a paint event before we are completely set up (e.g., a nested // 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. // 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; return;
DCHECK(buffer_context_ == context); DCHECK(!use_buffer_context_ || buffer_context_ == context);
static base::StatsRate plugin_paint("Plugin.Paint"); static base::StatsRate plugin_paint("Plugin.Paint");
base::StatsScope<base::StatsRate> scope(plugin_paint); base::StatsScope<base::StatsRate> scope(plugin_paint);
// Plugin invalidates trigger asynchronous paints with the original gfx::Rect paint_rect;
// invalidation rect; the plugin may be resized before the paint is handled, if (use_buffer_context_) {
// so we need to ensure that the damage rect is still sane. // Plugin invalidates trigger asynchronous paints with the original
const gfx::Rect paint_rect(damage_rect.Intersect( // invalidation rect; the plugin may be resized before the paint is handled,
gfx::Rect(0, 0, window_rect_.width(), window_rect_.height()))); // 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); ScopedActiveDelegate active_delegate(this);
...@@ -714,6 +721,13 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context, ...@@ -714,6 +721,13 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
CGContextSaveGState(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()) { switch (instance()->event_model()) {
#ifndef NP_NO_CARBON #ifndef NP_NO_CARBON
case NPEventModelCarbon: { case NPEventModelCarbon: {
...@@ -739,10 +753,15 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context, ...@@ -739,10 +753,15 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
} }
} }
// The backing buffer can change during the call to NPP_HandleEvent, in which if (use_buffer_context_) {
// case the old context is (or is about to be) invalid. // The backing buffer can change during the call to NPP_HandleEvent, in
if (context == buffer_context_) // 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); CGContextRestoreGState(context);
}
} }
void WebPluginDelegateImpl::WindowlessSetWindow() { void WebPluginDelegateImpl::WindowlessSetWindow() {
...@@ -1115,6 +1134,10 @@ void WebPluginDelegateImpl::UpdateIdleEventRate() { ...@@ -1115,6 +1134,10 @@ void WebPluginDelegateImpl::UpdateIdleEventRate() {
plugin_visible); plugin_visible);
} }
void WebPluginDelegateImpl::SetNoBufferContext() {
use_buffer_context_ = false;
}
void WebPluginDelegateImpl::FireIdleEvent() { void WebPluginDelegateImpl::FireIdleEvent() {
// Avoid a race condition between IO and UI threads during plugin shutdown // Avoid a race condition between IO and UI threads during plugin shutdown
if (!instance()) 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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "webkit/plugins/npapi/webplugin_delegate_impl.h" #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
#include "webkit/tools/test_shell/test_shell.h" #include "webkit/tools/test_shell/test_shell.h"
using webkit::npapi::WebPluginDelegateImpl;
using WebKit::WebCursorInfo; using WebKit::WebCursorInfo;
using WebKit::WebNavigationPolicy; using WebKit::WebNavigationPolicy;
using WebKit::WebPopupMenu; using WebKit::WebPopupMenu;
...@@ -176,8 +177,11 @@ webkit::npapi::WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate( ...@@ -176,8 +177,11 @@ webkit::npapi::WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
return NULL; return NULL;
gfx::PluginWindowHandle containing_view = NULL; gfx::PluginWindowHandle containing_view = NULL;
return webkit::npapi::WebPluginDelegateImpl::Create( WebPluginDelegateImpl* delegate =
path, mime_type, containing_view); WebPluginDelegateImpl::Create(path, mime_type, containing_view);
if (delegate)
delegate->SetNoBufferContext();
return delegate;
} }
void TestWebViewDelegate::CreatedPluginWindow( void TestWebViewDelegate::CreatedPluginWindow(
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h" #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/WebURLRequest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.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/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -127,6 +128,7 @@ using WebKit::WebWidget; ...@@ -127,6 +128,7 @@ using WebKit::WebWidget;
using WebKit::WebWindowFeatures; using WebKit::WebWindowFeatures;
using WebKit::WebWorker; using WebKit::WebWorker;
using WebKit::WebWorkerClient; using WebKit::WebWorkerClient;
using WebKit::WebVector;
using WebKit::WebView; using WebKit::WebView;
namespace { namespace {
...@@ -601,6 +603,37 @@ WebPlugin* TestWebViewDelegate::createPlugin(WebFrame* frame, ...@@ -601,6 +603,37 @@ WebPlugin* TestWebViewDelegate::createPlugin(WebFrame* frame,
if (plugins.empty()) if (plugins.empty())
return NULL; 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( return new webkit::npapi::WebPluginImpl(
frame, params, plugins.front().path, mime_types.front(), AsWeakPtr()); 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