| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "webkit/plugins/webview_plugin.h" |
| |
| #include "base/message_loop.h" |
| #include "base/metrics/histogram.h" |
| #include "skia/ext/platform_canvas.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLResponse.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| #include "webkit/glue/webpreferences.h" |
| |
| using WebKit::WebCanvas; |
| using WebKit::WebCursorInfo; |
| using WebKit::WebDragData; |
| using WebKit::WebDragOperationsMask; |
| using WebKit::WebFrame; |
| using WebKit::WebImage; |
| using WebKit::WebInputEvent; |
| using WebKit::WebMouseEvent; |
| using WebKit::WebPlugin; |
| using WebKit::WebPluginContainer; |
| using WebKit::WebPoint; |
| using WebKit::WebRect; |
| using WebKit::WebSize; |
| using WebKit::WebString; |
| using WebKit::WebURLError; |
| using WebKit::WebURLRequest; |
| using WebKit::WebURLResponse; |
| using WebKit::WebVector; |
| using WebKit::WebView; |
| |
| namespace webkit { |
| |
| WebViewPlugin::WebViewPlugin(WebViewPlugin::Delegate* delegate) |
| : delegate_(delegate), |
| container_(NULL), |
| finished_loading_(false) { |
| web_view_ = WebView::create(this); |
| web_view_->initializeMainFrame(this); |
| } |
| |
| // static |
| WebViewPlugin* WebViewPlugin::Create( |
| WebViewPlugin::Delegate* delegate, |
| const webkit_glue::WebPreferences& preferences, |
| const std::string& html_data, |
| const GURL& url) { |
| WebViewPlugin* plugin = new WebViewPlugin(delegate); |
| WebView* web_view = plugin->web_view(); |
| preferences.Apply(web_view); |
| web_view->mainFrame()->loadHTMLString(html_data, url); |
| return plugin; |
| } |
| |
| WebViewPlugin::~WebViewPlugin() { |
| web_view_->close(); |
| } |
| |
| void WebViewPlugin::ReplayReceivedData(WebPlugin* plugin) { |
| if (!response_.isNull()) { |
| plugin->didReceiveResponse(response_); |
| size_t total_bytes = 0; |
| for (std::list<std::string>::iterator it = data_.begin(); |
| it != data_.end(); ++it) { |
| plugin->didReceiveData(it->c_str(), it->length()); |
| total_bytes += it->length(); |
| } |
| UMA_HISTOGRAM_MEMORY_KB("PluginDocument.Memory", (total_bytes / 1024)); |
| UMA_HISTOGRAM_COUNTS("PluginDocument.NumChunks", data_.size()); |
| } |
| if (finished_loading_) { |
| plugin->didFinishLoading(); |
| } |
| if (error_.get()) { |
| plugin->didFailLoading(*error_); |
| } |
| } |
| |
| void WebViewPlugin::RestoreTitleText() { |
| if (container_) |
| container_->element().setAttribute("title", old_title_); |
| } |
| |
| WebKit::WebPluginContainer* WebViewPlugin::container() const { |
| return container_; |
| } |
| |
| bool WebViewPlugin::initialize(WebPluginContainer* container) { |
| container_ = container; |
| if (container_) |
| old_title_ = container_->element().getAttribute("title"); |
| return true; |
| } |
| |
| void WebViewPlugin::destroy() { |
| if (delegate_) { |
| delegate_->WillDestroyPlugin(); |
| delegate_ = NULL; |
| } |
| container_ = NULL; |
| MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| } |
| |
| NPObject* WebViewPlugin::scriptableObject() { |
| return NULL; |
| } |
| |
| bool WebViewPlugin::getFormValue(WebString& value) { |
| return false; |
| } |
| |
| void WebViewPlugin::paint(WebCanvas* canvas, const WebRect& rect) { |
| gfx::Rect paintRect(rect_.Intersect(rect)); |
| if (paintRect.IsEmpty()) |
| return; |
| |
| paintRect.Offset(-rect_.x(), -rect_.y()); |
| |
| canvas->translate(SkIntToScalar(rect_.x()), SkIntToScalar(rect_.y())); |
| canvas->save(); |
| |
| web_view_->layout(); |
| web_view_->paint(canvas, paintRect); |
| |
| canvas->restore(); |
| } |
| |
| // Coordinates are relative to the containing window. |
| void WebViewPlugin::updateGeometry( |
| const WebRect& frame_rect, const WebRect& clip_rect, |
| const WebVector<WebRect>& cut_out_rects, bool is_visible) { |
| if (frame_rect != rect_) { |
| rect_ = frame_rect; |
| web_view_->resize(WebSize(frame_rect.width, frame_rect.height)); |
| } |
| } |
| |
| bool WebViewPlugin::acceptsInputEvents() { |
| return true; |
| } |
| |
| bool WebViewPlugin::handleInputEvent(const WebInputEvent& event, |
| WebCursorInfo& cursor) { |
| if (event.type == WebInputEvent::ContextMenu) { |
| if (delegate_) { |
| const WebMouseEvent& mouse_event = |
| reinterpret_cast<const WebMouseEvent&>(event); |
| delegate_->ShowContextMenu(mouse_event); |
| } |
| return true; |
| } |
| current_cursor_ = cursor; |
| bool handled = web_view_->handleInputEvent(event); |
| cursor = current_cursor_; |
| return handled; |
| } |
| |
| void WebViewPlugin::didReceiveResponse(const WebURLResponse& response) { |
| DCHECK(response_.isNull()); |
| response_ = response; |
| } |
| |
| void WebViewPlugin::didReceiveData(const char* data, int data_length) { |
| data_.push_back(std::string(data, data_length)); |
| } |
| |
| void WebViewPlugin::didFinishLoading() { |
| DCHECK(!finished_loading_); |
| finished_loading_ = true; |
| } |
| |
| void WebViewPlugin::didFailLoading(const WebURLError& error) { |
| DCHECK(!error_.get()); |
| error_.reset(new WebURLError(error)); |
| } |
| |
| bool WebViewPlugin::acceptsLoadDrops() { |
| return false; |
| } |
| |
| void WebViewPlugin::setToolTipText(const WebKit::WebString& text, |
| WebKit::WebTextDirection hint) { |
| if (container_) |
| container_->element().setAttribute("title", text); |
| } |
| |
| void WebViewPlugin::startDragging(WebFrame*, |
| const WebDragData&, |
| WebDragOperationsMask, |
| const WebImage&, |
| const WebPoint&) { |
| // Immediately stop dragging. |
| web_view_->dragSourceSystemDragEnded(); |
| } |
| |
| void WebViewPlugin::didInvalidateRect(const WebRect& rect) { |
| if (container_) |
| container_->invalidateRect(rect); |
| } |
| |
| void WebViewPlugin::didChangeCursor(const WebCursorInfo& cursor) { |
| current_cursor_ = cursor; |
| } |
| |
| void WebViewPlugin::didClearWindowObject(WebFrame* frame) { |
| if (delegate_) |
| delegate_->BindWebFrame(frame); |
| } |
| |
| bool WebViewPlugin::canHandleRequest(WebFrame* frame, |
| const WebURLRequest& request) { |
| return GURL(request.url()).SchemeIs("chrome"); |
| } |
| |
| WebURLError WebViewPlugin::cancelledError(WebFrame* frame, |
| const WebURLRequest& request) { |
| // Return an error with a non-zero reason so isNull() on the corresponding |
| // ResourceError is false. |
| WebURLError error; |
| error.domain = "WebViewPlugin"; |
| error.reason = -1; |
| error.unreachableURL = request.url(); |
| return error; |
| } |
| |
| void WebViewPlugin::didReceiveResponse(WebFrame* frame, |
| unsigned identifier, |
| const WebURLResponse& response) { |
| WebFrameClient::didReceiveResponse(frame, identifier, response); |
| } |
| |
| } // namespace webkit |