Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: webkit/glue/plugins/webplugin_delegate_impl_mac.mm

Issue 164100: Set up a interposing library for Carbon calls made by plugins. (Closed)
Patch Set: Review comments and files that were lost in the move Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webkit/glue/plugins/fake_plugin_window_tracker_mac.cc ('k') | webkit/webkit.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import <Cocoa/Cocoa.h> 5 #import <Cocoa/Cocoa.h>
6 6
7 #include "webkit/glue/plugins/webplugin_delegate_impl.h" 7 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
8 8
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/stats_counters.h" 15 #include "base/stats_counters.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "webkit/api/public/WebInputEvent.h" 17 #include "webkit/api/public/WebInputEvent.h"
18 #include "webkit/default_plugin/plugin_impl.h" 18 #include "webkit/default_plugin/plugin_impl.h"
19 #include "webkit/glue/glue_util.h" 19 #include "webkit/glue/glue_util.h"
20 #include "webkit/glue/webplugin.h" 20 #include "webkit/glue/webplugin.h"
21 #include "webkit/glue/plugins/fake_plugin_window_tracker_mac.h"
21 #include "webkit/glue/plugins/plugin_constants_win.h" 22 #include "webkit/glue/plugins/plugin_constants_win.h"
22 #include "webkit/glue/plugins/plugin_instance.h" 23 #include "webkit/glue/plugins/plugin_instance.h"
23 #include "webkit/glue/plugins/plugin_lib.h" 24 #include "webkit/glue/plugins/plugin_lib.h"
24 #include "webkit/glue/plugins/plugin_list.h" 25 #include "webkit/glue/plugins/plugin_list.h"
25 #include "webkit/glue/plugins/plugin_stream_url.h" 26 #include "webkit/glue/plugins/plugin_stream_url.h"
26 #include "webkit/glue/webkit_glue.h" 27 #include "webkit/glue/webkit_glue.h"
27 28
28 using WebKit::WebCursorInfo; 29 using WebKit::WebCursorInfo;
29 using WebKit::WebKeyboardEvent; 30 using WebKit::WebKeyboardEvent;
30 using WebKit::WebInputEvent; 31 using WebKit::WebInputEvent;
(...skipping 20 matching lines...) Expand all
51 // this to keep the placeholder Carbon WindowRef's origin in sync with the 52 // this to keep the placeholder Carbon WindowRef's origin in sync with the
52 // actual browser window, without having to pass that geometry over IPC. If we 53 // actual browser window, without having to pass that geometry over IPC. If we
53 // end up needing to interpose on Carbon APIs in the plugin process (in order 54 // end up needing to interpose on Carbon APIs in the plugin process (in order
54 // to simulate window activation, for example), this could be replaced by 55 // to simulate window activation, for example), this could be replaced by
55 // interposing on GlobalToLocal and/or LocalToGlobal (see related TODO comments 56 // interposing on GlobalToLocal and/or LocalToGlobal (see related TODO comments
56 // below in WebPluginDelegateImpl::OnNullEvent()). 57 // below in WebPluginDelegateImpl::OnNullEvent()).
57 58
58 int g_current_x_offset = 0; 59 int g_current_x_offset = 0;
59 int g_current_y_offset = 0; 60 int g_current_y_offset = 0;
60 61
61 WindowRef g_last_front_window = NULL;
62 ProcessSerialNumber g_saved_front_process;
63
64 } // namespace 62 } // namespace
65 63
66 WebPluginDelegate* WebPluginDelegate::Create( 64 WebPluginDelegate* WebPluginDelegate::Create(
67 const FilePath& filename, 65 const FilePath& filename,
68 const std::string& mime_type, 66 const std::string& mime_type,
69 gfx::PluginWindowHandle containing_view) { 67 gfx::PluginWindowHandle containing_view) {
70 scoped_refptr<NPAPI::PluginLib> plugin = 68 scoped_refptr<NPAPI::PluginLib> plugin =
71 NPAPI::PluginLib::CreatePluginLib(filename); 69 NPAPI::PluginLib::CreatePluginLib(filename);
72 if (plugin.get() == NULL) 70 if (plugin.get() == NULL)
73 return NULL; 71 return NULL;
(...skipping 20 matching lines...) Expand all
94 handle_event_depth_(0), 92 handle_event_depth_(0),
95 user_gesture_message_posted_(this), 93 user_gesture_message_posted_(this),
96 user_gesture_msg_factory_(this), 94 user_gesture_msg_factory_(this),
97 null_event_factory_(this), 95 null_event_factory_(this),
98 last_mouse_x_(0), 96 last_mouse_x_(0),
99 last_mouse_y_(0) { 97 last_mouse_y_(0) {
100 memset(&window_, 0, sizeof(window_)); 98 memset(&window_, 0, sizeof(window_));
101 } 99 }
102 100
103 WebPluginDelegateImpl::~WebPluginDelegateImpl() { 101 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
102 FakePluginWindowTracker::SharedInstance()->RemoveFakeWindowForDelegate(
103 this, cg_context_.window);
104 DestroyInstance(); 104 DestroyInstance();
105
106 if (cg_context_.window)
107 DisposeWindow(cg_context_.window);
108 } 105 }
109 106
110 void WebPluginDelegateImpl::PluginDestroyed() { 107 void WebPluginDelegateImpl::PluginDestroyed() {
111 delete this; 108 delete this;
112 } 109 }
113 110
114 bool WebPluginDelegateImpl::Initialize(const GURL& url, 111 bool WebPluginDelegateImpl::Initialize(const GURL& url,
115 char** argn, 112 char** argn,
116 char** argv, 113 char** argv,
117 int argc, 114 int argc,
118 WebPlugin* plugin, 115 WebPlugin* plugin,
119 bool load_manually) { 116 bool load_manually) {
120 plugin_ = plugin; 117 plugin_ = plugin;
121 118
122 instance_->set_web_plugin(plugin); 119 instance_->set_web_plugin(plugin);
123 NPAPI::PluginInstance* old_instance = 120 NPAPI::PluginInstance* old_instance =
124 NPAPI::PluginInstance::SetInitializingInstance(instance_); 121 NPAPI::PluginInstance::SetInitializingInstance(instance_);
125 122
126 123
127 bool start_result = instance_->Start(url, argn, argv, argc, load_manually); 124 bool start_result = instance_->Start(url, argn, argv, argc, load_manually);
128 125
129 NPAPI::PluginInstance::SetInitializingInstance(old_instance); 126 NPAPI::PluginInstance::SetInitializingInstance(old_instance);
130 127
131 if (!start_result) 128 if (!start_result)
132 return false; 129 return false;
133 130
134 cg_context_.window = NULL; 131 FakePluginWindowTracker* window_tracker =
132 FakePluginWindowTracker::SharedInstance();
133 cg_context_.window = window_tracker->GenerateFakeWindowForDelegate(this);
134 Rect window_bounds = { 0, 0, window_rect_.height(), window_rect_.width() };
135 SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
135 window_.window = &cg_context_; 136 window_.window = &cg_context_;
136 window_.type = NPWindowTypeWindow; 137 window_.type = NPWindowTypeWindow;
137 138
138 plugin->SetWindow(NULL); 139 plugin->SetWindow(NULL);
139 plugin_url_ = url.spec(); 140 plugin_url_ = url.spec();
140 141
141 MessageLoop::current()->PostDelayedTask(FROM_HERE, 142 MessageLoop::current()->PostDelayedTask(FROM_HERE,
142 null_event_factory_.NewRunnableMethod( 143 null_event_factory_.NewRunnableMethod(
143 &WebPluginDelegateImpl::OnNullEvent), 144 &WebPluginDelegateImpl::OnNullEvent),
144 kPluginIdleThrottleDelayMs); 145 kPluginIdleThrottleDelayMs);
145 return true; 146 return true;
146 } 147 }
147 148
148 void WebPluginDelegateImpl::DestroyInstance() { 149 void WebPluginDelegateImpl::DestroyInstance() {
149 if (instance_ && (instance_->npp()->ndata != NULL)) { 150 if (instance_ && (instance_->npp()->ndata != NULL)) {
150 // Shutdown all streams before destroying so that 151 // Shutdown all streams before destroying so that
151 // no streams are left "in progress". Need to do 152 // no streams are left "in progress". Need to do
152 // this before calling set_web_plugin(NULL) because the 153 // this before calling set_web_plugin(NULL) because the
153 // instance uses the helper to do the download. 154 // instance uses the helper to do the download.
154 instance_->CloseStreams(); 155 instance_->CloseStreams();
155 instance_->NPP_Destroy(); 156 instance_->NPP_Destroy();
156 instance_->set_web_plugin(NULL); 157 instance_->set_web_plugin(NULL);
157 instance_ = 0; 158 instance_ = 0;
158 } 159 }
159 } 160 }
160 161
161 void WebPluginDelegateImpl::UpdateGeometry( 162 void WebPluginDelegateImpl::UpdateGeometry(
162 const gfx::Rect& window_rect, 163 const gfx::Rect& window_rect,
163 const gfx::Rect& clip_rect) { 164 const gfx::Rect& clip_rect) {
164
165 DCHECK(windowless_); 165 DCHECK(windowless_);
166 WindowlessUpdateGeometry(window_rect, clip_rect); 166 WindowlessUpdateGeometry(window_rect, clip_rect);
167 } 167 }
168 168
169 void WebPluginDelegateImpl::Paint(CGContextRef context, const gfx::Rect& rect) { 169 void WebPluginDelegateImpl::Paint(CGContextRef context, const gfx::Rect& rect) {
170 DCHECK(windowless_); 170 DCHECK(windowless_);
171 WindowlessPaint(context, rect); 171 WindowlessPaint(context, rect);
172 } 172 }
173 173
174 void WebPluginDelegateImpl::Print(CGContextRef context) { 174 void WebPluginDelegateImpl::Print(CGContextRef context) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 paint_event.where.v = 0; 277 paint_event.where.v = 0;
278 paint_event.modifiers = 0; 278 paint_event.modifiers = 0;
279 instance()->NPP_HandleEvent(&paint_event); 279 instance()->NPP_HandleEvent(&paint_event);
280 280
281 CGContextRestoreGState(context); 281 CGContextRestoreGState(context);
282 [NSGraphicsContext restoreGraphicsState]; 282 [NSGraphicsContext restoreGraphicsState];
283 } 283 }
284 284
285 // Moves our dummy window to the given offset relative to the last known 285 // Moves our dummy window to the given offset relative to the last known
286 // location of the real renderer window's content view. 286 // location of the real renderer window's content view.
287 static void UpdateDummyWindowLocationWithOffset(WindowRef window, 287 // If new_width or new_height is non-zero, the window size (content region)
288 int x_offset, int y_offset) { 288 // will be updated accordingly; if they are zero, the existing size will be
289 // preserved.
290 static void UpdateDummyWindowBoundsWithOffset(WindowRef window,
291 int x_offset, int y_offset,
292 int new_width, int new_height) {
289 int target_x = g_current_x_offset + x_offset; 293 int target_x = g_current_x_offset + x_offset;
290 int target_y = g_current_y_offset + y_offset; 294 int target_y = g_current_y_offset + y_offset;
291 Rect window_bounds; 295 Rect window_bounds;
292 GetWindowBounds(window, kWindowContentRgn, &window_bounds); 296 GetWindowBounds(window, kWindowContentRgn, &window_bounds);
293 if ((window_bounds.left != target_x) || 297 if ((window_bounds.left != target_x) ||
294 (window_bounds.top != target_y)) { 298 (window_bounds.top != target_y)) {
295 int height = window_bounds.bottom - window_bounds.top; 299 int height = new_height ? new_height
296 int width = window_bounds.right - window_bounds.left; 300 : window_bounds.bottom - window_bounds.top;
301 int width = new_width ? new_width
302 : window_bounds.right - window_bounds.left;
297 window_bounds.left = target_x; 303 window_bounds.left = target_x;
298 window_bounds.top = target_y; 304 window_bounds.top = target_y;
299 window_bounds.right = window_bounds.left + width; 305 window_bounds.right = window_bounds.left + width;
300 window_bounds.bottom = window_bounds.top + height; 306 window_bounds.bottom = window_bounds.top + height;
301 SetWindowBounds(window, kWindowContentRgn, &window_bounds); 307 SetWindowBounds(window, kWindowContentRgn, &window_bounds);
302 } 308 }
303 } 309 }
304 310
305 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { 311 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
306 if (!instance()) 312 if (!instance())
307 return; 313 return;
308 314
309 if (window_rect_.IsEmpty()) // wait for geometry to be set. 315 if (window_rect_.IsEmpty()) // wait for geometry to be set.
310 return; 316 return;
311 317
312 window_.clipRect.top = 0; 318 window_.clipRect.top = 0;
313 window_.clipRect.left = 0; 319 window_.clipRect.left = 0;
314 window_.clipRect.bottom = window_rect_.height(); 320 window_.clipRect.bottom = window_rect_.height();
315 window_.clipRect.right = window_rect_.width(); 321 window_.clipRect.right = window_rect_.width();
316 window_.height = window_rect_.height(); 322 window_.height = window_rect_.height();
317 window_.width = window_rect_.width(); 323 window_.width = window_rect_.width();
318 window_.x = 0; 324 window_.x = 0;
319 window_.y = 0; 325 window_.y = 0;
320 window_.type = NPWindowTypeWindow; 326 window_.type = NPWindowTypeWindow;
321 327
322 if (!force_set_window) 328 if (!force_set_window)
323 // Reset this flag before entering the instance in case of side-effects. 329 // Reset this flag before entering the instance in case of side-effects.
324 windowless_needs_set_window_ = false; 330 windowless_needs_set_window_ = false;
325 331
326 if (!cg_context_.window) { 332 UpdateDummyWindowBoundsWithOffset(cg_context_.window, window_rect_.x(),
327 // For all plugins we create a placeholder offscreen window for the use 333 window_rect_.y(), window_rect_.width(),
328 // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the 334 window_rect_.height());
329 // "browser window", even if we're not using the Quickdraw drawing model.
330 // Not having a valid window reference causes subtle bugs with plugins
331 // which retreive the NPWindow and validate the same. The NPWindow
332 // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
333 Rect window_bounds = { 0, 0, window_rect_.height(), window_rect_.width() };
334 WindowRef window_ref;
335 if (CreateNewWindow(kDocumentWindowClass,
336 kWindowStandardDocumentAttributes,
337 &window_bounds,
338 &window_ref) == noErr) {
339 cg_context_.window = window_ref;
340 SelectWindow(window_ref);
341 g_last_front_window = window_ref;
342 }
343 }
344 UpdateDummyWindowLocationWithOffset(cg_context_.window, window_rect_.x(),
345 window_rect_.y());
346 335
347 if (!force_set_window) 336 if (!force_set_window)
348 windowless_needs_set_window_ = false; 337 windowless_needs_set_window_ = false;
349 NPError err = instance()->NPP_SetWindow(&window_); 338 NPError err = instance()->NPP_SetWindow(&window_);
350 DCHECK(err == NPERR_NO_ERROR); 339 DCHECK(err == NPERR_NO_ERROR);
351 } 340 }
352 341
353 void WebPluginDelegateImpl::SetFocus() { 342 void WebPluginDelegateImpl::SetFocus() {
354 NPEvent focus_event = { 0 }; 343 NPEvent focus_event = { 0 };
355 focus_event.what = NPEventType_GetFocusEvent; 344 focus_event.what = NPEventType_GetFocusEvent;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 return false; 466 return false;
478 } 467 }
479 468
480 static void UpdateWindowLocation(WindowRef window, const WebMouseEvent& event) { 469 static void UpdateWindowLocation(WindowRef window, const WebMouseEvent& event) {
481 // TODO: figure out where the vertical offset of 22 comes from (and if 22 is 470 // TODO: figure out where the vertical offset of 22 comes from (and if 22 is
482 // exactly right) and replace with an appropriate calculation. It feels like 471 // exactly right) and replace with an appropriate calculation. It feels like
483 // window structure or the menu bar, but neither should be involved here. 472 // window structure or the menu bar, but neither should be involved here.
484 g_current_x_offset = event.globalX - event.windowX; 473 g_current_x_offset = event.globalX - event.windowX;
485 g_current_y_offset = event.globalY - event.windowY + 22; 474 g_current_y_offset = event.globalY - event.windowY + 22;
486 475
487 UpdateDummyWindowLocationWithOffset(window, event.windowX - event.x, 476 UpdateDummyWindowBoundsWithOffset(window, event.windowX - event.x,
488 event.windowY - event.y); 477 event.windowY - event.y, 0, 0);
489 } 478 }
490 479
491 bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, 480 bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event,
492 WebCursorInfo* cursor) { 481 WebCursorInfo* cursor) {
493 DCHECK(windowless_) << "events should only be received in windowless mode"; 482 DCHECK(windowless_) << "events should only be received in windowless mode";
494 DCHECK(cursor != NULL); 483 DCHECK(cursor != NULL);
495 484
496 NPEvent np_event = {0}; 485 NPEvent np_event = {0};
497 if (!NPEventFromWebInputEvent(event, &np_event)) { 486 if (!NPEventFromWebInputEvent(event, &np_event)) {
498 return false; 487 return false;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 NPEvent np_event = {0}; 543 NPEvent np_event = {0};
555 np_event.what = nullEvent; 544 np_event.what = nullEvent;
556 np_event.when = TickCount(); 545 np_event.when = TickCount();
557 np_event.modifiers = GetCurrentKeyModifiers(); 546 np_event.modifiers = GetCurrentKeyModifiers();
558 if (!Button()) 547 if (!Button())
559 np_event.modifiers |= btnState; 548 np_event.modifiers |= btnState;
560 np_event.where.h = last_mouse_x_; 549 np_event.where.h = last_mouse_x_;
561 np_event.where.v = last_mouse_y_; 550 np_event.where.v = last_mouse_y_;
562 instance()->NPP_HandleEvent(&np_event); 551 instance()->NPP_HandleEvent(&np_event);
563 552
564 WindowRef front_window = FrontWindow();
565 if (front_window == cg_context_.window) {
566 if (front_window != g_last_front_window) {
567 // If our dummy window is now the front window, but was not previously,
568 // it means that a plugin window has been destroyed. Make sure our fake
569 // browser window is selected.
570 // TODO: Use DYLD_INSERT_LIBRARIES to interpose on Carbon window
571 // APIs within the plugin process. This will allow us to (a) get rid of
572 // the dummy window, and (b) explicitly track the creation and
573 // destruction of windows by the plugin.
574 g_last_front_window = front_window;
575 SelectWindow(cg_context_.window);
576
577 // If the plugin process is still the front process, bring the prior
578 // front process (normally this will be the browser process) back to
579 // the front.
580 // TODO: make this an IPC message so that the browser can properly
581 // reactivate the window.
582 ProcessSerialNumber this_process, front_process;
583 GetCurrentProcess(&this_process);
584 GetFrontProcess(&front_process);
585 Boolean matched = false;
586 SameProcess(&this_process, &front_process, &matched);
587 if (matched)
588 SetFrontProcess(&g_saved_front_process);
589 g_last_front_window = FrontWindow();
590 }
591 } else if (front_window != g_last_front_window) {
592 // The plugin has just created a new window and brought it to the front.
593 // bring the plugin process to the front so that the user can see it (for
594 // example, an alert or file selection dialog).
595 // TODO: make this an IPC to order the plugin process above the browser
596 // process but not necessarily the frontmost.
597 ProcessSerialNumber this_process;
598 GetCurrentProcess(&this_process);
599 GetFrontProcess(&g_saved_front_process);
600 SetFrontProcess(&this_process);
601 g_last_front_window = front_window;
602 SelectWindow(front_window);
603 }
604
605 MessageLoop::current()->PostDelayedTask(FROM_HERE, 553 MessageLoop::current()->PostDelayedTask(FROM_HERE,
606 null_event_factory_.NewRunnableMethod( 554 null_event_factory_.NewRunnableMethod(
607 &WebPluginDelegateImpl::OnNullEvent), 555 &WebPluginDelegateImpl::OnNullEvent),
608 kPluginIdleThrottleDelayMs); 556 kPluginIdleThrottleDelayMs);
609 } 557 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/fake_plugin_window_tracker_mac.cc ('k') | webkit/webkit.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698