summaryrefslogtreecommitdiffstats
path: root/chrome/plugin
diff options
context:
space:
mode:
authoramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-11 01:57:28 +0000
committeramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-11 01:57:28 +0000
commit6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef (patch)
tree7bedf19228a20b83189ab96e617e72210991c7c4 /chrome/plugin
parent7e05f6c4baad4f81e06835b83febe2784568ebe1 (diff)
downloadchromium_src-6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef.zip
chromium_src-6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef.tar.gz
chromium_src-6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef.tar.bz2
Wire up windowless plugins. Mostly Mac related, some cross
platform aspects. BUG=10809 TEST=none Review URL: http://codereview.chromium.org/113637 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20453 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/plugin')
-rw-r--r--chrome/plugin/plugin_main.cc63
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc6
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h4
-rw-r--r--chrome/plugin/webplugin_proxy.cc95
-rw-r--r--chrome/plugin/webplugin_proxy.h20
5 files changed, 159 insertions, 29 deletions
diff --git a/chrome/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc
index fb8880f..4cc7911 100644
--- a/chrome/plugin/plugin_main.cc
+++ b/chrome/plugin/plugin_main.cc
@@ -27,6 +27,47 @@
#include "base/global_descriptors_posix.h"
#endif
+#if defined(OS_MACOSX)
+
+// To support Mac NPAPI plugins that use the Carbon event model (i.e., most
+// shipping plugins for MacOS X 10.5 and earlier), we need some way for the
+// Carbon event dispatcher to run, even though the plugin host process itself
+// does not use Carbon events. Rather than give control to the standard
+// Carbon event loop, we schedule a periodic task on the main thread which
+// empties the Carbon event queue every 20ms (chosen to match how often Safari
+// does the equivalent operation). This allows plugins to receive idle events
+// and schedule Carbon timers without swamping the CPU. If, in the future,
+// we remove support for the Carbon event model and only support the Cocoa
+// event model, this can be removed. Note that this approach does not install
+// standard application event handlers for the menubar, AppleEvents, and so on.
+// This is intentional, since the plugin process is not actually an application
+// with its own UI elements--all rendering and event handling happens via IPC
+// to the renderer process which invoked it.
+
+namespace {
+
+const int kPluginUpdateIntervalMs = 20; // 20ms = 50Hz
+
+void PluginCarbonEventTask() {
+ EventRef theEvent;
+ EventTargetRef theTarget;
+
+ theTarget = GetEventDispatcherTarget();
+
+ // Dispatch any pending events. but do not block if there are no events.
+ while (ReceiveNextEvent(0, NULL, kEventDurationNoWait,
+ true, &theEvent) == noErr) {
+ SendEventToEventTarget (theEvent, theTarget);
+ ReleaseEvent(theEvent);
+ }
+
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ NewRunnableFunction(PluginCarbonEventTask), kPluginUpdateIntervalMs);
+}
+
+}
+#endif
+
// main() routine for running as the plugin process.
int PluginMain(const MainFunctionParams& parameters) {
// The main thread of the plugin services IO.
@@ -37,9 +78,9 @@ int PluginMain(const MainFunctionParams& parameters) {
// Initialize the SystemMonitor
base::SystemMonitor::Start();
-#if defined(OS_WIN)
const CommandLine& parsed_command_line = parameters.command_line_;
+#if defined(OS_WIN)
sandbox::TargetServices* target_services =
parameters.sandbox_info_.TargetServices();
@@ -59,16 +100,32 @@ int PluginMain(const MainFunctionParams& parameters) {
DCHECK(sandbox_test_module);
}
}
-
+#endif
if (parsed_command_line.HasSwitch(switches::kPluginStartupDialog)) {
+#if defined(OS_WIN)
std::wstring title = chrome::kBrowserAppName;
title += L" plugin"; // makes attaching to process easier
win_util::MessageBox(NULL, L"plugin starting...", title,
MB_OK | MB_SETFOREGROUND);
- }
+#elif defined(OS_MACOSX)
+ // TODO(playmobil): In the long term, overriding this flag doesn't seem
+ // right, either use our own flag or open a dialog we can use.
+ // This is just to ease debugging in the interim.
+ LOG(WARNING) << "Plugin ("
+ << getpid()
+ << ") paused waiting for debugger to attach @ pid";
+ pause();
#else
NOTIMPLEMENTED() << " non-windows startup, plugin startup dialog etc.";
#endif
+ }
+
+#if defined(OS_MACOSX)
+ // Spin off a consumer for the native (Carbon) event stream so
+ // that plugin timers, event handlers, etc. will work properly.
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ NewRunnableFunction(PluginCarbonEventTask), kPluginUpdateIntervalMs);
+#endif
{
ChildProcess plugin_process(new PluginThread());
diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc
index 542f0a3..a8a42b0 100644
--- a/chrome/plugin/webplugin_delegate_stub.cc
+++ b/chrome/plugin/webplugin_delegate_stub.cc
@@ -272,11 +272,11 @@ void WebPluginDelegateStub::OnPrint(base::SharedMemoryHandle* shared_memory,
void WebPluginDelegateStub::OnUpdateGeometry(
const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
- const TransportDIB::Id& windowless_buffer_id,
- const TransportDIB::Id& background_buffer_id) {
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer) {
webplugin_->UpdateGeometry(
window_rect, clip_rect,
- windowless_buffer_id, background_buffer_id);
+ windowless_buffer, background_buffer);
}
void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id,
diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h
index 10ac7a4..15b88a8 100644
--- a/chrome/plugin/webplugin_delegate_stub.h
+++ b/chrome/plugin/webplugin_delegate_stub.h
@@ -71,8 +71,8 @@ class WebPluginDelegateStub : public IPC::Channel::Listener,
void OnUpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
- const TransportDIB::Id& windowless_buffer,
- const TransportDIB::Id& background_buffer);
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer);
void OnGetPluginScriptableObject(int* route_id, intptr_t* npobject_ptr);
void OnSendJavaScriptStream(const std::string& url,
const std::wstring& result,
diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc
index b2fe778..94f2b2f 100644
--- a/chrome/plugin/webplugin_proxy.cc
+++ b/chrome/plugin/webplugin_proxy.cc
@@ -369,11 +369,16 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) {
#if defined(OS_WIN)
if (!windowless_hdc_)
return;
+#elif defined(OS_MACOSX)
+ if (!windowless_context_.get())
+ return;
+#endif
// Clear the damaged area so that if the plugin doesn't paint there we won't
// end up with the old values.
gfx::Rect offset_rect = rect;
offset_rect.Offset(delegate_->GetRect().origin());
+#if defined(OS_WIN)
if (!background_hdc_) {
FillRect(windowless_hdc_, &offset_rect.ToRECT(),
static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
@@ -393,6 +398,22 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) {
SelectClipRgn(windowless_hdc_, NULL);
DeleteObject(clip_region);
+#elif defined(OS_MACOSX)
+ CGContextSaveGState(windowless_context_);
+ if (!background_context_.get()) {
+ CGContextSetFillColorWithColor(windowless_context_,
+ CGColorGetConstantColor(kCGColorWhite));
+ CGContextFillRect(windowless_context_, rect.ToCGRect());
+ } else {
+ scoped_cftyperef<CGImageRef> image(
+ CGBitmapContextCreateImage(background_context_));
+ scoped_cftyperef<CGImageRef> sub_image(
+ CGImageCreateWithImageInRect(image, rect.ToCGRect()));
+ CGContextDrawImage(background_context_, rect.ToCGRect(), sub_image);
+ }
+ CGContextClipToRect(windowless_context_, rect.ToCGRect());
+ delegate_->Paint(windowless_context_, rect);
+ CGContextRestoreGState(windowless_context_);
#else
// TODO(port): windowless painting.
NOTIMPLEMENTED();
@@ -402,22 +423,21 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) {
void WebPluginProxy::UpdateGeometry(
const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
- const TransportDIB::Id& windowless_buffer_id,
- const TransportDIB::Id& background_buffer_id) {
- // TODO(port): this isn't correct usage of a TransportDIB; for now,
- // the caller temporarly just stuffs the handle into the HANDLE
- // field of the TransportDIB::Id so it should behave like the older
- // code.
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer) {
gfx::Rect old = delegate_->GetRect();
gfx::Rect old_clip_rect = delegate_->GetClipRect();
delegate_->UpdateGeometry(window_rect, clip_rect);
-#if defined(OS_WIN)
bool moved = old.x() != window_rect.x() || old.y() != window_rect.y();
- if (windowless_buffer_id.handle) {
+#if defined(OS_MACOSX)
+ if (windowless_buffer.fd > 0) {
+#else
+ if (windowless_buffer) {
+#endif
// The plugin's rect changed, so now we have a new buffer to draw into.
- SetWindowlessBuffer(windowless_buffer_id.handle,
- background_buffer_id.handle);
+ SetWindowlessBuffer(windowless_buffer,
+ background_buffer);
} else if (moved) {
// The plugin moved, so update our world transform.
UpdateTransform();
@@ -428,15 +448,12 @@ void WebPluginProxy::UpdateGeometry(
old_clip_rect.IsEmpty() && !damaged_rect_.IsEmpty()) {
InvalidateRect(damaged_rect_);
}
-#else
- NOTIMPLEMENTED();
-#endif
}
#if defined(OS_WIN)
void WebPluginProxy::SetWindowlessBuffer(
- const base::SharedMemoryHandle& windowless_buffer,
- const base::SharedMemoryHandle& background_buffer) {
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer) {
// Convert the shared memory handle to a handle that works in our process,
// and then use that to create an HDC.
ConvertBuffer(windowless_buffer,
@@ -501,6 +518,54 @@ void WebPluginProxy::UpdateTransform() {
xf.eM22 = 1;
SetWorldTransform(windowless_hdc_, &xf);
}
+#elif defined(OS_MACOSX)
+void WebPluginProxy::UpdateTransform() {
+ NOTIMPLEMENTED();
+}
+
+void WebPluginProxy::SetWindowlessBuffer(
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer) {
+ // Convert the shared memory handle to a handle that works in our process,
+ // and then use that to create a CGContextRef.
+ windowless_dib_.reset(TransportDIB::Map(windowless_buffer));
+ background_dib_.reset(TransportDIB::Map(background_buffer));
+ scoped_cftyperef<CGColorSpaceRef> rgb_colorspace(
+ CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
+ windowless_context_.reset(CGBitmapContextCreate(
+ windowless_dib_->memory(),
+ delegate_->GetRect().width(),
+ delegate_->GetRect().height(),
+ 8, 4 * delegate_->GetRect().width(),
+ rgb_colorspace,
+ kCGImageAlphaPremultipliedFirst |
+ kCGBitmapByteOrder32Host));
+ CGContextTranslateCTM(windowless_context_, 0, delegate_->GetRect().height());
+ CGContextScaleCTM(windowless_context_, 1, -1);
+ if (background_dib_.get()) {
+ background_context_.reset(CGBitmapContextCreate(
+ background_dib_->memory(),
+ delegate_->GetRect().width(),
+ delegate_->GetRect().height(),
+ 8, 4 * delegate_->GetRect().width(),
+ rgb_colorspace,
+ kCGImageAlphaPremultipliedFirst |
+ kCGBitmapByteOrder32Host));
+ CGContextTranslateCTM(background_context_, 0,
+ delegate_->GetRect().height());
+ CGContextScaleCTM(background_context_, 1, -1);
+ }
+}
+#elif defined (OS_LINUX)
+void WebPluginProxy::UpdateTransform() {
+ NOTIMPLEMENTED();
+}
+
+void WebPluginProxy::SetWindowlessBuffer(
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer) {
+ NOTIMPLEMENTED();
+}
#endif
void WebPluginProxy::CancelDocumentLoad() {
diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h
index 103be5c..a55a3da2 100644
--- a/chrome/plugin/webplugin_proxy.h
+++ b/chrome/plugin/webplugin_proxy.h
@@ -9,6 +9,9 @@
#include "base/hash_tables.h"
#include "base/ref_counted.h"
+#if defined(OS_MACOSX)
+#include "base/scoped_cftyperef.h"
+#endif
#include "base/scoped_handle.h"
#include "base/scoped_ptr.h"
#include "base/shared_memory.h"
@@ -104,8 +107,8 @@ class WebPluginProxy : public WebPlugin {
void UpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
- const TransportDIB::Id& windowless_buffer,
- const TransportDIB::Id& background_buffer);
+ const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer);
void CancelDocumentLoad();
@@ -129,22 +132,22 @@ class WebPluginProxy : public WebPlugin {
// Handler for sending over the paint event to the plugin.
void OnPaint(const gfx::Rect& damaged_rect);
-#if defined(OS_WIN)
// Updates the shared memory section where windowless plugins paint.
- void SetWindowlessBuffer(const base::SharedMemoryHandle& windowless_buffer,
- const base::SharedMemoryHandle& background_buffer);
+ void SetWindowlessBuffer(const TransportDIB::Handle& windowless_buffer,
+ const TransportDIB::Handle& background_buffer);
+#if defined(OS_WIN)
// Converts a shared memory section handle from the renderer process into a
// bitmap and hdc that are mapped to this process.
void ConvertBuffer(const base::SharedMemoryHandle& buffer,
ScopedHandle* shared_section,
ScopedBitmap* bitmap,
ScopedHDC* hdc);
+#endif
// Called when a plugin's origin moves, so that we can update the world
// transform of the local HDC.
void UpdateTransform();
-#endif
typedef base::hash_map<int, WebPluginResourceClient*> ResourceClientMap;
ResourceClientMap resource_clients_;
@@ -174,6 +177,11 @@ class WebPluginProxy : public WebPlugin {
ScopedHandle background_shared_section_;
ScopedBitmap background_bitmap_;
ScopedHDC background_hdc_;
+#elif defined(OS_MACOSX)
+ scoped_ptr<TransportDIB> windowless_dib_;
+ scoped_ptr<TransportDIB> background_dib_;
+ scoped_cftyperef<CGContextRef> windowless_context_;
+ scoped_cftyperef<CGContextRef> background_context_;
#endif
ScopedRunnableMethodFactory<WebPluginProxy> runnable_method_factory_;