- add sources.
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_plugin_instance_impl.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/memory/linked_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_offset_string_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/time/time.h"
19 #include "cc/layers/texture_layer.h"
20 #include "content/common/content_constants_internal.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/common/page_zoom.h"
23 #include "content/public/renderer/content_renderer_client.h"
24 #include "content/renderer/pepper/common.h"
25 #include "content/renderer/pepper/content_decryptor_delegate.h"
26 #include "content/renderer/pepper/event_conversion.h"
27 #include "content/renderer/pepper/fullscreen_container.h"
28 #include "content/renderer/pepper/gfx_conversion.h"
29 #include "content/renderer/pepper/host_dispatcher_wrapper.h"
30 #include "content/renderer/pepper/host_globals.h"
31 #include "content/renderer/pepper/message_channel.h"
32 #include "content/renderer/pepper/npapi_glue.h"
33 #include "content/renderer/pepper/pepper_browser_connection.h"
34 #include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
35 #include "content/renderer/pepper/pepper_graphics_2d_host.h"
36 #include "content/renderer/pepper/pepper_in_process_router.h"
37 #include "content/renderer/pepper/pepper_platform_context_3d.h"
38 #include "content/renderer/pepper/pepper_url_loader_host.h"
39 #include "content/renderer/pepper/plugin_module.h"
40 #include "content/renderer/pepper/plugin_object.h"
41 #include "content/renderer/pepper/ppb_buffer_impl.h"
42 #include "content/renderer/pepper/ppb_graphics_3d_impl.h"
43 #include "content/renderer/pepper/ppb_image_data_impl.h"
44 #include "content/renderer/pepper/ppp_pdf.h"
45 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
46 #include "content/renderer/pepper/url_request_info_util.h"
47 #include "content/renderer/pepper/url_response_info_util.h"
48 #include "content/renderer/render_thread_impl.h"
49 #include "content/renderer/render_view_impl.h"
50 #include "content/renderer/render_widget_fullscreen_pepper.h"
51 #include "content/renderer/sad_plugin.h"
52 #include "media/base/audio_hardware_config.h"
53 #include "ppapi/c/dev/ppb_find_dev.h"
54 #include "ppapi/c/dev/ppb_zoom_dev.h"
55 #include "ppapi/c/dev/ppp_find_dev.h"
56 #include "ppapi/c/dev/ppp_selection_dev.h"
57 #include "ppapi/c/dev/ppp_text_input_dev.h"
58 #include "ppapi/c/dev/ppp_zoom_dev.h"
59 #include "ppapi/c/pp_rect.h"
60 #include "ppapi/c/ppb_audio_config.h"
61 #include "ppapi/c/ppb_core.h"
62 #include "ppapi/c/ppb_gamepad.h"
63 #include "ppapi/c/ppp_input_event.h"
64 #include "ppapi/c/ppp_instance.h"
65 #include "ppapi/c/ppp_messaging.h"
66 #include "ppapi/c/ppp_mouse_lock.h"
67 #include "ppapi/c/private/ppp_instance_private.h"
68 #include "ppapi/host/ppapi_host.h"
69 #include "ppapi/proxy/ppapi_messages.h"
70 #include "ppapi/proxy/url_loader_resource.h"
71 #include "ppapi/shared_impl/ppapi_permissions.h"
72 #include "ppapi/shared_impl/ppapi_preferences.h"
73 #include "ppapi/shared_impl/ppb_gamepad_shared.h"
74 #include "ppapi/shared_impl/ppb_input_event_shared.h"
75 #include "ppapi/shared_impl/ppb_url_util_shared.h"
76 #include "ppapi/shared_impl/ppb_view_shared.h"
77 #include "ppapi/shared_impl/ppp_instance_combined.h"
78 #include "ppapi/shared_impl/resource.h"
79 #include "ppapi/shared_impl/scoped_pp_resource.h"
80 #include "ppapi/shared_impl/time_conversion.h"
81 #include "ppapi/shared_impl/url_request_info_data.h"
82 #include "ppapi/shared_impl/var.h"
83 #include "ppapi/thunk/enter.h"
84 #include "ppapi/thunk/ppb_buffer_api.h"
85 #include "printing/metafile.h"
86 #include "printing/metafile_skia_wrapper.h"
87 #include "printing/units.h"
88 #include "skia/ext/platform_canvas.h"
89 #include "skia/ext/platform_device.h"
90 #include "third_party/WebKit/public/platform/WebGamepads.h"
91 #include "third_party/WebKit/public/platform/WebString.h"
92 #include "third_party/WebKit/public/platform/WebURL.h"
93 #include "third_party/WebKit/public/platform/WebURLError.h"
94 #include "third_party/WebKit/public/platform/WebURLRequest.h"
95 #include "third_party/WebKit/public/web/WebBindings.h"
96 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
97 #include "third_party/WebKit/public/web/WebCursorInfo.h"
98 #include "third_party/WebKit/public/web/WebDataSource.h"
99 #include "third_party/WebKit/public/web/WebDocument.h"
100 #include "third_party/WebKit/public/web/WebElement.h"
101 #include "third_party/WebKit/public/web/WebFrame.h"
102 #include "third_party/WebKit/public/web/WebInputEvent.h"
103 #include "third_party/WebKit/public/web/WebPluginContainer.h"
104 #include "third_party/WebKit/public/web/WebPrintParams.h"
105 #include "third_party/WebKit/public/web/WebPrintScalingOption.h"
106 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
107 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
108 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
109 #include "third_party/WebKit/public/web/WebView.h"
110 #include "third_party/skia/include/core/SkCanvas.h"
111 #include "third_party/skia/include/core/SkRect.h"
112 #include "ui/gfx/image/image_skia.h"
113 #include "ui/gfx/image/image_skia_rep.h"
114 #include "ui/gfx/range/range.h"
115 #include "ui/gfx/rect_conversions.h"
116 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
117 #include "v8/include/v8.h"
118 #include "webkit/renderer/compositor_bindings/web_layer_impl.h"
119
120 #if defined(OS_CHROMEOS)
121 #include "ui/events/keycodes/keyboard_codes_posix.h"
122 #endif
123
124 #if defined(OS_MACOSX)
125 #include "printing/metafile_impl.h"
126 #endif  // defined(OS_MACOSX)
127
128 #if defined(OS_WIN)
129 #include "base/metrics/histogram.h"
130 #include "base/win/windows_version.h"
131 #include "skia/ext/platform_canvas.h"
132 #include "ui/gfx/codec/jpeg_codec.h"
133 #include "ui/gfx/gdi_util.h"
134 #endif
135
136 using base::StringPrintf;
137 using ppapi::InputEventData;
138 using ppapi::PpapiGlobals;
139 using ppapi::PPB_InputEvent_Shared;
140 using ppapi::PPB_View_Shared;
141 using ppapi::PPP_Instance_Combined;
142 using ppapi::Resource;
143 using ppapi::ScopedPPResource;
144 using ppapi::StringVar;
145 using ppapi::TrackedCallback;
146 using ppapi::thunk::EnterResourceNoLock;
147 using ppapi::thunk::PPB_Buffer_API;
148 using ppapi::thunk::PPB_Gamepad_API;
149 using ppapi::thunk::PPB_Graphics2D_API;
150 using ppapi::thunk::PPB_Graphics3D_API;
151 using ppapi::thunk::PPB_ImageData_API;
152 using ppapi::Var;
153 using ppapi::ArrayBufferVar;
154 using ppapi::ViewData;
155 using WebKit::WebBindings;
156 using WebKit::WebCanvas;
157 using WebKit::WebCursorInfo;
158 using WebKit::WebDocument;
159 using WebKit::WebElement;
160 using WebKit::WebFrame;
161 using WebKit::WebInputEvent;
162 using WebKit::WebPlugin;
163 using WebKit::WebPluginContainer;
164 using WebKit::WebPrintParams;
165 using WebKit::WebPrintScalingOption;
166 using WebKit::WebScopedUserGesture;
167 using WebKit::WebString;
168 using WebKit::WebURLError;
169 using WebKit::WebURLLoader;
170 using WebKit::WebURLLoaderClient;
171 using WebKit::WebURLRequest;
172 using WebKit::WebURLResponse;
173 using WebKit::WebUserGestureIndicator;
174 using WebKit::WebUserGestureToken;
175 using WebKit::WebView;
176
177 namespace content {
178
179 #if defined(OS_WIN)
180 // Exported by pdf.dll
181 typedef bool (*RenderPDFPageToDCProc)(
182     const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
183     int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
184     int bounds_width, int bounds_height, bool fit_to_bounds,
185     bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds,
186     bool autorotate);
187
188 void DrawEmptyRectangle(HDC dc) {
189   // TODO(sanjeevr): This is a temporary hack. If we output a JPEG
190   // to the EMF, the EnumEnhMetaFile call fails in the browser
191   // process. The failure also happens if we output nothing here.
192   // We need to investigate the reason for this failure and fix it.
193   // In the meantime this temporary hack of drawing an empty
194   // rectangle in the DC gets us by.
195   Rectangle(dc, 0, 0, 0, 0);
196 }
197 #endif  // defined(OS_WIN)
198
199 namespace {
200
201 // Check PP_TextInput_Type and ui::TextInputType are kept in sync.
202 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_NONE) == \
203     int(PP_TEXTINPUT_TYPE_NONE), mismatching_enums);
204 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_TEXT) == \
205     int(PP_TEXTINPUT_TYPE_TEXT), mismatching_enums);
206 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_PASSWORD) == \
207     int(PP_TEXTINPUT_TYPE_PASSWORD), mismatching_enums);
208 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_SEARCH) == \
209     int(PP_TEXTINPUT_TYPE_SEARCH), mismatching_enums);
210 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_EMAIL) == \
211     int(PP_TEXTINPUT_TYPE_EMAIL), mismatching_enums);
212 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_NUMBER) == \
213     int(PP_TEXTINPUT_TYPE_NUMBER), mismatching_enums);
214 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_TELEPHONE) == \
215     int(PP_TEXTINPUT_TYPE_TELEPHONE), mismatching_enums);
216 COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_URL) == \
217     int(PP_TEXTINPUT_TYPE_URL), mismatching_enums);
218
219 // The default text input type is to regard the plugin always accept text input.
220 // This is for allowing users to use input methods even on completely-IME-
221 // unaware plugins (e.g., PPAPI Flash or PDF plugin for M16).
222 // Plugins need to explicitly opt out the text input mode if they know
223 // that they don't accept texts.
224 const ui::TextInputType kPluginDefaultTextInputType = ui::TEXT_INPUT_TYPE_TEXT;
225
226 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
227     COMPILE_ASSERT(static_cast<int>(WebCursorInfo::webkit_name) \
228                        == static_cast<int>(np_name), \
229                    mismatching_enums)
230
231 #define COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(webkit_name, pp_name) \
232     COMPILE_ASSERT(static_cast<int>(webkit_name) \
233                        == static_cast<int>(pp_name), \
234                    mismatching_enums)
235
236 // <embed>/<object> attributes.
237 const char kWidth[] = "width";
238 const char kHeight[] = "height";
239 const char kBorder[] = "border";  // According to w3c, deprecated.
240 const char kStyle[] = "style";
241
242 COMPILE_ASSERT_MATCHING_ENUM(TypePointer, PP_MOUSECURSOR_TYPE_POINTER);
243 COMPILE_ASSERT_MATCHING_ENUM(TypeCross, PP_MOUSECURSOR_TYPE_CROSS);
244 COMPILE_ASSERT_MATCHING_ENUM(TypeHand, PP_MOUSECURSOR_TYPE_HAND);
245 COMPILE_ASSERT_MATCHING_ENUM(TypeIBeam, PP_MOUSECURSOR_TYPE_IBEAM);
246 COMPILE_ASSERT_MATCHING_ENUM(TypeWait, PP_MOUSECURSOR_TYPE_WAIT);
247 COMPILE_ASSERT_MATCHING_ENUM(TypeHelp, PP_MOUSECURSOR_TYPE_HELP);
248 COMPILE_ASSERT_MATCHING_ENUM(TypeEastResize, PP_MOUSECURSOR_TYPE_EASTRESIZE);
249 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthResize, PP_MOUSECURSOR_TYPE_NORTHRESIZE);
250 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastResize,
251                              PP_MOUSECURSOR_TYPE_NORTHEASTRESIZE);
252 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestResize,
253                              PP_MOUSECURSOR_TYPE_NORTHWESTRESIZE);
254 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthResize, PP_MOUSECURSOR_TYPE_SOUTHRESIZE);
255 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastResize,
256                              PP_MOUSECURSOR_TYPE_SOUTHEASTRESIZE);
257 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestResize,
258                              PP_MOUSECURSOR_TYPE_SOUTHWESTRESIZE);
259 COMPILE_ASSERT_MATCHING_ENUM(TypeWestResize, PP_MOUSECURSOR_TYPE_WESTRESIZE);
260 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthSouthResize,
261                              PP_MOUSECURSOR_TYPE_NORTHSOUTHRESIZE);
262 COMPILE_ASSERT_MATCHING_ENUM(TypeEastWestResize,
263                              PP_MOUSECURSOR_TYPE_EASTWESTRESIZE);
264 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastSouthWestResize,
265                              PP_MOUSECURSOR_TYPE_NORTHEASTSOUTHWESTRESIZE);
266 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestSouthEastResize,
267                              PP_MOUSECURSOR_TYPE_NORTHWESTSOUTHEASTRESIZE);
268 COMPILE_ASSERT_MATCHING_ENUM(TypeColumnResize,
269                              PP_MOUSECURSOR_TYPE_COLUMNRESIZE);
270 COMPILE_ASSERT_MATCHING_ENUM(TypeRowResize, PP_MOUSECURSOR_TYPE_ROWRESIZE);
271 COMPILE_ASSERT_MATCHING_ENUM(TypeMiddlePanning,
272                              PP_MOUSECURSOR_TYPE_MIDDLEPANNING);
273 COMPILE_ASSERT_MATCHING_ENUM(TypeEastPanning, PP_MOUSECURSOR_TYPE_EASTPANNING);
274 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthPanning,
275                              PP_MOUSECURSOR_TYPE_NORTHPANNING);
276 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastPanning,
277                              PP_MOUSECURSOR_TYPE_NORTHEASTPANNING);
278 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestPanning,
279                              PP_MOUSECURSOR_TYPE_NORTHWESTPANNING);
280 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthPanning,
281                              PP_MOUSECURSOR_TYPE_SOUTHPANNING);
282 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastPanning,
283                              PP_MOUSECURSOR_TYPE_SOUTHEASTPANNING);
284 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestPanning,
285                              PP_MOUSECURSOR_TYPE_SOUTHWESTPANNING);
286 COMPILE_ASSERT_MATCHING_ENUM(TypeWestPanning, PP_MOUSECURSOR_TYPE_WESTPANNING);
287 COMPILE_ASSERT_MATCHING_ENUM(TypeMove, PP_MOUSECURSOR_TYPE_MOVE);
288 COMPILE_ASSERT_MATCHING_ENUM(TypeVerticalText,
289                              PP_MOUSECURSOR_TYPE_VERTICALTEXT);
290 COMPILE_ASSERT_MATCHING_ENUM(TypeCell, PP_MOUSECURSOR_TYPE_CELL);
291 COMPILE_ASSERT_MATCHING_ENUM(TypeContextMenu, PP_MOUSECURSOR_TYPE_CONTEXTMENU);
292 COMPILE_ASSERT_MATCHING_ENUM(TypeAlias, PP_MOUSECURSOR_TYPE_ALIAS);
293 COMPILE_ASSERT_MATCHING_ENUM(TypeProgress, PP_MOUSECURSOR_TYPE_PROGRESS);
294 COMPILE_ASSERT_MATCHING_ENUM(TypeNoDrop, PP_MOUSECURSOR_TYPE_NODROP);
295 COMPILE_ASSERT_MATCHING_ENUM(TypeCopy, PP_MOUSECURSOR_TYPE_COPY);
296 COMPILE_ASSERT_MATCHING_ENUM(TypeNone, PP_MOUSECURSOR_TYPE_NONE);
297 COMPILE_ASSERT_MATCHING_ENUM(TypeNotAllowed, PP_MOUSECURSOR_TYPE_NOTALLOWED);
298 COMPILE_ASSERT_MATCHING_ENUM(TypeZoomIn, PP_MOUSECURSOR_TYPE_ZOOMIN);
299 COMPILE_ASSERT_MATCHING_ENUM(TypeZoomOut, PP_MOUSECURSOR_TYPE_ZOOMOUT);
300 COMPILE_ASSERT_MATCHING_ENUM(TypeGrab, PP_MOUSECURSOR_TYPE_GRAB);
301 COMPILE_ASSERT_MATCHING_ENUM(TypeGrabbing, PP_MOUSECURSOR_TYPE_GRABBING);
302 // Do not assert WebCursorInfo::TypeCustom == PP_CURSORTYPE_CUSTOM;
303 // PP_CURSORTYPE_CUSTOM is pinned to allow new cursor types.
304
305 COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(WebKit::WebPrintScalingOptionNone,
306                                            PP_PRINTSCALINGOPTION_NONE);
307 COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(
308     WebKit::WebPrintScalingOptionFitToPrintableArea,
309     PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA);
310 COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(
311     WebKit::WebPrintScalingOptionSourceSize, PP_PRINTSCALINGOPTION_SOURCE_SIZE);
312
313 // Sets |*security_origin| to be the WebKit security origin associated with the
314 // document containing the given plugin instance. On success, returns true. If
315 // the instance is invalid, returns false and |*security_origin| will be
316 // unchanged.
317 bool SecurityOriginForInstance(PP_Instance instance_id,
318                                WebKit::WebSecurityOrigin* security_origin) {
319   PepperPluginInstanceImpl* instance =
320       HostGlobals::Get()->GetInstance(instance_id);
321   if (!instance)
322     return false;
323
324   WebElement plugin_element = instance->container()->element();
325   *security_origin = plugin_element.document().securityOrigin();
326   return true;
327 }
328
329 // Convert the given vector to an array of C-strings. The strings in the
330 // returned vector are only guaranteed valid so long as the vector of strings
331 // is not modified.
332 scoped_ptr<const char*[]> StringVectorToArgArray(
333     const std::vector<std::string>& vector) {
334   scoped_ptr<const char*[]> array(new const char*[vector.size()]);
335   for (size_t i = 0; i < vector.size(); ++i)
336     array[i] = vector[i].c_str();
337   return array.Pass();
338 }
339
340 // Returns true if this is a "system reserved" key which should not be sent to
341 // a plugin. Some poorly behaving plugins (like Flash) incorrectly report that
342 // they handle all keys sent to them. This can prevent keystrokes from working
343 // for things like screen brightness and volume control.
344 bool IsReservedSystemInputEvent(const WebKit::WebInputEvent& event) {
345 #if defined(OS_CHROMEOS)
346   if (event.type != WebInputEvent::KeyDown &&
347       event.type != WebInputEvent::KeyUp)
348     return false;
349   const WebKit::WebKeyboardEvent& key_event =
350       static_cast<const WebKit::WebKeyboardEvent&>(event);
351   switch (key_event.windowsKeyCode) {
352     case ui::VKEY_BRIGHTNESS_DOWN:
353     case ui::VKEY_BRIGHTNESS_UP:
354     case ui::VKEY_KBD_BRIGHTNESS_DOWN:
355     case ui::VKEY_KBD_BRIGHTNESS_UP:
356     case ui::VKEY_VOLUME_MUTE:
357     case ui::VKEY_VOLUME_DOWN:
358     case ui::VKEY_VOLUME_UP:
359       return true;
360     default:
361       return false;
362   }
363 #endif  // defined(OS_CHROMEOS)
364   return false;
365 }
366
367 class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
368  public:
369   PluginInstanceLockTarget(PepperPluginInstanceImpl* plugin)
370       : plugin_(plugin) {}
371
372   virtual void OnLockMouseACK(bool succeeded) OVERRIDE {
373     plugin_->OnLockMouseACK(succeeded);
374   }
375
376   virtual void OnMouseLockLost() OVERRIDE {
377     plugin_->OnMouseLockLost();
378   }
379
380   virtual bool HandleMouseLockedInputEvent(
381       const WebKit::WebMouseEvent &event) OVERRIDE {
382     plugin_->HandleMouseLockedInputEvent(event);
383     return true;
384   }
385
386  private:
387   PepperPluginInstanceImpl* plugin_;
388 };
389
390
391 }  // namespace
392
393 // static
394 PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create(
395     RenderViewImpl* render_view,
396     PluginModule* module,
397     WebPluginContainer* container,
398     const GURL& plugin_url) {
399   base::Callback<const void*(const char*)> get_plugin_interface_func =
400       base::Bind(&PluginModule::GetPluginInterface, module);
401   PPP_Instance_Combined* ppp_instance_combined =
402       PPP_Instance_Combined::Create(get_plugin_interface_func);
403   if (!ppp_instance_combined)
404     return NULL;
405   return new PepperPluginInstanceImpl(render_view, module,
406                                       ppp_instance_combined, container,
407                                       plugin_url);
408 }
409
410 PepperPluginInstanceImpl::ExternalDocumentLoader::ExternalDocumentLoader()
411     : finished_loading_(false) {
412 }
413
414 PepperPluginInstanceImpl::ExternalDocumentLoader::~ExternalDocumentLoader() {
415 }
416
417 void PepperPluginInstanceImpl::ExternalDocumentLoader::ReplayReceivedData(
418     WebURLLoaderClient* document_loader) {
419   for (std::list<std::string>::iterator it = data_.begin();
420        it != data_.end(); ++it) {
421     document_loader->didReceiveData(NULL, it->c_str(), it->length(),
422                                     0 /* encoded_data_length */);
423   }
424   if (finished_loading_) {
425     document_loader->didFinishLoading(NULL,
426                                       0 /* finish_time */);
427   }
428   if (error_.get()) {
429     document_loader->didFail(NULL, *error_);
430   }
431 }
432
433 void PepperPluginInstanceImpl::ExternalDocumentLoader::didReceiveData(
434     WebURLLoader* loader,
435     const char* data,
436     int data_length,
437     int encoded_data_length) {
438   data_.push_back(std::string(data, data_length));
439 }
440
441 void PepperPluginInstanceImpl::ExternalDocumentLoader::didFinishLoading(
442     WebURLLoader* loader,
443     double finish_time) {
444   DCHECK(!finished_loading_);
445   finished_loading_ = true;
446 }
447
448 void PepperPluginInstanceImpl::ExternalDocumentLoader::didFail(
449     WebURLLoader* loader,
450     const WebURLError& error) {
451   DCHECK(!error_.get());
452   error_.reset(new WebURLError(error));
453 }
454
455 PepperPluginInstanceImpl::GamepadImpl::GamepadImpl()
456     : Resource(ppapi::Resource::Untracked()) {
457 }
458
459 PepperPluginInstanceImpl::GamepadImpl::~GamepadImpl() {
460 }
461
462 PPB_Gamepad_API* PepperPluginInstanceImpl::GamepadImpl::AsPPB_Gamepad_API() {
463   return this;
464 }
465
466 void PepperPluginInstanceImpl::GamepadImpl::Sample(
467     PP_Instance instance,
468     PP_GamepadsSampleData* data) {
469   WebKit::WebGamepads webkit_data;
470   RenderThreadImpl::current()->SampleGamepads(&webkit_data);
471   ConvertWebKitGamepadData(
472       bit_cast<ppapi::WebKitGamepads>(webkit_data), data);
473 }
474
475 PepperPluginInstanceImpl::PepperPluginInstanceImpl(
476     RenderViewImpl* render_view,
477     PluginModule* module,
478     ppapi::PPP_Instance_Combined* instance_interface,
479     WebPluginContainer* container,
480     const GURL& plugin_url)
481     : render_view_(render_view),
482       module_(module),
483       instance_interface_(instance_interface),
484       pp_instance_(0),
485       container_(container),
486       layer_bound_to_fullscreen_(false),
487       plugin_url_(plugin_url),
488       full_frame_(false),
489       sent_initial_did_change_view_(false),
490       bound_graphics_2d_platform_(NULL),
491       has_webkit_focus_(false),
492       has_content_area_focus_(false),
493       find_identifier_(-1),
494       plugin_find_interface_(NULL),
495       plugin_input_event_interface_(NULL),
496       plugin_messaging_interface_(NULL),
497       plugin_mouse_lock_interface_(NULL),
498       plugin_pdf_interface_(NULL),
499       plugin_private_interface_(NULL),
500       plugin_selection_interface_(NULL),
501       plugin_textinput_interface_(NULL),
502       plugin_zoom_interface_(NULL),
503       checked_for_plugin_input_event_interface_(false),
504       checked_for_plugin_messaging_interface_(false),
505       checked_for_plugin_pdf_interface_(false),
506       gamepad_impl_(new GamepadImpl()),
507       plugin_print_interface_(NULL),
508       plugin_graphics_3d_interface_(NULL),
509       always_on_top_(false),
510       fullscreen_container_(NULL),
511       flash_fullscreen_(false),
512       desired_fullscreen_state_(false),
513       sad_plugin_(NULL),
514       input_event_mask_(0),
515       filtered_input_event_mask_(0),
516       text_input_type_(kPluginDefaultTextInputType),
517       text_input_caret_(0, 0, 0, 0),
518       text_input_caret_bounds_(0, 0, 0, 0),
519       text_input_caret_set_(false),
520       selection_caret_(0),
521       selection_anchor_(0),
522       pending_user_gesture_(0.0),
523       document_loader_(NULL),
524       external_document_load_(false),
525       npp_(new NPP_t),
526       isolate_(v8::Isolate::GetCurrent()),
527       view_change_weak_ptr_factory_(this) {
528   pp_instance_ = HostGlobals::Get()->AddInstance(this);
529
530   memset(&current_print_settings_, 0, sizeof(current_print_settings_));
531   module_->InstanceCreated(this);
532
533   if (render_view) {  // NULL in tests
534     render_view->PepperInstanceCreated(this);
535     view_data_.is_page_visible = !render_view->is_hidden();
536
537     // Set the initial focus.
538     SetContentAreaFocus(render_view_->has_focus());
539
540     if (!module_->IsProxied()) {
541       PepperBrowserConnection* browser_connection =
542           PepperBrowserConnection::Get(render_view_);
543       browser_connection->DidCreateInProcessInstance(
544           pp_instance(),
545           render_view_->GetRoutingID(),
546           container_->element().document().url(),
547           GetPluginURL());
548     }
549   }
550
551   RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
552   resource_creation_ = host_impl->CreateInProcessResourceCreationAPI(this);
553
554   if (GetContentClient()->renderer() &&  // NULL in unit tests.
555       GetContentClient()->renderer()->IsExternalPepperPlugin(module->name()))
556     external_document_load_ = true;
557 }
558
559 PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
560   DCHECK(!fullscreen_container_);
561
562   // Free all the plugin objects. This will automatically clear the back-
563   // pointer from the NPObject so WebKit can't call into the plugin any more.
564   //
565   // Swap out the set so we can delete from it (the objects will try to
566   // unregister themselves inside the delete call).
567   PluginObjectSet plugin_object_copy;
568   live_plugin_objects_.swap(plugin_object_copy);
569   for (PluginObjectSet::iterator i = plugin_object_copy.begin();
570        i != plugin_object_copy.end(); ++i)
571     delete *i;
572
573   if (TrackedCallback::IsPending(lock_mouse_callback_))
574     lock_mouse_callback_->Abort();
575
576   if (render_view_)
577     render_view_->PepperInstanceDeleted(this);
578
579   if (!module_->IsProxied() && render_view_) {
580     PepperBrowserConnection* browser_connection =
581         PepperBrowserConnection::Get(render_view_);
582     browser_connection->DidDeleteInProcessInstance(pp_instance());
583   }
584
585   UnSetAndDeleteLockTargetAdapter();
586   module_->InstanceDeleted(this);
587   // If we switched from the NaCl plugin module, notify it too.
588   if (original_module_.get())
589     original_module_->InstanceDeleted(this);
590
591   // This should be last since some of the above "instance deleted" calls will
592   // want to look up in the global map to get info off of our object.
593   HostGlobals::Get()->InstanceDeleted(pp_instance_);
594 }
595
596 // NOTE: Any of these methods that calls into the plugin needs to take into
597 // account that the plugin may use Var to remove the <embed> from the DOM, which
598 // will make the PepperWebPluginImpl drop its reference, usually the last one.
599 // If a method needs to access a member of the instance after the call has
600 // returned, then it needs to keep its own reference on the stack.
601
602 void PepperPluginInstanceImpl::Delete() {
603   // Keep a reference on the stack. See NOTE above.
604   scoped_refptr<PepperPluginInstanceImpl> ref(this);
605   // Force the MessageChannel to release its "passthrough object" which should
606   // release our last reference to the "InstanceObject" and will probably
607   // destroy it. We want to do this prior to calling DidDestroy in case the
608   // destructor of the instance object tries to use the instance.
609   message_channel_->SetPassthroughObject(NULL);
610   // If this is a NaCl plugin instance, shut down the NaCl plugin by calling
611   // its DidDestroy. Don't call DidDestroy on the untrusted plugin instance,
612   // since there is little that it can do at this point.
613   if (original_instance_interface_)
614     original_instance_interface_->DidDestroy(pp_instance());
615   else
616     instance_interface_->DidDestroy(pp_instance());
617   // Ensure we don't attempt to call functions on the destroyed instance.
618   original_instance_interface_.reset();
619   instance_interface_.reset();
620
621   if (fullscreen_container_) {
622     fullscreen_container_->Destroy();
623     fullscreen_container_ = NULL;
624   }
625
626   // Force-unbind any Graphics. In the case of Graphics2D, if the plugin
627   // leaks the graphics 2D, it may actually get cleaned up after our
628   // destruction, so we need its pointers to be up-to-date.
629   BindGraphics(pp_instance(), 0);
630   container_ = NULL;
631 }
632
633 void PepperPluginInstanceImpl::Paint(WebCanvas* canvas,
634                                      const gfx::Rect& plugin_rect,
635                                      const gfx::Rect& paint_rect) {
636   TRACE_EVENT0("ppapi", "PluginInstance::Paint");
637   if (module()->is_crashed()) {
638     // Crashed plugin painting.
639     if (!sad_plugin_)  // Lazily initialize bitmap.
640       sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
641     if (sad_plugin_)
642       PaintSadPlugin(canvas, plugin_rect, *sad_plugin_);
643     return;
644   }
645
646   if (bound_graphics_2d_platform_)
647     bound_graphics_2d_platform_->Paint(canvas, plugin_rect, paint_rect);
648 }
649
650 void PepperPluginInstanceImpl::InvalidateRect(const gfx::Rect& rect) {
651   if (fullscreen_container_) {
652     if (rect.IsEmpty())
653       fullscreen_container_->Invalidate();
654     else
655       fullscreen_container_->InvalidateRect(rect);
656   } else {
657     if (!container_ ||
658         view_data_.rect.size.width == 0 || view_data_.rect.size.height == 0)
659       return;  // Nothing to do.
660     if (rect.IsEmpty())
661       container_->invalidate();
662     else
663       container_->invalidateRect(rect);
664   }
665   if (texture_layer_) {
666     if (rect.IsEmpty()) {
667       texture_layer_->SetNeedsDisplay();
668     } else {
669       texture_layer_->SetNeedsDisplayRect(rect);
670     }
671   }
672 }
673
674 void PepperPluginInstanceImpl::ScrollRect(int dx,
675                                           int dy,
676                                           const gfx::Rect& rect) {
677   if (texture_layer_) {
678     InvalidateRect(rect);
679   } else if (fullscreen_container_) {
680     fullscreen_container_->ScrollRect(dx, dy, rect);
681   } else {
682     if (full_frame_ && !IsViewAccelerated()) {
683       container_->scrollRect(dx, dy, rect);
684     } else {
685       // Can't do optimized scrolling since there could be other elements on top
686       // of us or the view renders via the accelerated compositor which is
687       // incompatible with the move and backfill scrolling model.
688       InvalidateRect(rect);
689     }
690   }
691 }
692
693 void PepperPluginInstanceImpl::CommitBackingTexture() {
694   if (texture_layer_.get())
695     texture_layer_->SetNeedsDisplay();
696 }
697
698 void PepperPluginInstanceImpl::InstanceCrashed() {
699   // Force free all resources and vars.
700   HostGlobals::Get()->InstanceCrashed(pp_instance());
701
702   // Free any associated graphics.
703   SetFullscreen(false);
704   FlashSetFullscreen(false, false);
705   // Unbind current 2D or 3D graphics context.
706   BindGraphics(pp_instance(), 0);
707   InvalidateRect(gfx::Rect());
708
709   render_view_->PluginCrashed(module_->path(), module_->GetPeerProcessId());
710   UnSetAndDeleteLockTargetAdapter();
711 }
712
713 static void SetGPUHistogram(const ppapi::Preferences& prefs,
714                             const std::vector<std::string>& arg_names,
715                             const std::vector<std::string>& arg_values) {
716   // Calculate a histogram to let us determine how likely people are to try to
717   // run Stage3D content on machines that have it blacklisted.
718 #if defined(OS_WIN)
719   bool needs_gpu = false;
720   bool is_xp = base::win::GetVersion() <= base::win::VERSION_XP;
721
722   for (size_t i = 0; i < arg_names.size(); i++) {
723     if (arg_names[i] == "wmode") {
724       // In theory content other than Flash could have a "wmode" argument,
725       // but that's pretty unlikely.
726       if (arg_values[i] == "direct" || arg_values[i] == "gpu")
727         needs_gpu = true;
728       break;
729     }
730   }
731   // 0 : No 3D content and GPU is blacklisted
732   // 1 : No 3D content and GPU is not blacklisted
733   // 2 : 3D content but GPU is blacklisted
734   // 3 : 3D content and GPU is not blacklisted
735   // 4 : No 3D content and GPU is blacklisted on XP
736   // 5 : No 3D content and GPU is not blacklisted on XP
737   // 6 : 3D content but GPU is blacklisted on XP
738   // 7 : 3D content and GPU is not blacklisted on XP
739   UMA_HISTOGRAM_ENUMERATION("Flash.UsesGPU",
740       is_xp * 4 + needs_gpu * 2 + prefs.is_webgl_supported, 8);
741 #endif
742 }
743
744 bool PepperPluginInstanceImpl::Initialize(
745     const std::vector<std::string>& arg_names,
746     const std::vector<std::string>& arg_values,
747     bool full_frame) {
748   message_channel_.reset(new MessageChannel(this));
749
750   full_frame_ = full_frame;
751
752   UpdateTouchEventRequest();
753   container_->setWantsWheelEvents(IsAcceptingWheelEvents());
754
755   SetGPUHistogram(ppapi::Preferences(render_view_->webkit_preferences()),
756                   arg_names, arg_values);
757
758   argn_ = arg_names;
759   argv_ = arg_values;
760   scoped_ptr<const char*[]> argn_array(StringVectorToArgArray(argn_));
761   scoped_ptr<const char*[]> argv_array(StringVectorToArgArray(argv_));
762   bool success =  PP_ToBool(instance_interface_->DidCreate(pp_instance(),
763                                                            argn_.size(),
764                                                            argn_array.get(),
765                                                            argv_array.get()));
766   if (success)
767     message_channel_->StopQueueingJavaScriptMessages();
768   return success;
769 }
770
771 bool PepperPluginInstanceImpl::HandleDocumentLoad(
772     const WebKit::WebURLResponse& response) {
773   DCHECK(!document_loader_);
774   if (external_document_load_) {
775     // The external proxy isn't available, so save the response and record
776     // document load notifications for later replay.
777     external_document_response_ = response;
778     external_document_loader_.reset(new ExternalDocumentLoader());
779     document_loader_ = external_document_loader_.get();
780     return true;
781   }
782
783   if (module()->is_crashed()) {
784     // Don't create a resource for a crashed plugin.
785     container()->element().document().frame()->stopLoading();
786     return false;
787   }
788
789   DCHECK(!document_loader_);
790
791   // Create a loader resource host for this load. Note that we have to set
792   // the document_loader before issuing the in-process
793   // PPP_Instance.HandleDocumentLoad call below, since this may reentrantly
794   // call into the instance and expect it to be valid.
795   RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
796   PepperURLLoaderHost* loader_host =
797       new PepperURLLoaderHost(host_impl, true, pp_instance(), 0);
798   // TODO(teravest): Remove set_document_loader() from instance and clean up
799   // this relationship.
800   set_document_loader(loader_host);
801   loader_host->didReceiveResponse(NULL, response);
802
803   // This host will be pending until the resource object attaches to it.
804   //
805   // PpapiHost now owns the pointer to loader_host, so we don't have to worry
806   // about managing it.
807   int pending_host_id = host_impl->GetPpapiHost()->AddPendingResourceHost(
808       scoped_ptr<ppapi::host::ResourceHost>(loader_host));
809   DCHECK(pending_host_id);
810
811   DataFromWebURLResponse(
812       host_impl,
813       pp_instance(),
814       response,
815       base::Bind(&PepperPluginInstanceImpl::DidDataFromWebURLResponse,
816                  AsWeakPtr(),
817                  response,
818                  pending_host_id));
819
820   // If the load was not abandoned, document_loader_ will now be set. It's
821   // possible that the load was canceled by now and document_loader_ was
822   // already nulled out.
823   return true;
824 }
825
826 bool PepperPluginInstanceImpl::SendCompositionEventToPlugin(
827     PP_InputEvent_Type type, const base::string16& text) {
828   std::vector<WebKit::WebCompositionUnderline> empty;
829   return SendCompositionEventWithUnderlineInformationToPlugin(
830       type, text, empty, static_cast<int>(text.size()),
831       static_cast<int>(text.size()));
832 }
833
834 bool PepperPluginInstanceImpl::
835     SendCompositionEventWithUnderlineInformationToPlugin(
836         PP_InputEvent_Type type,
837         const base::string16& text,
838         const std::vector<WebKit::WebCompositionUnderline>& underlines,
839         int selection_start,
840         int selection_end) {
841   // Keep a reference on the stack. See NOTE above.
842   scoped_refptr<PepperPluginInstanceImpl> ref(this);
843
844   if (!LoadInputEventInterface())
845     return false;
846
847   PP_InputEvent_Class event_class = PP_INPUTEVENT_CLASS_IME;
848   if (!(filtered_input_event_mask_ & event_class) &&
849       !(input_event_mask_ & event_class))
850     return false;
851
852   ppapi::InputEventData event;
853   event.event_type = type;
854   event.event_time_stamp = ppapi::TimeTicksToPPTimeTicks(
855       base::TimeTicks::Now());
856
857   // Convert UTF16 text to UTF8 with offset conversion.
858   std::vector<size_t> utf16_offsets;
859   utf16_offsets.push_back(selection_start);
860   utf16_offsets.push_back(selection_end);
861   for (size_t i = 0; i < underlines.size(); ++i) {
862     utf16_offsets.push_back(underlines[i].startOffset);
863     utf16_offsets.push_back(underlines[i].endOffset);
864   }
865   std::vector<size_t> utf8_offsets(utf16_offsets);
866   event.character_text = base::UTF16ToUTF8AndAdjustOffsets(text, &utf8_offsets);
867
868   // Set the converted selection range.
869   event.composition_selection_start = (utf8_offsets[0] == std::string::npos ?
870       event.character_text.size() : utf8_offsets[0]);
871   event.composition_selection_end = (utf8_offsets[1] == std::string::npos ?
872       event.character_text.size() : utf8_offsets[1]);
873
874   // Set the converted segmentation points.
875   // Be sure to add 0 and size(), and remove duplication or errors.
876   std::set<size_t> offset_set(utf8_offsets.begin()+2, utf8_offsets.end());
877   offset_set.insert(0);
878   offset_set.insert(event.character_text.size());
879   offset_set.erase(std::string::npos);
880   event.composition_segment_offsets.assign(offset_set.begin(),
881                                            offset_set.end());
882
883   // Set the composition target.
884   for (size_t i = 0; i < underlines.size(); ++i) {
885     if (underlines[i].thick) {
886       std::vector<uint32_t>::iterator it =
887           std::find(event.composition_segment_offsets.begin(),
888                     event.composition_segment_offsets.end(),
889                     utf8_offsets[2*i+2]);
890       if (it != event.composition_segment_offsets.end()) {
891         event.composition_target_segment =
892             it - event.composition_segment_offsets.begin();
893         break;
894       }
895     }
896   }
897
898   // Send the event.
899   bool handled = false;
900   if (filtered_input_event_mask_ & event_class)
901     event.is_filtered = true;
902   else
903     handled = true;  // Unfiltered events are assumed to be handled.
904   scoped_refptr<PPB_InputEvent_Shared> event_resource(
905       new PPB_InputEvent_Shared(ppapi::OBJECT_IS_IMPL, pp_instance(), event));
906   handled |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
907       pp_instance(), event_resource->pp_resource()));
908   return handled;
909 }
910
911 void PepperPluginInstanceImpl::RequestInputEventsHelper(
912     uint32_t event_classes) {
913   if (event_classes & PP_INPUTEVENT_CLASS_TOUCH)
914     UpdateTouchEventRequest();
915   if (event_classes & PP_INPUTEVENT_CLASS_WHEEL)
916     container_->setWantsWheelEvents(IsAcceptingWheelEvents());
917 }
918
919 bool PepperPluginInstanceImpl::HandleCompositionStart(
920     const base::string16& text) {
921   return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_START,
922                                       text);
923 }
924
925 bool PepperPluginInstanceImpl::HandleCompositionUpdate(
926     const base::string16& text,
927     const std::vector<WebKit::WebCompositionUnderline>& underlines,
928     int selection_start,
929     int selection_end) {
930   return SendCompositionEventWithUnderlineInformationToPlugin(
931       PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE,
932       text, underlines, selection_start, selection_end);
933 }
934
935 bool PepperPluginInstanceImpl::HandleCompositionEnd(
936     const base::string16& text) {
937   return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_END,
938                                       text);
939 }
940
941 bool PepperPluginInstanceImpl::HandleTextInput(const base::string16& text) {
942   return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_TEXT,
943                                       text);
944 }
945
946 void PepperPluginInstanceImpl::GetSurroundingText(base::string16* text,
947                                                   gfx::Range* range) const {
948   std::vector<size_t> offsets;
949   offsets.push_back(selection_anchor_);
950   offsets.push_back(selection_caret_);
951   *text = base::UTF8ToUTF16AndAdjustOffsets(surrounding_text_, &offsets);
952   range->set_start(offsets[0] == base::string16::npos ? text->size()
953                                                       : offsets[0]);
954   range->set_end(offsets[1] == base::string16::npos ? text->size()
955                                                     : offsets[1]);
956 }
957
958 bool PepperPluginInstanceImpl::IsPluginAcceptingCompositionEvents() const {
959   return (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_IME) ||
960       (input_event_mask_ & PP_INPUTEVENT_CLASS_IME);
961 }
962
963 gfx::Rect PepperPluginInstanceImpl::GetCaretBounds() const {
964   if (!text_input_caret_set_) {
965     // If it is never set by the plugin, use the bottom left corner.
966     return gfx::Rect(view_data_.rect.point.x,
967                      view_data_.rect.point.y + view_data_.rect.size.height,
968                      0, 0);
969   }
970
971   // TODO(kinaba) Take CSS transformation into accont.
972   // TODO(kinaba) Take bounding_box into account. On some platforms, an
973   // "exclude rectangle" where candidate window must avoid the region can be
974   // passed to IME. Currently, we pass only the caret rectangle because
975   // it is the only information supported uniformly in Chromium.
976   gfx::Rect caret(text_input_caret_);
977   caret.Offset(view_data_.rect.point.x, view_data_.rect.point.y);
978   return caret;
979 }
980
981 bool PepperPluginInstanceImpl::HandleInputEvent(
982     const WebKit::WebInputEvent& event,
983     WebCursorInfo* cursor_info) {
984   TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleInputEvent");
985
986   if (WebInputEvent::isMouseEventType(event.type)) {
987     render_view_->PepperDidReceiveMouseEvent(this);
988   }
989
990   // Don't dispatch input events to crashed plugins.
991   if (module()->is_crashed())
992     return false;
993
994   // Don't send reserved system key events to plugins.
995   if (IsReservedSystemInputEvent(event))
996     return false;
997
998   // Keep a reference on the stack. See NOTE above.
999   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1000
1001   bool rv = false;
1002   if (LoadInputEventInterface()) {
1003     PP_InputEvent_Class event_class = ClassifyInputEvent(event.type);
1004     if (!event_class)
1005       return false;
1006
1007     if ((filtered_input_event_mask_ & event_class) ||
1008         (input_event_mask_ & event_class)) {
1009       // Actually send the event.
1010       std::vector< ppapi::InputEventData > events;
1011       CreateInputEventData(event, &events);
1012
1013       // Allow the user gesture to be pending after the plugin handles the
1014       // event. This allows out-of-process plugins to respond to the user
1015       // gesture after processing has finished here.
1016       if (WebUserGestureIndicator::isProcessingUserGesture()) {
1017         pending_user_gesture_ =
1018             ppapi::EventTimeToPPTimeTicks(event.timeStampSeconds);
1019         pending_user_gesture_token_ =
1020             WebUserGestureIndicator::currentUserGestureToken();
1021         pending_user_gesture_token_.setOutOfProcess();
1022       }
1023
1024       // Each input event may generate more than one PP_InputEvent.
1025       for (size_t i = 0; i < events.size(); i++) {
1026         if (filtered_input_event_mask_ & event_class)
1027           events[i].is_filtered = true;
1028         else
1029           rv = true;  // Unfiltered events are assumed to be handled.
1030         scoped_refptr<PPB_InputEvent_Shared> event_resource(
1031             new PPB_InputEvent_Shared(ppapi::OBJECT_IS_IMPL,
1032                                       pp_instance(), events[i]));
1033
1034         rv |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
1035             pp_instance(), event_resource->pp_resource()));
1036       }
1037     }
1038   }
1039
1040   if (cursor_)
1041     *cursor_info = *cursor_;
1042   return rv;
1043 }
1044
1045 void PepperPluginInstanceImpl::HandleMessage(PP_Var message) {
1046   TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleMessage");
1047   // Keep a reference on the stack. See NOTE above.
1048   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1049   if (!LoadMessagingInterface())
1050     return;
1051   plugin_messaging_interface_->HandleMessage(pp_instance(), message);
1052 }
1053
1054 PP_Var PepperPluginInstanceImpl::GetInstanceObject() {
1055   // Keep a reference on the stack. See NOTE above.
1056   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1057
1058   // If the plugin supports the private instance interface, try to retrieve its
1059   // instance object.
1060   if (LoadPrivateInterface())
1061     return plugin_private_interface_->GetInstanceObject(pp_instance());
1062   return PP_MakeUndefined();
1063 }
1064
1065 void PepperPluginInstanceImpl::ViewChanged(
1066     const gfx::Rect& position,
1067     const gfx::Rect& clip,
1068     const std::vector<gfx::Rect>& cut_outs_rects) {
1069   // WebKit can give weird (x,y) positions for empty clip rects (since the
1070   // position technically doesn't matter). But we want to make these
1071   // consistent since this is given to the plugin, so force everything to 0
1072   // in the "everything is clipped" case.
1073   gfx::Rect new_clip;
1074   if (!clip.IsEmpty())
1075     new_clip = clip;
1076
1077   cut_outs_rects_ = cut_outs_rects;
1078
1079   view_data_.rect = PP_FromGfxRect(position);
1080   view_data_.clip_rect = PP_FromGfxRect(clip);
1081   view_data_.device_scale = container_->deviceScaleFactor();
1082   view_data_.css_scale = container_->pageZoomFactor() *
1083                          container_->pageScaleFactor();
1084
1085   if (desired_fullscreen_state_ || view_data_.is_fullscreen) {
1086     WebElement element = container_->element();
1087     WebDocument document = element.document();
1088     bool is_fullscreen_element = (element == document.fullScreenElement());
1089     if (!view_data_.is_fullscreen && desired_fullscreen_state_ &&
1090         render_view_->is_fullscreen() && is_fullscreen_element) {
1091       // Entered fullscreen. Only possible via SetFullscreen().
1092       view_data_.is_fullscreen = true;
1093     } else if (view_data_.is_fullscreen && !is_fullscreen_element) {
1094       // Exited fullscreen. Possible via SetFullscreen() or F11/link,
1095       // so desired_fullscreen_state might be out-of-date.
1096       desired_fullscreen_state_ = false;
1097       view_data_.is_fullscreen = false;
1098
1099       // This operation will cause the plugin to re-layout which will send more
1100       // DidChangeView updates. Schedule an asynchronous update and suppress
1101       // notifications until that completes to avoid sending intermediate sizes
1102       // to the plugins.
1103       ScheduleAsyncDidChangeView();
1104
1105       // Reset the size attributes that we hacked to fill in the screen and
1106       // retrigger ViewChanged. Make sure we don't forward duplicates of
1107       // this view to the plugin.
1108       ResetSizeAttributesAfterFullscreen();
1109       return;
1110     }
1111   }
1112
1113   UpdateFlashFullscreenState(fullscreen_container_ != NULL);
1114
1115   SendDidChangeView();
1116 }
1117
1118 void PepperPluginInstanceImpl::SetWebKitFocus(bool has_focus) {
1119   if (has_webkit_focus_ == has_focus)
1120     return;
1121
1122   bool old_plugin_focus = PluginHasFocus();
1123   has_webkit_focus_ = has_focus;
1124   if (PluginHasFocus() != old_plugin_focus)
1125     SendFocusChangeNotification();
1126 }
1127
1128 void PepperPluginInstanceImpl::SetContentAreaFocus(bool has_focus) {
1129   if (has_content_area_focus_ == has_focus)
1130     return;
1131
1132   bool old_plugin_focus = PluginHasFocus();
1133   has_content_area_focus_ = has_focus;
1134   if (PluginHasFocus() != old_plugin_focus)
1135     SendFocusChangeNotification();
1136 }
1137
1138 void PepperPluginInstanceImpl::PageVisibilityChanged(bool is_visible) {
1139   if (is_visible == view_data_.is_page_visible)
1140     return;  // Nothing to do.
1141   view_data_.is_page_visible = is_visible;
1142
1143   // If the initial DidChangeView notification hasn't been sent to the plugin,
1144   // let it pass the visibility state for us, instead of sending a notification
1145   // immediately. It is possible that PepperPluginInstanceImpl::ViewChanged()
1146   // hasn't been called for the first time. In that case, most of the fields in
1147   // |view_data_| haven't been properly initialized.
1148   if (sent_initial_did_change_view_)
1149     SendDidChangeView();
1150 }
1151
1152 void PepperPluginInstanceImpl::ViewInitiatedPaint() {
1153   if (bound_graphics_2d_platform_)
1154     bound_graphics_2d_platform_->ViewInitiatedPaint();
1155   else if (bound_graphics_3d_.get())
1156     bound_graphics_3d_->ViewInitiatedPaint();
1157 }
1158
1159 void PepperPluginInstanceImpl::ViewFlushedPaint() {
1160   // Keep a reference on the stack. See NOTE above.
1161   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1162   if (bound_graphics_2d_platform_)
1163     bound_graphics_2d_platform_->ViewFlushedPaint();
1164   else if (bound_graphics_3d_.get())
1165     bound_graphics_3d_->ViewFlushedPaint();
1166 }
1167
1168 bool PepperPluginInstanceImpl::GetBitmapForOptimizedPluginPaint(
1169     const gfx::Rect& paint_bounds,
1170     TransportDIB** dib,
1171     gfx::Rect* location,
1172     gfx::Rect* clip,
1173     float* scale_factor) {
1174   if (!always_on_top_)
1175     return false;
1176   if (!bound_graphics_2d_platform_ ||
1177       !bound_graphics_2d_platform_->IsAlwaysOpaque()) {
1178     return false;
1179   }
1180
1181   // We specifically want to compare against the area covered by the backing
1182   // store when seeing if we cover the given paint bounds, since the backing
1183   // store could be smaller than the declared plugin area.
1184   PPB_ImageData_Impl* image_data = bound_graphics_2d_platform_->ImageData();
1185   // ImageDatas created by NaCl don't have a TransportDIB, so can't be
1186   // optimized this way.
1187   if (!image_data->GetTransportDIB())
1188     return false;
1189
1190   gfx::Point plugin_origin = PP_ToGfxPoint(view_data_.rect.point);
1191   gfx::Vector2d plugin_offset = plugin_origin.OffsetFromOrigin();
1192   // Convert |paint_bounds| to be relative to the left-top corner of the plugin.
1193   gfx::Rect relative_paint_bounds(paint_bounds);
1194   relative_paint_bounds.Offset(-plugin_offset);
1195
1196   gfx::Rect pixel_plugin_backing_store_rect(
1197       0, 0, image_data->width(), image_data->height());
1198   float scale = bound_graphics_2d_platform_->GetScale();
1199   gfx::Rect plugin_backing_store_rect = gfx::ToEnclosedRect(
1200       gfx::ScaleRect(pixel_plugin_backing_store_rect, scale));
1201
1202   gfx::Rect clip_page = PP_ToGfxRect(view_data_.clip_rect);
1203   gfx::Rect plugin_paint_rect =
1204       gfx::IntersectRects(plugin_backing_store_rect, clip_page);
1205   if (!plugin_paint_rect.Contains(relative_paint_bounds))
1206     return false;
1207
1208   // Don't do optimized painting if the area to paint intersects with the
1209   // cut-out rects, otherwise we will paint over them.
1210   for (std::vector<gfx::Rect>::const_iterator iter = cut_outs_rects_.begin();
1211        iter != cut_outs_rects_.end(); ++iter) {
1212     if (relative_paint_bounds.Intersects(*iter))
1213       return false;
1214   }
1215
1216   *dib = image_data->GetTransportDIB();
1217   plugin_backing_store_rect.Offset(plugin_offset);
1218   *location = plugin_backing_store_rect;
1219   clip_page.Offset(plugin_offset);
1220   *clip = clip_page;
1221   // The plugin scale factor is inverted, e.g. for a device scale factor of 2x
1222   // the plugin scale factor is 0.5.
1223   *scale_factor = 1.0 / scale;
1224   return true;
1225 }
1226
1227 base::string16 PepperPluginInstanceImpl::GetSelectedText(bool html) {
1228   // Keep a reference on the stack. See NOTE above.
1229   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1230   if (!LoadSelectionInterface())
1231     return base::string16();
1232
1233   PP_Var rv = plugin_selection_interface_->GetSelectedText(pp_instance(),
1234                                                            PP_FromBool(html));
1235   StringVar* string = StringVar::FromPPVar(rv);
1236   base::string16 selection;
1237   if (string)
1238     selection = UTF8ToUTF16(string->value());
1239   // Release the ref the plugin transfered to us.
1240   HostGlobals::Get()->GetVarTracker()->ReleaseVar(rv);
1241   return selection;
1242 }
1243
1244 base::string16 PepperPluginInstanceImpl::GetLinkAtPosition(
1245     const gfx::Point& point) {
1246   // Keep a reference on the stack. See NOTE above.
1247   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1248   if (!LoadPdfInterface())
1249     return base::string16();
1250
1251   PP_Point p;
1252   p.x = point.x();
1253   p.y = point.y();
1254   PP_Var rv = plugin_pdf_interface_->GetLinkAtPosition(pp_instance(), p);
1255   StringVar* string = StringVar::FromPPVar(rv);
1256   base::string16 link;
1257   if (string)
1258     link = UTF8ToUTF16(string->value());
1259   // Release the ref the plugin transfered to us.
1260   PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(rv);
1261   return link;
1262 }
1263
1264 void PepperPluginInstanceImpl::RequestSurroundingText(
1265     size_t desired_number_of_characters) {
1266   // Keep a reference on the stack. See NOTE above.
1267   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1268   if (!LoadTextInputInterface())
1269     return;
1270   plugin_textinput_interface_->RequestSurroundingText(
1271       pp_instance(), desired_number_of_characters);
1272 }
1273
1274 void PepperPluginInstanceImpl::Zoom(double factor, bool text_only) {
1275   // Keep a reference on the stack. See NOTE above.
1276   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1277   if (!LoadZoomInterface())
1278     return;
1279   plugin_zoom_interface_->Zoom(pp_instance(), factor, PP_FromBool(text_only));
1280 }
1281
1282 bool PepperPluginInstanceImpl::StartFind(const base::string16& search_text,
1283                                          bool case_sensitive,
1284                                          int identifier) {
1285   // Keep a reference on the stack. See NOTE above.
1286   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1287   if (!LoadFindInterface())
1288     return false;
1289   find_identifier_ = identifier;
1290   return PP_ToBool(
1291       plugin_find_interface_->StartFind(
1292           pp_instance(),
1293           UTF16ToUTF8(search_text.c_str()).c_str(),
1294           PP_FromBool(case_sensitive)));
1295 }
1296
1297 void PepperPluginInstanceImpl::SelectFindResult(bool forward) {
1298   // Keep a reference on the stack. See NOTE above.
1299   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1300   if (LoadFindInterface())
1301     plugin_find_interface_->SelectFindResult(pp_instance(),
1302                                              PP_FromBool(forward));
1303 }
1304
1305 void PepperPluginInstanceImpl::StopFind() {
1306   // Keep a reference on the stack. See NOTE above.
1307   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1308   if (!LoadFindInterface())
1309     return;
1310   find_identifier_ = -1;
1311   plugin_find_interface_->StopFind(pp_instance());
1312 }
1313
1314 bool PepperPluginInstanceImpl::LoadFindInterface() {
1315   if (!plugin_find_interface_) {
1316     plugin_find_interface_ =
1317         static_cast<const PPP_Find_Dev*>(module_->GetPluginInterface(
1318             PPP_FIND_DEV_INTERFACE));
1319   }
1320
1321   return !!plugin_find_interface_;
1322 }
1323
1324 bool PepperPluginInstanceImpl::LoadInputEventInterface() {
1325   if (!checked_for_plugin_input_event_interface_) {
1326     checked_for_plugin_input_event_interface_ = true;
1327     plugin_input_event_interface_ =
1328         static_cast<const PPP_InputEvent*>(module_->GetPluginInterface(
1329             PPP_INPUT_EVENT_INTERFACE));
1330   }
1331   return !!plugin_input_event_interface_;
1332 }
1333
1334 bool PepperPluginInstanceImpl::LoadMessagingInterface() {
1335   if (!checked_for_plugin_messaging_interface_) {
1336     checked_for_plugin_messaging_interface_ = true;
1337     plugin_messaging_interface_ =
1338         static_cast<const PPP_Messaging*>(module_->GetPluginInterface(
1339             PPP_MESSAGING_INTERFACE));
1340   }
1341   return !!plugin_messaging_interface_;
1342 }
1343
1344 bool PepperPluginInstanceImpl::LoadMouseLockInterface() {
1345   if (!plugin_mouse_lock_interface_) {
1346     plugin_mouse_lock_interface_ =
1347         static_cast<const PPP_MouseLock*>(module_->GetPluginInterface(
1348             PPP_MOUSELOCK_INTERFACE));
1349   }
1350
1351   return !!plugin_mouse_lock_interface_;
1352 }
1353
1354 bool PepperPluginInstanceImpl::LoadPdfInterface() {
1355   if (!checked_for_plugin_pdf_interface_) {
1356     checked_for_plugin_pdf_interface_ = true;
1357     plugin_pdf_interface_ =
1358         static_cast<const PPP_Pdf_1*>(module_->GetPluginInterface(
1359             PPP_PDF_INTERFACE_1));
1360   }
1361
1362   return !!plugin_pdf_interface_;
1363 }
1364
1365 bool PepperPluginInstanceImpl::LoadPrintInterface() {
1366   // Only check for the interface if the plugin has dev permission.
1367   if (!module_->permissions().HasPermission(ppapi::PERMISSION_DEV))
1368     return false;
1369   if (!plugin_print_interface_) {
1370     plugin_print_interface_ = static_cast<const PPP_Printing_Dev*>(
1371         module_->GetPluginInterface(PPP_PRINTING_DEV_INTERFACE));
1372   }
1373   return !!plugin_print_interface_;
1374 }
1375
1376 bool PepperPluginInstanceImpl::LoadPrivateInterface() {
1377   // Only check for the interface if the plugin has private permission.
1378   if (!module_->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
1379     return false;
1380   if (!plugin_private_interface_) {
1381     plugin_private_interface_ = static_cast<const PPP_Instance_Private*>(
1382         module_->GetPluginInterface(PPP_INSTANCE_PRIVATE_INTERFACE));
1383   }
1384
1385   return !!plugin_private_interface_;
1386 }
1387
1388 bool PepperPluginInstanceImpl::LoadSelectionInterface() {
1389   if (!plugin_selection_interface_) {
1390     plugin_selection_interface_ =
1391         static_cast<const PPP_Selection_Dev*>(module_->GetPluginInterface(
1392             PPP_SELECTION_DEV_INTERFACE));
1393   }
1394   return !!plugin_selection_interface_;
1395 }
1396
1397 bool PepperPluginInstanceImpl::LoadTextInputInterface() {
1398   if (!plugin_textinput_interface_) {
1399     plugin_textinput_interface_ =
1400         static_cast<const PPP_TextInput_Dev*>(module_->GetPluginInterface(
1401             PPP_TEXTINPUT_DEV_INTERFACE));
1402   }
1403
1404   return !!plugin_textinput_interface_;
1405 }
1406
1407 bool PepperPluginInstanceImpl::LoadZoomInterface() {
1408   if (!plugin_zoom_interface_) {
1409     plugin_zoom_interface_ =
1410         static_cast<const PPP_Zoom_Dev*>(module_->GetPluginInterface(
1411             PPP_ZOOM_DEV_INTERFACE));
1412   }
1413
1414   return !!plugin_zoom_interface_;
1415 }
1416
1417 bool PepperPluginInstanceImpl::PluginHasFocus() const {
1418   return flash_fullscreen_ || (has_webkit_focus_ && has_content_area_focus_);
1419 }
1420
1421 void PepperPluginInstanceImpl::SendFocusChangeNotification() {
1422   // Keep a reference on the stack. RenderViewImpl::PepperFocusChanged may
1423   // remove the <embed> from the DOM, which will make the PepperWebPluginImpl
1424   // drop its reference, usually the last one. This is similar to possible
1425   // plugin behavior described at the NOTE above Delete().
1426   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1427
1428   bool has_focus = PluginHasFocus();
1429   render_view_->PepperFocusChanged(this, has_focus);
1430
1431   // instance_interface_ may have been cleared in Delete() if the
1432   // PepperWebPluginImpl is destroyed.
1433   if (instance_interface_)
1434     instance_interface_->DidChangeFocus(pp_instance(), PP_FromBool(has_focus));
1435 }
1436
1437 void PepperPluginInstanceImpl::UpdateTouchEventRequest() {
1438   bool raw_touch = (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_TOUCH) ||
1439                    (input_event_mask_ & PP_INPUTEVENT_CLASS_TOUCH);
1440   container_->requestTouchEventType(raw_touch ?
1441       WebKit::WebPluginContainer::TouchEventRequestTypeRaw :
1442       WebKit::WebPluginContainer::TouchEventRequestTypeSynthesizedMouse);
1443 }
1444
1445 bool PepperPluginInstanceImpl::IsAcceptingWheelEvents() const {
1446   return (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_WHEEL) ||
1447       (input_event_mask_ & PP_INPUTEVENT_CLASS_WHEEL);
1448 }
1449
1450 void PepperPluginInstanceImpl::ScheduleAsyncDidChangeView() {
1451   if (view_change_weak_ptr_factory_.HasWeakPtrs())
1452     return;  // Already scheduled.
1453   base::MessageLoop::current()->PostTask(
1454       FROM_HERE,
1455       base::Bind(&PepperPluginInstanceImpl::SendAsyncDidChangeView,
1456                  view_change_weak_ptr_factory_.GetWeakPtr()));
1457 }
1458
1459 void PepperPluginInstanceImpl::SendAsyncDidChangeView() {
1460   // The bound callback that owns the weak pointer is still valid until after
1461   // this function returns. SendDidChangeView checks HasWeakPtrs, so we need to
1462   // invalidate them here.
1463   // NOTE: If we ever want to have more than one pending callback, it should
1464   // use a different factory, or we should have a different strategy here.
1465   view_change_weak_ptr_factory_.InvalidateWeakPtrs();
1466   SendDidChangeView();
1467 }
1468
1469 void PepperPluginInstanceImpl::SendDidChangeView() {
1470   // Don't send DidChangeView to crashed plugins.
1471   if (module()->is_crashed())
1472     return;
1473
1474   if (view_change_weak_ptr_factory_.HasWeakPtrs() ||
1475       (sent_initial_did_change_view_ &&
1476        last_sent_view_data_.Equals(view_data_)))
1477     return;  // Nothing to update.
1478
1479   const PP_Size& size = view_data_.rect.size;
1480   // Avoid sending a notification with a huge rectangle.
1481   if (size.width < 0  || size.width > kMaxPluginSideLength ||
1482       size.height < 0 || size.height > kMaxPluginSideLength ||
1483       // We know this won't overflow due to above checks.
1484       static_cast<uint32>(size.width) * static_cast<uint32>(size.height) >
1485           kMaxPluginSize) {
1486     return;
1487   }
1488
1489   sent_initial_did_change_view_ = true;
1490   last_sent_view_data_ = view_data_;
1491   ScopedPPResource resource(
1492       ScopedPPResource::PassRef(),
1493       (new PPB_View_Shared(ppapi::OBJECT_IS_IMPL,
1494                            pp_instance(), view_data_))->GetReference());
1495
1496   instance_interface_->DidChangeView(pp_instance(), resource,
1497                                      &view_data_.rect,
1498                                      &view_data_.clip_rect);
1499 }
1500
1501 void PepperPluginInstanceImpl::ReportGeometry() {
1502   // If this call was delayed, we may have transitioned back to fullscreen in
1503   // the mean time, so only report the geometry if we are actually in normal
1504   // mode.
1505   if (container_ && !fullscreen_container_ && !flash_fullscreen_)
1506     container_->reportGeometry();
1507 }
1508
1509 bool PepperPluginInstanceImpl::GetPreferredPrintOutputFormat(
1510     PP_PrintOutputFormat_Dev* format) {
1511   // Keep a reference on the stack. See NOTE above.
1512   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1513   if (!LoadPrintInterface())
1514     return false;
1515   uint32_t supported_formats =
1516       plugin_print_interface_->QuerySupportedFormats(pp_instance());
1517   if (supported_formats & PP_PRINTOUTPUTFORMAT_PDF) {
1518     *format = PP_PRINTOUTPUTFORMAT_PDF;
1519     return true;
1520   }
1521   return false;
1522 }
1523
1524 bool PepperPluginInstanceImpl::SupportsPrintInterface() {
1525   PP_PrintOutputFormat_Dev format;
1526   return GetPreferredPrintOutputFormat(&format);
1527 }
1528
1529 bool PepperPluginInstanceImpl::IsPrintScalingDisabled() {
1530   DCHECK(plugin_print_interface_);
1531   if (!plugin_print_interface_)
1532     return false;
1533   return plugin_print_interface_->IsScalingDisabled(pp_instance()) == PP_TRUE;
1534 }
1535
1536 int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
1537   // Keep a reference on the stack. See NOTE above.
1538   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1539   PP_PrintOutputFormat_Dev format;
1540   if (!GetPreferredPrintOutputFormat(&format)) {
1541     // PrintBegin should not have been called since SupportsPrintInterface
1542     // would have returned false;
1543     NOTREACHED();
1544     return 0;
1545   }
1546   int num_pages = 0;
1547   PP_PrintSettings_Dev print_settings;
1548   print_settings.printable_area = PP_FromGfxRect(print_params.printableArea);
1549   print_settings.content_area = PP_FromGfxRect(print_params.printContentArea);
1550   print_settings.paper_size = PP_FromGfxSize(print_params.paperSize);
1551   print_settings.dpi = print_params.printerDPI;
1552   print_settings.orientation = PP_PRINTORIENTATION_NORMAL;
1553   print_settings.grayscale = PP_FALSE;
1554   print_settings.print_scaling_option = static_cast<PP_PrintScalingOption_Dev>(
1555       print_params.printScalingOption);
1556   print_settings.format = format;
1557   num_pages = plugin_print_interface_->Begin(pp_instance(),
1558                                              &print_settings);
1559   if (!num_pages)
1560     return 0;
1561   current_print_settings_ = print_settings;
1562   canvas_.clear();
1563   ranges_.clear();
1564   return num_pages;
1565 }
1566
1567 bool PepperPluginInstanceImpl::PrintPage(int page_number,
1568                                          WebKit::WebCanvas* canvas) {
1569 #if defined(ENABLE_FULL_PRINTING)
1570   DCHECK(plugin_print_interface_);
1571   PP_PrintPageNumberRange_Dev page_range;
1572   page_range.first_page_number = page_range.last_page_number = page_number;
1573   // The canvas only has a metafile on it for print preview.
1574   bool save_for_later =
1575       (printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas) != NULL);
1576 #if defined(OS_MACOSX) || defined(OS_WIN)
1577   save_for_later = save_for_later && skia::IsPreviewMetafile(*canvas);
1578 #endif
1579   if (save_for_later) {
1580     ranges_.push_back(page_range);
1581     canvas_ = skia::SharePtr(canvas);
1582     return true;
1583   } else {
1584     return PrintPageHelper(&page_range, 1, canvas);
1585   }
1586 #else  // defined(ENABLED_PRINTING)
1587   return false;
1588 #endif
1589 }
1590
1591 bool PepperPluginInstanceImpl::PrintPageHelper(
1592     PP_PrintPageNumberRange_Dev* page_ranges,
1593     int num_ranges,
1594     WebKit::WebCanvas* canvas) {
1595   // Keep a reference on the stack. See NOTE above.
1596   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1597   DCHECK(plugin_print_interface_);
1598   if (!plugin_print_interface_)
1599     return false;
1600   PP_Resource print_output = plugin_print_interface_->PrintPages(
1601       pp_instance(), page_ranges, num_ranges);
1602   if (!print_output)
1603     return false;
1604
1605   bool ret = false;
1606
1607   if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF)
1608     ret = PrintPDFOutput(print_output, canvas);
1609
1610   // Now we need to release the print output resource.
1611   PluginModule::GetCore()->ReleaseResource(print_output);
1612
1613   return ret;
1614 }
1615
1616 void PepperPluginInstanceImpl::PrintEnd() {
1617   // Keep a reference on the stack. See NOTE above.
1618   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1619   if (!ranges_.empty())
1620     PrintPageHelper(&(ranges_.front()), ranges_.size(), canvas_.get());
1621   canvas_.clear();
1622   ranges_.clear();
1623
1624   DCHECK(plugin_print_interface_);
1625   if (plugin_print_interface_)
1626     plugin_print_interface_->End(pp_instance());
1627
1628   memset(&current_print_settings_, 0, sizeof(current_print_settings_));
1629 #if defined(OS_MACOSX)
1630   last_printed_page_ = NULL;
1631 #endif  // defined(OS_MACOSX)
1632 }
1633
1634 bool PepperPluginInstanceImpl::CanRotateView() {
1635   if (!LoadPdfInterface())
1636     return false;
1637
1638   return true;
1639 }
1640
1641 void PepperPluginInstanceImpl::RotateView(WebPlugin::RotationType type) {
1642   if (!LoadPdfInterface())
1643     return;
1644   PP_PrivatePageTransformType transform_type =
1645       type == WebPlugin::RotationType90Clockwise ?
1646       PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CW :
1647       PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CCW;
1648   plugin_pdf_interface_->Transform(pp_instance(), transform_type);
1649   // NOTE: plugin instance may have been deleted.
1650 }
1651
1652 bool PepperPluginInstanceImpl::FlashIsFullscreenOrPending() {
1653   return fullscreen_container_ != NULL;
1654 }
1655
1656 bool PepperPluginInstanceImpl::IsFullscreenOrPending() {
1657   return desired_fullscreen_state_;
1658 }
1659
1660 bool PepperPluginInstanceImpl::SetFullscreen(bool fullscreen) {
1661   // Keep a reference on the stack. See NOTE above.
1662   scoped_refptr<PepperPluginInstanceImpl> ref(this);
1663
1664   // Check whether we are trying to switch to the state we're already going
1665   // to (i.e. if we're already switching to fullscreen but the fullscreen
1666   // container isn't ready yet, don't do anything more).
1667   if (fullscreen == IsFullscreenOrPending())
1668     return false;
1669
1670   if (fullscreen && !render_view_->IsPluginFullscreenAllowed())
1671     return false;
1672
1673   // Check whether we are trying to switch while the state is in transition.
1674   // The 2nd request gets dropped while messing up the internal state, so
1675   // disallow this.
1676   if (view_data_.is_fullscreen != desired_fullscreen_state_)
1677     return false;
1678
1679   if (fullscreen && !IsProcessingUserGesture())
1680     return false;
1681
1682   VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off");
1683   desired_fullscreen_state_ = fullscreen;
1684
1685   if (fullscreen) {
1686     // Create the user gesture in case we're processing one that's pending.
1687     WebScopedUserGesture user_gesture(CurrentUserGestureToken());
1688     // WebKit does not resize the plugin to fill the screen in fullscreen mode,
1689     // so we will tweak plugin's attributes to support the expected behavior.
1690     KeepSizeAttributesBeforeFullscreen();
1691     SetSizeAttributesForFullscreen();
1692     container_->element().requestFullScreen();
1693   } else {
1694     container_->element().document().cancelFullScreen();
1695   }
1696   return true;
1697 }
1698
1699 void PepperPluginInstanceImpl::UpdateFlashFullscreenState(
1700     bool flash_fullscreen) {
1701   bool is_mouselock_pending = TrackedCallback::IsPending(lock_mouse_callback_);
1702
1703   if (flash_fullscreen == flash_fullscreen_) {
1704     // Manually clear callback when fullscreen fails with mouselock pending.
1705     if (!flash_fullscreen && is_mouselock_pending)
1706       lock_mouse_callback_->Run(PP_ERROR_FAILED);
1707     return;
1708   }
1709
1710   UpdateLayer();
1711
1712   bool old_plugin_focus = PluginHasFocus();
1713   flash_fullscreen_ = flash_fullscreen;
1714   if (is_mouselock_pending && !IsMouseLocked()) {
1715     if (!IsProcessingUserGesture() &&
1716         !module_->permissions().HasPermission(
1717             ppapi::PERMISSION_BYPASS_USER_GESTURE)) {
1718       lock_mouse_callback_->Run(PP_ERROR_NO_USER_GESTURE);
1719     } else {
1720       // Open a user gesture here so the Webkit user gesture checks will succeed
1721       // for out-of-process plugins.
1722       WebScopedUserGesture user_gesture(CurrentUserGestureToken());
1723       if (!LockMouse())
1724         lock_mouse_callback_->Run(PP_ERROR_FAILED);
1725     }
1726   }
1727
1728   if (PluginHasFocus() != old_plugin_focus)
1729     SendFocusChangeNotification();
1730 }
1731
1732 bool PepperPluginInstanceImpl::IsViewAccelerated() {
1733   if (!container_)
1734     return false;
1735
1736   WebDocument document = container_->element().document();
1737   WebFrame* frame = document.frame();
1738   if (!frame)
1739     return false;
1740   WebView* view = frame->view();
1741   if (!view)
1742     return false;
1743
1744   return view->isAcceleratedCompositingActive();
1745 }
1746
1747 bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output,
1748                                               WebKit::WebCanvas* canvas) {
1749 #if defined(ENABLE_FULL_PRINTING)
1750   ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
1751   if (enter.failed())
1752     return false;
1753
1754   BufferAutoMapper mapper(enter.object());
1755   if (!mapper.data() || !mapper.size()) {
1756     NOTREACHED();
1757     return false;
1758   }
1759 #if defined(OS_WIN)
1760   // For Windows, we need the PDF DLL to render the output PDF to a DC.
1761   HMODULE pdf_module = GetModuleHandle(L"pdf.dll");
1762   if (!pdf_module)
1763     return false;
1764   RenderPDFPageToDCProc render_proc =
1765       reinterpret_cast<RenderPDFPageToDCProc>(
1766           GetProcAddress(pdf_module, "RenderPDFPageToDC"));
1767   if (!render_proc)
1768     return false;
1769 #endif  // defined(OS_WIN)
1770
1771   bool ret = false;
1772 #if defined(OS_POSIX) && !defined(OS_ANDROID)
1773   // On Linux we just set the final bits in the native metafile
1774   // (NativeMetafile and PreviewMetafile must have compatible formats,
1775   // i.e. both PDF for this to work).
1776   printing::Metafile* metafile =
1777       printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas);
1778   DCHECK(metafile != NULL);
1779   if (metafile)
1780     ret = metafile->InitFromData(mapper.data(), mapper.size());
1781 #elif defined(OS_WIN)
1782   printing::Metafile* metafile =
1783     printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas);
1784   if (metafile) {
1785     // We only have a metafile when doing print preview, so we just want to
1786     // pass the PDF off to preview.
1787     ret = metafile->InitFromData(mapper.data(), mapper.size());
1788   } else {
1789     // On Windows, we now need to render the PDF to the DC that backs the
1790     // supplied canvas.
1791     HDC dc = skia::BeginPlatformPaint(canvas);
1792     DrawEmptyRectangle(dc);
1793     gfx::Size size_in_pixels;
1794     size_in_pixels.set_width(printing::ConvertUnit(
1795         current_print_settings_.printable_area.size.width,
1796         static_cast<int>(printing::kPointsPerInch),
1797         current_print_settings_.dpi));
1798     size_in_pixels.set_height(printing::ConvertUnit(
1799         current_print_settings_.printable_area.size.height,
1800         static_cast<int>(printing::kPointsPerInch),
1801         current_print_settings_.dpi));
1802     // We need to scale down DC to fit an entire page into DC available area.
1803     // First, we'll try to use default scaling based on the 72dpi that is
1804     // used in webkit for printing.
1805     // If default scaling is not enough to fit the entire PDF without
1806     // Current metafile is based on screen DC and have current screen size.
1807     // Writing outside of those boundaries will result in the cut-off output.
1808     // On metafiles (this is the case here), scaling down will still record
1809     // original coordinates and we'll be able to print in full resolution.
1810     // Before playback we'll need to counter the scaling up that will happen
1811     // in the browser (printed_document_win.cc).
1812     double dynamic_scale = gfx::CalculatePageScale(dc, size_in_pixels.width(),
1813                                                    size_in_pixels.height());
1814     double page_scale = static_cast<double>(printing::kPointsPerInch) /
1815         static_cast<double>(current_print_settings_.dpi);
1816
1817     if (dynamic_scale < page_scale) {
1818       page_scale = dynamic_scale;
1819       printing::MetafileSkiaWrapper::SetCustomScaleOnCanvas(*canvas,
1820                                                             page_scale);
1821     }
1822
1823     gfx::ScaleDC(dc, page_scale);
1824
1825     ret = render_proc(static_cast<unsigned char*>(mapper.data()), mapper.size(),
1826                       0, dc, current_print_settings_.dpi,
1827                       current_print_settings_.dpi, 0, 0, size_in_pixels.width(),
1828                       size_in_pixels.height(), true, false, true, true, true);
1829     skia::EndPlatformPaint(canvas);
1830   }
1831 #endif  // defined(OS_WIN)
1832
1833   return ret;
1834 #else  // defined(ENABLE_FULL_PRINTING)
1835   return false;
1836 #endif
1837 }
1838
1839 static void IgnoreCallback(unsigned, bool) {}
1840
1841 void PepperPluginInstanceImpl::UpdateLayer() {
1842   if (!container_)
1843     return;
1844
1845   gpu::Mailbox mailbox;
1846   if (bound_graphics_3d_.get()) {
1847     PlatformContext3D* context = bound_graphics_3d_->platform_context();
1848     context->GetBackingMailbox(&mailbox);
1849   }
1850   bool want_3d_layer = !mailbox.IsZero();
1851   bool want_2d_layer = bound_graphics_2d_platform_ &&
1852                        CommandLine::ForCurrentProcess()->HasSwitch(
1853                            switches::kEnableSoftwareCompositing);
1854   bool want_layer = want_3d_layer || want_2d_layer;
1855
1856   if ((want_layer == !!texture_layer_.get()) &&
1857       (want_3d_layer == layer_is_hardware_) &&
1858       layer_bound_to_fullscreen_ == !!fullscreen_container_)
1859     return;
1860
1861   if (texture_layer_) {
1862     if (!layer_bound_to_fullscreen_)
1863       container_->setWebLayer(NULL);
1864     else if (fullscreen_container_)
1865       fullscreen_container_->SetLayer(NULL);
1866     web_layer_.reset();
1867     texture_layer_ = NULL;
1868   }
1869   if (want_layer) {
1870     bool opaque = false;
1871     if (want_3d_layer) {
1872       DCHECK(bound_graphics_3d_.get());
1873       texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
1874       opaque = bound_graphics_3d_->IsOpaque();
1875       texture_layer_->SetTextureMailbox(
1876           cc::TextureMailbox(mailbox, 0),
1877           cc::SingleReleaseCallback::Create(base::Bind(&IgnoreCallback)));
1878     } else {
1879       DCHECK(bound_graphics_2d_platform_);
1880       texture_layer_ = cc::TextureLayer::CreateForMailbox(this);
1881       bound_graphics_2d_platform_->AttachedToNewLayer();
1882       opaque = bound_graphics_2d_platform_->IsAlwaysOpaque();
1883       texture_layer_->SetFlipped(false);
1884     }
1885     web_layer_.reset(new webkit::WebLayerImpl(texture_layer_));
1886     if (fullscreen_container_) {
1887       fullscreen_container_->SetLayer(web_layer_.get());
1888       // Ignore transparency in fullscreen, since that's what Flash always
1889       // wants to do, and that lets it not recreate a context if
1890       // wmode=transparent was specified.
1891       texture_layer_->SetContentsOpaque(true);
1892     } else {
1893       container_->setWebLayer(web_layer_.get());
1894       texture_layer_->SetContentsOpaque(opaque);
1895     }
1896   }
1897   layer_bound_to_fullscreen_ = !!fullscreen_container_;
1898   layer_is_hardware_ = want_3d_layer;
1899 }
1900
1901 unsigned PepperPluginInstanceImpl::PrepareTexture() {
1902   return 0;
1903 }
1904
1905 WebKit::WebGraphicsContext3D* PepperPluginInstanceImpl::Context3d() {
1906   return NULL;
1907 }
1908
1909 bool PepperPluginInstanceImpl::PrepareTextureMailbox(
1910     cc::TextureMailbox* mailbox,
1911     scoped_ptr<cc::SingleReleaseCallback>* release_callback,
1912     bool use_shared_memory) {
1913   if (!bound_graphics_2d_platform_)
1914     return false;
1915   return bound_graphics_2d_platform_->PrepareTextureMailbox(
1916       mailbox, release_callback);
1917 }
1918
1919 void PepperPluginInstanceImpl::AddPluginObject(PluginObject* plugin_object) {
1920   DCHECK(live_plugin_objects_.find(plugin_object) ==
1921          live_plugin_objects_.end());
1922   live_plugin_objects_.insert(plugin_object);
1923 }
1924
1925 void PepperPluginInstanceImpl::RemovePluginObject(PluginObject* plugin_object) {
1926   // Don't actually verify that the object is in the set since during module
1927   // deletion we'll be in the process of freeing them.
1928   live_plugin_objects_.erase(plugin_object);
1929 }
1930
1931 bool PepperPluginInstanceImpl::IsProcessingUserGesture() {
1932   PP_TimeTicks now = ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
1933   // Give a lot of slack so tests won't be flaky.
1934   const PP_TimeTicks kUserGestureDurationInSeconds = 10.0;
1935   return pending_user_gesture_token_.hasGestures() &&
1936          (now - pending_user_gesture_ < kUserGestureDurationInSeconds);
1937 }
1938
1939 WebUserGestureToken PepperPluginInstanceImpl::CurrentUserGestureToken() {
1940   if (!IsProcessingUserGesture())
1941     pending_user_gesture_token_ = WebUserGestureToken();
1942   return pending_user_gesture_token_;
1943 }
1944
1945 void PepperPluginInstanceImpl::OnLockMouseACK(bool succeeded) {
1946   if (TrackedCallback::IsPending(lock_mouse_callback_))
1947     lock_mouse_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
1948 }
1949
1950 void PepperPluginInstanceImpl::OnMouseLockLost() {
1951   if (LoadMouseLockInterface())
1952     plugin_mouse_lock_interface_->MouseLockLost(pp_instance());
1953 }
1954
1955 void PepperPluginInstanceImpl::HandleMouseLockedInputEvent(
1956     const WebKit::WebMouseEvent& event) {
1957   // |cursor_info| is ignored since it is hidden when the mouse is locked.
1958   WebKit::WebCursorInfo cursor_info;
1959   HandleInputEvent(event, &cursor_info);
1960 }
1961
1962 void PepperPluginInstanceImpl::SimulateInputEvent(
1963     const InputEventData& input_event) {
1964   WebView* web_view = container()->element().document().frame()->view();
1965   if (!web_view) {
1966     NOTREACHED();
1967     return;
1968   }
1969
1970   bool handled = SimulateIMEEvent(input_event);
1971   if (handled)
1972     return;
1973
1974   std::vector<linked_ptr<WebInputEvent> > events =
1975       CreateSimulatedWebInputEvents(
1976           input_event,
1977           view_data_.rect.point.x + view_data_.rect.size.width / 2,
1978           view_data_.rect.point.y + view_data_.rect.size.height / 2);
1979   for (std::vector<linked_ptr<WebInputEvent> >::iterator it = events.begin();
1980       it != events.end(); ++it) {
1981     web_view->handleInputEvent(*it->get());
1982   }
1983 }
1984
1985 bool PepperPluginInstanceImpl::SimulateIMEEvent(
1986     const InputEventData& input_event) {
1987   switch (input_event.event_type) {
1988     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
1989     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
1990       SimulateImeSetCompositionEvent(input_event);
1991       break;
1992     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
1993       DCHECK(input_event.character_text.empty());
1994       SimulateImeSetCompositionEvent(input_event);
1995       break;
1996     case PP_INPUTEVENT_TYPE_IME_TEXT:
1997       render_view_->SimulateImeConfirmComposition(
1998           UTF8ToUTF16(input_event.character_text), gfx::Range());
1999       break;
2000     default:
2001       return false;
2002   }
2003   return true;
2004 }
2005
2006 void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent(
2007     const InputEventData& input_event) {
2008   std::vector<size_t> offsets;
2009   offsets.push_back(input_event.composition_selection_start);
2010   offsets.push_back(input_event.composition_selection_end);
2011   offsets.insert(offsets.end(),
2012                  input_event.composition_segment_offsets.begin(),
2013                  input_event.composition_segment_offsets.end());
2014
2015   base::string16 utf16_text =
2016       base::UTF8ToUTF16AndAdjustOffsets(input_event.character_text, &offsets);
2017
2018   std::vector<WebKit::WebCompositionUnderline> underlines;
2019   for (size_t i = 2; i + 1 < offsets.size(); ++i) {
2020     WebKit::WebCompositionUnderline underline;
2021     underline.startOffset = offsets[i];
2022     underline.endOffset = offsets[i + 1];
2023     if (input_event.composition_target_segment == static_cast<int32_t>(i - 2))
2024       underline.thick = true;
2025     underlines.push_back(underline);
2026   }
2027
2028   render_view_->SimulateImeSetComposition(
2029       utf16_text, underlines, offsets[0], offsets[1]);
2030 }
2031
2032 ContentDecryptorDelegate*
2033     PepperPluginInstanceImpl::GetContentDecryptorDelegate() {
2034   if (content_decryptor_delegate_)
2035     return content_decryptor_delegate_.get();
2036
2037   const PPP_ContentDecryptor_Private* plugin_decryption_interface =
2038       static_cast<const PPP_ContentDecryptor_Private*>(
2039           module_->GetPluginInterface(
2040               PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE));
2041   if (!plugin_decryption_interface)
2042     return NULL;
2043
2044   content_decryptor_delegate_.reset(
2045       new ContentDecryptorDelegate(pp_instance_, plugin_decryption_interface));
2046   return content_decryptor_delegate_.get();
2047 }
2048
2049 PP_Bool PepperPluginInstanceImpl::BindGraphics(PP_Instance instance,
2050                                                PP_Resource device) {
2051   TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::BindGraphics");
2052   // The Graphics3D instance can't be destroyed until we call
2053   // UpdateLayer().
2054   scoped_refptr<ppapi::Resource> old_graphics = bound_graphics_3d_.get();
2055   if (bound_graphics_3d_.get()) {
2056     bound_graphics_3d_->BindToInstance(false);
2057     bound_graphics_3d_ = NULL;
2058   }
2059   if (bound_graphics_2d_platform_) {
2060     bound_graphics_2d_platform_->BindToInstance(NULL);
2061     bound_graphics_2d_platform_ = NULL;
2062   }
2063
2064   // Special-case clearing the current device.
2065   if (!device) {
2066     UpdateLayer();
2067     InvalidateRect(gfx::Rect());
2068     return PP_TRUE;
2069   }
2070
2071   // Refuse to bind if in transition to fullscreen with PPB_FlashFullscreen or
2072   // to/from fullscreen with PPB_Fullscreen.
2073   if ((fullscreen_container_ && !flash_fullscreen_) ||
2074       desired_fullscreen_state_ != view_data_.is_fullscreen)
2075     return PP_FALSE;
2076
2077   const ppapi::host::PpapiHost* ppapi_host =
2078       RendererPpapiHost::GetForPPInstance(instance)->GetPpapiHost();
2079   ppapi::host::ResourceHost* host = ppapi_host->GetResourceHost(device);
2080   PepperGraphics2DHost* graphics_2d = NULL;
2081   if (host) {
2082     if (host->IsGraphics2DHost())
2083       graphics_2d = static_cast<PepperGraphics2DHost*>(host);
2084     DLOG_IF(ERROR, !graphics_2d) << "Resource is not PepperGraphics2DHost.";
2085   }
2086
2087   EnterResourceNoLock<PPB_Graphics3D_API> enter_3d(device, false);
2088   PPB_Graphics3D_Impl* graphics_3d = enter_3d.succeeded() ?
2089       static_cast<PPB_Graphics3D_Impl*>(enter_3d.object()) : NULL;
2090
2091   if (graphics_2d) {
2092     if (graphics_2d->BindToInstance(this)) {
2093       bound_graphics_2d_platform_ = graphics_2d;
2094       UpdateLayer();
2095       return PP_TRUE;
2096     }
2097   } else if (graphics_3d) {
2098     // Make sure graphics can only be bound to the instance it is
2099     // associated with.
2100     if (graphics_3d->pp_instance() == pp_instance() &&
2101         graphics_3d->BindToInstance(true)) {
2102       bound_graphics_3d_ = graphics_3d;
2103       UpdateLayer();
2104       return PP_TRUE;
2105     }
2106   }
2107
2108   // The instance cannot be bound or the device is not a valid resource type.
2109   return PP_FALSE;
2110 }
2111
2112 PP_Bool PepperPluginInstanceImpl::IsFullFrame(PP_Instance instance) {
2113   return PP_FromBool(full_frame());
2114 }
2115
2116 const ViewData* PepperPluginInstanceImpl::GetViewData(PP_Instance instance) {
2117   return &view_data_;
2118 }
2119
2120 PP_Bool PepperPluginInstanceImpl::FlashIsFullscreen(PP_Instance instance) {
2121   return PP_FromBool(flash_fullscreen_);
2122 }
2123
2124 PP_Var PepperPluginInstanceImpl::GetWindowObject(PP_Instance instance) {
2125   if (!container_)
2126     return PP_MakeUndefined();
2127
2128   WebFrame* frame = container_->element().document().frame();
2129   if (!frame)
2130     return PP_MakeUndefined();
2131
2132   return NPObjectToPPVar(this, frame->windowObject());
2133 }
2134
2135 PP_Var PepperPluginInstanceImpl::GetOwnerElementObject(PP_Instance instance) {
2136   if (!container_)
2137     return PP_MakeUndefined();
2138   return NPObjectToPPVar(this, container_->scriptableObjectForElement());
2139 }
2140
2141 PP_Var PepperPluginInstanceImpl::ExecuteScript(PP_Instance instance,
2142                                                PP_Var script,
2143                                                PP_Var* exception) {
2144   // Executing the script may remove the plugin from the DOM, so we need to keep
2145   // a reference to ourselves so that we can still process the result after the
2146   // WebBindings::evaluate() below.
2147   scoped_refptr<PepperPluginInstanceImpl> ref(this);
2148   TryCatch try_catch(exception);
2149   if (try_catch.has_exception())
2150     return PP_MakeUndefined();
2151
2152   // Convert the script into an inconvenient NPString object.
2153   StringVar* script_string = StringVar::FromPPVar(script);
2154   if (!script_string) {
2155     try_catch.SetException("Script param to ExecuteScript must be a string.");
2156     return PP_MakeUndefined();
2157   }
2158   NPString np_script;
2159   np_script.UTF8Characters = script_string->value().c_str();
2160   np_script.UTF8Length = script_string->value().length();
2161
2162   // Get the current frame to pass to the evaluate function.
2163   WebFrame* frame = container_->element().document().frame();
2164   if (!frame) {
2165     try_catch.SetException("No frame to execute script in.");
2166     return PP_MakeUndefined();
2167   }
2168
2169   NPVariant result;
2170   bool ok = false;
2171   if (IsProcessingUserGesture()) {
2172     WebKit::WebScopedUserGesture user_gesture(CurrentUserGestureToken());
2173     ok = WebBindings::evaluate(NULL, frame->windowObject(), &np_script,
2174                                &result);
2175   } else {
2176     ok = WebBindings::evaluate(NULL, frame->windowObject(), &np_script,
2177                                &result);
2178   }
2179   if (!ok) {
2180     // TryCatch doesn't catch the exceptions properly. Since this is only for
2181     // a trusted API, just set to a general exception message.
2182     try_catch.SetException("Exception caught");
2183     WebBindings::releaseVariantValue(&result);
2184     return PP_MakeUndefined();
2185   }
2186
2187   PP_Var ret = NPVariantToPPVar(this, &result);
2188   WebBindings::releaseVariantValue(&result);
2189   return ret;
2190 }
2191
2192 uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputSampleRate(
2193     PP_Instance instance) {
2194   RenderThreadImpl* thread = RenderThreadImpl::current();
2195   return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
2196 }
2197
2198 uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputBufferSize(
2199     PP_Instance instance) {
2200   RenderThreadImpl* thread = RenderThreadImpl::current();
2201   return thread->GetAudioHardwareConfig()->GetOutputBufferSize();
2202 }
2203
2204 PP_Var PepperPluginInstanceImpl::GetDefaultCharSet(PP_Instance instance) {
2205   return StringVar::StringToPPVar(
2206       render_view_->webkit_preferences().default_encoding);
2207 }
2208
2209 // These PPB_ContentDecryptor_Private calls are responses to
2210 // PPP_ContentDecryptor_Private calls made on |content_decryptor_delegate_|.
2211 // Therefore, |content_decryptor_delegate_| must have been initialized when
2212 // the following methods are called.
2213 void PepperPluginInstanceImpl::KeyAdded(PP_Instance instance,
2214                                         PP_Var key_system_var,
2215                                         PP_Var session_id_var) {
2216   content_decryptor_delegate_->KeyAdded(key_system_var, session_id_var);
2217 }
2218
2219 void PepperPluginInstanceImpl::KeyMessage(PP_Instance instance,
2220                                           PP_Var key_system_var,
2221                                           PP_Var session_id_var,
2222                                           PP_Var message_var,
2223                                           PP_Var default_url_var) {
2224   content_decryptor_delegate_->KeyMessage(
2225       key_system_var, session_id_var, message_var, default_url_var);
2226 }
2227
2228 void PepperPluginInstanceImpl::KeyError(PP_Instance instance,
2229                                         PP_Var key_system_var,
2230                                         PP_Var session_id_var,
2231                                         int32_t media_error,
2232                                         int32_t system_code) {
2233   content_decryptor_delegate_->KeyError(
2234       key_system_var, session_id_var, media_error, system_code);
2235 }
2236
2237 void PepperPluginInstanceImpl::DeliverBlock(
2238     PP_Instance instance,
2239     PP_Resource decrypted_block,
2240     const PP_DecryptedBlockInfo* block_info) {
2241   content_decryptor_delegate_->DeliverBlock(decrypted_block, block_info);
2242 }
2243
2244 void PepperPluginInstanceImpl::DecoderInitializeDone(
2245     PP_Instance instance,
2246     PP_DecryptorStreamType decoder_type,
2247     uint32_t request_id,
2248     PP_Bool success) {
2249   content_decryptor_delegate_->DecoderInitializeDone(
2250       decoder_type, request_id, success);
2251 }
2252
2253 void PepperPluginInstanceImpl::DecoderDeinitializeDone(
2254     PP_Instance instance,
2255     PP_DecryptorStreamType decoder_type,
2256     uint32_t request_id) {
2257   content_decryptor_delegate_->DecoderDeinitializeDone(decoder_type,
2258                                                        request_id);
2259 }
2260
2261 void PepperPluginInstanceImpl::DecoderResetDone(
2262     PP_Instance instance,
2263     PP_DecryptorStreamType decoder_type,
2264     uint32_t request_id) {
2265   content_decryptor_delegate_->DecoderResetDone(decoder_type, request_id);
2266 }
2267
2268
2269 void PepperPluginInstanceImpl::DeliverFrame(
2270     PP_Instance instance,
2271     PP_Resource decrypted_frame,
2272     const PP_DecryptedFrameInfo* frame_info) {
2273   content_decryptor_delegate_->DeliverFrame(decrypted_frame, frame_info);
2274 }
2275
2276 void PepperPluginInstanceImpl::DeliverSamples(
2277     PP_Instance instance,
2278     PP_Resource audio_frames,
2279     const PP_DecryptedSampleInfo* sample_info) {
2280   content_decryptor_delegate_->DeliverSamples(audio_frames, sample_info);
2281 }
2282
2283 void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
2284     PP_Instance instance,
2285     int32_t total,
2286     PP_Bool final_result) {
2287   DCHECK_NE(find_identifier_, -1);
2288   render_view_->reportFindInPageMatchCount(
2289       find_identifier_, total, PP_ToBool(final_result));
2290 }
2291
2292 void PepperPluginInstanceImpl::SelectedFindResultChanged(PP_Instance instance,
2293                                                          int32_t index) {
2294   DCHECK_NE(find_identifier_, -1);
2295   render_view_->reportFindInPageSelection(
2296       find_identifier_, index + 1, WebKit::WebRect());
2297 }
2298
2299 PP_Bool PepperPluginInstanceImpl::IsFullscreen(PP_Instance instance) {
2300   return PP_FromBool(view_data_.is_fullscreen);
2301 }
2302
2303 PP_Bool PepperPluginInstanceImpl::SetFullscreen(PP_Instance instance,
2304                                                 PP_Bool fullscreen) {
2305   return PP_FromBool(SetFullscreen(PP_ToBool(fullscreen)));
2306 }
2307
2308 PP_Bool PepperPluginInstanceImpl::GetScreenSize(PP_Instance instance,
2309                                                 PP_Size* size) {
2310   WebKit::WebScreenInfo info = render_view_->screenInfo();
2311   *size = PP_MakeSize(info.rect.width, info.rect.height);
2312   return PP_TRUE;
2313 }
2314
2315 ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
2316     PP_Instance instance,
2317     ppapi::SingletonResourceID id) {
2318   // Flash APIs and some others aren't implemented in-process.
2319   switch (id) {
2320     case ppapi::BROKER_SINGLETON_ID:
2321     case ppapi::BROWSER_FONT_SINGLETON_ID:
2322     case ppapi::CRX_FILESYSTEM_SINGLETON_ID:
2323     case ppapi::EXTENSIONS_COMMON_SINGLETON_ID:
2324     case ppapi::FLASH_CLIPBOARD_SINGLETON_ID:
2325     case ppapi::FLASH_FILE_SINGLETON_ID:
2326     case ppapi::FLASH_FULLSCREEN_SINGLETON_ID:
2327     case ppapi::FLASH_SINGLETON_ID:
2328     case ppapi::NETWORK_PROXY_SINGLETON_ID:
2329     case ppapi::PDF_SINGLETON_ID:
2330     case ppapi::TRUETYPE_FONT_SINGLETON_ID:
2331       NOTIMPLEMENTED();
2332       return NULL;
2333     case ppapi::GAMEPAD_SINGLETON_ID:
2334       return gamepad_impl_.get();
2335   }
2336
2337   NOTREACHED();
2338   return NULL;
2339 }
2340
2341 int32_t PepperPluginInstanceImpl::RequestInputEvents(PP_Instance instance,
2342                                                      uint32_t event_classes) {
2343   input_event_mask_ |= event_classes;
2344   filtered_input_event_mask_ &= ~(event_classes);
2345   RequestInputEventsHelper(event_classes);
2346   return ValidateRequestInputEvents(false, event_classes);
2347 }
2348
2349 int32_t PepperPluginInstanceImpl::RequestFilteringInputEvents(
2350     PP_Instance instance,
2351     uint32_t event_classes) {
2352   filtered_input_event_mask_ |= event_classes;
2353   input_event_mask_ &= ~(event_classes);
2354   RequestInputEventsHelper(event_classes);
2355   return ValidateRequestInputEvents(true, event_classes);
2356 }
2357
2358 void PepperPluginInstanceImpl::ClearInputEventRequest(PP_Instance instance,
2359                                                       uint32_t event_classes) {
2360   input_event_mask_ &= ~(event_classes);
2361   filtered_input_event_mask_ &= ~(event_classes);
2362   RequestInputEventsHelper(event_classes);
2363 }
2364
2365 void PepperPluginInstanceImpl::ZoomChanged(PP_Instance instance,
2366                                            double factor) {
2367   // We only want to tell the page to change its zoom if the whole page is the
2368   // plugin.  If we're in an iframe, then don't do anything.
2369   if (!IsFullPagePlugin())
2370     return;
2371   container()->zoomLevelChanged(content::ZoomFactorToZoomLevel(factor));
2372 }
2373
2374 void PepperPluginInstanceImpl::ZoomLimitsChanged(PP_Instance instance,
2375                                                  double minimum_factor,
2376                                                  double maximum_factor) {
2377   if (minimum_factor > maximum_factor) {
2378     NOTREACHED();
2379     return;
2380   }
2381   double minimum_level = ZoomFactorToZoomLevel(minimum_factor);
2382   double maximum_level = ZoomFactorToZoomLevel(maximum_factor);
2383   render_view_->webview()->zoomLimitsChanged(minimum_level, maximum_level);
2384 }
2385
2386 void PepperPluginInstanceImpl::PostMessage(PP_Instance instance,
2387                                            PP_Var message) {
2388   message_channel_->PostMessageToJavaScript(message);
2389 }
2390
2391 PP_Bool PepperPluginInstanceImpl::SetCursor(PP_Instance instance,
2392                                             PP_MouseCursor_Type type,
2393                                             PP_Resource image,
2394                                             const PP_Point* hot_spot) {
2395   if (!ValidateSetCursorParams(type, image, hot_spot))
2396     return PP_FALSE;
2397
2398   if (type != PP_MOUSECURSOR_TYPE_CUSTOM) {
2399     DoSetCursor(new WebCursorInfo(static_cast<WebCursorInfo::Type>(type)));
2400     return PP_TRUE;
2401   }
2402
2403   EnterResourceNoLock<PPB_ImageData_API> enter(image, true);
2404   if (enter.failed())
2405     return PP_FALSE;
2406   PPB_ImageData_Impl* image_data =
2407       static_cast<PPB_ImageData_Impl*>(enter.object());
2408
2409   ImageDataAutoMapper auto_mapper(image_data);
2410   if (!auto_mapper.is_valid())
2411     return PP_FALSE;
2412
2413   scoped_ptr<WebCursorInfo> custom_cursor(
2414       new WebCursorInfo(WebCursorInfo::TypeCustom));
2415   custom_cursor->hotSpot.x = hot_spot->x;
2416   custom_cursor->hotSpot.y = hot_spot->y;
2417
2418   const SkBitmap* bitmap = image_data->GetMappedBitmap();
2419   // Make a deep copy, so that the cursor remains valid even after the original
2420   // image data gets freed.
2421   if (!bitmap->copyTo(&custom_cursor->customImage.getSkBitmap(),
2422                       bitmap->config())) {
2423     return PP_FALSE;
2424   }
2425
2426   DoSetCursor(custom_cursor.release());
2427   return PP_TRUE;
2428 }
2429
2430 int32_t PepperPluginInstanceImpl::LockMouse(
2431     PP_Instance instance,
2432     scoped_refptr<TrackedCallback> callback) {
2433   if (TrackedCallback::IsPending(lock_mouse_callback_))
2434     return PP_ERROR_INPROGRESS;
2435
2436   if (IsMouseLocked())
2437     return PP_OK;
2438
2439   if (!CanAccessMainFrame())
2440     return PP_ERROR_NOACCESS;
2441
2442   if (!IsProcessingUserGesture())
2443     return PP_ERROR_NO_USER_GESTURE;
2444
2445   // Attempt mouselock only if Flash isn't waiting on fullscreen, otherwise
2446   // we wait and call LockMouse() in UpdateFlashFullscreenState().
2447   if (!FlashIsFullscreenOrPending() || flash_fullscreen_) {
2448     // Open a user gesture here so the Webkit user gesture checks will succeed
2449     // for out-of-process plugins.
2450     WebScopedUserGesture user_gesture(CurrentUserGestureToken());
2451     if (!LockMouse())
2452       return PP_ERROR_FAILED;
2453   }
2454
2455   // Either mouselock succeeded or a Flash fullscreen is pending.
2456   lock_mouse_callback_ = callback;
2457   return PP_OK_COMPLETIONPENDING;
2458 }
2459
2460 void PepperPluginInstanceImpl::UnlockMouse(PP_Instance instance) {
2461   GetMouseLockDispatcher()->UnlockMouse(GetOrCreateLockTargetAdapter());
2462 }
2463
2464 void PepperPluginInstanceImpl::SetTextInputType(PP_Instance instance,
2465                                                 PP_TextInput_Type type) {
2466   int itype = type;
2467   if (itype < 0 || itype > ui::TEXT_INPUT_TYPE_URL)
2468     itype = ui::TEXT_INPUT_TYPE_NONE;
2469   text_input_type_ = static_cast<ui::TextInputType>(itype);
2470   render_view_->PepperTextInputTypeChanged(this);
2471 }
2472
2473 void PepperPluginInstanceImpl::UpdateCaretPosition(
2474     PP_Instance instance,
2475     const PP_Rect& caret,
2476     const PP_Rect& bounding_box) {
2477   text_input_caret_ = PP_ToGfxRect(caret);
2478   text_input_caret_bounds_ = PP_ToGfxRect(bounding_box);
2479   text_input_caret_set_ = true;
2480   render_view_->PepperCaretPositionChanged(this);
2481 }
2482
2483 void PepperPluginInstanceImpl::CancelCompositionText(PP_Instance instance) {
2484   render_view_->PepperCancelComposition(this);
2485 }
2486
2487 void PepperPluginInstanceImpl::SelectionChanged(PP_Instance instance) {
2488   // TODO(kinaba): currently the browser always calls RequestSurroundingText.
2489   // It can be optimized so that it won't call it back until the information
2490   // is really needed.
2491
2492   // Avoid calling in nested context or else this will reenter the plugin. This
2493   // uses a weak pointer rather than exploiting the fact that this class is
2494   // refcounted because we don't actually want this operation to affect the
2495   // lifetime of the instance.
2496   base::MessageLoop::current()->PostTask(
2497       FROM_HERE,
2498       base::Bind(&PepperPluginInstanceImpl::RequestSurroundingText,
2499                  AsWeakPtr(),
2500                  static_cast<size_t>(kExtraCharsForTextInput)));
2501 }
2502
2503 void PepperPluginInstanceImpl::UpdateSurroundingText(PP_Instance instance,
2504                                                      const char* text,
2505                                                      uint32_t caret,
2506                                                      uint32_t anchor) {
2507   surrounding_text_ = text;
2508   selection_caret_ = caret;
2509   selection_anchor_ = anchor;
2510   render_view_->PepperSelectionChanged(this);
2511 }
2512
2513 PP_Var PepperPluginInstanceImpl::ResolveRelativeToDocument(
2514     PP_Instance instance,
2515     PP_Var relative,
2516     PP_URLComponents_Dev* components) {
2517   StringVar* relative_string = StringVar::FromPPVar(relative);
2518   if (!relative_string)
2519     return PP_MakeNull();
2520
2521   WebElement plugin_element = container()->element();
2522   GURL document_url = plugin_element.document().baseURL();
2523   return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(
2524       document_url.Resolve(relative_string->value()),
2525       components);
2526 }
2527
2528 PP_Bool PepperPluginInstanceImpl::DocumentCanRequest(PP_Instance instance,
2529                                                      PP_Var url) {
2530   StringVar* url_string = StringVar::FromPPVar(url);
2531   if (!url_string)
2532     return PP_FALSE;
2533
2534   WebKit::WebSecurityOrigin security_origin;
2535   if (!SecurityOriginForInstance(instance, &security_origin))
2536     return PP_FALSE;
2537
2538   GURL gurl(url_string->value());
2539   if (!gurl.is_valid())
2540     return PP_FALSE;
2541
2542   return BoolToPPBool(security_origin.canRequest(gurl));
2543 }
2544
2545 PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument(
2546     PP_Instance instance,
2547     PP_Instance target) {
2548   WebKit::WebSecurityOrigin our_origin;
2549   if (!SecurityOriginForInstance(instance, &our_origin))
2550     return PP_FALSE;
2551
2552   WebKit::WebSecurityOrigin target_origin;
2553   if (!SecurityOriginForInstance(instance, &target_origin))
2554     return PP_FALSE;
2555
2556   return BoolToPPBool(our_origin.canAccess(target_origin));
2557 }
2558
2559 PP_Var PepperPluginInstanceImpl::GetDocumentURL(
2560     PP_Instance instance,
2561     PP_URLComponents_Dev* components) {
2562   WebKit::WebDocument document = container()->element().document();
2563   return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
2564                                                       components);
2565 }
2566
2567 PP_Var PepperPluginInstanceImpl::GetPluginInstanceURL(
2568     PP_Instance instance,
2569     PP_URLComponents_Dev* components) {
2570   return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(plugin_url_,
2571                                                       components);
2572 }
2573
2574 PP_Var PepperPluginInstanceImpl::GetPluginReferrerURL(
2575     PP_Instance instance,
2576     PP_URLComponents_Dev* components) {
2577   WebKit::WebDocument document = container()->element().document();
2578   if (!full_frame_)
2579     return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
2580                                                         components);
2581   WebFrame* frame = document.frame();
2582   if (!frame)
2583     return PP_MakeUndefined();
2584   const WebURLRequest& request = frame->dataSource()->originalRequest();
2585   WebString referer = request.httpHeaderField("Referer");
2586   if (referer.isEmpty())
2587     return PP_MakeUndefined();
2588   return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(GURL(referer),
2589                                                       components);
2590 }
2591
2592 PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
2593     scoped_refptr<PluginModule> module) {
2594   // Save the original module and switch over to the new one now that this
2595   // plugin is using the IPC-based proxy.
2596   original_module_ = module_;
2597   module_ = module;
2598
2599   // Don't send any messages to the plugin until DidCreate() has finished.
2600   message_channel_->QueueJavaScriptMessages();
2601
2602   // For NaCl instances, remember the NaCl plugin instance interface, so we
2603   // can shut it down by calling its DidDestroy in our Delete() method.
2604   original_instance_interface_.reset(instance_interface_.release());
2605
2606   base::Callback<const void*(const char*)> get_plugin_interface_func =
2607       base::Bind(&PluginModule::GetPluginInterface, module_.get());
2608   PPP_Instance_Combined* ppp_instance_combined =
2609       PPP_Instance_Combined::Create(get_plugin_interface_func);
2610   if (!ppp_instance_combined) {
2611     // The proxy must support at least one usable PPP_Instance interface.
2612     // While this could be a failure to implement the interface in the NaCl
2613     // module, it is more likely that the NaCl process has crashed. Either
2614     // way, report that module initialization failed.
2615     return PP_EXTERNAL_PLUGIN_ERROR_MODULE;
2616   }
2617
2618   instance_interface_.reset(ppp_instance_combined);
2619   // Clear all PPP interfaces we may have cached.
2620   plugin_find_interface_ = NULL;
2621   plugin_input_event_interface_ = NULL;
2622   checked_for_plugin_input_event_interface_ = false;
2623   plugin_messaging_interface_ = NULL;
2624   checked_for_plugin_messaging_interface_ = false;
2625   plugin_mouse_lock_interface_ = NULL;
2626   plugin_pdf_interface_ = NULL;
2627   checked_for_plugin_pdf_interface_ = false;
2628   plugin_private_interface_ = NULL;
2629   plugin_selection_interface_ = NULL;
2630   plugin_textinput_interface_ = NULL;
2631   plugin_zoom_interface_ = NULL;
2632
2633   // Re-send the DidCreate event via the proxy.
2634   scoped_ptr<const char*[]> argn_array(StringVectorToArgArray(argn_));
2635   scoped_ptr<const char*[]> argv_array(StringVectorToArgArray(argv_));
2636   if (!instance_interface_->DidCreate(pp_instance(), argn_.size(),
2637                                       argn_array.get(), argv_array.get()))
2638     return PP_EXTERNAL_PLUGIN_ERROR_INSTANCE;
2639   message_channel_->StopQueueingJavaScriptMessages();
2640
2641   // Clear sent_initial_did_change_view_ and cancel any pending DidChangeView
2642   // event. This way, SendDidChangeView will send the "current" view
2643   // immediately (before other events like HandleDocumentLoad).
2644   sent_initial_did_change_view_ = false;
2645   view_change_weak_ptr_factory_.InvalidateWeakPtrs();
2646   SendDidChangeView();
2647
2648   DCHECK(external_document_load_);
2649   external_document_load_ = false;
2650   if (!external_document_response_.isNull()) {
2651     document_loader_ = NULL;
2652     // Pass the response to the new proxy.
2653     HandleDocumentLoad(external_document_response_);
2654     external_document_response_ = WebKit::WebURLResponse();
2655     // Replay any document load events we've received to the real loader.
2656     external_document_loader_->ReplayReceivedData(document_loader_);
2657     external_document_loader_.reset(NULL);
2658   }
2659
2660   return PP_EXTERNAL_PLUGIN_OK;
2661 }
2662
2663 bool PepperPluginInstanceImpl::IsValidInstanceOf(PluginModule* module) {
2664   DCHECK(module);
2665   return module == module_.get() ||
2666          module == original_module_.get();
2667 }
2668
2669 NPP PepperPluginInstanceImpl::instanceNPP() {
2670   return npp_.get();
2671 }
2672
2673 v8::Isolate* PepperPluginInstanceImpl::GetIsolate() const {
2674   return isolate_;
2675 }
2676
2677 PepperPluginInstance* PepperPluginInstance::Get(PP_Instance instance_id) {
2678   return HostGlobals::Get()->GetInstance(instance_id);
2679 }
2680
2681 RenderView* PepperPluginInstanceImpl::GetRenderView() {
2682   return render_view_;
2683 }
2684
2685 WebKit::WebPluginContainer* PepperPluginInstanceImpl::GetContainer() {
2686   return container_;
2687 }
2688
2689 ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() {
2690   return HostGlobals::Get()->GetVarTracker();
2691 }
2692
2693 const GURL& PepperPluginInstanceImpl::GetPluginURL() {
2694   return plugin_url_;
2695 }
2696
2697 base::FilePath PepperPluginInstanceImpl::GetModulePath() {
2698   return module_->path();
2699 }
2700
2701 PP_Resource PepperPluginInstanceImpl::CreateImage(gfx::ImageSkia* source_image,
2702                                                   float scale) {
2703   gfx::ImageSkiaRep image_skia_rep = source_image->GetRepresentation(scale);
2704
2705   if (image_skia_rep.is_null() || image_skia_rep.scale() != scale)
2706     return 0;
2707
2708   scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl(
2709       pp_instance(),
2710       PPB_ImageData_Impl::PLATFORM));
2711   if (!image_data->Init(
2712           PPB_ImageData_Impl::GetNativeImageDataFormat(),
2713           image_skia_rep.pixel_width(),
2714           image_skia_rep.pixel_height(),
2715           false)) {
2716     return 0;
2717   }
2718
2719   ImageDataAutoMapper mapper(image_data.get());
2720   if (!mapper.is_valid())
2721     return 0;
2722
2723   skia::PlatformCanvas* canvas = image_data->GetPlatformCanvas();
2724   // Note: Do not SkBitmap::copyTo the canvas bitmap directly because it will
2725   // ignore the allocated pixels in shared memory and re-allocate a new buffer.
2726   canvas->writePixels(image_skia_rep.sk_bitmap(), 0, 0);
2727
2728   return image_data->GetReference();
2729 }
2730
2731 PP_ExternalPluginResult PepperPluginInstanceImpl::SwitchToOutOfProcessProxy(
2732     const base::FilePath& file_path,
2733     ppapi::PpapiPermissions permissions,
2734     const IPC::ChannelHandle& channel_handle,
2735     base::ProcessId plugin_pid,
2736     int plugin_child_id) {
2737   // Create a new module for each instance of the external plugin that is using
2738   // the IPC based out-of-process proxy. We can't use the existing module,
2739   // because it is configured for the in-process plugin, and we must keep it
2740   // that way to allow the page to create other instances.
2741   scoped_refptr<PluginModule> external_plugin_module(
2742       module_->CreateModuleForExternalPluginInstance());
2743
2744   RendererPpapiHostImpl* renderer_ppapi_host =
2745       external_plugin_module->CreateOutOfProcessModule(
2746           render_view_,
2747           file_path,
2748           permissions,
2749           channel_handle,
2750           plugin_pid,
2751           plugin_child_id,
2752           true);
2753   if (!renderer_ppapi_host) {
2754     DLOG(ERROR) << "CreateExternalPluginModule() failed";
2755     return PP_EXTERNAL_PLUGIN_ERROR_MODULE;
2756   }
2757
2758   // Finally, switch the instance to the proxy.
2759   return external_plugin_module->InitAsProxiedExternalPlugin(this);
2760 }
2761
2762 void PepperPluginInstanceImpl::SetAlwaysOnTop(bool on_top) {
2763   always_on_top_ = on_top;
2764 }
2765
2766 void PepperPluginInstanceImpl::DoSetCursor(WebCursorInfo* cursor) {
2767   cursor_.reset(cursor);
2768   if (fullscreen_container_) {
2769     fullscreen_container_->DidChangeCursor(*cursor);
2770   } else {
2771     render_view_->PepperDidChangeCursor(this, *cursor);
2772   }
2773 }
2774
2775 bool PepperPluginInstanceImpl::IsFullPagePlugin() {
2776   WebFrame* frame = container()->element().document().frame();
2777   return frame->view()->mainFrame()->document().isPluginDocument();
2778 }
2779
2780 bool PepperPluginInstanceImpl::FlashSetFullscreen(bool fullscreen,
2781                                                   bool delay_report) {
2782   TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::FlashSetFullscreen");
2783   // Keep a reference on the stack. See NOTE above.
2784   scoped_refptr<PepperPluginInstanceImpl> ref(this);
2785
2786   // We check whether we are trying to switch to the state we're already going
2787   // to (i.e. if we're already switching to fullscreen but the fullscreen
2788   // container isn't ready yet, don't do anything more).
2789   if (fullscreen == FlashIsFullscreenOrPending())
2790     return true;
2791
2792   if (fullscreen && !render_view_->IsPluginFullscreenAllowed())
2793     return false;
2794
2795   // Unbind current 2D or 3D graphics context.
2796   VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off");
2797   if (fullscreen) {
2798     DCHECK(!fullscreen_container_);
2799     fullscreen_container_ = render_view_->CreatePepperFullscreenContainer(this);
2800     UpdateLayer();
2801   } else {
2802     DCHECK(fullscreen_container_);
2803     fullscreen_container_->Destroy();
2804     fullscreen_container_ = NULL;
2805     UpdateFlashFullscreenState(false);
2806     if (!delay_report) {
2807       ReportGeometry();
2808     } else {
2809       base::MessageLoop::current()->PostTask(
2810           FROM_HERE,
2811           base::Bind(&PepperPluginInstanceImpl::ReportGeometry, this));
2812     }
2813   }
2814
2815   return true;
2816 }
2817
2818 bool PepperPluginInstanceImpl::IsRectTopmost(const gfx::Rect& rect) {
2819   if (flash_fullscreen_)
2820     return true;
2821
2822   return container_->isRectTopmost(rect);
2823 }
2824
2825 int32_t PepperPluginInstanceImpl::Navigate(
2826     const ppapi::URLRequestInfoData& request,
2827     const char* target,
2828     bool from_user_action) {
2829   if (!container_)
2830     return PP_ERROR_FAILED;
2831
2832   WebDocument document = container_->element().document();
2833   WebFrame* frame = document.frame();
2834   if (!frame)
2835     return PP_ERROR_FAILED;
2836
2837   ppapi::URLRequestInfoData completed_request = request;
2838
2839   WebURLRequest web_request;
2840   if (!CreateWebURLRequest(pp_instance_,
2841                            &completed_request,
2842                            frame,
2843                            &web_request)) {
2844     return PP_ERROR_FAILED;
2845   }
2846   web_request.setFirstPartyForCookies(document.firstPartyForCookies());
2847   web_request.setHasUserGesture(from_user_action);
2848
2849   GURL gurl(web_request.url());
2850   if (gurl.SchemeIs("javascript")) {
2851     // In imitation of the NPAPI implementation, only |target_frame == frame| is
2852     // allowed for security reasons.
2853     WebFrame* target_frame =
2854         frame->view()->findFrameByName(WebString::fromUTF8(target), frame);
2855     if (target_frame != frame)
2856       return PP_ERROR_NOACCESS;
2857
2858     // TODO(viettrungluu): NPAPI sends the result back to the plugin -- do we
2859     // need that?
2860     WebString result = container_->executeScriptURL(gurl, from_user_action);
2861     return result.isNull() ? PP_ERROR_FAILED : PP_OK;
2862   }
2863
2864   // Only GETs and POSTs are supported.
2865   if (web_request.httpMethod() != "GET" &&
2866       web_request.httpMethod() != "POST")
2867     return PP_ERROR_BADARGUMENT;
2868
2869   WebString target_str = WebString::fromUTF8(target);
2870   container_->loadFrameRequest(web_request, target_str, false, NULL);
2871   return PP_OK;
2872 }
2873
2874 int PepperPluginInstanceImpl::MakePendingFileRefRendererHost(
2875     const base::FilePath& path) {
2876   RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
2877   PepperFileRefRendererHost* file_ref_host(
2878       new PepperFileRefRendererHost(host_impl, pp_instance(), 0, path));
2879   return host_impl->GetPpapiHost()->AddPendingResourceHost(
2880       scoped_ptr<ppapi::host::ResourceHost>(file_ref_host));
2881 }
2882
2883 bool PepperPluginInstanceImpl::CanAccessMainFrame() const {
2884   if (!container_)
2885     return false;
2886   WebKit::WebDocument containing_document = container_->element().document();
2887
2888   if (!containing_document.frame() ||
2889       !containing_document.frame()->view() ||
2890       !containing_document.frame()->view()->mainFrame()) {
2891     return false;
2892   }
2893   WebKit::WebDocument main_document =
2894       containing_document.frame()->view()->mainFrame()->document();
2895
2896   return containing_document.securityOrigin().canAccess(
2897       main_document.securityOrigin());
2898 }
2899
2900 void PepperPluginInstanceImpl::KeepSizeAttributesBeforeFullscreen() {
2901   WebElement element = container_->element();
2902   width_before_fullscreen_ = element.getAttribute(WebString::fromUTF8(kWidth));
2903   height_before_fullscreen_ =
2904       element.getAttribute(WebString::fromUTF8(kHeight));
2905   border_before_fullscreen_ =
2906       element.getAttribute(WebString::fromUTF8(kBorder));
2907   style_before_fullscreen_ = element.getAttribute(WebString::fromUTF8(kStyle));
2908 }
2909
2910 void PepperPluginInstanceImpl::SetSizeAttributesForFullscreen() {
2911   WebKit::WebScreenInfo info = render_view_->screenInfo();
2912   screen_size_for_fullscreen_ = gfx::Size(info.rect.width, info.rect.height);
2913   std::string width = StringPrintf("%d", screen_size_for_fullscreen_.width());
2914   std::string height = StringPrintf("%d", screen_size_for_fullscreen_.height());
2915
2916   WebElement element = container_->element();
2917   element.setAttribute(WebString::fromUTF8(kWidth), WebString::fromUTF8(width));
2918   element.setAttribute(WebString::fromUTF8(kHeight),
2919                        WebString::fromUTF8(height));
2920   element.setAttribute(WebString::fromUTF8(kBorder), WebString::fromUTF8("0"));
2921
2922   // There should be no style settings that matter in fullscreen mode,
2923   // so just replace them instead of appending.
2924   // NOTE: "position: fixed" and "display: block" reset the plugin and
2925   // using %% settings might not work without them (e.g. if the plugin is a
2926   // child of a container element).
2927   std::string style;
2928   style += StringPrintf("width: %s !important; ", width.c_str());
2929   style += StringPrintf("height: %s !important; ", height.c_str());
2930   style += "margin: 0 !important; padding: 0 !important; border: 0 !important";
2931   container_->element().setAttribute(kStyle, WebString::fromUTF8(style));
2932 }
2933
2934 void PepperPluginInstanceImpl::ResetSizeAttributesAfterFullscreen() {
2935   screen_size_for_fullscreen_ = gfx::Size();
2936   WebElement element = container_->element();
2937   element.setAttribute(WebString::fromUTF8(kWidth), width_before_fullscreen_);
2938   element.setAttribute(WebString::fromUTF8(kHeight), height_before_fullscreen_);
2939   element.setAttribute(WebString::fromUTF8(kBorder), border_before_fullscreen_);
2940   element.setAttribute(WebString::fromUTF8(kStyle), style_before_fullscreen_);
2941 }
2942
2943 bool PepperPluginInstanceImpl::IsMouseLocked() {
2944   return GetMouseLockDispatcher()->IsMouseLockedTo(
2945       GetOrCreateLockTargetAdapter());
2946 }
2947
2948 bool PepperPluginInstanceImpl::LockMouse() {
2949   return GetMouseLockDispatcher()->LockMouse(GetOrCreateLockTargetAdapter());
2950 }
2951
2952 MouseLockDispatcher::LockTarget*
2953     PepperPluginInstanceImpl::GetOrCreateLockTargetAdapter() {
2954   if (!lock_target_.get()) {
2955     lock_target_.reset(new PluginInstanceLockTarget(this));
2956   }
2957   return lock_target_.get();
2958 }
2959
2960 MouseLockDispatcher* PepperPluginInstanceImpl::GetMouseLockDispatcher() {
2961   if (flash_fullscreen_) {
2962     RenderWidgetFullscreenPepper* container =
2963         static_cast<RenderWidgetFullscreenPepper*>(fullscreen_container_);
2964     return container->mouse_lock_dispatcher();
2965   } else {
2966     return render_view_->mouse_lock_dispatcher();
2967   }
2968 }
2969
2970 void PepperPluginInstanceImpl::UnSetAndDeleteLockTargetAdapter() {
2971   if (lock_target_.get()) {
2972     GetMouseLockDispatcher()->OnLockTargetDestroyed(lock_target_.get());
2973     lock_target_.reset();
2974   }
2975 }
2976
2977 void PepperPluginInstanceImpl::DidDataFromWebURLResponse(
2978     const WebKit::WebURLResponse& response,
2979     int pending_host_id,
2980     const ppapi::URLResponseInfoData& data) {
2981   RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
2982
2983   if (host_impl->in_process_router()) {
2984     // Running in-process, we can just create the resource and call the
2985     // PPP_Instance function directly.
2986     scoped_refptr<ppapi::proxy::URLLoaderResource> loader_resource(
2987         new ppapi::proxy::URLLoaderResource(
2988             host_impl->in_process_router()->GetPluginConnection(pp_instance()),
2989             pp_instance(), pending_host_id, data));
2990
2991     PP_Resource loader_pp_resource = loader_resource->GetReference();
2992     if (!instance_interface_->HandleDocumentLoad(
2993             pp_instance(), loader_pp_resource))
2994       loader_resource->Close();
2995     // We don't pass a ref into the plugin, if it wants one, it will have taken
2996     // an additional one.
2997     ppapi::PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(
2998         loader_pp_resource);
2999   } else {
3000     // Running out-of-process. Initiate an IPC call to notify the plugin
3001     // process.
3002     ppapi::proxy::HostDispatcher* dispatcher =
3003         ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
3004     dispatcher->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad(
3005         ppapi::API_ID_PPP_INSTANCE, pp_instance(), pending_host_id, data));
3006   }
3007 }
3008
3009 }  // namespace content