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_webplugin_impl.h"
6
7#include <cmath>
8
9#include "base/debug/crash_logging.h"
10#include "base/message_loop/message_loop.h"
11#include "content/public/common/page_zoom.h"
12#include "content/public/renderer/content_renderer_client.h"
13#include "content/renderer/pepper/message_channel.h"
14#include "content/renderer/pepper/npobject_var.h"
15#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
16#include "content/renderer/pepper/plugin_module.h"
17#include "content/renderer/render_view_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/WebPrintScalingOption.h"
32#include "url/gurl.h"
33
34using ppapi::NPObjectVar;
35using blink::WebCanvas;
36using blink::WebPlugin;
37using blink::WebPluginContainer;
38using blink::WebPluginParams;
39using blink::WebPoint;
40using blink::WebPrintParams;
41using blink::WebRect;
42using blink::WebSize;
43using blink::WebString;
44using blink::WebURL;
45using blink::WebVector;
46
47namespace content {
48
49struct PepperWebPluginImpl::InitData {
50  scoped_refptr<PluginModule> module;
51  base::WeakPtr<RenderViewImpl> render_view;
52  RenderFrame* render_frame;
53  std::vector<std::string> arg_names;
54  std::vector<std::string> arg_values;
55  GURL url;
56};
57
58PepperWebPluginImpl::PepperWebPluginImpl(
59    PluginModule* plugin_module,
60    const WebPluginParams& params,
61    const base::WeakPtr<RenderViewImpl>& render_view,
62    RenderFrame* render_frame)
63    : init_data_(new InitData()),
64      full_frame_(params.loadManually),
65      instance_object_(PP_MakeUndefined()),
66      container_(NULL) {
67  DCHECK(plugin_module);
68  init_data_->module = plugin_module;
69  init_data_->render_view = render_view;
70  init_data_->render_frame = render_frame;
71  for (size_t i = 0; i < params.attributeNames.size(); ++i) {
72    init_data_->arg_names.push_back(params.attributeNames[i].utf8());
73    init_data_->arg_values.push_back(params.attributeValues[i].utf8());
74  }
75  init_data_->url = params.url;
76
77  // Set subresource URL for crash reporting.
78  base::debug::SetCrashKeyValue("subresource_url", init_data_->url.spec());
79}
80
81PepperWebPluginImpl::~PepperWebPluginImpl() {
82}
83
84blink::WebPluginContainer* PepperWebPluginImpl::container() const {
85  return container_;
86}
87
88bool PepperWebPluginImpl::initialize(WebPluginContainer* container) {
89  // The plugin delegate may have gone away.
90  instance_ = init_data_->module->CreateInstance(
91      init_data_->render_view->main_render_frame(), container, init_data_->url);
92  if (!instance_.get())
93    return false;
94
95  // Enable script objects for this plugin.
96  container->allowScriptObjects();
97
98  bool success = instance_->Initialize(init_data_->arg_names,
99                                       init_data_->arg_values,
100                                       full_frame_);
101  if (!success) {
102    instance_->Delete();
103    instance_ = NULL;
104
105    blink::WebPlugin* replacement_plugin =
106        GetContentClient()->renderer()->CreatePluginReplacement(
107            init_data_->render_frame, init_data_->module->path());
108    if (!replacement_plugin || !replacement_plugin->initialize(container))
109      return false;
110
111    container->setPlugin(replacement_plugin);
112    return true;
113  }
114
115  init_data_.reset();
116  container_ = container;
117  return true;
118}
119
120void PepperWebPluginImpl::destroy() {
121  // Tell |container_| to clear references to this plugin's script objects.
122  if (container_)
123    container_->clearScriptObjects();
124
125  if (instance_.get()) {
126    ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
127    instance_object_ = PP_MakeUndefined();
128    instance_->Delete();
129    instance_ = NULL;
130  }
131
132  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
133}
134
135NPObject* PepperWebPluginImpl::scriptableObject() {
136  // Call through the plugin to get its instance object. The plugin should pass
137  // us a reference which we release in destroy().
138  if (instance_object_.type == PP_VARTYPE_UNDEFINED)
139    instance_object_ = instance_->GetInstanceObject();
140  // GetInstanceObject talked to the plugin which may have removed the instance
141  // from the DOM, in which case instance_ would be NULL now.
142  if (!instance_.get())
143    return NULL;
144
145  scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(instance_object_));
146  // If there's an InstanceObject, tell the Instance's MessageChannel to pass
147  // any non-postMessage calls to it.
148  if (object.get()) {
149    instance_->message_channel().SetPassthroughObject(object->np_object());
150  }
151  NPObject* message_channel_np_object(instance_->message_channel().np_object());
152  // The object is expected to be retained before it is returned.
153  blink::WebBindings::retainObject(message_channel_np_object);
154  return message_channel_np_object;
155}
156
157NPP PepperWebPluginImpl::pluginNPP() {
158  return instance_->instanceNPP();
159}
160
161bool PepperWebPluginImpl::getFormValue(WebString& value) {
162  return false;
163}
164
165void PepperWebPluginImpl::paint(WebCanvas* canvas, const WebRect& rect) {
166  if (!instance_->FlashIsFullscreenOrPending())
167    instance_->Paint(canvas, plugin_rect_, rect);
168}
169
170void PepperWebPluginImpl::updateGeometry(
171    const WebRect& window_rect,
172    const WebRect& clip_rect,
173    const WebVector<WebRect>& cut_outs_rects,
174    bool is_visible) {
175  plugin_rect_ = window_rect;
176  if (!instance_->FlashIsFullscreenOrPending()) {
177    std::vector<gfx::Rect> cut_outs;
178    for (size_t i = 0; i < cut_outs_rects.size(); ++i)
179      cut_outs.push_back(cut_outs_rects[i]);
180    instance_->ViewChanged(plugin_rect_, clip_rect, cut_outs);
181  }
182}
183
184void PepperWebPluginImpl::updateFocus(bool focused) {
185  instance_->SetWebKitFocus(focused);
186}
187
188void PepperWebPluginImpl::updateVisibility(bool visible) {
189}
190
191bool PepperWebPluginImpl::acceptsInputEvents() {
192  return true;
193}
194
195bool PepperWebPluginImpl::handleInputEvent(const blink::WebInputEvent& event,
196                                           blink::WebCursorInfo& cursor_info) {
197  if (instance_->FlashIsFullscreenOrPending())
198    return false;
199  return instance_->HandleInputEvent(event, &cursor_info);
200}
201
202void PepperWebPluginImpl::didReceiveResponse(
203    const blink::WebURLResponse& response) {
204  DCHECK(!instance_->document_loader());
205  instance_->HandleDocumentLoad(response);
206}
207
208void PepperWebPluginImpl::didReceiveData(const char* data, int data_length) {
209  blink::WebURLLoaderClient* document_loader = instance_->document_loader();
210  if (document_loader)
211    document_loader->didReceiveData(NULL, data, data_length, 0);
212}
213
214void PepperWebPluginImpl::didFinishLoading() {
215  blink::WebURLLoaderClient* document_loader = instance_->document_loader();
216  if (document_loader)
217    document_loader->didFinishLoading(NULL, 0.0);
218}
219
220void PepperWebPluginImpl::didFailLoading(const blink::WebURLError& error) {
221  blink::WebURLLoaderClient* document_loader = instance_->document_loader();
222  if (document_loader)
223    document_loader->didFail(NULL, error);
224}
225
226void PepperWebPluginImpl::didFinishLoadingFrameRequest(
227    const blink::WebURL& url,
228    void* notify_data) {
229}
230
231void PepperWebPluginImpl::didFailLoadingFrameRequest(
232    const blink::WebURL& url,
233    void* notify_data,
234    const blink::WebURLError& error) {
235}
236
237bool PepperWebPluginImpl::hasSelection() const {
238  return !selectionAsText().isEmpty();
239}
240
241WebString PepperWebPluginImpl::selectionAsText() const {
242  return instance_->GetSelectedText(false);
243}
244
245WebString PepperWebPluginImpl::selectionAsMarkup() const {
246  return instance_->GetSelectedText(true);
247}
248
249WebURL PepperWebPluginImpl::linkAtPosition(const WebPoint& position) const {
250  return GURL(instance_->GetLinkAtPosition(position));
251}
252
253void PepperWebPluginImpl::setZoomLevel(double level, bool text_only) {
254  instance_->Zoom(content::ZoomLevelToZoomFactor(level), text_only);
255}
256
257bool PepperWebPluginImpl::startFind(const blink::WebString& search_text,
258                                    bool case_sensitive,
259                                    int identifier) {
260  return instance_->StartFind(search_text, case_sensitive, identifier);
261}
262
263void PepperWebPluginImpl::selectFindResult(bool forward) {
264  instance_->SelectFindResult(forward);
265}
266
267void PepperWebPluginImpl::stopFind() {
268  instance_->StopFind();
269}
270
271bool PepperWebPluginImpl::supportsPaginatedPrint() {
272  return instance_->SupportsPrintInterface();
273}
274
275bool PepperWebPluginImpl::isPrintScalingDisabled() {
276  return instance_->IsPrintScalingDisabled();
277}
278
279int PepperWebPluginImpl::printBegin(const WebPrintParams& print_params) {
280  return instance_->PrintBegin(print_params);
281}
282
283bool PepperWebPluginImpl::printPage(int page_number,
284                                    blink::WebCanvas* canvas) {
285  return instance_->PrintPage(page_number, canvas);
286}
287
288void PepperWebPluginImpl::printEnd() {
289  return instance_->PrintEnd();
290}
291
292bool PepperWebPluginImpl::canRotateView() {
293  return instance_->CanRotateView();
294}
295
296void PepperWebPluginImpl::rotateView(RotationType type) {
297  instance_->RotateView(type);
298}
299
300bool PepperWebPluginImpl::isPlaceholder() {
301  return false;
302}
303
304}  // namespace content
305