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