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