diff options
Diffstat (limited to 'components/plugins/renderer/webview_plugin.cc')
-rw-r--r-- | components/plugins/renderer/webview_plugin.cc | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc new file mode 100644 index 0000000..20969d5 --- /dev/null +++ b/components/plugins/renderer/webview_plugin.cc @@ -0,0 +1,224 @@ +// Copyright 2013 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 "components/plugins/renderer/webview_plugin.h" + +#include "base/message_loop/message_loop.h" +#include "base/metrics/histogram.h" +#include "base/safe_numerics.h" +#include "content/public/renderer/web_preferences.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/WebKit/public/platform/WebSize.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" +#include "third_party/WebKit/public/web/WebCursorInfo.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "third_party/WebKit/public/web/WebPluginContainer.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "webkit/common/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; + +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 WebPreferences& preferences, + const std::string& html_data, + const GURL& url) { + WebViewPlugin* plugin = new WebViewPlugin(delegate); + WebView* web_view = plugin->web_view(); + content::ApplyWebPreferences(preferences, 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(), base::checked_numeric_cast<int, size_t>(it->length())); + total_bytes += it->length(); + } + UMA_HISTOGRAM_MEMORY_KB( + "PluginDocument.Memory", + (base::checked_numeric_cast<int, size_t>(total_bytes / 1024))); + UMA_HISTOGRAM_COUNTS( + "PluginDocument.NumChunks", + (base::checked_numeric_cast<int, size_t>(data_.size()))); + } + if (finished_loading_) { + plugin->didFinishLoading(); + } + if (error_) { + plugin->didFailLoading(*error_); + } +} + +void WebViewPlugin::RestoreTitleText() { + if (container_) + container_->element().setAttribute("title", old_title_); +} + +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; + base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); +} + +NPObject* WebViewPlugin::scriptableObject() { return NULL; } + +struct _NPP* WebViewPlugin::pluginNPP() { return NULL; } + +bool WebViewPlugin::getFormValue(WebString& value) { return false; } + +void WebViewPlugin::paint(WebCanvas* canvas, const WebRect& rect) { + gfx::Rect paint_rect = gfx::IntersectRects(rect_, rect); + if (paint_rect.IsEmpty()) + return; + + paint_rect.Offset(-rect_.x(), -rect_.y()); + + canvas->translate(SkIntToScalar(rect_.x()), SkIntToScalar(rect_.y())); + canvas->save(); + + web_view_->layout(); + web_view_->paint(canvas, paint_rect); + + 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 (static_cast<gfx::Rect>(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) { + // For tap events, don't handle them. They will be converted to + // mouse events later and passed to here. + if (event.type == WebInputEvent::GestureTap) + return false; + + 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 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); +} + +void WebViewPlugin::didReceiveResponse(WebFrame* frame, + unsigned identifier, + const WebURLResponse& response) { + WebFrameClient::didReceiveResponse(frame, identifier, response); +} |