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