diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-20 03:08:08 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-20 03:08:08 +0000 |
commit | c56c384c7bbce7338e1621df5d7df05457af52e2 (patch) | |
tree | 58014be47cbe3b49012f42e55ec4688eaeb27275 /webkit/glue | |
parent | 9b0ebab53b516a8866f7e32bdd55d11caea41f54 (diff) | |
download | chromium_src-c56c384c7bbce7338e1621df5d7df05457af52e2.zip chromium_src-c56c384c7bbce7338e1621df5d7df05457af52e2.tar.gz chromium_src-c56c384c7bbce7338e1621df5d7df05457af52e2.tar.bz2 |
Move WebPluginContainer into the WebKit API
This change introduces the following new interfaces:
WebPlugin
WebPluginContainer
The implementation of WebPluginContainer is moved to webkit/api/src/WebPluginContainerImpl.{h,cpp}, and WebPluginImpl from webkit/glue now implements WebKit::WebPlugin.
This change does not completely eliminate dependencies in WebPluginImpl on WebCore. The rest will be removed in a separate change.
A hack was added to TemporaryGlue to deal with the fact that ChromeClientImpl still resides in webkit/glue. Also, StackingOrderIterator in webkit/glue because there is another CL out to remove that from the source tree.
Note: This change depends on another CL that I am brewing to make WebCanvas be a CGContext on Mac.
R=jam
BUG=10036
TEST=covered by existing tests
Review URL: http://codereview.chromium.org/165464
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23797 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r-- | webkit/glue/chromium_bridge_impl.cc | 11 | ||||
-rw-r--r-- | webkit/glue/temporary_glue.cc | 18 | ||||
-rw-r--r-- | webkit/glue/webframeloaderclient_impl.cc | 6 | ||||
-rw-r--r-- | webkit/glue/webframeloaderclient_impl.h | 7 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.cc | 738 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.h | 139 |
6 files changed, 271 insertions, 648 deletions
diff --git a/webkit/glue/chromium_bridge_impl.cc b/webkit/glue/chromium_bridge_impl.cc index 04acbd8..9d35344 100644 --- a/webkit/glue/chromium_bridge_impl.cc +++ b/webkit/glue/chromium_bridge_impl.cc @@ -37,7 +37,6 @@ #include "webkit/glue/glue_util.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/glue/webplugin_impl.h" #include "webkit/glue/webview_impl.h" #if defined(OS_WIN) @@ -104,16 +103,6 @@ void ChromiumBridge::notifyJSOutOfMemory(Frame* frame) { // Plugin --------------------------------------------------------------------- -NPObject* ChromiumBridge::pluginScriptableObject(Widget* widget) { - if (!widget) - return NULL; - - // NOTE: We have to trust that the widget passed to us here is a - // WebPluginImpl. There isn't a way to dynamically verify it, since the - // derived class (Widget) has no identifier. - return static_cast<WebPluginContainer*>(widget)->GetPluginScriptableObject(); -} - bool ChromiumBridge::popupsAllowed(NPP npp) { bool popups_allowed = false; if (npp) { diff --git a/webkit/glue/temporary_glue.cc b/webkit/glue/temporary_glue.cc index 23724ed..6c167aa 100644 --- a/webkit/glue/temporary_glue.cc +++ b/webkit/glue/temporary_glue.cc @@ -8,9 +8,11 @@ #include <wtf/Assertions.h> #undef LOG +#include "webkit/glue/chrome_client_impl.h" #include "webkit/glue/webview_impl.h" using WebCore::Frame; +using WebCore::Page; namespace WebKit { @@ -24,4 +26,20 @@ WebMediaPlayer* TemporaryGlue::createWebMediaPlayer( return webview->delegate()->CreateWebMediaPlayer(client); } +// static +void TemporaryGlue::setCursorForPlugin( + const WebCursorInfo& cursor_info, Frame* frame) { + Page* page = frame->page(); + if (!page) + return; + + ChromeClientImpl* chrome_client = + static_cast<ChromeClientImpl*>(page->chrome()->client()); + + // A windowless plugin can change the cursor in response to the WM_MOUSEMOVE + // event. We need to reflect the changed cursor in the frame view as the + // mouse is moved in the boundaries of the windowless plugin. + chrome_client->SetCursorForPlugin(cursor_info); +} + } // namespace WebKit diff --git a/webkit/glue/webframeloaderclient_impl.cc b/webkit/glue/webframeloaderclient_impl.cc index 520d999..ed356d9 100644 --- a/webkit/glue/webframeloaderclient_impl.cc +++ b/webkit/glue/webframeloaderclient_impl.cc @@ -38,6 +38,7 @@ #include "webkit/api/public/WebURL.h" #include "webkit/api/public/WebURLError.h" #include "webkit/api/public/WebVector.h" +#include "webkit/api/src/WebPluginContainerImpl.h" #include "webkit/api/src/WrappedResourceRequest.h" #include "webkit/api/src/WrappedResourceResponse.h" #include "webkit/glue/glue_util.h" @@ -60,6 +61,7 @@ using base::TimeDelta; using WebKit::WebData; using WebKit::WebNavigationType; using WebKit::WebNavigationPolicy; +using WebKit::WebPluginContainerImpl; using WebKit::WebString; using WebKit::WebURL; using WebKit::WebURLError; @@ -907,7 +909,7 @@ void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error) { if (plugin_widget_.get()) { if (sent_initial_response_to_plugin_) { - plugin_widget_->didFail(error); + plugin_widget_->didFailLoading(error); sent_initial_response_to_plugin_ = false; } plugin_widget_ = NULL; @@ -1321,7 +1323,7 @@ PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& size, // TO // This method gets called when a plugin is put in place of html content // (e.g., acrobat reader). void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) { - plugin_widget_ = static_cast<WebPluginContainer*>(pluginWidget); + plugin_widget_ = static_cast<WebPluginContainerImpl*>(pluginWidget); DCHECK(plugin_widget_.get()); } diff --git a/webkit/glue/webframeloaderclient_impl.h b/webkit/glue/webframeloaderclient_impl.h index 0c57399..95cef30 100644 --- a/webkit/glue/webframeloaderclient_impl.h +++ b/webkit/glue/webframeloaderclient_impl.h @@ -13,7 +13,10 @@ #include "webkit/glue/webview_delegate.h" class WebFrameImpl; -class WebPluginContainer; + +namespace WebKit { +class WebPluginContainerImpl; +} class WebFrameLoaderClient : public WebCore::FrameLoaderClient { public: @@ -226,7 +229,7 @@ class WebFrameLoaderClient : public WebCore::FrameLoaderClient { GURL expected_client_redirect_dest_; // Contains a pointer to the plugin widget. - WTF::RefPtr<WebPluginContainer> plugin_widget_; + WTF::RefPtr<WebKit::WebPluginContainerImpl> plugin_widget_; // Indicates if we need to send over the initial notification to the plugin // which specifies that the plugin should be ready to accept data. diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index 1282971..5fd1ef503 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -6,38 +6,17 @@ #include "Document.h" #include "DocumentLoader.h" -#include "Event.h" -#include "EventNames.h" -#include "FloatPoint.h" -#include "FormData.h" #include "FormState.h" -#include "FocusController.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoadRequest.h" -#include "FrameTree.h" -#include "FrameView.h" -#include "GraphicsContext.h" #include "HTMLFormElement.h" -#include "HTMLNames.h" #include "HTMLPlugInElement.h" -#include "IntRect.h" #include "KURL.h" -#include "KeyboardEvent.h" -#include "MouseEvent.h" -#include "Page.h" -#include "PlatformContextSkia.h" -#include "PlatformMouseEvent.h" -#include "PlatformKeyboardEvent.h" #include "PlatformString.h" -#include "PlatformWidget.h" -#include "RenderBox.h" -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" #include "ResourceResponse.h" #include "ScriptController.h" #include "ScriptValue.h" -#include "ScrollView.h" #include "Widget.h" #undef LOG @@ -45,20 +24,23 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/string_util.h" -#include "base/sys_string_conversions.h" +//#include "base/sys_string_conversions.h" #include "net/base/escape.h" #include "webkit/api/public/WebCursorInfo.h" #include "webkit/api/public/WebData.h" #include "webkit/api/public/WebHTTPBody.h" +#include "webkit/api/public/WebHTTPHeaderVisitor.h" #include "webkit/api/public/WebInputEvent.h" #include "webkit/api/public/WebKit.h" #include "webkit/api/public/WebKitClient.h" +#include "webkit/api/public/WebRect.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebURL.h" #include "webkit/api/public/WebURLLoader.h" #include "webkit/api/public/WebURLLoaderClient.h" #include "webkit/api/public/WebURLResponse.h" -#include "webkit/api/src/WebInputEventConversion.h" +#include "webkit/api/public/WebVector.h" +#include "webkit/api/src/WebPluginContainerImpl.h" #include "webkit/glue/chrome_client_impl.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/multipart_response_delegate.h" @@ -71,22 +53,28 @@ #include "webkit/glue/webview_impl.h" #include "googleurl/src/gurl.h" +using WebKit::WebCanvas; using WebKit::WebCursorInfo; using WebKit::WebData; using WebKit::WebHTTPBody; +using WebKit::WebHTTPHeaderVisitor; using WebKit::WebInputEvent; using WebKit::WebKeyboardEvent; -using WebKit::WebKeyboardEventBuilder; using WebKit::WebMouseEvent; -using WebKit::WebMouseEventBuilder; +using WebKit::WebPluginContainer; +using WebKit::WebPluginContainerImpl; +using WebKit::WebRect; using WebKit::WebString; using WebKit::WebURLError; using WebKit::WebURLLoader; using WebKit::WebURLLoaderClient; using WebKit::WebURLRequest; using WebKit::WebURLResponse; +using WebKit::WebVector; using webkit_glue::MultipartResponseDelegate; +namespace { + // This class handles individual multipart responses. It is instantiated when // we receive HTTP status code 206 in the HTTP response. This indicates // that the response could have multiple parts each separated by a boundary @@ -147,199 +135,80 @@ class MultiPartResponseClient : public WebURLLoaderClient { WebPluginResourceClient* resource_client_; }; -static std::wstring GetAllHeaders(const WebCore::ResourceResponse& response) { - std::wstring result; - const WebCore::String& status = response.httpStatusText(); - if (status.isEmpty()) - return result; - - result.append(L"HTTP "); - result.append(FormatNumber(response.httpStatusCode())); - result.append(L" "); - result.append(webkit_glue::StringToStdWString(status)); - result.append(L"\n"); - - WebCore::HTTPHeaderMap::const_iterator it = - response.httpHeaderFields().begin(); - for (; it != response.httpHeaderFields().end(); ++it) { - if (!it->first.isEmpty() && !it->second.isEmpty()) { - result.append(webkit_glue::StringToStdWString(it->first)); - result.append(L": "); - result.append(webkit_glue::StringToStdWString(it->second)); - result.append(L"\n"); - } - } - - return result; -} - -WebPluginContainer::WebPluginContainer(WebPluginImpl* impl) - : impl_(impl), - ignore_response_error_(false) { -} - -WebPluginContainer::~WebPluginContainer() { - impl_->SetContainer(NULL); - MessageLoop::current()->DeleteSoon(FROM_HERE, impl_); -} - -NPObject* WebPluginContainer::GetPluginScriptableObject() { - return impl_->GetPluginScriptableObject(); -} - -#if USE(JSC) -bool WebPluginContainer::isPluginView() const { - return true; -} -#endif - - -void WebPluginContainer::setFrameRect(const WebCore::IntRect& rect) { - WebCore::Widget::setFrameRect(rect); - impl_->setFrameRect(rect); -} - -void WebPluginContainer::paint(WebCore::GraphicsContext* gc, - const WebCore::IntRect& damage_rect) { - // In theory, we should call impl_->print(gc); when - // impl_->webframe_->printing() is true but it still has placement issues so - // keep that code off for now. - impl_->paint(gc, damage_rect); -} - -void WebPluginContainer::invalidateRect(const WebCore::IntRect& rect) { - if (parent()) { - WebCore::IntRect damageRect = convertToContainingWindow(rect); - - // Get our clip rect and intersect with it to ensure we don't - // invalidate too much. - WebCore::IntRect clipRect = parent()->windowClipRect(); - damageRect.intersect(clipRect); - - parent()->hostWindow()->repaint(damageRect, true); +class HeaderFlattener : public WebHTTPHeaderVisitor { + public: + HeaderFlattener(std::string* buf) : buf_(buf) { } -} - -void WebPluginContainer::setFocus() { - WebCore::Widget::setFocus(); - impl_->setFocus(); -} - -void WebPluginContainer::show() { - setSelfVisible(true); - impl_->UpdateVisibility(); - - WebCore::Widget::show(); -} -void WebPluginContainer::hide() { - setSelfVisible(false); - impl_->UpdateVisibility(); - - WebCore::Widget::hide(); -} - -void WebPluginContainer::handleEvent(WebCore::Event* event) { - impl_->handleEvent(event); -} - -void WebPluginContainer::frameRectsChanged() { - WebCore::Widget::frameRectsChanged(); - // This is a hack to tickle re-positioning of the plugin in the case where - // our parent view was scrolled. - impl_->setFrameRect(frameRect()); -} - -// We override this function, to make sure that geometry updates are sent -// over to the plugin. For e.g. when a plugin is instantiated it does -// not have a valid parent. As a result the first geometry update from -// webkit is ignored. This function is called when the plugin eventually -// gets a parent. -void WebPluginContainer::setParentVisible(bool visible) { - if (isParentVisible() == visible) - return; // No change. - - WebCore::Widget::setParentVisible(visible); - if (!isSelfVisible()) - return; // This widget has explicitely been marked as not visible. - - impl_->UpdateVisibility(); -} - -// We override this function so that if the plugin is windowed, we can call -// NPP_SetWindow at the first possible moment. This ensures that NPP_SetWindow -// is called before the manual load data is sent to a plugin. If this order is -// reversed, Flash won't load videos. -void WebPluginContainer::setParent(WebCore::ScrollView* view) { - WebCore::Widget::setParent(view); - if (view) { - impl_->setFrameRect(frameRect()); + virtual void visitHeader(const WebString& name, const WebString& value) { + // TODO(darin): Should we really exclude headers with an empty value? + if (!name.isEmpty() && !value.isEmpty()) { + buf_->append(name.utf8()); + buf_->append(": "); + buf_->append(value.utf8()); + buf_->append("\n"); + } } -} - -void WebPluginContainer::windowCutoutRects(const WebCore::IntRect& bounds, - WTF::Vector<WebCore::IntRect>* - cutouts) const { - impl_->windowCutoutRects(bounds, cutouts); -} - -void WebPluginContainer::didReceiveResponse( - const WebCore::ResourceResponse& response) { - set_ignore_response_error(false); - - // Manual loading, so make sure that the plugin receives window geometry - // before data, or else plugins misbehave. - frameRectsChanged(); - HttpResponseInfo http_response_info; - ReadHttpResponseInfo(response, &http_response_info); + private: + std::string* buf_; +}; - impl_->delegate_->DidReceiveManualResponse( - http_response_info.url, - base::SysWideToNativeMB(http_response_info.mime_type), - base::SysWideToNativeMB(GetAllHeaders(response)), - http_response_info.expected_length, - http_response_info.last_modified); -} +std::string GetAllHeaders(const WebURLResponse& response) { + // TODO(darin): It is possible for httpStatusText to be empty and still have + // an interesting response, so this check seems wrong. + std::string result; + const WebString& status = response.httpStatusText(); + if (status.isEmpty()) + return result; -void WebPluginContainer::didReceiveData(const char *buffer, int length) { - impl_->delegate_->DidReceiveManualData(buffer, length); -} + // TODO(darin): Shouldn't we also report HTTP version numbers? + result.append("HTTP "); + result.append(WideToUTF8(FormatNumber(response.httpStatusCode()))); + result.append(" "); + result.append(status.utf8()); + result.append("\n"); -void WebPluginContainer::didFinishLoading() { - impl_->delegate_->DidFinishManualLoading(); -} + HeaderFlattener flattener(&result); + response.visitHTTPHeaderFields(&flattener); -void WebPluginContainer::didFail(const WebCore::ResourceError&) { - if (!ignore_response_error_) - impl_->delegate_->DidManualLoadFail(); + return result; } -void WebPluginContainer::ReadHttpResponseInfo( - const WebCore::ResourceResponse& response, - HttpResponseInfo* http_response) { - std::wstring url = webkit_glue::StringToStdWString(response.url().string()); - http_response->url = WideToASCII(url); +struct ResponseInfo { + std::string url; + std::string mime_type; + uint32 last_modified; + uint32 expected_length; +}; - http_response->mime_type = - webkit_glue::StringToStdWString(response.mimeType()); +void GetResponseInfo(const WebURLResponse& response, + ResponseInfo* response_info) { + response_info->url = response.url().spec(); + response_info->mime_type = response.mimeType().utf8(); - http_response->last_modified = + // Measured in seconds since 12:00 midnight GMT, January 1, 1970. + response_info->last_modified = static_cast<uint32>(response.lastModifiedDate()); + // If the length comes in as -1, then it indicates that it was not // read off the HTTP headers. We replicate Safari webkit behavior here, // which is to set it to 0. - http_response->expected_length = + response_info->expected_length = static_cast<uint32>(std::max(response.expectedContentLength(), 0LL)); - WebCore::String content_encoding = - response.httpHeaderField("Content-Encoding"); - if (!content_encoding.isNull() && content_encoding != "identity") { + + WebString content_encoding = + response.httpHeaderField(WebString::fromUTF8("Content-Encoding")); + if (!content_encoding.isNull() && + !EqualsASCII(content_encoding, "identity")) { // Don't send the compressed content length to the plugin, which only // cares about the decoded length. - http_response->expected_length = 0; + response_info->expected_length = 0; } } +} // namespace + PassRefPtr<WebCore::Widget> WebPluginImpl::Create(const GURL& url, char** argn, char** argv, @@ -360,9 +229,10 @@ PassRefPtr<WebCore::Widget> WebPluginImpl::Create(const GURL& url, return NULL; } - WebPluginContainer* container = new WebPluginContainer(webplugin); - webplugin->SetContainer(container); - return adoptRef(container); + PassRefPtr<WebPluginContainerImpl> container = + WebPluginContainerImpl::create(element, webplugin); + webplugin->SetContainer(container.get()); + return container; } WebPluginImpl::WebPluginImpl(WebCore::HTMLPlugInElement* element, @@ -383,6 +253,7 @@ WebPluginImpl::WebPluginImpl(WebCore::HTMLPlugInElement* element, plugin_url_(plugin_url), load_manually_(load_manually), first_geometry_update_(true), + ignore_response_error_(false), mime_type_(mime_type), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { @@ -390,6 +261,142 @@ WebPluginImpl::WebPluginImpl(WebCore::HTMLPlugInElement* element, ArrayToVector(arg_count, arg_values, &arg_values_); } +// WebKit::WebPlugin ----------------------------------------------------------- + +void WebPluginImpl::destroy() { + SetContainer(NULL); + MessageLoop::current()->DeleteSoon(FROM_HERE, this); +} + +NPObject* WebPluginImpl::scriptableObject() { + return delegate_->GetPluginScriptableObject(); +} + +void WebPluginImpl::paint(WebCanvas* canvas, const WebRect& paint_rect) { + // Note that |context| is only used when in windowless mode. +#if WEBKIT_USING_SKIA + gfx::NativeDrawingContext context = canvas->beginPlatformPaint(); +#elif WEBKIT_USING_CG + gfx::NativeDrawingContext context = canvas; +#endif + + delegate_->Paint(context, paint_rect); + +#if WEBKIT_USING_SKIA + canvas->endPlatformPaint(); +#endif +} + +void WebPluginImpl::updateGeometry( + const WebRect& window_rect, const WebRect& clip_rect, + const WebVector<WebRect>& cutout_rects) { + if (window_) { + WebCore::Frame* frame = element_->document()->frame(); + WebFrameImpl* webframe = WebFrameImpl::FromFrame(frame); + WebViewImpl* webview = webframe->GetWebViewImpl(); + if (webview->delegate()) { + // Notify the window hosting the plugin (the WebViewDelegate) that + // it needs to adjust the plugin, so that all the HWNDs can be moved + // at the same time. + WebPluginGeometry move; + move.window = window_; + move.window_rect = window_rect; + move.clip_rect = clip_rect; + for (size_t i = 0; i < cutout_rects.size(); ++i) + move.cutout_rects.push_back(cutout_rects[i]); + move.rects_valid = true; + move.visible = true; // Assume visible or else we wouldn't be here. + + webview->delegate()->DidMovePlugin(move); + } + } + + if (first_geometry_update_ || window_rect != window_rect_ || + clip_rect != clip_rect_) { + window_rect_ = window_rect; + clip_rect_ = clip_rect; + // Notify the plugin that its parameters have changed. + delegate_->UpdateGeometry(window_rect_, clip_rect_); + + // Initiate a download on the plugin url. This should be done for the + // first update geometry sequence. We need to ensure that the plugin + // receives the geometry update before it starts receiving data. + if (first_geometry_update_) { + first_geometry_update_ = false; + // An empty url corresponds to an EMBED tag with no src attribute. + if (!load_manually_ && plugin_url_.is_valid()) { + // The Flash plugin hangs for a while if it receives data before + // receiving valid plugin geometry. By valid geometry we mean the + // geometry received by a call to setFrameRect in the Webkit + // layout code path. To workaround this issue we download the + // plugin source url on a timer. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, method_factory_.NewRunnableMethod( + &WebPluginImpl::OnDownloadPluginSrcUrl), 0); + } + } + } +} + +void WebPluginImpl::updateFocus(bool focused) { + if (focused && windowless_) + delegate_->SetFocus(); +} + +void WebPluginImpl::updateVisibility(bool visible) { + if (!window_) + return; + + WebCore::Frame* frame = element_->document()->frame(); + WebFrameImpl* webframe = WebFrameImpl::FromFrame(frame); + WebViewImpl* webview = webframe->GetWebViewImpl(); + if (!webview->delegate()) + return; + + WebPluginGeometry move; + move.window = window_; + move.window_rect = gfx::Rect(); + move.clip_rect = gfx::Rect(); + move.rects_valid = false; + move.visible = visible; + + webview->delegate()->DidMovePlugin(move); +} + +bool WebPluginImpl::handleInputEvent( + const WebInputEvent& event, WebCursorInfo& cursor_info) { + return delegate_->HandleInputEvent(event, &cursor_info); +} + +void WebPluginImpl::didReceiveResponse(const WebURLResponse& response) { + ignore_response_error_ = false; + + ResponseInfo response_info; + GetResponseInfo(response, &response_info); + + delegate_->DidReceiveManualResponse( + response_info.url, + response_info.mime_type, + GetAllHeaders(response), + response_info.expected_length, + response_info.last_modified); +} + +void WebPluginImpl::didReceiveData(const char* data, int data_length) { + delegate_->DidReceiveManualData(data, data_length); +} + +void WebPluginImpl::didFinishLoading() { + delegate_->DidFinishManualLoading(); +} + +void WebPluginImpl::didFailLoading(const WebURLError& error) { + if (!ignore_response_error_) + delegate_->DidManualLoadFail(); +} + +// ----------------------------------------------------------------------------- + WebPluginImpl::~WebPluginImpl() { } @@ -661,123 +668,7 @@ void WebPluginImpl::Invalidate() { void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { if (widget_) - widget_->invalidateRect(webkit_glue::ToIntRect(rect)); -} - -WebCore::IntRect WebPluginImpl::windowClipRect() const { - // This is based on the code in WebCore/plugins/win/PluginViewWin.cpp: - WebCore::IntRect rect(0, 0, widget_->width(), widget_->height()); - - // Start by clipping to our bounds. - WebCore::IntRect clip_rect = widget_->convertToContainingWindow( - WebCore::IntRect(0, 0, widget_->width(), widget_->height())); - - // Take our element and get the clip rect from the enclosing layer and - // frame view. - WebCore::RenderLayer* layer = element_->renderer()->enclosingLayer(); - - // document()->renderer() can be NULL when we receive messages from the - // plugins while we are destroying a frame. - if (element_->renderer()->document()->renderer()) { - WebCore::FrameView* parent_view = element_->document()->view(); - clip_rect.intersect(parent_view->windowClipRectForLayer(layer, true)); - } - - return clip_rect; -} - -void WebPluginImpl::windowCutoutRects( - const WebCore::IntRect& bounds, - WTF::Vector<WebCore::IntRect>* cutouts) const { - WebCore::RenderObject* plugin_node = element_->renderer(); - ASSERT(plugin_node); - - // Find all iframes that stack higher than this plugin. - bool higher = false; - StackingOrderIterator iterator; - WebCore::RenderLayer* root = element_->document()->renderer()-> - enclosingLayer(); - iterator.Reset(bounds, root); - - while (WebCore::RenderObject* ro = iterator.Next()) { - if (ro == plugin_node) { - // All nodes after this one are higher than plugin. - higher = true; - } else if (higher) { - // Is this a visible iframe? - WebCore::Node* n = ro->node(); - if (n && n->hasTagName(WebCore::HTMLNames::iframeTag)) { - if (!ro->style() || ro->style()->visibility() == WebCore::VISIBLE) { - WebCore::IntPoint point = roundedIntPoint(ro->localToAbsolute()); - WebCore::RenderBox* rbox = WebCore::toRenderBox(ro); - WebCore::IntSize size(rbox->width(), rbox->height()); - cutouts->append(WebCore::IntRect(point, size)); - } - } - } - } -} - -void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) { - if (!parent()) - return; - - // Compute a new position and clip rect for ourselves relative to the - // containing window. We ask our delegate to reposition us accordingly. - WebCore::Frame* frame = element_->document()->frame(); - WebFrameImpl* webframe = WebFrameImpl::FromFrame(frame); - WebViewImpl* webview = webframe->GetWebViewImpl(); - // It is valid for this function to be invoked in code paths where the - // the webview is closed. - if (!webview->delegate()) { - return; - } - - gfx::Rect window_rect; - gfx::Rect clip_rect; - std::vector<gfx::Rect> cutout_rects; - CalculateBounds(rect, &window_rect, &clip_rect, &cutout_rects); - - if (window_) { - // Notify the window hosting the plugin (the WebViewDelegate) that - // it needs to adjust the plugin, so that all the HWNDs can be moved - // at the same time. - WebPluginGeometry move; - move.window = window_; - move.window_rect = window_rect; - move.clip_rect = clip_rect; - move.cutout_rects = cutout_rects; - move.rects_valid = true; - move.visible = widget_->isVisible(); - - webview->delegate()->DidMovePlugin(move); - } - - if (first_geometry_update_ || window_rect != window_rect_ || - clip_rect != clip_rect_) { - window_rect_ = window_rect; - clip_rect_ = clip_rect; - // Notify the plugin that its parameters have changed. - delegate_->UpdateGeometry(window_rect_, clip_rect_); - - // Initiate a download on the plugin url. This should be done for the - // first update geometry sequence. We need to ensure that the plugin - // receives the geometry update before it starts receiving data. - if (first_geometry_update_) { - first_geometry_update_ = false; - // An empty url corresponds to an EMBED tag with no src attribute. - if (!load_manually_ && plugin_url_.is_valid()) { - // The Flash plugin hangs for a while if it receives data before - // receiving valid plugin geometry. By valid geometry we mean the - // geometry received by a call to setFrameRect in the Webkit - // layout code path. To workaround this issue we download the - // plugin source url on a timer. - MessageLoop::current()->PostDelayedTask( - FROM_HERE, method_factory_.NewRunnableMethod( - &WebPluginImpl::OnDownloadPluginSrcUrl), 0); - } - } - } + widget_->invalidateRect(rect); } void WebPluginImpl::OnDownloadPluginSrcUrl() { @@ -786,142 +677,6 @@ void WebPluginImpl::OnDownloadPluginSrcUrl() { false); } -void WebPluginImpl::paint(WebCore::GraphicsContext* gc, - const WebCore::IntRect& damage_rect) { - if (gc->paintingDisabled()) - return; - - if (!parent()) - return; - - // Don't paint anything if the plugin doesn't intersect the damage rect. - if (!widget_->frameRect().intersects(damage_rect)) - return; - - gc->save(); - - DCHECK(parent()->isFrameView()); - WebCore::FrameView* view = static_cast<WebCore::FrameView*>(parent()); - - // The plugin is positioned in window coordinates, so it needs to be painted - // in window coordinates. - WebCore::IntPoint origin = view->windowToContents(WebCore::IntPoint(0, 0)); - gc->translate(static_cast<float>(origin.x()), - static_cast<float>(origin.y())); - -#if defined(OS_WIN) || defined(OS_LINUX) - // Note that |context| is only used when in windowless mode. - gfx::NativeDrawingContext context = - gc->platformContext()->canvas()->beginPlatformPaint(); -#elif defined(OS_MACOSX) - gfx::NativeDrawingContext context = gc->platformContext(); -#endif - - WebCore::IntRect window_rect = - WebCore::IntRect(view->contentsToWindow(damage_rect.location()), - damage_rect.size()); - - delegate_->Paint(context, webkit_glue::FromIntRect(window_rect)); - -#if defined(OS_WIN) || defined(OS_LINUX) - gc->platformContext()->canvas()->endPlatformPaint(); -#endif - gc->restore(); -} - -void WebPluginImpl::print(WebCore::GraphicsContext* gc) { - if (gc->paintingDisabled()) - return; - - if (!parent()) - return; - - gc->save(); -#if defined(OS_WIN) - gfx::NativeDrawingContext hdc = - gc->platformContext()->canvas()->beginPlatformPaint(); - delegate_->Print(hdc); - gc->platformContext()->canvas()->endPlatformPaint(); -#else - NOTIMPLEMENTED(); -#endif - gc->restore(); -} - -void WebPluginImpl::setFocus() { - if (windowless_) - delegate_->SetFocus(); -} - -void WebPluginImpl::handleEvent(WebCore::Event* event) { - if (!windowless_) - return; - - // Pass events to the plugin. - // The events we pass are defined at: - // http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/structures5.html#1000000 - // Don't take the documentation as truth, however. I've found - // many cases where mozilla behaves differently than the spec. - if (event->isMouseEvent()) - handleMouseEvent(static_cast<WebCore::MouseEvent*>(event)); - else if (event->isKeyboardEvent()) - handleKeyboardEvent(static_cast<WebCore::KeyboardEvent*>(event)); -} - -void WebPluginImpl::handleMouseEvent(WebCore::MouseEvent* event) { - DCHECK(parent()->isFrameView()); - // We cache the parent FrameView here as the plugin widget could be deleted - // in the call to HandleEvent. See http://b/issue?id=1362948 - WebCore::FrameView* parent_view = static_cast<WebCore::FrameView*>(parent()); - - WebMouseEventBuilder web_event(parent_view, *event); - if (web_event.type == WebInputEvent::Undefined) - return; - - if (event->type() == WebCore::eventNames().mousedownEvent) { - // Ensure that the frame containing the plugin has focus. - WebCore::Frame* containing_frame = webframe_->frame(); - if (WebCore::Page* current_page = containing_frame->page()) { - current_page->focusController()->setFocusedFrame(containing_frame); - } - // Give focus to our containing HTMLPluginElement. - containing_frame->document()->setFocusedNode(element_); - } - - // TODO(pkasting): http://b/1119691 This conditional seems exactly backwards, - // but it matches Safari's code, and if I reverse it, giving focus to a - // transparent (windowless) plugin fails. - WebCursorInfo cursor_info; - if (!delegate_->HandleInputEvent(web_event, &cursor_info)) - event->setDefaultHandled(); - - WebCore::Page* page = parent_view->frame()->page(); - if (!page) - return; - - ChromeClientImpl* chrome_client = - static_cast<ChromeClientImpl*>(page->chrome()->client()); - - // A windowless plugin can change the cursor in response to the WM_MOUSEMOVE - // event. We need to reflect the changed cursor in the frame view as the - // mouse is moved in the boundaries of the windowless plugin. - chrome_client->SetCursorForPlugin(cursor_info); -} - -void WebPluginImpl::handleKeyboardEvent(WebCore::KeyboardEvent* event) { - WebKeyboardEventBuilder web_event(*event); - if (web_event.type == WebInputEvent::Undefined) - return; - // TODO(pkasting): http://b/1119691 See above. - WebCursorInfo cursor_info; - if (!delegate_->HandleInputEvent(web_event, &cursor_info)) - event->setDefaultHandled(); -} - -NPObject* WebPluginImpl::GetPluginScriptableObject() { - return delegate_->GetPluginScriptableObject(); -} - WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( WebURLLoader* loader) { ClientInfo* client_info = GetClientInfoFromLoader(loader); @@ -963,12 +718,8 @@ void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, if (!client) return; - const WebCore::ResourceResponse& resource_response = - *webkit_glue::WebURLResponseToResourceResponse(&response); - - WebPluginContainer::HttpResponseInfo http_response_info; - WebPluginContainer::ReadHttpResponseInfo(resource_response, - &http_response_info); + ResponseInfo response_info; + GetResponseInfo(response, &response_info); bool cancel = false; bool request_is_seekable = true; @@ -1022,10 +773,11 @@ void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, loader->setDefersLoading(true); client->DidReceiveResponse( - base::SysWideToNativeMB(http_response_info.mime_type), - base::SysWideToNativeMB(GetAllHeaders(resource_response)), - http_response_info.expected_length, - http_response_info.last_modified, request_is_seekable); + response_info.mime_type, + GetAllHeaders(response), + response_info.expected_length, + response_info.last_modified, + request_is_seekable); // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP // error codes in the stream header and as a result, was unaware of the @@ -1120,39 +872,6 @@ void WebPluginImpl::SetContainer(WebPluginContainer* container) { widget_ = container; } -WebCore::ScrollView* WebPluginImpl::parent() const { - if (widget_) - return widget_->parent(); - - return NULL; -} - -void WebPluginImpl::CalculateBounds(const WebCore::IntRect& frame_rect, - gfx::Rect* window_rect, - gfx::Rect* clip_rect, - std::vector<gfx::Rect>* cutout_rects) { - DCHECK(parent()->isFrameView()); - WebCore::FrameView* view = static_cast<WebCore::FrameView*>(parent()); - - WebCore::IntRect web_window_rect = - WebCore::IntRect(view->contentsToWindow(frame_rect.location()), - frame_rect.size()); - *window_rect = webkit_glue::FromIntRect(web_window_rect); - // Calculate a clip-rect so that we don't overlap the scrollbars, etc. - *clip_rect = webkit_glue::FromIntRect(windowClipRect()); - clip_rect->Offset(-window_rect->x(), -window_rect->y()); - - cutout_rects->clear(); - WTF::Vector<WebCore::IntRect> rects; - widget_->windowCutoutRects(frame_rect, &rects); - // Convert to gfx::Rect and subtract out the plugin position. - for (size_t i = 0; i < rects.size(); i++) { - gfx::Rect r = webkit_glue::FromIntRect(rects[i]); - r.Offset(-frame_rect.x(), -frame_rect.y()); - cutout_rects->push_back(r); - } -} - void WebPluginImpl::HandleURLRequest(const char *method, bool is_javascript_url, const char* target, unsigned int len, @@ -1293,7 +1012,7 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id, void WebPluginImpl::CancelDocumentLoad() { if (frame()->loader()->activeDocumentLoader()) { - widget_->set_ignore_response_error(true); + ignore_response_error_ = true; frame()->loader()->activeDocumentLoader()->stopLoading(); } } @@ -1397,13 +1116,14 @@ bool WebPluginImpl::ReinitializePluginForResponse( mime_type_ = actual_mime_type; delegate_ = plugin_delegate; + // Force a geometry update to occur to ensure that the plugin becomes - // visible. - widget_->frameRectsChanged(); + // visible. TODO(darin): Avoid this cast! + static_cast<WebPluginContainerImpl*>(widget_)->frameRectsChanged(); // The plugin move sequences accumulated via DidMove are sent to the browser // whenever the renderer paints. Force a paint here to ensure that changes // to the plugin window are propagated to the browser. - widget_->invalidateRect(widget_->frameRect()); + widget_->invalidate(); return true; } @@ -1458,23 +1178,3 @@ void WebPluginImpl::TearDownPluginInstance( webframe_ = NULL; method_factory_.RevokeAll(); } - -void WebPluginImpl::UpdateVisibility() { - if (!window_) - return; - - WebCore::Frame* frame = element_->document()->frame(); - WebFrameImpl* webframe = WebFrameImpl::FromFrame(frame); - WebViewImpl* webview = webframe->GetWebViewImpl(); - if (!webview->delegate()) - return; - - WebPluginGeometry move; - move.window = window_; - move.window_rect = gfx::Rect(); - move.clip_rect = gfx::Rect(); - move.rects_valid = false; - move.visible = widget_->isVisible(); - - webview->delegate()->DidMovePlugin(move); -} diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h index 84ead6f..bd58c0a 100644 --- a/webkit/glue/webplugin_impl.h +++ b/webkit/glue/webplugin_impl.h @@ -14,6 +14,7 @@ #include "base/basictypes.h" #include "base/gfx/native_widget_types.h" #include "base/linked_ptr.h" +#include "webkit/api/public/WebPlugin.h" #include "webkit/api/public/WebURLLoaderClient.h" #include "webkit/api/public/WebURLRequest.h" #include "webkit/glue/webframe_impl.h" @@ -40,6 +41,7 @@ class Widget; } namespace WebKit { +class WebPluginContainer; class WebURLResponse; class WebURLLoader; } @@ -48,75 +50,11 @@ namespace webkit_glue { class MultipartResponseDelegate; } -// Implements WebCore::Widget functions that WebPluginImpl needs. This class -// exists because it is possible for the plugin widget to be deleted at any -// time because of a delegate javascript call. However we don't want the -// WebPluginImpl to be deleted from under us because it could be lower in the -// call stack. -class WebPluginContainer : public WebCore::Widget { - public: - WebPluginContainer(WebPluginImpl* impl); - virtual ~WebPluginContainer(); - NPObject* GetPluginScriptableObject(); - - // Widget methods: - virtual void setFrameRect(const WebCore::IntRect& rect); - virtual void paint(WebCore::GraphicsContext*, const WebCore::IntRect& rect); - virtual void invalidateRect(const WebCore::IntRect&); - virtual void setFocus(); - virtual void show(); - virtual void hide(); - virtual void handleEvent(WebCore::Event* event); - virtual void frameRectsChanged(); - virtual void setParentVisible(bool visible); - virtual void setParent(WebCore::ScrollView* view); - -#if USE(JSC) - virtual bool isPluginView() const; -#endif - - // Returns window-relative rectangles that should clip this widget. - // Only rects that intersect the given bounds are relevant. - // Use this to implement iframe shim behavior. - // - // TODO(tulrich): add this method to WebCore/platform/Widget.h so it - // can be used by any platform. - void windowCutoutRects(const WebCore::IntRect& bounds, - WTF::Vector<WebCore::IntRect>* cutouts) const; - - // These methods are invoked from webkit when it has data to be sent to the - // plugin. The plugin in this case does not initiate a download for the data. - void didReceiveResponse(const WebCore::ResourceResponse& response); - void didReceiveData(const char *buffer, int length); - void didFinishLoading(); - void didFail(const WebCore::ResourceError&); - - void set_ignore_response_error(bool ignore_response_error) { - ignore_response_error_ = ignore_response_error; - } - - struct HttpResponseInfo { - std::string url; - std::wstring mime_type; - uint32 last_modified; - uint32 expected_length; - }; - - // Helper function to read fields in a HTTP response structure. - // These fields are written to the HttpResponseInfo structure passed in. - static void ReadHttpResponseInfo(const WebCore::ResourceResponse& response, - HttpResponseInfo* http_response); - - private: - WebPluginImpl* impl_; - // Set to true if the next response error should be ignored. - bool ignore_response_error_; -}; - // This is the WebKit side of the plugin implementation that forwards calls, // after changing out of WebCore types, to a delegate. The delegate may // be in a different process. class WebPluginImpl : public WebPlugin, + public WebKit::WebPlugin, public WebKit::WebURLLoaderClient { public: // Creates a WebPlugin instance, as long as the delegate's initialization @@ -133,21 +71,34 @@ class WebPluginImpl : public WebPlugin, const std::string& mime_type); virtual ~WebPluginImpl(); - virtual NPObject* GetPluginScriptableObject(); - // Helper function for sorting post data. static bool SetPostData(WebKit::WebURLRequest* request, const char* buf, uint32 length); private: - friend class WebPluginContainer; - WebPluginImpl(WebCore::HTMLPlugInElement* element, WebFrameImpl* frame, WebPluginDelegate* delegate, const GURL& plugin_url, bool load_manually, const std::string& mime_type, int arg_count, char** arg_names, char** arg_values); + // WebKit::WebPlugin methods: + virtual void destroy(); + virtual NPObject* scriptableObject(); + virtual void paint( + WebKit::WebCanvas* canvas, const WebKit::WebRect& paint_rect); + virtual void updateGeometry( + const WebKit::WebRect& frame_rect, const WebKit::WebRect& clip_rect, + const WebKit::WebVector<WebKit::WebRect>& cut_outs); + virtual void updateFocus(bool focused); + virtual void updateVisibility(bool visible); + virtual bool handleInputEvent( + const WebKit::WebInputEvent& event, WebKit::WebCursorInfo& cursor_info); + virtual void didReceiveResponse(const WebKit::WebURLResponse& response); + virtual void didReceiveData(const char* data, int data_length); + virtual void didFinishLoading(); + virtual void didFailLoading(const WebKit::WebURLError& error); + // WebPlugin implementation: #if defined(OS_LINUX) gfx::PluginWindowHandle CreatePluginContainer(); @@ -208,47 +159,14 @@ class WebPluginImpl : public WebPlugin, void Invalidate(); void InvalidateRect(const gfx::Rect& rect); - // Widget implementation: - WebCore::IntRect windowClipRect() const; - - // Returns window-relative rectangles that should clip this widget. - // Only rects that intersect the given bounds are relevant. - // Use this to implement iframe shim behavior. - // - // TODO(tulrich): windowCutoutRects() is not in WebCore::Widgets - // yet; need to add it. - void windowCutoutRects(const WebCore::IntRect& bounds, - WTF::Vector<WebCore::IntRect>* rects) const; - - // Called by WebPluginContainer::setFrameRect, which overrides - // Widget setFrameRect when our window changes size or position. - // Used to notify the plugin when the size or position changes. - void setFrameRect(const WebCore::IntRect& rect); - - // Called by WebPluginContainer::paint, which overrides Widget::paint so we - // can notify the underlying widget to repaint. - void paint(WebCore::GraphicsContext*, const WebCore::IntRect& rect); - void print(WebCore::GraphicsContext*); - - // Called by WebPluginContainer::setFocus, which overrides Widget::setFocus. - // Notifies the plugin about focus changes. - void setFocus(); - - // Handle widget events. - void handleEvent(WebCore::Event* event); - void handleMouseEvent(WebCore::MouseEvent* event); - void handleKeyboardEvent(WebCore::KeyboardEvent* event); - // Sets the actual Widget for the plugin. - void SetContainer(WebPluginContainer* container); + void SetContainer(WebKit::WebPluginContainer* container); // Destroys the plugin instance. // The response_handle_to_ignore parameter if not NULL indicates the // resource handle to be left valid during plugin shutdown. void TearDownPluginInstance(WebKit::WebURLLoader* loader_to_ignore); - WebCore::ScrollView* parent() const; - // WebURLLoaderClient implementation. We implement this interface in the // renderer process, and then use the simple WebPluginResourceClient interface // to relay the callbacks to the plugin. @@ -275,13 +193,6 @@ class WebPluginImpl : public WebPlugin, WebCore::Frame* frame() { return webframe_ ? webframe_->frame() : NULL; } - // Calculates the bounds of the plugin widget based on the frame - // rect passed in. - void CalculateBounds(const WebCore::IntRect& frame_rect, - gfx::Rect* window_rect, - gfx::Rect* clip_rect, - std::vector<gfx::Rect>* cutout_rects); - void HandleURLRequest(const char *method, bool is_javascript_url, const char* target, unsigned int len, @@ -316,9 +227,6 @@ class WebPluginImpl : public WebPlugin, // to handle the response identified by the loader parameter. bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader); - // Notifies us that the visibility of the plugin has changed. - void UpdateVisibility(); - // Helper functions to convert an array of names/values to a vector. static void ArrayToVector(int total_values, char** values, std::vector<std::string>* value_vector); @@ -349,7 +257,7 @@ class WebPluginImpl : public WebPlugin, // Don't use RefPtr here since doing so extends the lifetime of a plugin // beyond the frame which causes crashes and videos playing after navigating // away etc. - WebPluginContainer* widget_; + WebKit::WebPluginContainer* widget_; typedef std::map<WebPluginResourceClient*, webkit_glue::MultipartResponseDelegate*> @@ -367,6 +275,9 @@ class WebPluginImpl : public WebPlugin, // Indicates if this is the first geometry update received by the plugin. bool first_geometry_update_; + // Set to true if the next response error should be ignored. + bool ignore_response_error_; + // The current plugin geometry and clip rectangle. gfx::Rect window_rect_; gfx::Rect clip_rect_; |