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