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.
5 #include "content/renderer/pepper/pepper_webplugin_impl.h"
9 #include "base/debug/crash_logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "content/public/renderer/content_renderer_client.h"
12 #include "content/renderer/pepper/message_channel.h"
13 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
14 #include "content/renderer/pepper/plugin_instance_throttler_impl.h"
15 #include "content/renderer/pepper/plugin_module.h"
16 #include "content/renderer/pepper/v8object_var.h"
17 #include "content/renderer/render_frame_impl.h"
18 #include "ppapi/shared_impl/ppapi_globals.h"
19 #include "ppapi/shared_impl/var_tracker.h"
20 #include "third_party/WebKit/public/platform/WebPoint.h"
21 #include "third_party/WebKit/public/platform/WebRect.h"
22 #include "third_party/WebKit/public/platform/WebSize.h"
23 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
24 #include "third_party/WebKit/public/web/WebBindings.h"
25 #include "third_party/WebKit/public/web/WebDocument.h"
26 #include "third_party/WebKit/public/web/WebElement.h"
27 #include "third_party/WebKit/public/web/WebFrame.h"
28 #include "third_party/WebKit/public/web/WebPluginContainer.h"
29 #include "third_party/WebKit/public/web/WebPluginParams.h"
30 #include "third_party/WebKit/public/web/WebPrintParams.h"
31 #include "third_party/WebKit/public/web/WebPrintPresetOptions.h"
32 #include "third_party/WebKit/public/web/WebPrintScalingOption.h"
35 using ppapi::V8ObjectVar
;
36 using blink::WebCanvas
;
37 using blink::WebPlugin
;
38 using blink::WebPluginContainer
;
39 using blink::WebPluginParams
;
40 using blink::WebPoint
;
41 using blink::WebPrintParams
;
44 using blink::WebString
;
46 using blink::WebVector
;
50 struct PepperWebPluginImpl::InitData
{
51 scoped_refptr
<PluginModule
> module
;
52 RenderFrameImpl
* render_frame
;
53 std::vector
<std::string
> arg_names
;
54 std::vector
<std::string
> arg_values
;
58 PepperWebPluginImpl::PepperWebPluginImpl(
59 PluginModule
* plugin_module
,
60 const WebPluginParams
& params
,
61 RenderFrameImpl
* render_frame
,
62 scoped_ptr
<PluginInstanceThrottlerImpl
> throttler
)
63 : init_data_(new InitData()),
64 full_frame_(params
.loadManually
),
65 throttler_(throttler
.Pass()),
66 instance_object_(PP_MakeUndefined()),
69 DCHECK(plugin_module
);
70 init_data_
->module
= plugin_module
;
71 init_data_
->render_frame
= render_frame
;
72 for (size_t i
= 0; i
< params
.attributeNames
.size(); ++i
) {
73 init_data_
->arg_names
.push_back(params
.attributeNames
[i
].utf8());
74 init_data_
->arg_values
.push_back(params
.attributeValues
[i
].utf8());
76 init_data_
->url
= params
.url
;
78 // Set subresource URL for crash reporting.
79 base::debug::SetCrashKeyValue("subresource_url", init_data_
->url
.spec());
82 throttler_
->SetWebPlugin(this);
85 PepperWebPluginImpl::~PepperWebPluginImpl() {}
87 blink::WebPluginContainer
* PepperWebPluginImpl::container() const {
91 bool PepperWebPluginImpl::initialize(WebPluginContainer
* container
) {
92 // The plugin delegate may have gone away.
93 instance_
= init_data_
->module
->CreateInstance(
94 init_data_
->render_frame
, container
, init_data_
->url
);
98 // Enable script objects for this plugin.
99 container
->allowScriptObjects();
101 auto weak_this
= weak_factory_
.GetWeakPtr();
103 instance_
->Initialize(init_data_
->arg_names
, init_data_
->arg_values
,
104 full_frame_
, throttler_
.Pass());
105 // The above call to Initialize can result in re-entrancy and destruction of
106 // the plugin instance. In this case it's quite unclear whether this object
107 // could also have been destroyed. We could return false here, but it would be
108 // better if this object was guaranteed to outlast the recursive call.
109 // Otherwise, the caller of this function would also have to take care that,
110 // in the case of the object being deleted, we never access it again, and we
111 // would just keep passing that responsibility further up the call stack.
112 // Classes tend not to be written with this possibility in mind so it's best
113 // to make this assumption as far down the call stack (as close to the
114 // re-entrant call) as possible. Also take care not to access the plugin
115 // instance again in that case. crbug.com/487146.
124 blink::WebPlugin
* replacement_plugin
=
125 GetContentClient()->renderer()->CreatePluginReplacement(
126 init_data_
->render_frame
, init_data_
->module
->path());
127 if (!replacement_plugin
|| !replacement_plugin
->initialize(container
))
130 container
->setPlugin(replacement_plugin
);
135 container_
= container
;
139 void PepperWebPluginImpl::destroy() {
140 // Tell |container_| to clear references to this plugin's script objects.
142 container_
->clearScriptObjects();
144 if (instance_
.get()) {
145 ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_
);
146 instance_object_
= PP_MakeUndefined();
151 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
154 v8::Local
<v8::Object
> PepperWebPluginImpl::v8ScriptableObject(
155 v8::Isolate
* isolate
) {
156 // Re-entrancy may cause JS to try to execute script on the plugin before it
157 // is fully initialized. See e.g. crbug.com/503401.
158 if (!instance_
.get())
159 return v8::Local
<v8::Object
>();
160 // Call through the plugin to get its instance object. The plugin should pass
161 // us a reference which we release in destroy().
162 if (instance_object_
.type
== PP_VARTYPE_UNDEFINED
)
163 instance_object_
= instance_
->GetInstanceObject(isolate
);
164 // GetInstanceObject talked to the plugin which may have removed the instance
165 // from the DOM, in which case instance_ would be NULL now.
166 if (!instance_
.get())
167 return v8::Local
<v8::Object
>();
169 scoped_refptr
<V8ObjectVar
> object_var(
170 V8ObjectVar::FromPPVar(instance_object_
));
171 // If there's an InstanceObject, tell the Instance's MessageChannel to pass
172 // any non-postMessage calls to it.
173 if (object_var
.get()) {
174 MessageChannel
* message_channel
= instance_
->message_channel();
176 message_channel
->SetPassthroughObject(object_var
->GetHandle());
179 v8::Local
<v8::Object
> result
= instance_
->GetMessageChannelObject();
183 bool PepperWebPluginImpl::getFormValue(WebString
& value
) { return false; }
185 void PepperWebPluginImpl::paint(WebCanvas
* canvas
, const WebRect
& rect
) {
186 if (!instance_
->FlashIsFullscreenOrPending())
187 instance_
->Paint(canvas
, plugin_rect_
, rect
);
190 void PepperWebPluginImpl::updateGeometry(
191 const WebRect
& window_rect
,
192 const WebRect
& clip_rect
,
193 const WebRect
& unobscured_rect
,
194 const WebVector
<WebRect
>& cut_outs_rects
,
196 plugin_rect_
= window_rect
;
197 if (instance_
&& !instance_
->FlashIsFullscreenOrPending()) {
198 std::vector
<gfx::Rect
> cut_outs
;
199 for (size_t i
= 0; i
< cut_outs_rects
.size(); ++i
)
200 cut_outs
.push_back(cut_outs_rects
[i
]);
201 instance_
->ViewChanged(plugin_rect_
, clip_rect
, unobscured_rect
, cut_outs
);
205 void PepperWebPluginImpl::updateFocus(bool focused
,
206 blink::WebFocusType focus_type
) {
207 instance_
->SetWebKitFocus(focused
);
210 void PepperWebPluginImpl::updateVisibility(bool visible
) {}
212 bool PepperWebPluginImpl::acceptsInputEvents() { return true; }
214 bool PepperWebPluginImpl::handleInputEvent(const blink::WebInputEvent
& event
,
215 blink::WebCursorInfo
& cursor_info
) {
216 if (instance_
->FlashIsFullscreenOrPending())
218 return instance_
->HandleInputEvent(event
, &cursor_info
);
221 void PepperWebPluginImpl::didReceiveResponse(
222 const blink::WebURLResponse
& response
) {
223 DCHECK(!instance_
->document_loader());
224 instance_
->HandleDocumentLoad(response
);
227 void PepperWebPluginImpl::didReceiveData(const char* data
, int data_length
) {
228 blink::WebURLLoaderClient
* document_loader
= instance_
->document_loader();
230 document_loader
->didReceiveData(NULL
, data
, data_length
, 0);
233 void PepperWebPluginImpl::didFinishLoading() {
234 blink::WebURLLoaderClient
* document_loader
= instance_
->document_loader();
236 document_loader
->didFinishLoading(
237 NULL
, 0.0, blink::WebURLLoaderClient::kUnknownEncodedDataLength
);
240 void PepperWebPluginImpl::didFailLoading(const blink::WebURLError
& error
) {
241 blink::WebURLLoaderClient
* document_loader
= instance_
->document_loader();
243 document_loader
->didFail(NULL
, error
);
246 void PepperWebPluginImpl::didFinishLoadingFrameRequest(const blink::WebURL
& url
,
247 void* notify_data
) {}
249 void PepperWebPluginImpl::didFailLoadingFrameRequest(
250 const blink::WebURL
& url
,
252 const blink::WebURLError
& error
) {}
254 bool PepperWebPluginImpl::hasSelection() const {
255 return !selectionAsText().isEmpty();
258 WebString
PepperWebPluginImpl::selectionAsText() const {
259 return instance_
->GetSelectedText(false);
262 WebString
PepperWebPluginImpl::selectionAsMarkup() const {
263 return instance_
->GetSelectedText(true);
266 WebURL
PepperWebPluginImpl::linkAtPosition(const WebPoint
& position
) const {
267 return GURL(instance_
->GetLinkAtPosition(position
));
270 bool PepperWebPluginImpl::startFind(const blink::WebString
& search_text
,
273 return instance_
->StartFind(search_text
, case_sensitive
, identifier
);
276 void PepperWebPluginImpl::selectFindResult(bool forward
) {
277 instance_
->SelectFindResult(forward
);
280 void PepperWebPluginImpl::stopFind() { instance_
->StopFind(); }
282 bool PepperWebPluginImpl::supportsPaginatedPrint() {
283 return instance_
->SupportsPrintInterface();
286 bool PepperWebPluginImpl::isPrintScalingDisabled() {
287 return instance_
->IsPrintScalingDisabled();
290 int PepperWebPluginImpl::printBegin(const WebPrintParams
& print_params
) {
291 return instance_
->PrintBegin(print_params
);
294 void PepperWebPluginImpl::printPage(int page_number
, blink::WebCanvas
* canvas
) {
295 instance_
->PrintPage(page_number
, canvas
);
298 void PepperWebPluginImpl::printEnd() { instance_
->PrintEnd(); }
300 bool PepperWebPluginImpl::getPrintPresetOptionsFromDocument(
301 blink::WebPrintPresetOptions
* preset_options
) {
302 return instance_
->GetPrintPresetOptionsFromDocument(preset_options
);
305 bool PepperWebPluginImpl::canRotateView() { return instance_
->CanRotateView(); }
307 void PepperWebPluginImpl::rotateView(RotationType type
) {
308 instance_
->RotateView(type
);
311 bool PepperWebPluginImpl::isPlaceholder() { return false; }
313 } // namespace content