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/plugin/webplugin_delegate_stub.h"
7 #include "build/build_config.h"
10 #include "base/command_line.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "content/child/npapi/plugin_instance.h"
13 #include "content/child/npapi/webplugin_delegate_impl.h"
14 #include "content/child/npapi/webplugin_resource_client.h"
15 #include "content/child/plugin_messages.h"
16 #include "content/common/cursors/webcursor.h"
17 #include "content/plugin/plugin_channel.h"
18 #include "content/plugin/plugin_thread.h"
19 #include "content/plugin/webplugin_proxy.h"
20 #include "content/public/common/content_client.h"
21 #include "content/public/common/content_constants.h"
22 #include "content/public/common/content_switches.h"
23 #include "skia/ext/platform_device.h"
24 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
25 #include "third_party/WebKit/public/web/WebBindings.h"
26 #include "third_party/npapi/bindings/npapi.h"
27 #include "third_party/npapi/bindings/npruntime.h"
29 using blink::WebBindings
;
30 using blink::WebCursorInfo
;
34 static void DestroyWebPluginAndDelegate(
35 base::WeakPtr
<NPObjectStub
> scriptable_object
,
36 WebPluginDelegateImpl
* delegate
,
37 WebPlugin
* webplugin
) {
38 // The plugin may not expect us to try to release the scriptable object
39 // after calling NPP_Destroy on the instance, so delete the stub now.
40 if (scriptable_object
.get())
41 scriptable_object
->DeleteSoon();
44 // Save the object owner Id so we can unregister it as a valid owner
45 // after the instance has been destroyed.
46 NPP owner
= delegate
->GetPluginNPP();
48 // WebPlugin must outlive WebPluginDelegate.
49 delegate
->PluginDestroyed();
51 // PluginDestroyed can call into script, so only unregister as an object
52 // owner after that has completed.
53 WebBindings::unregisterObjectOwner(owner
);
59 WebPluginDelegateStub::WebPluginDelegateStub(
60 const std::string
& mime_type
, int instance_id
, PluginChannel
* channel
) :
61 mime_type_(mime_type
),
62 instance_id_(instance_id
),
66 in_destructor_(false) {
70 WebPluginDelegateStub::~WebPluginDelegateStub() {
71 in_destructor_
= true;
72 GetContentClient()->SetActiveURL(page_url_
);
74 if (channel_
->in_send()) {
75 // The delegate or an npobject is in the callstack, so don't delete it
77 base::MessageLoop::current()->PostNonNestableTask(
79 base::Bind(&DestroyWebPluginAndDelegate
,
80 plugin_scriptable_object_
,
84 // Safe to delete right away.
85 DestroyWebPluginAndDelegate(
86 plugin_scriptable_object_
, delegate_
, webplugin_
);
89 // Remove the NPObject owner mapping for this instance.
91 channel_
->RemoveMappingForNPObjectOwner(instance_id_
);
94 bool WebPluginDelegateStub::OnMessageReceived(const IPC::Message
& msg
) {
95 GetContentClient()->SetActiveURL(page_url_
);
97 // A plugin can execute a script to delete itself in any of its NPP methods.
98 // Hold an extra reference to ourself so that if this does occur and we're
99 // handling a sync message, we don't crash when attempting to send a reply.
100 // The exception to this is when we're already in the destructor.
105 IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateStub
, msg
)
106 IPC_MESSAGE_HANDLER(PluginMsg_Init
, OnInit
)
107 IPC_MESSAGE_HANDLER(PluginMsg_WillSendRequest
, OnWillSendRequest
)
108 IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveResponse
, OnDidReceiveResponse
)
109 IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveData
, OnDidReceiveData
)
110 IPC_MESSAGE_HANDLER(PluginMsg_DidFinishLoading
, OnDidFinishLoading
)
111 IPC_MESSAGE_HANDLER(PluginMsg_DidFail
, OnDidFail
)
112 IPC_MESSAGE_HANDLER(PluginMsg_DidFinishLoadWithReason
,
113 OnDidFinishLoadWithReason
)
114 IPC_MESSAGE_HANDLER(PluginMsg_SetFocus
, OnSetFocus
)
115 IPC_MESSAGE_HANDLER(PluginMsg_HandleInputEvent
, OnHandleInputEvent
)
116 IPC_MESSAGE_HANDLER(PluginMsg_Paint
, OnPaint
)
117 IPC_MESSAGE_HANDLER(PluginMsg_DidPaint
, OnDidPaint
)
118 IPC_MESSAGE_HANDLER(PluginMsg_GetPluginScriptableObject
,
119 OnGetPluginScriptableObject
)
120 IPC_MESSAGE_HANDLER(PluginMsg_GetFormValue
, OnGetFormValue
)
121 IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometry
, OnUpdateGeometry
)
122 IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometrySync
, OnUpdateGeometry
)
123 IPC_MESSAGE_HANDLER(PluginMsg_SendJavaScriptStream
,
124 OnSendJavaScriptStream
)
125 IPC_MESSAGE_HANDLER(PluginMsg_SetContentAreaFocus
, OnSetContentAreaFocus
)
126 #if defined(OS_WIN) && !defined(USE_AURA)
127 IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionUpdated
,
128 OnImeCompositionUpdated
)
129 IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionCompleted
,
130 OnImeCompositionCompleted
)
132 #if defined(OS_MACOSX)
133 IPC_MESSAGE_HANDLER(PluginMsg_SetWindowFocus
, OnSetWindowFocus
)
134 IPC_MESSAGE_HANDLER(PluginMsg_ContainerHidden
, OnContainerHidden
)
135 IPC_MESSAGE_HANDLER(PluginMsg_ContainerShown
, OnContainerShown
)
136 IPC_MESSAGE_HANDLER(PluginMsg_WindowFrameChanged
, OnWindowFrameChanged
)
137 IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionCompleted
,
138 OnImeCompositionCompleted
)
140 IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualResponse
,
141 OnDidReceiveManualResponse
)
142 IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualData
, OnDidReceiveManualData
)
143 IPC_MESSAGE_HANDLER(PluginMsg_DidFinishManualLoading
,
144 OnDidFinishManualLoading
)
145 IPC_MESSAGE_HANDLER(PluginMsg_DidManualLoadFail
, OnDidManualLoadFail
)
146 IPC_MESSAGE_HANDLER(PluginMsg_HandleURLRequestReply
,
147 OnHandleURLRequestReply
)
148 IPC_MESSAGE_HANDLER(PluginMsg_HTTPRangeRequestReply
,
149 OnHTTPRangeRequestReply
)
150 IPC_MESSAGE_HANDLER(PluginMsg_FetchURL
, OnFetchURL
)
151 IPC_MESSAGE_UNHANDLED(handled
= false)
152 IPC_END_MESSAGE_MAP()
161 bool WebPluginDelegateStub::Send(IPC::Message
* msg
) {
162 return channel_
->Send(msg
);
165 void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params
& params
,
168 page_url_
= params
.page_url
;
169 GetContentClient()->SetActiveURL(page_url_
);
171 *transparent
= false;
173 if (params
.arg_names
.size() != params
.arg_values
.size()) {
178 const base::CommandLine
& command_line
=
179 *base::CommandLine::ForCurrentProcess();
180 base::FilePath path
=
181 command_line
.GetSwitchValuePath(switches::kPluginPath
);
183 webplugin_
= new WebPluginProxy(channel_
.get(),
186 params
.host_render_view_routing_id
);
187 delegate_
= WebPluginDelegateImpl::Create(webplugin_
, path
, mime_type_
);
189 if (delegate_
->GetQuirks() &
190 WebPluginDelegateImpl::PLUGIN_QUIRK_DIE_AFTER_UNLOAD
) {
191 PluginThread::current()->SetForcefullyTerminatePluginProcess();
194 webplugin_
->set_delegate(delegate_
);
195 std::vector
<std::string
> arg_names
= params
.arg_names
;
196 std::vector
<std::string
> arg_values
= params
.arg_values
;
198 // Register the plugin as a valid object owner.
199 WebBindings::registerObjectOwner(delegate_
->GetPluginNPP());
201 // Add an NPObject owner mapping for this instance, to support ownership
202 // tracking in the renderer.
203 channel_
->AddMappingForNPObjectOwner(instance_id_
,
204 delegate_
->GetPluginNPP());
206 *result
= delegate_
->Initialize(params
.url
,
209 params
.load_manually
);
210 *transparent
= delegate_
->instance()->transparent();
214 void WebPluginDelegateStub::OnWillSendRequest(int id
, const GURL
& url
,
215 int http_status_code
) {
216 WebPluginResourceClient
* client
= webplugin_
->GetResourceClient(id
);
220 client
->WillSendRequest(url
, http_status_code
);
223 void WebPluginDelegateStub::OnDidReceiveResponse(
224 const PluginMsg_DidReceiveResponseParams
& params
) {
225 WebPluginResourceClient
* client
= webplugin_
->GetResourceClient(params
.id
);
229 client
->DidReceiveResponse(params
.mime_type
,
231 params
.expected_length
,
232 params
.last_modified
,
233 params
.request_is_seekable
);
236 void WebPluginDelegateStub::OnDidReceiveData(int id
,
237 const std::vector
<char>& buffer
,
239 WebPluginResourceClient
* client
= webplugin_
->GetResourceClient(id
);
243 client
->DidReceiveData(&buffer
.front(), static_cast<int>(buffer
.size()),
247 void WebPluginDelegateStub::OnDidFinishLoading(int id
) {
248 WebPluginResourceClient
* client
= webplugin_
->GetResourceClient(id
);
252 client
->DidFinishLoading(id
);
255 void WebPluginDelegateStub::OnDidFail(int id
) {
256 WebPluginResourceClient
* client
= webplugin_
->GetResourceClient(id
);
263 void WebPluginDelegateStub::OnDidFinishLoadWithReason(
264 const GURL
& url
, int reason
, int notify_id
) {
265 delegate_
->DidFinishLoadWithReason(url
, reason
, notify_id
);
268 void WebPluginDelegateStub::OnSetFocus(bool focused
) {
269 delegate_
->SetFocus(focused
);
270 #if defined(OS_WIN) && !defined(USE_AURA)
272 webplugin_
->UpdateIMEStatus();
276 void WebPluginDelegateStub::OnHandleInputEvent(
277 const blink::WebInputEvent
*event
,
280 WebCursor::CursorInfo cursor_info
;
281 *handled
= delegate_
->HandleInputEvent(*event
, &cursor_info
);
282 cursor
->InitFromCursorInfo(cursor_info
);
285 void WebPluginDelegateStub::OnPaint(const gfx::Rect
& damaged_rect
) {
286 webplugin_
->Paint(damaged_rect
);
289 void WebPluginDelegateStub::OnDidPaint() {
290 webplugin_
->DidPaint();
293 void WebPluginDelegateStub::OnUpdateGeometry(
294 const PluginMsg_UpdateGeometry_Param
& param
) {
295 webplugin_
->UpdateGeometry(
296 param
.window_rect
, param
.clip_rect
,
297 param
.windowless_buffer0
, param
.windowless_buffer1
,
298 param
.windowless_buffer_index
);
301 void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id
) {
302 NPObject
* object
= delegate_
->GetPluginScriptableObject();
304 *route_id
= MSG_ROUTING_NONE
;
308 *route_id
= channel_
->GenerateRouteID();
309 // We will delete the stub immediately before calling PluginDestroyed on the
310 // delegate. It will delete itself sooner if the proxy tells it that it has
311 // been released, or if the channel to the proxy is closed.
312 NPObjectStub
* scriptable_stub
= new NPObjectStub(
313 object
, channel_
.get(), *route_id
,
314 webplugin_
->host_render_view_routing_id(), page_url_
);
315 plugin_scriptable_object_
= scriptable_stub
->AsWeakPtr();
317 // Release ref added by GetPluginScriptableObject (our stub holds its own).
318 WebBindings::releaseObject(object
);
321 void WebPluginDelegateStub::OnGetFormValue(base::string16
* value
,
326 *success
= delegate_
->GetFormValue(value
);
329 void WebPluginDelegateStub::OnSendJavaScriptStream(const GURL
& url
,
330 const std::string
& result
,
333 delegate_
->SendJavaScriptStream(url
, result
, success
, notify_id
);
336 void WebPluginDelegateStub::OnSetContentAreaFocus(bool has_focus
) {
338 delegate_
->SetContentAreaHasFocus(has_focus
);
341 #if defined(OS_WIN) && !defined(USE_AURA)
342 void WebPluginDelegateStub::OnImeCompositionUpdated(
343 const base::string16
& text
,
344 const std::vector
<int>& clauses
,
345 const std::vector
<int>& target
,
346 int cursor_position
) {
348 delegate_
->ImeCompositionUpdated(text
, clauses
, target
, cursor_position
);
349 webplugin_
->UpdateIMEStatus();
352 void WebPluginDelegateStub::OnImeCompositionCompleted(
353 const base::string16
& text
) {
355 delegate_
->ImeCompositionCompleted(text
);
359 #if defined(OS_MACOSX)
360 void WebPluginDelegateStub::OnSetWindowFocus(bool has_focus
) {
362 delegate_
->SetWindowHasFocus(has_focus
);
365 void WebPluginDelegateStub::OnContainerHidden() {
367 delegate_
->SetContainerVisibility(false);
370 void WebPluginDelegateStub::OnContainerShown(gfx::Rect window_frame
,
371 gfx::Rect view_frame
,
374 delegate_
->WindowFrameChanged(window_frame
, view_frame
);
375 delegate_
->SetContainerVisibility(true);
376 delegate_
->SetWindowHasFocus(has_focus
);
380 void WebPluginDelegateStub::OnWindowFrameChanged(const gfx::Rect
& window_frame
,
381 const gfx::Rect
& view_frame
) {
383 delegate_
->WindowFrameChanged(window_frame
, view_frame
);
386 void WebPluginDelegateStub::OnImeCompositionCompleted(
387 const base::string16
& text
) {
389 delegate_
->ImeCompositionCompleted(text
);
393 void WebPluginDelegateStub::OnDidReceiveManualResponse(
395 const PluginMsg_DidReceiveResponseParams
& params
) {
396 delegate_
->DidReceiveManualResponse(url
, params
.mime_type
, params
.headers
,
397 params
.expected_length
,
398 params
.last_modified
);
401 void WebPluginDelegateStub::OnDidReceiveManualData(
402 const std::vector
<char>& buffer
) {
403 delegate_
->DidReceiveManualData(&buffer
.front(),
404 static_cast<int>(buffer
.size()));
407 void WebPluginDelegateStub::OnDidFinishManualLoading() {
408 delegate_
->DidFinishManualLoading();
411 void WebPluginDelegateStub::OnDidManualLoadFail() {
412 delegate_
->DidManualLoadFail();
415 void WebPluginDelegateStub::OnHandleURLRequestReply(
416 unsigned long resource_id
, const GURL
& url
, int notify_id
) {
417 WebPluginResourceClient
* resource_client
=
418 delegate_
->CreateResourceClient(resource_id
, url
, notify_id
);
419 webplugin_
->OnResourceCreated(resource_id
, resource_client
);
422 void WebPluginDelegateStub::OnHTTPRangeRequestReply(
423 unsigned long resource_id
, int range_request_id
) {
424 WebPluginResourceClient
* resource_client
=
425 delegate_
->CreateSeekableResourceClient(resource_id
, range_request_id
);
426 webplugin_
->OnResourceCreated(resource_id
, resource_client
);
429 void WebPluginDelegateStub::OnFetchURL(
430 const PluginMsg_FetchURL_Params
& params
) {
431 const char* data
= NULL
;
432 if (params
.post_data
.size())
433 data
= ¶ms
.post_data
[0];
435 delegate_
->FetchURL(params
.resource_id
,
438 params
.first_party_for_cookies
,
441 static_cast<unsigned int>(params
.post_data
.size()),
442 Referrer(params
.referrer
, params
.referrer_policy
),
443 params
.notify_redirect
,
444 params
.is_plugin_src_load
,
445 channel_
->renderer_id(),
446 params
.render_frame_id
,
447 webplugin_
->host_render_view_routing_id());
450 } // namespace content