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