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