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