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/pepper_plugin_instance_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/WebPrintScalingOption.h" 32 #include "url/gurl.h" 33 34 using ppapi::V8ObjectVar; 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 v8::Local<v8::Object> PepperWebPluginImpl::v8ScriptableObject( 130 v8::Isolate* isolate) { 131 // Call through the plugin to get its instance object. The plugin should pass 132 // us a reference which we release in destroy(). 133 if (instance_object_.type == PP_VARTYPE_UNDEFINED) 134 instance_object_ = instance_->GetInstanceObject(isolate); 135 // GetInstanceObject talked to the plugin which may have removed the instance 136 // from the DOM, in which case instance_ would be NULL now. 137 if (!instance_.get()) 138 return v8::Local<v8::Object>(); 139 140 scoped_refptr<V8ObjectVar> object_var( 141 V8ObjectVar::FromPPVar(instance_object_)); 142 // If there's an InstanceObject, tell the Instance's MessageChannel to pass 143 // any non-postMessage calls to it. 144 if (object_var.get()) { 145 MessageChannel* message_channel = instance_->message_channel(); 146 if (message_channel) 147 message_channel->SetPassthroughObject(object_var->GetHandle()); 148 } 149 150 v8::Handle<v8::Object> result = instance_->GetMessageChannelObject(); 151 return result; 152 } 153 154 bool PepperWebPluginImpl::getFormValue(WebString& value) { return false; } 155 156 void PepperWebPluginImpl::paint(WebCanvas* canvas, const WebRect& rect) { 157 if (!instance_->FlashIsFullscreenOrPending()) 158 instance_->Paint(canvas, plugin_rect_, rect); 159 } 160 161 void PepperWebPluginImpl::updateGeometry( 162 const WebRect& window_rect, 163 const WebRect& clip_rect, 164 const WebVector<WebRect>& cut_outs_rects, 165 bool is_visible) { 166 plugin_rect_ = window_rect; 167 if (!instance_->FlashIsFullscreenOrPending()) { 168 std::vector<gfx::Rect> cut_outs; 169 for (size_t i = 0; i < cut_outs_rects.size(); ++i) 170 cut_outs.push_back(cut_outs_rects[i]); 171 instance_->ViewChanged(plugin_rect_, clip_rect, cut_outs); 172 } 173 } 174 175 void PepperWebPluginImpl::updateFocus(bool focused) { 176 instance_->SetWebKitFocus(focused); 177 } 178 179 void PepperWebPluginImpl::updateVisibility(bool visible) {} 180 181 bool PepperWebPluginImpl::acceptsInputEvents() { return true; } 182 183 bool PepperWebPluginImpl::handleInputEvent(const blink::WebInputEvent& event, 184 blink::WebCursorInfo& cursor_info) { 185 if (instance_->FlashIsFullscreenOrPending()) 186 return false; 187 return instance_->HandleInputEvent(event, &cursor_info); 188 } 189 190 void PepperWebPluginImpl::didReceiveResponse( 191 const blink::WebURLResponse& response) { 192 DCHECK(!instance_->document_loader()); 193 instance_->HandleDocumentLoad(response); 194 } 195 196 void PepperWebPluginImpl::didReceiveData(const char* data, int data_length) { 197 blink::WebURLLoaderClient* document_loader = instance_->document_loader(); 198 if (document_loader) 199 document_loader->didReceiveData(NULL, data, data_length, 0); 200 } 201 202 void PepperWebPluginImpl::didFinishLoading() { 203 blink::WebURLLoaderClient* document_loader = instance_->document_loader(); 204 if (document_loader) 205 document_loader->didFinishLoading( 206 NULL, 0.0, blink::WebURLLoaderClient::kUnknownEncodedDataLength); 207 } 208 209 void PepperWebPluginImpl::didFailLoading(const blink::WebURLError& error) { 210 blink::WebURLLoaderClient* document_loader = instance_->document_loader(); 211 if (document_loader) 212 document_loader->didFail(NULL, error); 213 } 214 215 void PepperWebPluginImpl::didFinishLoadingFrameRequest(const blink::WebURL& url, 216 void* notify_data) {} 217 218 void PepperWebPluginImpl::didFailLoadingFrameRequest( 219 const blink::WebURL& url, 220 void* notify_data, 221 const blink::WebURLError& error) {} 222 223 bool PepperWebPluginImpl::hasSelection() const { 224 return !selectionAsText().isEmpty(); 225 } 226 227 WebString PepperWebPluginImpl::selectionAsText() const { 228 return instance_->GetSelectedText(false); 229 } 230 231 WebString PepperWebPluginImpl::selectionAsMarkup() const { 232 return instance_->GetSelectedText(true); 233 } 234 235 WebURL PepperWebPluginImpl::linkAtPosition(const WebPoint& position) const { 236 return GURL(instance_->GetLinkAtPosition(position)); 237 } 238 239 void PepperWebPluginImpl::setZoomLevel(double level, bool text_only) { 240 instance_->Zoom(content::ZoomLevelToZoomFactor(level), text_only); 241 } 242 243 bool PepperWebPluginImpl::startFind(const blink::WebString& search_text, 244 bool case_sensitive, 245 int identifier) { 246 return instance_->StartFind(search_text, case_sensitive, identifier); 247 } 248 249 void PepperWebPluginImpl::selectFindResult(bool forward) { 250 instance_->SelectFindResult(forward); 251 } 252 253 void PepperWebPluginImpl::stopFind() { instance_->StopFind(); } 254 255 bool PepperWebPluginImpl::supportsPaginatedPrint() { 256 return instance_->SupportsPrintInterface(); 257 } 258 259 bool PepperWebPluginImpl::isPrintScalingDisabled() { 260 return instance_->IsPrintScalingDisabled(); 261 } 262 263 int PepperWebPluginImpl::printBegin(const WebPrintParams& print_params) { 264 return instance_->PrintBegin(print_params); 265 } 266 267 bool PepperWebPluginImpl::printPage(int page_number, blink::WebCanvas* canvas) { 268 return instance_->PrintPage(page_number, canvas); 269 } 270 271 void PepperWebPluginImpl::printEnd() { return instance_->PrintEnd(); } 272 273 bool PepperWebPluginImpl::canRotateView() { return instance_->CanRotateView(); } 274 275 void PepperWebPluginImpl::rotateView(RotationType type) { 276 instance_->RotateView(type); 277 } 278 279 bool PepperWebPluginImpl::isPlaceholder() { return false; } 280 281 } // namespace content 282