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