From e612d764f473f54807cb24bedc1b147bb9672ca6 Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Wed, 31 Mar 2010 04:32:30 +0000 Subject: Move plugin-related files in webkit/glue to webkit/glue/plugins to make them easier to find. With a random subset of files in webkit/glue, it's impossible to predict where you should find a file. No code change TEST=none BUG=none Review URL: http://codereview.chromium.org/1559008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43177 0039d316-1c4b-4281-b951-d872f2087c98 --- .../glue/plugins/gtk_plugin_container_manager.cc | 4 +- .../plugins/mac_accelerated_surface_container.cc | 2 +- .../mac_accelerated_surface_container_manager.cc | 2 +- webkit/glue/plugins/npapi_extension_thunk.cc | 4 +- webkit/glue/plugins/plugin_host.cc | 6 +- webkit/glue/plugins/plugin_instance.cc | 4 +- webkit/glue/plugins/plugin_lib.h | 4 +- webkit/glue/plugins/plugin_list.h | 2 +- webkit/glue/plugins/plugin_stream_url.cc | 4 +- webkit/glue/plugins/plugin_stream_url.h | 4 +- webkit/glue/plugins/webplugin.cc | 23 + webkit/glue/plugins/webplugin.h | 194 ++++ webkit/glue/plugins/webplugin_delegate.h | 161 +++ webkit/glue/plugins/webplugin_delegate_impl.h | 4 +- webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 2 +- webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 6 +- webkit/glue/plugins/webplugin_delegate_impl_win.cc | 2 +- webkit/glue/plugins/webplugin_impl.cc | 1207 ++++++++++++++++++++ webkit/glue/plugins/webplugin_impl.h | 321 ++++++ webkit/glue/plugins/webplugin_impl_unittest.cc | 232 ++++ webkit/glue/plugins/webplugin_page_delegate.h | 69 ++ webkit/glue/plugins/webplugininfo.h | 47 + webkit/glue/webkit_glue.gypi | 12 +- webkit/glue/webkitclient_impl.cc | 2 +- webkit/glue/webplugin.cc | 23 - webkit/glue/webplugin.h | 194 ---- webkit/glue/webplugin_delegate.h | 161 --- webkit/glue/webplugin_impl.cc | 1207 -------------------- webkit/glue/webplugin_impl.h | 321 ------ webkit/glue/webplugin_impl_unittest.cc | 232 ---- webkit/glue/webplugin_page_delegate.h | 69 -- webkit/glue/webplugininfo.h | 47 - 32 files changed, 2286 insertions(+), 2286 deletions(-) create mode 100644 webkit/glue/plugins/webplugin.cc create mode 100644 webkit/glue/plugins/webplugin.h create mode 100644 webkit/glue/plugins/webplugin_delegate.h create mode 100644 webkit/glue/plugins/webplugin_impl.cc create mode 100644 webkit/glue/plugins/webplugin_impl.h create mode 100644 webkit/glue/plugins/webplugin_impl_unittest.cc create mode 100644 webkit/glue/plugins/webplugin_page_delegate.h create mode 100644 webkit/glue/plugins/webplugininfo.h delete mode 100644 webkit/glue/webplugin.cc delete mode 100644 webkit/glue/webplugin.h delete mode 100644 webkit/glue/webplugin_delegate.h delete mode 100644 webkit/glue/webplugin_impl.cc delete mode 100644 webkit/glue/webplugin_impl.h delete mode 100644 webkit/glue/webplugin_impl_unittest.cc delete mode 100644 webkit/glue/webplugin_page_delegate.h delete mode 100644 webkit/glue/webplugininfo.h (limited to 'webkit/glue') diff --git a/webkit/glue/plugins/gtk_plugin_container_manager.cc b/webkit/glue/plugins/gtk_plugin_container_manager.cc index 53b6f4d..9d9ee4b 100644 --- a/webkit/glue/plugins/gtk_plugin_container_manager.cc +++ b/webkit/glue/plugins/gtk_plugin_container_manager.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -9,7 +9,7 @@ #include "base/logging.h" #include "gfx/gtk_util.h" #include "webkit/glue/plugins/gtk_plugin_container.h" -#include "webkit/glue/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" GtkWidget* GtkPluginContainerManager::CreatePluginContainer( gfx::PluginWindowHandle id) { diff --git a/webkit/glue/plugins/mac_accelerated_surface_container.cc b/webkit/glue/plugins/mac_accelerated_surface_container.cc index 7d9ae67..8eca9d2 100644 --- a/webkit/glue/plugins/mac_accelerated_surface_container.cc +++ b/webkit/glue/plugins/mac_accelerated_surface_container.cc @@ -6,8 +6,8 @@ #include "app/surface/io_surface_support_mac.h" #include "base/logging.h" -#include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/mac_accelerated_surface_container_manager.h" +#include "webkit/glue/plugins/webplugin.h" MacAcceleratedSurfaceContainer::MacAcceleratedSurfaceContainer() : x_(0), diff --git a/webkit/glue/plugins/mac_accelerated_surface_container_manager.cc b/webkit/glue/plugins/mac_accelerated_surface_container_manager.cc index a149661..635348f 100644 --- a/webkit/glue/plugins/mac_accelerated_surface_container_manager.cc +++ b/webkit/glue/plugins/mac_accelerated_surface_container_manager.cc @@ -5,8 +5,8 @@ #include "webkit/glue/plugins/mac_accelerated_surface_container_manager.h" #include "base/logging.h" -#include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/mac_accelerated_surface_container.h" +#include "webkit/glue/plugins/webplugin.h" MacAcceleratedSurfaceContainerManager::MacAcceleratedSurfaceContainerManager() : current_id_(0) { diff --git a/webkit/glue/plugins/npapi_extension_thunk.cc b/webkit/glue/plugins/npapi_extension_thunk.cc index 0c25655..141d960 100644 --- a/webkit/glue/plugins/npapi_extension_thunk.cc +++ b/webkit/glue/plugins/npapi_extension_thunk.cc @@ -9,10 +9,10 @@ #include "base/utf_string_conversions.h" #include "third_party/npapi/bindings/npapi_extensions.h" #include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugin.h" +#include "webkit/glue/plugins/webplugin_delegate.h" #include "webkit/glue/scoped_clipboard_writer_glue.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/glue/webplugin.h" -#include "webkit/glue/webplugin_delegate.h" // FindInstance() // Finds a PluginInstance from an NPP. diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc index b262188..bc2a6f2 100644 --- a/webkit/glue/plugins/plugin_host.cc +++ b/webkit/glue/plugins/plugin_host.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -16,14 +16,14 @@ #include "net/base/net_util.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" #include "webkit/default_plugin/default_plugin_shared.h" -#include "webkit/glue/webplugininfo.h" -#include "webkit/glue/webplugin_delegate.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/plugins/npapi_extension_thunk.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "webkit/glue/plugins/webplugininfo.h" #include "third_party/npapi/bindings/npapi_extensions.h" #include "third_party/npapi/bindings/npruntime.h" diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc index 037d043..db5ccbf 100644 --- a/webkit/glue/plugins/plugin_instance.cc +++ b/webkit/glue/plugins/plugin_instance.cc @@ -10,13 +10,13 @@ #include "base/message_loop.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "webkit/glue/webplugin.h" -#include "webkit/glue/webplugin_delegate.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/plugins/plugin_host.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/plugins/plugin_string_stream.h" +#include "webkit/glue/plugins/webplugin.h" +#include "webkit/glue/plugins/webplugin_delegate.h" #include "net/base/escape.h" #if defined(OS_MACOSX) diff --git a/webkit/glue/plugins/plugin_lib.h b/webkit/glue/plugins/plugin_lib.h index 6af2893..dc0b304 100644 --- a/webkit/glue/plugins/plugin_lib.h +++ b/webkit/glue/plugins/plugin_lib.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -14,7 +14,7 @@ #include "base/ref_counted.h" #include "build/build_config.h" #include "webkit/glue/plugins/plugin_list.h" -#include "webkit/glue/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" struct WebPluginInfo; diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h index b80d83b..d4aa31c 100644 --- a/webkit/glue/plugins/plugin_list.h +++ b/webkit/glue/plugins/plugin_list.h @@ -14,7 +14,7 @@ #include "base/file_path.h" #include "base/lock.h" #include "third_party/npapi/bindings/nphostapi.h" -#include "webkit/glue/webplugininfo.h" +#include "webkit/glue/plugins/webplugininfo.h" class GURL; diff --git a/webkit/glue/plugins/plugin_stream_url.cc b/webkit/glue/plugins/plugin_stream_url.cc index 38f7edd..6694139 100644 --- a/webkit/glue/plugins/plugin_stream_url.cc +++ b/webkit/glue/plugins/plugin_stream_url.cc @@ -1,12 +1,12 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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/glue/plugins/plugin_stream_url.h" -#include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/plugin_host.h" #include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugin.h" namespace NPAPI { diff --git a/webkit/glue/plugins/plugin_stream_url.h b/webkit/glue/plugins/plugin_stream_url.h index 7d3f59a..688723c 100644 --- a/webkit/glue/plugins/plugin_stream_url.h +++ b/webkit/glue/plugins/plugin_stream_url.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -6,8 +6,8 @@ #define WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_URL_H__ -#include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/plugin_stream.h" +#include "webkit/glue/plugins/webplugin.h" #include "googleurl/src/gurl.h" namespace NPAPI { diff --git a/webkit/glue/plugins/webplugin.cc b/webkit/glue/plugins/webplugin.cc new file mode 100644 index 0000000..6443318 --- /dev/null +++ b/webkit/glue/plugins/webplugin.cc @@ -0,0 +1,23 @@ +// Copyright (c) 2010 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/glue/plugins/webplugin.h" + +namespace webkit_glue { + +WebPluginGeometry::WebPluginGeometry() + : window(gfx::kNullPluginWindow), + rects_valid(false), + visible(false) { +} + +bool WebPluginGeometry::Equals(const WebPluginGeometry& rhs) const { + return window == rhs.window && + window_rect == rhs.window_rect && + clip_rect == rhs.clip_rect && + cutout_rects == rhs.cutout_rects && + rects_valid == rhs.rects_valid && + visible == rhs.visible; +} +} // namespace webkit_glue diff --git a/webkit/glue/plugins/webplugin.h b/webkit/glue/plugins/webplugin.h new file mode 100644 index 0000000..cde5fce --- /dev/null +++ b/webkit/glue/plugins/webplugin.h @@ -0,0 +1,194 @@ +// Copyright (c) 2006-2009 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. + +#ifndef WEBKIT_GLUE_WEBPLUGIN_H_ +#define WEBKIT_GLUE_WEBPLUGIN_H_ + +#include +#include + +#include "base/basictypes.h" +#include "gfx/native_widget_types.h" +#include "gfx/rect.h" + +// TODO(port): this typedef is obviously incorrect on non-Windows +// platforms, but now a lot of code now accidentally depends on them +// existing. #ifdef out these declarations and fix all the users. +typedef void* HANDLE; + +class GURL; +struct NPObject; + +namespace WebKit { +class WebFrame; +} + +namespace webkit_glue { + +class WebPluginDelegate; +class WebPluginParentView; +class WebPluginResourceClient; + +// Describes the new location for a plugin window. +struct WebPluginGeometry { + WebPluginGeometry(); + + bool Equals(const WebPluginGeometry& rhs) const; + + // On Windows, this is the plugin window in the plugin process. + // On X11, this is the XID of the plugin-side GtkPlug containing the + // GtkSocket hosting the actual plugin window. + // + // On Mac OS X, all of the plugin types are currently "windowless" + // (window == 0) except for the special case of the GPU plugin, + // which currently performs rendering on behalf of the Pepper 3D API + // and WebGL. The GPU plugin uses a simple integer for the + // PluginWindowHandle which is used to map to a side data structure + // containing information about the plugin. Soon this plugin will be + // generalized, at which point this mechanism will be rethought or + // removed. + gfx::PluginWindowHandle window; + gfx::Rect window_rect; + // Clip rect (include) and cutouts (excludes), relative to + // window_rect origin. + gfx::Rect clip_rect; + std::vector cutout_rects; + bool rects_valid; + bool visible; +}; + +// The WebKit side of a plugin implementation. It provides wrappers around +// operations that need to interact with the frame and other WebCore objects. +class WebPlugin { + public: + virtual ~WebPlugin() {} + + // Called by the plugin delegate to let the WebPlugin know if the plugin is + // windowed (i.e. handle is not NULL) or windowless (handle is NULL). This + // tells the WebPlugin to send mouse/keyboard events to the plugin delegate, + // as well as the information about the HDC for paint operations. + virtual void SetWindow(gfx::PluginWindowHandle window) = 0; + + // Whether input events should be sent to the delegate. + virtual void SetAcceptsInputEvents(bool accepts) = 0; + + // Called by the plugin delegate to let it know that the window is being + // destroyed. + virtual void WillDestroyWindow(gfx::PluginWindowHandle window) = 0; +#if defined(OS_WIN) + // The pump_messages_event is a event handle which is valid only for + // windowless plugins and is used in NPP_HandleEvent calls to pump messages + // if the plugin enters a modal loop. + // Cancels a pending request. + virtual void SetWindowlessPumpEvent(HANDLE pump_messages_event) = 0; +#endif + virtual void CancelResource(unsigned long id) = 0; + virtual void Invalidate() = 0; + virtual void InvalidateRect(const gfx::Rect& rect) = 0; + + // Returns the NPObject for the browser's window object. + virtual NPObject* GetWindowScriptNPObject() = 0; + + // Returns the DOM element that loaded the plugin. + virtual NPObject* GetPluginElement() = 0; + + // Cookies + virtual void SetCookie(const GURL& url, + const GURL& first_party_for_cookies, + const std::string& cookie) = 0; + virtual std::string GetCookies(const GURL& url, + const GURL& first_party_for_cookies) = 0; + + // Shows a modal HTML dialog containing the given URL. json_arguments are + // passed to the dialog via the DOM 'window.chrome.dialogArguments', and the + // retval is the string returned by 'window.chrome.send("DialogClose", + // retval)'. + virtual void ShowModalHTMLDialog(const GURL& url, int width, int height, + const std::string& json_arguments, + std::string* json_retval) = 0; + + // When a default plugin has downloaded the plugin list and finds it is + // available, it calls this method to notify the renderer. Also it will update + // the status when user clicks on the plugin to install. + virtual void OnMissingPluginStatus(int status) = 0; + + // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated + // by plugins. If the plugin wants notification of the result, notify_id will + // be non-zero. + virtual void HandleURLRequest(const char* url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + bool popups_allowed) = 0; + + // Cancels document load. + virtual void CancelDocumentLoad() = 0; + + // Initiates a HTTP range request for an existing stream. + virtual void InitiateHTTPRangeRequest(const char* url, + const char* range_info, + int range_request_id) = 0; + + // Returns true iff in off the record (Incognito) mode. + virtual bool IsOffTheRecord() = 0; + + // Called when the WebPluginResourceClient instance is deleted. + virtual void ResourceClientDeleted( + WebPluginResourceClient* resource_client) {} + + // Defers the loading of the resource identified by resource_id. This is + // controlled by the defer parameter. + virtual void SetDeferResourceLoading(unsigned long resource_id, + bool defer) = 0; + +#if defined(OS_MACOSX) + // Synthesize a fake window handle for the plug-in to identify the instance + // to the browser, allowing mapping to a surface for hardware accelleration + // of plug-in content. The browser generates the handle which is then set on + // the plug-in. + virtual void BindFakePluginWindowHandle() {} + + // Tell the browser (via the renderer) to invalidate because the + // accelerated buffers have changed. + virtual void AcceleratedFrameBuffersDidSwap(gfx::PluginWindowHandle window) {} + + // Tell the renderer and browser to associate the given plugin handle with + // |accelerated_surface_identifier|. The geometry is used to resize any + // native "window" (which on the Mac is a CALayer). + virtual void SetAcceleratedSurface(gfx::PluginWindowHandle window, + int32 width, + int32 height, + uint64 accelerated_surface_identifier) {} +#endif + + // Gets the WebPluginDelegate that implements the interface. + // This API is only for use with Pepper, and is only overridden + // by in-renderer implementations. + virtual WebPluginDelegate* delegate() { return NULL; } +}; + +// Simpler version of ResourceHandleClient that lends itself to proxying. +class WebPluginResourceClient { + public: + virtual ~WebPluginResourceClient() {} + virtual void WillSendRequest(const GURL& url) = 0; + // The request_is_seekable parameter indicates whether byte range requests + // can be issued for the underlying stream. + virtual void DidReceiveResponse(const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified, + bool request_is_seekable) = 0; + virtual void DidReceiveData(const char* buffer, int length, + int data_offset) = 0; + virtual void DidFinishLoading() = 0; + virtual void DidFail() = 0; + virtual bool IsMultiByteResponseExpected() = 0; +}; + +} // namespace webkit_glue + +#endif // #ifndef WEBKIT_GLUE_WEBPLUGIN_H_ diff --git a/webkit/glue/plugins/webplugin_delegate.h b/webkit/glue/plugins/webplugin_delegate.h new file mode 100644 index 0000000..0b08c9e --- /dev/null +++ b/webkit/glue/plugins/webplugin_delegate.h @@ -0,0 +1,161 @@ +// Copyright (c) 2010 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. + +#ifndef WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ +#define WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ + +#include +#include + +#include "base/string16.h" +#include "build/build_config.h" +#include "gfx/native_widget_types.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/npapi_extensions.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h" +#include "webkit/glue/plugins/webplugin_2d_device_delegate.h" +#include "webkit/glue/plugins/webplugin_3d_device_delegate.h" +#include "webkit/glue/plugins/webplugin_audio_device_delegate.h" +#include "webkit/glue/plugins/webplugin_file_delegate.h" +#include "webkit/glue/plugins/webplugin_print_delegate.h" + + +class FilePath; +class GURL; +struct NPObject; + +namespace WebKit { +class WebInputEvent; +struct WebCursorInfo; +} + +namespace gfx { +class Rect; +} + +namespace webkit_glue { + +class WebPlugin; +class WebPluginResourceClient; + +// This is the interface that a plugin implementation needs to provide. +class WebPluginDelegate : public WebPlugin2DDeviceDelegate, + public WebPlugin3DDeviceDelegate, + public WebPluginAudioDeviceDelegate, + public WebPluginPrintDelegate, + public WebPluginFileDelegate { + public: + virtual ~WebPluginDelegate() {} + + // Initializes the plugin implementation with the given (UTF8) arguments. + // Note that the lifetime of WebPlugin must be longer than this delegate. + // If this function returns false the plugin isn't started and shouldn't be + // called again. If this method succeeds, then the WebPlugin is valid until + // PluginDestroyed is called. + // The load_manually parameter if true indicates that the plugin data would + // be passed from webkit. if false indicates that the plugin should download + // the data. This also controls whether the plugin is instantiated as a full + // page plugin (NP_FULL) or embedded (NP_EMBED). + virtual bool Initialize(const GURL& url, + const std::vector& arg_names, + const std::vector& arg_values, + WebPlugin* plugin, + bool load_manually) = 0; + + // Called when the WebPlugin is being destroyed. This is a signal to the + // delegate that it should tear-down the plugin implementation and not call + // methods on the WebPlugin again. + virtual void PluginDestroyed() = 0; + + // Update the geometry of the plugin. This is a request to move the + // plugin, relative to its containing window, to the coords given by + // window_rect. Its contents should be clipped to the coords given + // by clip_rect, which are relative to the origin of the plugin + // window. The clip_rect is in plugin-relative coordinates. + virtual void UpdateGeometry(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) = 0; + + // Tells the plugin to paint the damaged rect. |canvas| is only used for + // windowless plugins. + virtual void Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect) = 0; + + // Tells the plugin to print itself. + virtual void Print(gfx::NativeDrawingContext hdc) = 0; + + // Informs the plugin that it now has focus. This is only called in + // windowless mode. + virtual void SetFocus() = 0; + + // For windowless plugins, gives them a user event like mouse/keyboard. + // Returns whether the event was handled. This is only called in windowsless + // mode. See NPAPI NPP_HandleEvent for more information. + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebKit::WebCursorInfo* cursor) = 0; + + // Gets the NPObject associated with the plugin for scripting. + virtual NPObject* GetPluginScriptableObject() = 0; + + // Receives notification about a resource load that the plugin initiated + // for a frame. + virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason, + int notify_id) = 0; + + // Returns the process id of the process that is running the plugin. + virtual int GetProcessId() = 0; + + // The result, UTF-8 encoded, of the script execution is returned via this + // function. + virtual void SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, + int notify_id) = 0; + + // Receives notification about data being available. + virtual void DidReceiveManualResponse(const GURL& url, + const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified) = 0; + + // Receives the data. + virtual void DidReceiveManualData(const char* buffer, int length) = 0; + + // Indicates end of data load. + virtual void DidFinishManualLoading() = 0; + + // Indicates a failure in data receipt. + virtual void DidManualLoadFail() = 0; + + // Only supported when the plugin is the default plugin. + virtual void InstallMissingPlugin() = 0; + + // Creates a WebPluginResourceClient instance and returns the same. + virtual WebPluginResourceClient* CreateResourceClient( + unsigned long resource_id, + const GURL& url, + int notify_id) = 0; + + // Creates a WebPluginResourceClient instance for an existing stream that is + // has become seekable. + virtual WebPluginResourceClient* CreateSeekableResourceClient( + unsigned long resource_id, int range_request_id) = 0; + + // See WebPluginContainerImpl's description of the interface. + virtual bool SupportsFind() { return false; } + virtual void StartFind(const std::string& search_text, + bool case_sensitive, + int identifier) {} + virtual void SelectFindResult(bool forward) {} + virtual void StopFind() {} + virtual void NumberOfFindResultsChanged(int total, bool final_result) {} + virtual void SelectedFindResultChanged(int index) {} + + // Used for zooming of full page plugins. 0 means reset, while -1 means zoom + // out and +1 means zoom in. + virtual void Zoom(int factor) {} +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index a66f282..3295a08 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -19,8 +19,8 @@ #include "gfx/native_widget_types.h" #include "gfx/rect.h" #include "third_party/npapi/bindings/npapi.h" +#include "webkit/glue/plugins/webplugin_delegate.h" #include "webkit/glue/webcursor.h" -#include "webkit/glue/webplugin_delegate.h" #if defined(OS_MACOSX) #include "app/surface/accelerated_surface_mac.h" diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index 2c6b239..2501b01 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -20,13 +20,13 @@ #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" -#include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/gtk_plugin_container.h" #include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webkit_glue.h" #include "third_party/npapi/bindings/npapi_x11.h" diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index 1d0b138..bf74453 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -19,13 +19,13 @@ #include "base/string_util.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" #include "webkit/default_plugin/plugin_impl.h" -#include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/coregraphics_private_symbols_mac.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/plugins/plugin_web_event_converter_mac.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webkit_glue.h" #ifndef NP_NO_CARBON @@ -1125,7 +1125,7 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( if (!(event_converter.get() && event_converter->InitWithEvent(event))) return false; void* plugin_event = event_converter->plugin_event(); - + if (fabsf(zoom_level - 1.0) > kEpsilon) event_converter->SetZoomLevel(zoom_level); diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc index 2c31856..1c83565 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc @@ -24,8 +24,8 @@ #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/glue/webplugin.h" using WebKit::WebCursorInfo; using WebKit::WebKeyboardEvent; diff --git a/webkit/glue/plugins/webplugin_impl.cc b/webkit/glue/plugins/webplugin_impl.cc new file mode 100644 index 0000000..e701675 --- /dev/null +++ b/webkit/glue/plugins/webplugin_impl.cc @@ -0,0 +1,1207 @@ +// Copyright (c) 2010 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 "base/logging.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "gfx/rect.h" +#include "net/base/escape.h" +#include "net/base/net_errors.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCookieJar.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCString.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" +#include "third_party/WebKit/WebKit/chromium/public/WebDevToolsAgent.h" +#include "third_party/WebKit/WebKit/chromium/public/WebData.h" +#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h" +#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" +#include "third_party/WebKit/WebKit/chromium/public/WebKit.h" +#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h" +#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" +#include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURL.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" +#include "third_party/WebKit/WebKit/chromium/public/WebView.h" +#include "webkit/glue/multipart_response_delegate.h" +#include "webkit/glue/plugins/plugin_host.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "webkit/glue/plugins/webplugin_impl.h" +#include "webkit/glue/plugins/webplugin_page_delegate.h" +#include "googleurl/src/gurl.h" + +using WebKit::WebCanvas; +using WebKit::WebConsoleMessage; +using WebKit::WebCookieJar; +using WebKit::WebCString; +using WebKit::WebCursorInfo; +using WebKit::WebData; +using WebKit::WebDataSource; +using WebKit::WebDevToolsAgent; +using WebKit::WebFrame; +using WebKit::WebHTTPBody; +using WebKit::WebHTTPHeaderVisitor; +using WebKit::WebInputEvent; +using WebKit::WebKeyboardEvent; +using WebKit::WebMouseEvent; +using WebKit::WebPluginContainer; +using WebKit::WebPluginParams; +using WebKit::WebRect; +using WebKit::WebString; +using WebKit::WebURL; +using WebKit::WebURLError; +using WebKit::WebURLLoader; +using WebKit::WebURLLoaderClient; +using WebKit::WebURLRequest; +using WebKit::WebURLResponse; +using WebKit::WebVector; +using WebKit::WebView; +using webkit_glue::MultipartResponseDelegate; + +namespace webkit_glue { +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 +// specified in the response header. +class MultiPartResponseClient : public WebURLLoaderClient { + public: + explicit MultiPartResponseClient(WebPluginResourceClient* resource_client) + : resource_client_(resource_client) { + Clear(); + } + + virtual void willSendRequest( + WebURLLoader*, WebURLRequest&, const WebURLResponse&) {} + virtual void didSendData( + WebURLLoader*, unsigned long long, unsigned long long) {} + + // Called when the multipart parser encounters an embedded multipart + // response. + virtual void didReceiveResponse( + WebURLLoader*, const WebURLResponse& response) { + if (!MultipartResponseDelegate::ReadContentRanges( + response, + &byte_range_lower_bound_, + &byte_range_upper_bound_)) { + NOTREACHED(); + return; + } + + resource_response_ = response; + } + + // Receives individual part data from a multipart response. + virtual void didReceiveData( + WebURLLoader*, const char* data, int data_size) { + // TODO(ananta) + // We should defer further loads on multipart resources on the same lines + // as regular resources requested by plugins to prevent reentrancy. + resource_client_->DidReceiveData( + data, data_size, byte_range_lower_bound_); + } + + virtual void didFinishLoading(WebURLLoader*) {} + virtual void didFail(WebURLLoader*, const WebURLError&) {} + + void Clear() { + resource_response_.reset(); + byte_range_lower_bound_ = 0; + byte_range_upper_bound_ = 0; + } + + private: + WebURLResponse resource_response_; + // The lower bound of the byte range. + int byte_range_lower_bound_; + // The upper bound of the byte range. + int byte_range_upper_bound_; + // The handler for the data. + WebPluginResourceClient* resource_client_; +}; + +class HeaderFlattener : public WebHTTPHeaderVisitor { + public: + HeaderFlattener(std::string* buf) : buf_(buf) { + } + + 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"); + } + } + + private: + std::string* buf_; +}; + +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; + + // TODO(darin): Shouldn't we also report HTTP version numbers? + result = StringPrintf("HTTP %d ", response.httpStatusCode()); + result.append(status.utf8()); + result.append("\n"); + + HeaderFlattener flattener(&result); + response.visitHTTPHeaderFields(&flattener); + + return result; +} + +struct ResponseInfo { + GURL url; + std::string mime_type; + uint32 last_modified; + uint32 expected_length; +}; + +void GetResponseInfo(const WebURLResponse& response, + ResponseInfo* response_info) { + response_info->url = response.url(); + response_info->mime_type = response.mimeType().utf8(); + + // Measured in seconds since 12:00 midnight GMT, January 1, 1970. + response_info->last_modified = + static_cast(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. + response_info->expected_length = + static_cast(std::max(response.expectedContentLength(), 0LL)); + + 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. + response_info->expected_length = 0; + } +} + +} // namespace + +// WebKit::WebPlugin ---------------------------------------------------------- + +bool WebPluginImpl::initialize(WebPluginContainer* container) { + if (!page_delegate_) + return false; + + std::string actual_mime_type; + WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate( + plugin_url_, mime_type_, &actual_mime_type); + if (!plugin_delegate) + return NULL; + + // Set the container before Initialize because the plugin may + // synchronously call NPN_GetValue to get its container during its + // initialization. + SetContainer(container); + bool ok = plugin_delegate->Initialize( + plugin_url_, arg_names_, arg_values_, this, load_manually_); + if (!ok) { + plugin_delegate->PluginDestroyed(); + return false; + } + + if (!actual_mime_type.empty()) + mime_type_ = actual_mime_type; + delegate_ = plugin_delegate; + + return true; +} + +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) { + if (!delegate_) + return; + + // Note that |canvas| is only used when in windowless mode. + delegate_->Paint(canvas, paint_rect); +} + +void WebPluginImpl::updateGeometry( + const WebRect& window_rect, const WebRect& clip_rect, + const WebVector& cutout_rects, bool is_visible) { + WebPluginGeometry new_geometry; + new_geometry.window = window_; + new_geometry.window_rect = window_rect; + new_geometry.clip_rect = clip_rect; + new_geometry.visible = is_visible; + new_geometry.rects_valid = true; + for (size_t i = 0; i < cutout_rects.size(); ++i) + new_geometry.cutout_rects.push_back(cutout_rects[i]); + + // Only send DidMovePlugin if the geometry changed in some way. + if (window_ && + page_delegate_ && + (first_geometry_update_ || !new_geometry.Equals(geometry_))) { + page_delegate_->DidMovePlugin(new_geometry); + } + + // Only UpdateGeometry if either the window or clip rects have changed. + if (first_geometry_update_ || + new_geometry.window_rect != geometry_.window_rect || + new_geometry.clip_rect != geometry_.clip_rect) { + // Notify the plugin that its parameters have changed. + delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.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_) { + // 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); + } + } + + first_geometry_update_ = false; + geometry_ = new_geometry; +} + +void WebPluginImpl::updateFocus(bool focused) { + if (focused && accepts_input_events_) + delegate_->SetFocus(); +} + +void WebPluginImpl::updateVisibility(bool visible) { + if (!window_ || !page_delegate_) + return; + + WebPluginGeometry move; + move.window = window_; + move.window_rect = gfx::Rect(); + move.clip_rect = gfx::Rect(); + move.rects_valid = false; + move.visible = visible; + + page_delegate_->DidMovePlugin(move); +} + +bool WebPluginImpl::acceptsInputEvents() { + return accepts_input_events_; +} + +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(); +} + +void WebPluginImpl::didFinishLoadingFrameRequest( + const WebURL& url, void* notify_data) { + if (delegate_) { + // We're converting a void* into an arbitrary int id. Though + // these types are the same size on all the platforms we support, + // the compiler may complain as though they are different, so to + // make the casting gods happy go through an intptr_t (the union + // of void* and int) rather than converting straight across. + delegate_->DidFinishLoadWithReason( + url, NPRES_DONE, reinterpret_cast(notify_data)); + } +} + +void WebPluginImpl::didFailLoadingFrameRequest( + const WebURL& url, void* notify_data, const WebURLError& error) { + if (!delegate_) + return; + + NPReason reason = + error.reason == net::ERR_ABORTED ? NPRES_USER_BREAK : NPRES_NETWORK_ERR; + // See comment in didFinishLoadingFrameRequest about the cast here. + delegate_->DidFinishLoadWithReason( + url, reason, reinterpret_cast(notify_data)); +} + +bool WebPluginImpl::supportsPaginatedPrint() { + if (!delegate_) + return false; + return delegate_->PrintSupportsPrintExtension(); +} + +int WebPluginImpl::printBegin(const WebRect& printable_area, int printer_dpi) { + if (!delegate_) + return 0; + + if (!supportsPaginatedPrint()) + return 0; + + return delegate_->PrintBegin(printable_area, printer_dpi); +} + +bool WebPluginImpl::printPage(int page_number, WebCanvas* canvas) { + if (!delegate_) + return false; + + return delegate_->PrintPage(page_number, canvas); +} + +void WebPluginImpl::printEnd() { + if (delegate_) + delegate_->PrintEnd(); +} + + +// ----------------------------------------------------------------------------- + +WebPluginImpl::WebPluginImpl( + WebFrame* webframe, const WebPluginParams& params, + const base::WeakPtr& page_delegate) + : windowless_(false), + window_(NULL), + accepts_input_events_(false), + page_delegate_(page_delegate), + webframe_(webframe), + delegate_(NULL), + container_(NULL), + plugin_url_(params.url), + load_manually_(params.loadManually), + first_geometry_update_(true), + ignore_response_error_(false), + mime_type_(params.mimeType.utf8()), + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { + DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); + StringToLowerASCII(&mime_type_); + + for (size_t i = 0; i < params.attributeNames.size(); ++i) { + arg_names_.push_back(params.attributeNames[i].utf8()); + arg_values_.push_back(params.attributeValues[i].utf8()); + } +} + +WebPluginImpl::~WebPluginImpl() { +} + +void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) { +#if defined(OS_MACOSX) + // The only time this is called twice, and the second time with a + // non-zero PluginWindowHandle, is the case when this WebPluginImpl + // is created on behalf of the GPU plugin. This entire code path + // will go away soon, as soon as the GPU plugin becomes the GPU + // process, so it is being separated out for easy deletion. + + // The logic we want here is: if (window) DCHECK(!window_); + DCHECK(!(window_ && window)); + window_ = window; + // Lie to ourselves about being windowless even if we got a fake + // plugin window handle, so we continue to get input events. + windowless_ = true; + accepts_input_events_ = true; + // We do not really need to notify the page delegate that a plugin + // window was created -- so don't. +#else + if (window) { + DCHECK(!windowless_); + window_ = window; + accepts_input_events_ = false; + if (page_delegate_) { + // Tell the view delegate that the plugin window was created, so that it + // can create necessary container widgets. + page_delegate_->CreatedPluginWindow(window); + } + } else { + DCHECK(!window_); // Make sure not called twice. + windowless_ = true; + accepts_input_events_ = true; + } +#endif +} + +void WebPluginImpl::WillDestroyWindow(gfx::PluginWindowHandle window) { + DCHECK_EQ(window, window_); + window_ = NULL; + if (page_delegate_) + page_delegate_->WillDestroyPluginWindow(window); +} + +GURL WebPluginImpl::CompleteURL(const char* url) { + if (!webframe_) { + NOTREACHED(); + return GURL(); + } + // TODO(darin): Is conversion from UTF8 correct here? + return webframe_->completeURL(WebString::fromUTF8(url)); +} + +void WebPluginImpl::CancelResource(unsigned long id) { + for (size_t i = 0; i < clients_.size(); ++i) { + if (clients_[i].id == id) { + if (clients_[i].loader.get()) { + clients_[i].loader->setDefersLoading(false); + clients_[i].loader->cancel(); + RemoveClient(i); + } + return; + } + } +} + +bool WebPluginImpl::SetPostData(WebURLRequest* request, + const char *buf, + uint32 length) { + std::vector names; + std::vector values; + std::vector body; + bool rv = NPAPI::PluginHost::SetPostData(buf, length, &names, &values, &body); + + for (size_t i = 0; i < names.size(); ++i) { + request->addHTTPHeaderField(WebString::fromUTF8(names[i]), + WebString::fromUTF8(values[i])); + } + + WebString content_type_header = WebString::fromUTF8("Content-Type"); + const WebString& content_type = + request->httpHeaderField(content_type_header); + if (content_type.isEmpty()) { + request->setHTTPHeaderField( + content_type_header, + WebString::fromUTF8("application/x-www-form-urlencoded")); + } + + WebHTTPBody http_body; + if (body.size()) { + http_body.initialize(); + http_body.appendData(WebData(&body[0], body.size())); + } + request->setHTTPBody(http_body); + + return rv; +} + +WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame( + const char* url, + bool is_javascript_url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + Referrer referrer_flag) { + // If there is no target, there is nothing to do + if (!target) + return NOT_ROUTED; + + // This could happen if the WebPluginContainer was already deleted. + if (!webframe_) + return NOT_ROUTED; + + WebString target_str = WebString::fromUTF8(target); + + // Take special action for JavaScript URLs + if (is_javascript_url) { + WebFrame* target_frame = + webframe_->view()->findFrameByName(target_str, webframe_); + // For security reasons, do not allow JavaScript on frames + // other than this frame. + if (target_frame != webframe_) { + // TODO(darin): Localize this message. + const char kMessage[] = + "Ignoring cross-frame javascript URL load requested by plugin."; + webframe_->addMessageToConsole( + WebConsoleMessage(WebConsoleMessage::LevelError, + WebString::fromUTF8(kMessage))); + return ROUTED; + } + + // Route javascript calls back to the plugin. + return NOT_ROUTED; + } + + // If we got this far, we're routing content to a target frame. + // Go fetch the URL. + + GURL complete_url = CompleteURL(url); + + if (strcmp(method, "GET") != 0) { + // We're only going to route HTTP/HTTPS requests + if (!(complete_url.SchemeIs("http") || complete_url.SchemeIs("https"))) + return INVALID_URL; + } + + WebURLRequest request(complete_url); + SetReferrer(&request, referrer_flag); + + request.setHTTPMethod(WebString::fromUTF8(method)); + request.setFirstPartyForCookies( + webframe_->document().firstPartyForCookies()); + if (len > 0) { + if (!SetPostData(&request, buf, len)) { + // Uhoh - we're in trouble. There isn't a good way + // to recover at this point. Break out. + NOTREACHED(); + return ROUTED; + } + } + + container_->loadFrameRequest( + request, target_str, notify_id != 0, reinterpret_cast(notify_id)); + return ROUTED; +} + +NPObject* WebPluginImpl::GetWindowScriptNPObject() { + if (!webframe_) { + NOTREACHED(); + return NULL; + } + return webframe_->windowObject(); +} + +NPObject* WebPluginImpl::GetPluginElement() { + return container_->scriptableObjectForElement(); +} + +void WebPluginImpl::SetCookie(const GURL& url, + const GURL& first_party_for_cookies, + const std::string& cookie) { + if (!page_delegate_) + return; + + WebCookieJar* cookie_jar = page_delegate_->GetCookieJar(); + if (!cookie_jar) { + DLOG(WARNING) << "No cookie jar!"; + return; + } + + cookie_jar->setCookie( + url, first_party_for_cookies, WebString::fromUTF8(cookie)); +} + +std::string WebPluginImpl::GetCookies(const GURL& url, + const GURL& first_party_for_cookies) { + if (!page_delegate_) + return std::string(); + + WebCookieJar* cookie_jar = page_delegate_->GetCookieJar(); + if (!cookie_jar) { + DLOG(WARNING) << "No cookie jar!"; + return std::string(); + } + + return UTF16ToUTF8(cookie_jar->cookies(url, first_party_for_cookies)); +} + +void WebPluginImpl::ShowModalHTMLDialog(const GURL& url, int width, int height, + const std::string& json_arguments, + std::string* json_retval) { + if (page_delegate_) { + page_delegate_->ShowModalHTMLDialogForPlugin( + url, gfx::Size(width, height), json_arguments, json_retval); + } +} + +void WebPluginImpl::OnMissingPluginStatus(int status) { + NOTREACHED(); +} + +void WebPluginImpl::Invalidate() { + if (container_) + container_->invalidate(); +} + +void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { + if (container_) + container_->invalidateRect(rect); +} + +void WebPluginImpl::OnDownloadPluginSrcUrl() { + HandleURLRequestInternal( + plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL); +} + +WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( + WebURLLoader* loader) { + ClientInfo* client_info = GetClientInfoFromLoader(loader); + if (client_info) + return client_info->client; + return NULL; +} + +WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader( + WebURLLoader* loader) { + for (size_t i = 0; i < clients_.size(); ++i) { + if (clients_[i].loader.get() == loader) + return &clients_[i]; + } + + NOTREACHED(); + return 0; +} + +void WebPluginImpl::willSendRequest(WebURLLoader* loader, + WebURLRequest& request, + const WebURLResponse&) { + WebPluginResourceClient* client = GetClientFromLoader(loader); + if (client) + client->WillSendRequest(request.url()); +} + +void WebPluginImpl::didSendData(WebURLLoader* loader, + unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent) { +} + +void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, + const WebURLResponse& response) { + static const int kHttpPartialResponseStatusCode = 206; + static const int kHttpResponseSuccessStatusCode = 200; + + WebPluginResourceClient* client = GetClientFromLoader(loader); + if (!client) + return; + + ResponseInfo response_info; + GetResponseInfo(response, &response_info); + + bool request_is_seekable = true; + if (client->IsMultiByteResponseExpected()) { + if (response.httpStatusCode() == kHttpPartialResponseStatusCode) { + HandleHttpMultipartResponse(response, client); + return; + } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) { + // If the client issued a byte range request and the server responds with + // HTTP 200 OK, it indicates that the server does not support byte range + // requests. + // We need to emulate Firefox behavior by doing the following:- + // 1. Destroy the plugin instance in the plugin process. Ensure that + // existing resource requests initiated for the plugin instance + // continue to remain valid. + // 2. Create a new plugin instance and notify it about the response + // received here. + if (!ReinitializePluginForResponse(loader)) { + NOTREACHED(); + return; + } + + // The server does not support byte range requests. No point in creating + // seekable streams. + request_is_seekable = false; + + delete client; + client = NULL; + + // Create a new resource client for this request. + for (size_t i = 0; i < clients_.size(); ++i) { + if (clients_[i].loader.get() == loader) { + WebPluginResourceClient* resource_client = + delegate_->CreateResourceClient(clients_[i].id, plugin_url_, 0); + clients_[i].client = resource_client; + client = resource_client; + break; + } + } + + DCHECK(client != NULL); + } + } + + // Calling into a plugin could result in reentrancy if the plugin yields + // control to the OS like entering a modal loop etc. Prevent this by + // stopping further loading until the plugin notifies us that it is ready to + // accept data + loader->setDefersLoading(true); + + client->DidReceiveResponse( + response_info.mime_type, + GetAllHeaders(response), + response_info.expected_length, + response_info.last_modified, + request_is_seekable); + + if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) { + ClientInfo* client_info = GetClientInfoFromLoader(loader); + if (client_info) + devtools_agent->didReceiveResponse(client_info->id, response); + } + + // 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 + // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF + // destroy the stream and invoke the NPP_DestroyStream function on the + // plugin if the HTTP request fails. + const GURL& url = response.url(); + if (url.SchemeIs("http") || url.SchemeIs("https")) { + if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) { + // The plugin instance could be in the process of deletion here. + // Verify if the WebPluginResourceClient instance still exists before + // use. + ClientInfo* client_info = GetClientInfoFromLoader(loader); + if (client_info) { + client_info->pending_failure_notification = true; + } + } + } +} + +void WebPluginImpl::didReceiveData(WebURLLoader* loader, + const char *buffer, + int length) { + WebPluginResourceClient* client = GetClientFromLoader(loader); + if (!client) + return; + + // ClientInfo can be removed from clients_ vector by next statements. + if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) { + ClientInfo* client_info = GetClientInfoFromLoader(loader); + if (client_info) + devtools_agent->didReceiveData(client_info->id, length); + } + MultiPartResponseHandlerMap::iterator index = + multi_part_response_map_.find(client); + if (index != multi_part_response_map_.end()) { + MultipartResponseDelegate* multi_part_handler = (*index).second; + DCHECK(multi_part_handler != NULL); + multi_part_handler->OnReceivedData(buffer, length); + } else { + loader->setDefersLoading(true); + client->DidReceiveData(buffer, length, 0); + } +} + +void WebPluginImpl::didFinishLoading(WebURLLoader* loader) { + ClientInfo* client_info = GetClientInfoFromLoader(loader); + if (client_info && client_info->client) { + MultiPartResponseHandlerMap::iterator index = + multi_part_response_map_.find(client_info->client); + if (index != multi_part_response_map_.end()) { + delete (*index).second; + multi_part_response_map_.erase(index); + if (page_delegate_) + page_delegate_->DidStopLoadingForPlugin(); + } + loader->setDefersLoading(true); + WebPluginResourceClient* resource_client = client_info->client; + // The ClientInfo can get deleted in the call to DidFinishLoading below. + // It is not safe to access this structure after that. + client_info->client = NULL; + resource_client->DidFinishLoading(); + + if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) + devtools_agent->didFinishLoading(client_info->id); + } +} + +void WebPluginImpl::didFail(WebURLLoader* loader, + const WebURLError& error) { + ClientInfo* client_info = GetClientInfoFromLoader(loader); + if (client_info && client_info->client) { + loader->setDefersLoading(true); + WebPluginResourceClient* resource_client = client_info->client; + // The ClientInfo can get deleted in the call to DidFail below. + // It is not safe to access this structure after that. + client_info->client = NULL; + resource_client->DidFail(); + + if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) + devtools_agent->didFailLoading(client_info->id, error); + } +} + +void WebPluginImpl::RemoveClient(size_t i) { + clients_.erase(clients_.begin() + i); +} + +void WebPluginImpl::RemoveClient(WebURLLoader* loader) { + for (size_t i = 0; i < clients_.size(); ++i) { + if (clients_[i].loader.get() == loader) { + RemoveClient(i); + return; + } + } +} + +void WebPluginImpl::SetContainer(WebPluginContainer* container) { + if (!container) + TearDownPluginInstance(NULL); + container_ = container; +} + +void WebPluginImpl::HandleURLRequest(const char* url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + bool popups_allowed) { + // GetURL/PostURL requests initiated explicitly by plugins should specify the + // plugin SRC url as the referrer if it is available. + HandleURLRequestInternal( + url, method, target, buf, len, notify_id, popups_allowed, PLUGIN_SRC); +} + +void WebPluginImpl::HandleURLRequestInternal(const char* url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + bool popups_allowed, + Referrer referrer_flag) { + // For this request, we either route the output to a frame + // because a target has been specified, or we handle the request + // here, i.e. by executing the script if it is a javascript url + // or by initiating a download on the URL, etc. There is one special + // case in that the request is a javascript url and the target is "_self", + // in which case we route the output to the plugin rather than routing it + // to the plugin's frame. + bool is_javascript_url = StartsWithASCII(url, "javascript:", false); + RoutingStatus routing_status = RouteToFrame( + url, is_javascript_url, method, target, buf, len, notify_id, + referrer_flag); + if (routing_status == ROUTED) + return; + + if (is_javascript_url) { + GURL gurl(url); + WebString result = container_->executeScriptURL(gurl, popups_allowed); + + // delegate_ could be NULL because executeScript caused the container to + // be deleted. + if (delegate_) { + delegate_->SendJavaScriptStream( + gurl, result.utf8(), !result.isNull(), notify_id); + } + + return; + } + + unsigned long resource_id = GetNextResourceId(); + if (!resource_id) + return; + + GURL complete_url = CompleteURL(url); + WebPluginResourceClient* resource_client = delegate_->CreateResourceClient( + resource_id, complete_url, notify_id); + if (!resource_client) + return; + + // If the RouteToFrame call returned a failure then inform the result + // back to the plugin asynchronously. + if ((routing_status == INVALID_URL) || + (routing_status == GENERAL_FAILURE)) { + resource_client->DidFail(); + return; + } + + // CreateResourceClient() sends a synchronous IPC message so it's possible + // that TearDownPluginInstance() may have been called in the nested + // message loop. If so, don't start the request. + if (!delegate_) + return; + + InitiateHTTPRequest(resource_id, resource_client, complete_url, method, buf, + len, NULL, referrer_flag); +} + +unsigned long WebPluginImpl::GetNextResourceId() { + if (!webframe_) + return 0; + WebView* view = webframe_->view(); + if (!view) + return 0; + return view->createUniqueIdentifierForRequest(); +} + +bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id, + WebPluginResourceClient* client, + const GURL& url, + const char* method, + const char* buf, + int buf_len, + const char* range_info, + Referrer referrer_flag) { + if (!client) { + NOTREACHED(); + return false; + } + + ClientInfo info; + info.id = resource_id; + info.client = client; + info.request.initialize(); + info.request.setURL(url); + info.request.setFirstPartyForCookies( + webframe_->document().firstPartyForCookies()); + info.request.setRequestorProcessID(delegate_->GetProcessId()); + info.request.setTargetType(WebURLRequest::TargetIsObject); + info.request.setHTTPMethod(WebString::fromUTF8(method)); + info.pending_failure_notification = false; + + if (range_info) { + info.request.addHTTPHeaderField(WebString::fromUTF8("Range"), + WebString::fromUTF8(range_info)); + } + + if (strcmp(method, "POST") == 0) { + // Adds headers or form data to a request. This must be called before + // we initiate the actual request. + SetPostData(&info.request, buf, buf_len); + } + + SetReferrer(&info.request, referrer_flag); + + // Sets the routing id to associate the ResourceRequest with the RenderView. + webframe_->dispatchWillSendRequest(info.request); + if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) { + devtools_agent->identifierForInitialRequest(resource_id, webframe_, + info.request); + devtools_agent->willSendRequest(resource_id, info.request); + } + + info.loader.reset(WebKit::webKitClient()->createURLLoader()); + if (!info.loader.get()) + return false; + info.loader->loadAsynchronously(info.request, this); + + clients_.push_back(info); + return true; +} + +void WebPluginImpl::CancelDocumentLoad() { + if (webframe_) { + ignore_response_error_ = true; + webframe_->stopLoading(); + } +} + +void WebPluginImpl::InitiateHTTPRangeRequest( + const char* url, const char* range_info, int range_request_id) { + unsigned long resource_id = GetNextResourceId(); + if (!resource_id) + return; + + GURL complete_url = CompleteURL(url); + + WebPluginResourceClient* resource_client = + delegate_->CreateSeekableResourceClient(resource_id, range_request_id); + InitiateHTTPRequest( + resource_id, resource_client, complete_url, "GET", NULL, 0, range_info, + load_manually_ ? NO_REFERRER : PLUGIN_SRC); +} + +void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id, + bool defer) { + std::vector::iterator client_index = clients_.begin(); + while (client_index != clients_.end()) { + ClientInfo& client_info = *client_index; + + if (client_info.id == resource_id) { + client_info.loader->setDefersLoading(defer); + + // If we determined that the request had failed via the HTTP headers + // in the response then we send out a failure notification to the + // plugin process, as certain plugins don't handle HTTP failure codes + // correctly. + if (!defer && client_info.client && + client_info.pending_failure_notification) { + // The ClientInfo and the iterator can become invalid due to the call + // to DidFail below. + WebPluginResourceClient* resource_client = client_info.client; + client_info.loader->cancel(); + clients_.erase(client_index++); + resource_client->DidFail(); + + // Report that resource loading finished. + if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) + devtools_agent->didFinishLoading(resource_id); + } + break; + } + client_index++; + } +} + +void WebPluginImpl::HandleHttpMultipartResponse( + const WebURLResponse& response, WebPluginResourceClient* client) { + std::string multipart_boundary; + if (!MultipartResponseDelegate::ReadMultipartBoundary( + response, &multipart_boundary)) { + NOTREACHED(); + return; + } + + if (page_delegate_) + page_delegate_->DidStartLoadingForPlugin(); + + MultiPartResponseClient* multi_part_response_client = + new MultiPartResponseClient(client); + + MultipartResponseDelegate* multi_part_response_handler = + new MultipartResponseDelegate(multi_part_response_client, NULL, + response, + multipart_boundary); + multi_part_response_map_[client] = multi_part_response_handler; +} + +bool WebPluginImpl::ReinitializePluginForResponse( + WebURLLoader* loader) { + WebFrame* webframe = webframe_; + if (!webframe) + return false; + + WebView* webview = webframe->view(); + if (!webview) + return false; + + WebPluginContainer* container_widget = container_; + + // Destroy the current plugin instance. + TearDownPluginInstance(loader); + + container_ = container_widget; + webframe_ = webframe; + + std::string actual_mime_type; + WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate( + plugin_url_, mime_type_, &actual_mime_type); + + bool ok = plugin_delegate->Initialize( + plugin_url_, arg_names_, arg_values_, this, load_manually_); + + if (!ok) { + container_ = NULL; + // TODO(iyengar) Should we delete the current plugin instance here? + return false; + } + + mime_type_ = actual_mime_type; + delegate_ = plugin_delegate; + + // Force a geometry update to occur to ensure that the plugin becomes + // visible. + container_->reportGeometry(); + + // 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. + container_->invalidate(); + return true; +} + +void WebPluginImpl::TearDownPluginInstance( + WebURLLoader* loader_to_ignore) { + // The container maintains a list of JSObjects which are related to this + // plugin. Tell the frame we're gone so that it can invalidate all of + // those sub JSObjects. + if (container_) + container_->clearScriptObjects(); + + if (delegate_) { + // Call PluginDestroyed() first to prevent the plugin from calling us back + // in the middle of tearing down the render tree. + delegate_->PluginDestroyed(); + delegate_ = NULL; + } + + // Cancel any pending requests because otherwise this deleted object will + // be called by the ResourceDispatcher. + std::vector::iterator client_index = clients_.begin(); + while (client_index != clients_.end()) { + ClientInfo& client_info = *client_index; + + if (loader_to_ignore == client_info.loader) { + client_index++; + continue; + } + + if (client_info.loader.get()) + client_info.loader->cancel(); + + client_index = clients_.erase(client_index); + } + + // This needs to be called now and not in the destructor since the + // webframe_ might not be valid anymore. + webframe_ = NULL; + method_factory_.RevokeAll(); +} + +void WebPluginImpl::SetReferrer(WebKit::WebURLRequest* request, + Referrer referrer_flag) { + switch (referrer_flag) { + case DOCUMENT_URL: + webframe_->setReferrerForRequest(*request, GURL()); + break; + + case PLUGIN_SRC: + webframe_->setReferrerForRequest(*request, plugin_url_); + break; + + default: + break; + } +} + +WebDevToolsAgent* WebPluginImpl::GetDevToolsAgent() { + if (!webframe_) + return NULL; + WebView* view = webframe_->view(); + if (!view) + return NULL; + return view->devToolsAgent(); +} + +} // namespace webkit_glue diff --git a/webkit/glue/plugins/webplugin_impl.h b/webkit/glue/plugins/webplugin_impl.h new file mode 100644 index 0000000..fd6ea25 --- /dev/null +++ b/webkit/glue/plugins/webplugin_impl.h @@ -0,0 +1,321 @@ +// Copyright (c) 2010 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. + +#ifndef WEBKIT_GLUE_WEBPLUGIN_IMPL_H_ +#define WEBKIT_GLUE_WEBPLUGIN_IMPL_H_ + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/linked_ptr.h" +#include "base/task.h" +#include "base/weak_ptr.h" +#include "gfx/native_widget_types.h" +#include "googleurl/src/gurl.h" +#include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h" +#include "third_party/WebKit/WebKit/chromium/public/WebRect.h" +#include "third_party/WebKit/WebKit/chromium/public/WebString.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebVector.h" +#include "webkit/glue/plugins/webplugin.h" + +class WebViewDelegate; + +namespace WebKit { +class WebDevToolsAgent; +class WebFrame; +class WebPluginContainer; +class WebURLResponse; +class WebURLLoader; +class WebURLRequest; +} + +namespace webkit_glue { + +class MultipartResponseDelegate; +class WebPluginDelegate; +class WebPluginPageDelegate; + +// 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: + WebPluginImpl( + WebKit::WebFrame* frame, + const WebKit::WebPluginParams& params, + const base::WeakPtr& page_delegate); + virtual ~WebPluginImpl(); + + // Helper function for sorting post data. + static bool SetPostData(WebKit::WebURLRequest* request, + const char* buf, + uint32 length); + + virtual WebPluginDelegate* delegate() { return delegate_; } + + private: + // WebKit::WebPlugin methods: + virtual bool initialize( + WebKit::WebPluginContainer* container); + 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& cut_outs, bool is_visible); + virtual void updateFocus(bool focused); + virtual void updateVisibility(bool visible); + virtual bool acceptsInputEvents(); + 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); + virtual void didFinishLoadingFrameRequest( + const WebKit::WebURL& url, void* notify_data); + virtual void didFailLoadingFrameRequest( + const WebKit::WebURL& url, void* notify_data, + const WebKit::WebURLError& error); + virtual bool supportsPaginatedPrint(); + virtual int printBegin(const WebKit::WebRect& printable_area, + int printer_dpi); + virtual bool printPage(int page_number, WebKit::WebCanvas* canvas); + virtual void printEnd(); + + // WebPlugin implementation: + void SetWindow(gfx::PluginWindowHandle window); + + // Whether input events should be sent to the delegate. + virtual void SetAcceptsInputEvents(bool accepts) { + accepts_input_events_ = accepts; + } + + void WillDestroyWindow(gfx::PluginWindowHandle window); +#if defined(OS_WIN) + void SetWindowlessPumpEvent(HANDLE pump_messages_event) { } +#endif + + // Given a (maybe partial) url, completes using the base url. + GURL CompleteURL(const char* url); + + // Executes the script passed in. The notify_needed and notify_data arguments + // are passed in by the plugin process. These indicate whether the plugin + // expects a notification on script execution. We pass them back to the + // plugin as is. This avoids having to track the notification arguments in + // the plugin process. + bool ExecuteScript(const std::string& url, const std::wstring& script, + bool notify_needed, intptr_t notify_data, + bool popups_allowed); + + enum RoutingStatus { + ROUTED, + NOT_ROUTED, + INVALID_URL, + GENERAL_FAILURE + }; + + // Determines the referrer value sent along with outgoing HTTP requests + // issued by plugins. + enum Referrer { + PLUGIN_SRC, + DOCUMENT_URL, + NO_REFERRER + }; + + // Given a download request, check if we need to route the output to a frame. + // Returns ROUTED if the load is done and routed to a frame, NOT_ROUTED or + // corresponding error codes otherwise. + RoutingStatus RouteToFrame(const char* url, + bool is_javascript_url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + Referrer referrer_flag); + + // Cancels a pending request. + void CancelResource(unsigned long id); + + // Returns the next avaiable resource id. Returns 0 if the operation fails. + // It may fail if the page has already been closed. + unsigned long GetNextResourceId(); + + // Initiates HTTP GET/POST requests. + // Returns true on success. + bool InitiateHTTPRequest(unsigned long resource_id, + WebPluginResourceClient* client, + const GURL& url, + const char* method, + const char* buf, + int len, + const char* range_info, + Referrer referrer_flag); + + gfx::Rect GetWindowClipRect(const gfx::Rect& rect); + + NPObject* GetWindowScriptNPObject(); + NPObject* GetPluginElement(); + + void SetCookie(const GURL& url, + const GURL& first_party_for_cookies, + const std::string& cookie); + std::string GetCookies(const GURL& url, + const GURL& first_party_for_cookies); + + void ShowModalHTMLDialog(const GURL& url, int width, int height, + const std::string& json_arguments, + std::string* json_retval); + void OnMissingPluginStatus(int status); + void Invalidate(); + void InvalidateRect(const gfx::Rect& rect); + + // Sets the actual Widget for the plugin. + 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); + + // WebURLLoaderClient implementation. We implement this interface in the + // renderer process, and then use the simple WebPluginResourceClient interface + // to relay the callbacks to the plugin. + virtual void willSendRequest(WebKit::WebURLLoader* loader, + WebKit::WebURLRequest& request, + const WebKit::WebURLResponse&); + virtual void didSendData(WebKit::WebURLLoader* loader, + unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent); + virtual void didReceiveResponse(WebKit::WebURLLoader* loader, + const WebKit::WebURLResponse& response); + virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer, + int length); + virtual void didFinishLoading(WebKit::WebURLLoader* loader); + virtual void didFail(WebKit::WebURLLoader* loader, const WebKit::WebURLError&); + + // Helper function to remove the stored information about a resource + // request given its index in m_clients. + void RemoveClient(size_t i); + + // Helper function to remove the stored information about a resource + // request given a handle. + void RemoveClient(WebKit::WebURLLoader* loader); + + void HandleURLRequest(const char* url, + const char *method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + bool popups_allowed); + + void CancelDocumentLoad(); + + void InitiateHTTPRangeRequest( + const char* url, const char* range_info, int pending_request_id); + + void SetDeferResourceLoading(unsigned long resource_id, bool defer); + + // Ignore in-process plugins mode for this flag. + bool IsOffTheRecord() { return false; } + + // Handles HTTP multipart responses, i.e. responses received with a HTTP + // status code of 206. + void HandleHttpMultipartResponse(const WebKit::WebURLResponse& response, + WebPluginResourceClient* client); + + void HandleURLRequestInternal(const char* url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + int notify_id, + bool popups_allowed, + Referrer referrer_flag); + + // Tears down the existing plugin instance and creates a new plugin instance + // to handle the response identified by the loader parameter. + bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader); + + // Delayed task for downloading the plugin source URL. + void OnDownloadPluginSrcUrl(); + + struct ClientInfo { + unsigned long id; + WebPluginResourceClient* client; + WebKit::WebURLRequest request; + bool pending_failure_notification; + linked_ptr loader; + }; + + // Helper functions + WebPluginResourceClient* GetClientFromLoader(WebKit::WebURLLoader* loader); + ClientInfo* GetClientInfoFromLoader(WebKit::WebURLLoader* loader); + + // Helper function to set the referrer on the request passed in. + void SetReferrer(WebKit::WebURLRequest* request, Referrer referrer_flag); + + // Returns DevToolsAgent for the frame or 0. + WebKit::WebDevToolsAgent* GetDevToolsAgent(); + + std::vector clients_; + + bool windowless_; + gfx::PluginWindowHandle window_; + bool accepts_input_events_; + base::WeakPtr page_delegate_; + WebKit::WebFrame* webframe_; + + WebPluginDelegate* delegate_; + + // This is just a weak reference. + WebKit::WebPluginContainer* container_; + + typedef std::map + MultiPartResponseHandlerMap; + // Tracks HTTP multipart response handlers instantiated for + // a WebPluginResourceClient instance. + MultiPartResponseHandlerMap multi_part_response_map_; + + // The plugin source URL. + GURL plugin_url_; + + // Indicates if the download would be initiated by the plugin or us. + bool load_manually_; + + // 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. + WebPluginGeometry geometry_; + + // The mime type of the plugin. + std::string mime_type_; + + // Holds the list of argument names and values passed to the plugin. We keep + // these so that we can re-initialize the plugin if we need to. + std::vector arg_names_; + std::vector arg_values_; + + ScopedRunnableMethodFactory method_factory_; + + DISALLOW_COPY_AND_ASSIGN(WebPluginImpl); +}; + +} // namespace webkit_glue + +#endif // #ifndef WEBKIT_GLUE_WEBPLUGIN_IMPL_H_ diff --git a/webkit/glue/plugins/webplugin_impl_unittest.cc b/webkit/glue/plugins/webplugin_impl_unittest.cc new file mode 100644 index 0000000..e70e39a --- /dev/null +++ b/webkit/glue/plugins/webplugin_impl_unittest.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2010 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 "base/string_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCString.h" +#include "third_party/WebKit/WebKit/chromium/public/WebString.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" +#include "webkit/glue/plugins/webplugin_impl.h" + +using WebKit::WebHTTPBody; +using WebKit::WebString; +using WebKit::WebURLRequest; +using webkit_glue::WebPluginImpl; + +namespace { + +class WebPluginImplTest : public testing::Test { +}; + +} + +static std::string GetHeader(const WebURLRequest& request, const char* name) { + std::string result; + TrimWhitespace( + request.httpHeaderField(WebString::fromUTF8(name)).utf8(), + TRIM_ALL, + &result); + return result; +} + +static std::string GetBodyText(const WebURLRequest& request) { + const WebHTTPBody& body = request.httpBody(); + if (body.isNull()) + return std::string(); + + std::string result; + size_t i = 0; + WebHTTPBody::Element element; + while (body.elementAt(i++, element)) { + if (element.type == WebHTTPBody::Element::TypeData) { + result.append(element.data.data(), element.data.size()); + } else { + NOTREACHED() << "unexpected element type encountered!"; + } + } + return result; +} + +// The Host functions for NPN_PostURL and NPN_PostURLNotify +// need to parse out some HTTP headers. Make sure it works +// with the following tests + +TEST(WebPluginImplTest, PostParserSimple) { + // Test a simple case with headers & data + const char *ex1 = "foo: bar\nContent-length: 10\n\nabcdefghij"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + EXPECT_EQ("abcdefghij", GetBodyText(request)); +} + +TEST(WebPluginImplTest, PostParserLongHeader) { + // Test a simple case with long headers + const char *ex1 = "foo: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\nabcdefghij"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ(100U, GetHeader(request, "foo").length()); +} + +TEST(WebPluginImplTest, PostParserManyHeaders) { + // Test a simple case with long headers + const char *ex1 = "h1:h1\nh2:h2\nh3:h3\nh4:h4\nh5:h5\nh6:h6\nh7:h7\nh8:h8\nh9:h9\nh10:h10\n\nbody"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ("h1", GetHeader(request, "h1")); + EXPECT_EQ("h2", GetHeader(request, "h2")); + EXPECT_EQ("h3", GetHeader(request, "h3")); + EXPECT_EQ("h4", GetHeader(request, "h4")); + EXPECT_EQ("h5", GetHeader(request, "h5")); + EXPECT_EQ("h6", GetHeader(request, "h6")); + EXPECT_EQ("h7", GetHeader(request, "h7")); + EXPECT_EQ("h8", GetHeader(request, "h8")); + EXPECT_EQ("h9", GetHeader(request, "h9")); + EXPECT_EQ("h10", GetHeader(request, "h10")); + EXPECT_EQ("body", GetBodyText(request)); +} + +TEST(WebPluginImplTest, PostParserDuplicateHeaders) { + // Test a simple case with long headers + // What value gets returned doesn't really matter. It shouldn't error + // out. + const char *ex1 = "h1:h1\nh1:h2\n\nbody"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); +} + +TEST(WebPluginImplTest, PostParserNoHeaders) { + // Test a simple case with no headers but with data + const char *ex1 = "\nabcdefghij"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ(0U, GetHeader(request, "foo").length()); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + EXPECT_EQ("abcdefghij", GetBodyText(request)); +} + +TEST(WebPluginImplTest, PostParserNoBody) { + // Test a simple case with headers and no body + const char *ex1 = "Foo:bar\n\n"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + EXPECT_EQ(0U, GetBodyText(request).length()); +} + +TEST(WebPluginImplTest, PostParserBodyWithNewLines) { + // Test a simple case with headers and no body + const char *ex1 = "Foo:bar\n\n\n\nabcdefg\n\nabcdefg"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ(GetBodyText(request), "\n\nabcdefg\n\nabcdefg"); +} + +TEST(WebPluginImplTest, PostParserErrorNoBody) { + // Test with headers and no body + const char *ex1 = "Foo:bar\n"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); +} + +TEST(WebPluginImplTest, PostParserErrorEmpty) { + // Test with an empty string + const char *ex1 = ""; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); +} + +TEST(WebPluginImplTest, PostParserEmptyName) { + // Test an error case with an empty header name field + const char *ex1 = "foo:bar\n:blat\n\nbody"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ("body", GetBodyText(request)); +} + +TEST(WebPluginImplTest, PostParserEmptyValue) { + // Test an error case with an empty value field + const char *ex1 = "foo:bar\nbar:\n\nbody"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ("body", GetBodyText(request)); +} + +TEST(WebPluginImplTest, PostParserCRLF) { + // Test an error case with an empty value field + const char *ex1 = "foo: bar\r\nbar:\r\n\r\nbody\r\n\r\nbody2"; + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + static_cast(strlen(ex1))); + EXPECT_EQ(true, rv); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ("body\r\n\r\nbody2", GetBodyText(request)); +} + +TEST(WebPluginImplTest, PostParserBodyWithBinaryData) { + // Test a simple case with headers and binary data. + char ex1[33] = "foo: bar\nContent-length: 10\n\n"; + unsigned int binary_data = 0xFFFFFFF0; + memcpy(ex1 + strlen("foo: bar\nContent-length: 10\n\n"), &binary_data, + sizeof(binary_data)); + + WebURLRequest request; + request.initialize(); + bool rv = WebPluginImpl::SetPostData(&request, ex1, + sizeof(ex1)/sizeof(ex1[0])); + EXPECT_EQ(true, rv); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + + std::string body = GetBodyText(request); + + EXPECT_EQ(0xF0, (unsigned char)body[0]); + EXPECT_EQ(0xFF, (unsigned char)body[1]); + EXPECT_EQ(0xFF, (unsigned char)body[2]); + EXPECT_EQ(0xFF, (unsigned char)body[3]); +} diff --git a/webkit/glue/plugins/webplugin_page_delegate.h b/webkit/glue/plugins/webplugin_page_delegate.h new file mode 100644 index 0000000..8bc5723 --- /dev/null +++ b/webkit/glue/plugins/webplugin_page_delegate.h @@ -0,0 +1,69 @@ +// Copyright (c) 2009 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. + +#ifndef WEBKIT_GLUE_WEBPLUGIN_PAGE_DELEGATE_ +#define WEBKIT_GLUE_WEBPLUGIN_PAGE_DELEGATE_ + +#include "gfx/native_widget_types.h" + +class GURL; + +namespace WebKit { +class WebCookieJar; +} + +namespace webkit_glue { + +class WebPluginDelegate; +struct WebPluginGeometry; + +// Used by the WebPlugin to communicate back to the containing page. +class WebPluginPageDelegate { + public: + // This method is called to create a WebPluginDelegate implementation when a + // new plugin is instanced. See webkit_glue::CreateWebPluginDelegateHelper + // for a default WebPluginDelegate implementation. + virtual WebPluginDelegate* CreatePluginDelegate( + const GURL& url, + const std::string& mime_type, + std::string* actual_mime_type) = 0; + + // Called when a windowed plugin is created. + // Lets the view delegate create anything it is using to wrap the plugin. + virtual void CreatedPluginWindow( + gfx::PluginWindowHandle handle) = 0; + + // Called when a windowed plugin is closing. + // Lets the view delegate shut down anything it is using to wrap the plugin. + virtual void WillDestroyPluginWindow( + gfx::PluginWindowHandle handle) = 0; + + // Keeps track of the necessary window move for a plugin window that resulted + // from a scroll operation. That way, all plugin windows can be moved at the + // same time as each other and the page. + virtual void DidMovePlugin( + const WebPluginGeometry& move) = 0; + + // Notifies the parent view that a load has begun. + virtual void DidStartLoadingForPlugin() = 0; + + // Notifies the parent view that all loads are finished. + virtual void DidStopLoadingForPlugin() = 0; + + // Asks the browser to show a modal HTML dialog. The dialog is passed the + // given arguments as a JSON string, and returns its result as a JSON string + // through json_retval. + virtual void ShowModalHTMLDialogForPlugin( + const GURL& url, + const gfx::Size& size, + const std::string& json_arguments, + std::string* json_retval) = 0; + + // The WebCookieJar to use for this plugin. + virtual WebKit::WebCookieJar* GetCookieJar() = 0; +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_WEBPLUGIN_PAGE_DELEGATE_H_ diff --git a/webkit/glue/plugins/webplugininfo.h b/webkit/glue/plugins/webplugininfo.h new file mode 100644 index 0000000..21f34df --- /dev/null +++ b/webkit/glue/plugins/webplugininfo.h @@ -0,0 +1,47 @@ +// Copyright (c) 2006-2008 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. + +#ifndef WEBKIT_GLUE_WEBPLUGININFO_H_ +#define WEBKIT_GLUE_WEBPLUGININFO_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/file_path.h" + +// Describes a mime type entry for a plugin. +struct WebPluginMimeType { + // The name of the mime type (e.g., "application/x-shockwave-flash"). + std::string mime_type; + + // A list of all the file extensions for this mime type. + std::vector file_extensions; + + // Description of the mime type. + std::wstring description; +}; + +// Describes an available NPAPI plugin. +struct WebPluginInfo { + // The name of the plugin (i.e. Flash). + std::wstring name; + + // The path to the plugin file (DLL/bundle/library). + FilePath path; + + // The version number of the plugin file (may be OS-specific) + std::wstring version; + + // A description of the plugin that we get from its version info. + std::wstring desc; + + // A list of all the mime types that this plugin supports. + std::vector mime_types; + + // Whether the plugin is enabled. + bool enabled; +}; + +#endif // WEBKIT_GLUE_WEBPLUGININFO_H_ diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index ff96daa..55066f7 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -184,13 +184,19 @@ 'plugins/plugin_stubs.cc', 'plugins/plugin_web_event_converter_mac.h', 'plugins/plugin_web_event_converter_mac.mm', + 'plugins/webplugin.cc', + 'plugins/webplugin.h', 'plugins/webplugin_2d_device_delegate.h', 'plugins/webplugin_3d_device_delegate.h', + 'plugins/webplugin_delegate.h', 'plugins/webplugin_delegate_impl.cc', 'plugins/webplugin_delegate_impl.h', 'plugins/webplugin_delegate_impl_gtk.cc', 'plugins/webplugin_delegate_impl_mac.mm', 'plugins/webplugin_delegate_impl_win.cc', + 'plugins/webplugin_impl.cc', + 'plugins/webplugin_impl.h', + 'plugins/webplugininfo.h', 'alt_error_page_resource_fetcher.cc', 'alt_error_page_resource_fetcher.h', 'context_menu.h', @@ -255,12 +261,6 @@ 'webmenurunner_mac.mm', 'webpasswordautocompletelistener_impl.cc', 'webpasswordautocompletelistener_impl.h', - 'webplugin.cc', - 'webplugin.h', - 'webplugin_delegate.h', - 'webplugin_impl.cc', - 'webplugin_impl.h', - 'webplugininfo.h', 'webpreferences.cc', 'webpreferences.h', 'websocketstreamhandle_bridge.h', diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc index a8fcac3..34c24c6 100644 --- a/webkit/glue/webkitclient_impl.cc +++ b/webkit/glue/webkitclient_impl.cc @@ -35,8 +35,8 @@ #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" #include "third_party/WebKit/WebKit/chromium/public/WebURL.h" #include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugininfo.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/glue/webplugininfo.h" #include "webkit/glue/websocketstreamhandle_impl.h" #include "webkit/glue/weburlloader_impl.h" diff --git a/webkit/glue/webplugin.cc b/webkit/glue/webplugin.cc deleted file mode 100644 index 237e60c..0000000 --- a/webkit/glue/webplugin.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2010 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/glue/webplugin.h" - -namespace webkit_glue { - -WebPluginGeometry::WebPluginGeometry() - : window(gfx::kNullPluginWindow), - rects_valid(false), - visible(false) { -} - -bool WebPluginGeometry::Equals(const WebPluginGeometry& rhs) const { - return window == rhs.window && - window_rect == rhs.window_rect && - clip_rect == rhs.clip_rect && - cutout_rects == rhs.cutout_rects && - rects_valid == rhs.rects_valid && - visible == rhs.visible; -} -} // namespace webkit_glue diff --git a/webkit/glue/webplugin.h b/webkit/glue/webplugin.h deleted file mode 100644 index cde5fce..0000000 --- a/webkit/glue/webplugin.h +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2006-2009 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. - -#ifndef WEBKIT_GLUE_WEBPLUGIN_H_ -#define WEBKIT_GLUE_WEBPLUGIN_H_ - -#include -#include - -#include "base/basictypes.h" -#include "gfx/native_widget_types.h" -#include "gfx/rect.h" - -// TODO(port): this typedef is obviously incorrect on non-Windows -// platforms, but now a lot of code now accidentally depends on them -// existing. #ifdef out these declarations and fix all the users. -typedef void* HANDLE; - -class GURL; -struct NPObject; - -namespace WebKit { -class WebFrame; -} - -namespace webkit_glue { - -class WebPluginDelegate; -class WebPluginParentView; -class WebPluginResourceClient; - -// Describes the new location for a plugin window. -struct WebPluginGeometry { - WebPluginGeometry(); - - bool Equals(const WebPluginGeometry& rhs) const; - - // On Windows, this is the plugin window in the plugin process. - // On X11, this is the XID of the plugin-side GtkPlug containing the - // GtkSocket hosting the actual plugin window. - // - // On Mac OS X, all of the plugin types are currently "windowless" - // (window == 0) except for the special case of the GPU plugin, - // which currently performs rendering on behalf of the Pepper 3D API - // and WebGL. The GPU plugin uses a simple integer for the - // PluginWindowHandle which is used to map to a side data structure - // containing information about the plugin. Soon this plugin will be - // generalized, at which point this mechanism will be rethought or - // removed. - gfx::PluginWindowHandle window; - gfx::Rect window_rect; - // Clip rect (include) and cutouts (excludes), relative to - // window_rect origin. - gfx::Rect clip_rect; - std::vector cutout_rects; - bool rects_valid; - bool visible; -}; - -// The WebKit side of a plugin implementation. It provides wrappers around -// operations that need to interact with the frame and other WebCore objects. -class WebPlugin { - public: - virtual ~WebPlugin() {} - - // Called by the plugin delegate to let the WebPlugin know if the plugin is - // windowed (i.e. handle is not NULL) or windowless (handle is NULL). This - // tells the WebPlugin to send mouse/keyboard events to the plugin delegate, - // as well as the information about the HDC for paint operations. - virtual void SetWindow(gfx::PluginWindowHandle window) = 0; - - // Whether input events should be sent to the delegate. - virtual void SetAcceptsInputEvents(bool accepts) = 0; - - // Called by the plugin delegate to let it know that the window is being - // destroyed. - virtual void WillDestroyWindow(gfx::PluginWindowHandle window) = 0; -#if defined(OS_WIN) - // The pump_messages_event is a event handle which is valid only for - // windowless plugins and is used in NPP_HandleEvent calls to pump messages - // if the plugin enters a modal loop. - // Cancels a pending request. - virtual void SetWindowlessPumpEvent(HANDLE pump_messages_event) = 0; -#endif - virtual void CancelResource(unsigned long id) = 0; - virtual void Invalidate() = 0; - virtual void InvalidateRect(const gfx::Rect& rect) = 0; - - // Returns the NPObject for the browser's window object. - virtual NPObject* GetWindowScriptNPObject() = 0; - - // Returns the DOM element that loaded the plugin. - virtual NPObject* GetPluginElement() = 0; - - // Cookies - virtual void SetCookie(const GURL& url, - const GURL& first_party_for_cookies, - const std::string& cookie) = 0; - virtual std::string GetCookies(const GURL& url, - const GURL& first_party_for_cookies) = 0; - - // Shows a modal HTML dialog containing the given URL. json_arguments are - // passed to the dialog via the DOM 'window.chrome.dialogArguments', and the - // retval is the string returned by 'window.chrome.send("DialogClose", - // retval)'. - virtual void ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - std::string* json_retval) = 0; - - // When a default plugin has downloaded the plugin list and finds it is - // available, it calls this method to notify the renderer. Also it will update - // the status when user clicks on the plugin to install. - virtual void OnMissingPluginStatus(int status) = 0; - - // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated - // by plugins. If the plugin wants notification of the result, notify_id will - // be non-zero. - virtual void HandleURLRequest(const char* url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - bool popups_allowed) = 0; - - // Cancels document load. - virtual void CancelDocumentLoad() = 0; - - // Initiates a HTTP range request for an existing stream. - virtual void InitiateHTTPRangeRequest(const char* url, - const char* range_info, - int range_request_id) = 0; - - // Returns true iff in off the record (Incognito) mode. - virtual bool IsOffTheRecord() = 0; - - // Called when the WebPluginResourceClient instance is deleted. - virtual void ResourceClientDeleted( - WebPluginResourceClient* resource_client) {} - - // Defers the loading of the resource identified by resource_id. This is - // controlled by the defer parameter. - virtual void SetDeferResourceLoading(unsigned long resource_id, - bool defer) = 0; - -#if defined(OS_MACOSX) - // Synthesize a fake window handle for the plug-in to identify the instance - // to the browser, allowing mapping to a surface for hardware accelleration - // of plug-in content. The browser generates the handle which is then set on - // the plug-in. - virtual void BindFakePluginWindowHandle() {} - - // Tell the browser (via the renderer) to invalidate because the - // accelerated buffers have changed. - virtual void AcceleratedFrameBuffersDidSwap(gfx::PluginWindowHandle window) {} - - // Tell the renderer and browser to associate the given plugin handle with - // |accelerated_surface_identifier|. The geometry is used to resize any - // native "window" (which on the Mac is a CALayer). - virtual void SetAcceleratedSurface(gfx::PluginWindowHandle window, - int32 width, - int32 height, - uint64 accelerated_surface_identifier) {} -#endif - - // Gets the WebPluginDelegate that implements the interface. - // This API is only for use with Pepper, and is only overridden - // by in-renderer implementations. - virtual WebPluginDelegate* delegate() { return NULL; } -}; - -// Simpler version of ResourceHandleClient that lends itself to proxying. -class WebPluginResourceClient { - public: - virtual ~WebPluginResourceClient() {} - virtual void WillSendRequest(const GURL& url) = 0; - // The request_is_seekable parameter indicates whether byte range requests - // can be issued for the underlying stream. - virtual void DidReceiveResponse(const std::string& mime_type, - const std::string& headers, - uint32 expected_length, - uint32 last_modified, - bool request_is_seekable) = 0; - virtual void DidReceiveData(const char* buffer, int length, - int data_offset) = 0; - virtual void DidFinishLoading() = 0; - virtual void DidFail() = 0; - virtual bool IsMultiByteResponseExpected() = 0; -}; - -} // namespace webkit_glue - -#endif // #ifndef WEBKIT_GLUE_WEBPLUGIN_H_ diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h deleted file mode 100644 index 0b08c9e..0000000 --- a/webkit/glue/webplugin_delegate.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2010 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. - -#ifndef WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ -#define WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ - -#include -#include - -#include "base/string16.h" -#include "build/build_config.h" -#include "gfx/native_widget_types.h" -#include "third_party/npapi/bindings/npapi.h" -#include "third_party/npapi/bindings/npapi_extensions.h" -#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h" -#include "webkit/glue/plugins/webplugin_2d_device_delegate.h" -#include "webkit/glue/plugins/webplugin_3d_device_delegate.h" -#include "webkit/glue/plugins/webplugin_audio_device_delegate.h" -#include "webkit/glue/plugins/webplugin_file_delegate.h" -#include "webkit/glue/plugins/webplugin_print_delegate.h" - - -class FilePath; -class GURL; -struct NPObject; - -namespace WebKit { -class WebInputEvent; -struct WebCursorInfo; -} - -namespace gfx { -class Rect; -} - -namespace webkit_glue { - -class WebPlugin; -class WebPluginResourceClient; - -// This is the interface that a plugin implementation needs to provide. -class WebPluginDelegate : public WebPlugin2DDeviceDelegate, - public WebPlugin3DDeviceDelegate, - public WebPluginAudioDeviceDelegate, - public WebPluginPrintDelegate, - public WebPluginFileDelegate { - public: - virtual ~WebPluginDelegate() {} - - // Initializes the plugin implementation with the given (UTF8) arguments. - // Note that the lifetime of WebPlugin must be longer than this delegate. - // If this function returns false the plugin isn't started and shouldn't be - // called again. If this method succeeds, then the WebPlugin is valid until - // PluginDestroyed is called. - // The load_manually parameter if true indicates that the plugin data would - // be passed from webkit. if false indicates that the plugin should download - // the data. This also controls whether the plugin is instantiated as a full - // page plugin (NP_FULL) or embedded (NP_EMBED). - virtual bool Initialize(const GURL& url, - const std::vector& arg_names, - const std::vector& arg_values, - WebPlugin* plugin, - bool load_manually) = 0; - - // Called when the WebPlugin is being destroyed. This is a signal to the - // delegate that it should tear-down the plugin implementation and not call - // methods on the WebPlugin again. - virtual void PluginDestroyed() = 0; - - // Update the geometry of the plugin. This is a request to move the - // plugin, relative to its containing window, to the coords given by - // window_rect. Its contents should be clipped to the coords given - // by clip_rect, which are relative to the origin of the plugin - // window. The clip_rect is in plugin-relative coordinates. - virtual void UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect) = 0; - - // Tells the plugin to paint the damaged rect. |canvas| is only used for - // windowless plugins. - virtual void Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect) = 0; - - // Tells the plugin to print itself. - virtual void Print(gfx::NativeDrawingContext hdc) = 0; - - // Informs the plugin that it now has focus. This is only called in - // windowless mode. - virtual void SetFocus() = 0; - - // For windowless plugins, gives them a user event like mouse/keyboard. - // Returns whether the event was handled. This is only called in windowsless - // mode. See NPAPI NPP_HandleEvent for more information. - virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, - WebKit::WebCursorInfo* cursor) = 0; - - // Gets the NPObject associated with the plugin for scripting. - virtual NPObject* GetPluginScriptableObject() = 0; - - // Receives notification about a resource load that the plugin initiated - // for a frame. - virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason, - int notify_id) = 0; - - // Returns the process id of the process that is running the plugin. - virtual int GetProcessId() = 0; - - // The result, UTF-8 encoded, of the script execution is returned via this - // function. - virtual void SendJavaScriptStream(const GURL& url, - const std::string& result, - bool success, - int notify_id) = 0; - - // Receives notification about data being available. - virtual void DidReceiveManualResponse(const GURL& url, - const std::string& mime_type, - const std::string& headers, - uint32 expected_length, - uint32 last_modified) = 0; - - // Receives the data. - virtual void DidReceiveManualData(const char* buffer, int length) = 0; - - // Indicates end of data load. - virtual void DidFinishManualLoading() = 0; - - // Indicates a failure in data receipt. - virtual void DidManualLoadFail() = 0; - - // Only supported when the plugin is the default plugin. - virtual void InstallMissingPlugin() = 0; - - // Creates a WebPluginResourceClient instance and returns the same. - virtual WebPluginResourceClient* CreateResourceClient( - unsigned long resource_id, - const GURL& url, - int notify_id) = 0; - - // Creates a WebPluginResourceClient instance for an existing stream that is - // has become seekable. - virtual WebPluginResourceClient* CreateSeekableResourceClient( - unsigned long resource_id, int range_request_id) = 0; - - // See WebPluginContainerImpl's description of the interface. - virtual bool SupportsFind() { return false; } - virtual void StartFind(const std::string& search_text, - bool case_sensitive, - int identifier) {} - virtual void SelectFindResult(bool forward) {} - virtual void StopFind() {} - virtual void NumberOfFindResultsChanged(int total, bool final_result) {} - virtual void SelectedFindResultChanged(int index) {} - - // Used for zooming of full page plugins. 0 means reset, while -1 means zoom - // out and +1 means zoom in. - virtual void Zoom(int factor) {} -}; - -} // namespace webkit_glue - -#endif // WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc deleted file mode 100644 index f42d36e..0000000 --- a/webkit/glue/webplugin_impl.cc +++ /dev/null @@ -1,1207 +0,0 @@ -// Copyright (c) 2006-2009 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 "base/logging.h" -#include "base/message_loop.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "gfx/rect.h" -#include "net/base/escape.h" -#include "net/base/net_errors.h" -#include "skia/ext/platform_canvas.h" -#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h" -#include "third_party/WebKit/WebKit/chromium/public/WebCookieJar.h" -#include "third_party/WebKit/WebKit/chromium/public/WebCString.h" -#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" -#include "third_party/WebKit/WebKit/chromium/public/WebDevToolsAgent.h" -#include "third_party/WebKit/WebKit/chromium/public/WebData.h" -#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" -#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" -#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h" -#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h" -#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" -#include "third_party/WebKit/WebKit/chromium/public/WebKit.h" -#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h" -#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" -#include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURL.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" -#include "third_party/WebKit/WebKit/chromium/public/WebView.h" -#include "webkit/glue/multipart_response_delegate.h" -#include "webkit/glue/webplugin_impl.h" -#include "webkit/glue/plugins/plugin_host.h" -#include "webkit/glue/plugins/plugin_instance.h" -#include "webkit/glue/webplugin_delegate.h" -#include "webkit/glue/webplugin_page_delegate.h" -#include "googleurl/src/gurl.h" - -using WebKit::WebCanvas; -using WebKit::WebConsoleMessage; -using WebKit::WebCookieJar; -using WebKit::WebCString; -using WebKit::WebCursorInfo; -using WebKit::WebData; -using WebKit::WebDataSource; -using WebKit::WebDevToolsAgent; -using WebKit::WebFrame; -using WebKit::WebHTTPBody; -using WebKit::WebHTTPHeaderVisitor; -using WebKit::WebInputEvent; -using WebKit::WebKeyboardEvent; -using WebKit::WebMouseEvent; -using WebKit::WebPluginContainer; -using WebKit::WebPluginParams; -using WebKit::WebRect; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderClient; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; -using WebKit::WebVector; -using WebKit::WebView; -using webkit_glue::MultipartResponseDelegate; - -namespace webkit_glue { -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 -// specified in the response header. -class MultiPartResponseClient : public WebURLLoaderClient { - public: - explicit MultiPartResponseClient(WebPluginResourceClient* resource_client) - : resource_client_(resource_client) { - Clear(); - } - - virtual void willSendRequest( - WebURLLoader*, WebURLRequest&, const WebURLResponse&) {} - virtual void didSendData( - WebURLLoader*, unsigned long long, unsigned long long) {} - - // Called when the multipart parser encounters an embedded multipart - // response. - virtual void didReceiveResponse( - WebURLLoader*, const WebURLResponse& response) { - if (!MultipartResponseDelegate::ReadContentRanges( - response, - &byte_range_lower_bound_, - &byte_range_upper_bound_)) { - NOTREACHED(); - return; - } - - resource_response_ = response; - } - - // Receives individual part data from a multipart response. - virtual void didReceiveData( - WebURLLoader*, const char* data, int data_size) { - // TODO(ananta) - // We should defer further loads on multipart resources on the same lines - // as regular resources requested by plugins to prevent reentrancy. - resource_client_->DidReceiveData( - data, data_size, byte_range_lower_bound_); - } - - virtual void didFinishLoading(WebURLLoader*) {} - virtual void didFail(WebURLLoader*, const WebURLError&) {} - - void Clear() { - resource_response_.reset(); - byte_range_lower_bound_ = 0; - byte_range_upper_bound_ = 0; - } - - private: - WebURLResponse resource_response_; - // The lower bound of the byte range. - int byte_range_lower_bound_; - // The upper bound of the byte range. - int byte_range_upper_bound_; - // The handler for the data. - WebPluginResourceClient* resource_client_; -}; - -class HeaderFlattener : public WebHTTPHeaderVisitor { - public: - HeaderFlattener(std::string* buf) : buf_(buf) { - } - - 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"); - } - } - - private: - std::string* buf_; -}; - -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; - - // TODO(darin): Shouldn't we also report HTTP version numbers? - result = StringPrintf("HTTP %d ", response.httpStatusCode()); - result.append(status.utf8()); - result.append("\n"); - - HeaderFlattener flattener(&result); - response.visitHTTPHeaderFields(&flattener); - - return result; -} - -struct ResponseInfo { - GURL url; - std::string mime_type; - uint32 last_modified; - uint32 expected_length; -}; - -void GetResponseInfo(const WebURLResponse& response, - ResponseInfo* response_info) { - response_info->url = response.url(); - response_info->mime_type = response.mimeType().utf8(); - - // Measured in seconds since 12:00 midnight GMT, January 1, 1970. - response_info->last_modified = - static_cast(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. - response_info->expected_length = - static_cast(std::max(response.expectedContentLength(), 0LL)); - - 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. - response_info->expected_length = 0; - } -} - -} // namespace - -// WebKit::WebPlugin ---------------------------------------------------------- - -bool WebPluginImpl::initialize(WebPluginContainer* container) { - if (!page_delegate_) - return false; - - std::string actual_mime_type; - WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate( - plugin_url_, mime_type_, &actual_mime_type); - if (!plugin_delegate) - return NULL; - - // Set the container before Initialize because the plugin may - // synchronously call NPN_GetValue to get its container during its - // initialization. - SetContainer(container); - bool ok = plugin_delegate->Initialize( - plugin_url_, arg_names_, arg_values_, this, load_manually_); - if (!ok) { - plugin_delegate->PluginDestroyed(); - return false; - } - - if (!actual_mime_type.empty()) - mime_type_ = actual_mime_type; - delegate_ = plugin_delegate; - - return true; -} - -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) { - if (!delegate_) - return; - - // Note that |canvas| is only used when in windowless mode. - delegate_->Paint(canvas, paint_rect); -} - -void WebPluginImpl::updateGeometry( - const WebRect& window_rect, const WebRect& clip_rect, - const WebVector& cutout_rects, bool is_visible) { - WebPluginGeometry new_geometry; - new_geometry.window = window_; - new_geometry.window_rect = window_rect; - new_geometry.clip_rect = clip_rect; - new_geometry.visible = is_visible; - new_geometry.rects_valid = true; - for (size_t i = 0; i < cutout_rects.size(); ++i) - new_geometry.cutout_rects.push_back(cutout_rects[i]); - - // Only send DidMovePlugin if the geometry changed in some way. - if (window_ && - page_delegate_ && - (first_geometry_update_ || !new_geometry.Equals(geometry_))) { - page_delegate_->DidMovePlugin(new_geometry); - } - - // Only UpdateGeometry if either the window or clip rects have changed. - if (first_geometry_update_ || - new_geometry.window_rect != geometry_.window_rect || - new_geometry.clip_rect != geometry_.clip_rect) { - // Notify the plugin that its parameters have changed. - delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.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_) { - // 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); - } - } - - first_geometry_update_ = false; - geometry_ = new_geometry; -} - -void WebPluginImpl::updateFocus(bool focused) { - if (focused && accepts_input_events_) - delegate_->SetFocus(); -} - -void WebPluginImpl::updateVisibility(bool visible) { - if (!window_ || !page_delegate_) - return; - - WebPluginGeometry move; - move.window = window_; - move.window_rect = gfx::Rect(); - move.clip_rect = gfx::Rect(); - move.rects_valid = false; - move.visible = visible; - - page_delegate_->DidMovePlugin(move); -} - -bool WebPluginImpl::acceptsInputEvents() { - return accepts_input_events_; -} - -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(); -} - -void WebPluginImpl::didFinishLoadingFrameRequest( - const WebURL& url, void* notify_data) { - if (delegate_) { - // We're converting a void* into an arbitrary int id. Though - // these types are the same size on all the platforms we support, - // the compiler may complain as though they are different, so to - // make the casting gods happy go through an intptr_t (the union - // of void* and int) rather than converting straight across. - delegate_->DidFinishLoadWithReason( - url, NPRES_DONE, reinterpret_cast(notify_data)); - } -} - -void WebPluginImpl::didFailLoadingFrameRequest( - const WebURL& url, void* notify_data, const WebURLError& error) { - if (!delegate_) - return; - - NPReason reason = - error.reason == net::ERR_ABORTED ? NPRES_USER_BREAK : NPRES_NETWORK_ERR; - // See comment in didFinishLoadingFrameRequest about the cast here. - delegate_->DidFinishLoadWithReason( - url, reason, reinterpret_cast(notify_data)); -} - -bool WebPluginImpl::supportsPaginatedPrint() { - if (!delegate_) - return false; - return delegate_->PrintSupportsPrintExtension(); -} - -int WebPluginImpl::printBegin(const WebRect& printable_area, int printer_dpi) { - if (!delegate_) - return 0; - - if (!supportsPaginatedPrint()) - return 0; - - return delegate_->PrintBegin(printable_area, printer_dpi); -} - -bool WebPluginImpl::printPage(int page_number, WebCanvas* canvas) { - if (!delegate_) - return false; - - return delegate_->PrintPage(page_number, canvas); -} - -void WebPluginImpl::printEnd() { - if (delegate_) - delegate_->PrintEnd(); -} - - -// ----------------------------------------------------------------------------- - -WebPluginImpl::WebPluginImpl( - WebFrame* webframe, const WebPluginParams& params, - const base::WeakPtr& page_delegate) - : windowless_(false), - window_(NULL), - accepts_input_events_(false), - page_delegate_(page_delegate), - webframe_(webframe), - delegate_(NULL), - container_(NULL), - plugin_url_(params.url), - load_manually_(params.loadManually), - first_geometry_update_(true), - ignore_response_error_(false), - mime_type_(params.mimeType.utf8()), - ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { - DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); - StringToLowerASCII(&mime_type_); - - for (size_t i = 0; i < params.attributeNames.size(); ++i) { - arg_names_.push_back(params.attributeNames[i].utf8()); - arg_values_.push_back(params.attributeValues[i].utf8()); - } -} - -WebPluginImpl::~WebPluginImpl() { -} - -void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) { -#if defined(OS_MACOSX) - // The only time this is called twice, and the second time with a - // non-zero PluginWindowHandle, is the case when this WebPluginImpl - // is created on behalf of the GPU plugin. This entire code path - // will go away soon, as soon as the GPU plugin becomes the GPU - // process, so it is being separated out for easy deletion. - - // The logic we want here is: if (window) DCHECK(!window_); - DCHECK(!(window_ && window)); - window_ = window; - // Lie to ourselves about being windowless even if we got a fake - // plugin window handle, so we continue to get input events. - windowless_ = true; - accepts_input_events_ = true; - // We do not really need to notify the page delegate that a plugin - // window was created -- so don't. -#else - if (window) { - DCHECK(!windowless_); - window_ = window; - accepts_input_events_ = false; - if (page_delegate_) { - // Tell the view delegate that the plugin window was created, so that it - // can create necessary container widgets. - page_delegate_->CreatedPluginWindow(window); - } - } else { - DCHECK(!window_); // Make sure not called twice. - windowless_ = true; - accepts_input_events_ = true; - } -#endif -} - -void WebPluginImpl::WillDestroyWindow(gfx::PluginWindowHandle window) { - DCHECK_EQ(window, window_); - window_ = NULL; - if (page_delegate_) - page_delegate_->WillDestroyPluginWindow(window); -} - -GURL WebPluginImpl::CompleteURL(const char* url) { - if (!webframe_) { - NOTREACHED(); - return GURL(); - } - // TODO(darin): Is conversion from UTF8 correct here? - return webframe_->completeURL(WebString::fromUTF8(url)); -} - -void WebPluginImpl::CancelResource(unsigned long id) { - for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].id == id) { - if (clients_[i].loader.get()) { - clients_[i].loader->setDefersLoading(false); - clients_[i].loader->cancel(); - RemoveClient(i); - } - return; - } - } -} - -bool WebPluginImpl::SetPostData(WebURLRequest* request, - const char *buf, - uint32 length) { - std::vector names; - std::vector values; - std::vector body; - bool rv = NPAPI::PluginHost::SetPostData(buf, length, &names, &values, &body); - - for (size_t i = 0; i < names.size(); ++i) { - request->addHTTPHeaderField(WebString::fromUTF8(names[i]), - WebString::fromUTF8(values[i])); - } - - WebString content_type_header = WebString::fromUTF8("Content-Type"); - const WebString& content_type = - request->httpHeaderField(content_type_header); - if (content_type.isEmpty()) { - request->setHTTPHeaderField( - content_type_header, - WebString::fromUTF8("application/x-www-form-urlencoded")); - } - - WebHTTPBody http_body; - if (body.size()) { - http_body.initialize(); - http_body.appendData(WebData(&body[0], body.size())); - } - request->setHTTPBody(http_body); - - return rv; -} - -WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame( - const char* url, - bool is_javascript_url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - Referrer referrer_flag) { - // If there is no target, there is nothing to do - if (!target) - return NOT_ROUTED; - - // This could happen if the WebPluginContainer was already deleted. - if (!webframe_) - return NOT_ROUTED; - - WebString target_str = WebString::fromUTF8(target); - - // Take special action for JavaScript URLs - if (is_javascript_url) { - WebFrame* target_frame = - webframe_->view()->findFrameByName(target_str, webframe_); - // For security reasons, do not allow JavaScript on frames - // other than this frame. - if (target_frame != webframe_) { - // TODO(darin): Localize this message. - const char kMessage[] = - "Ignoring cross-frame javascript URL load requested by plugin."; - webframe_->addMessageToConsole( - WebConsoleMessage(WebConsoleMessage::LevelError, - WebString::fromUTF8(kMessage))); - return ROUTED; - } - - // Route javascript calls back to the plugin. - return NOT_ROUTED; - } - - // If we got this far, we're routing content to a target frame. - // Go fetch the URL. - - GURL complete_url = CompleteURL(url); - - if (strcmp(method, "GET") != 0) { - // We're only going to route HTTP/HTTPS requests - if (!(complete_url.SchemeIs("http") || complete_url.SchemeIs("https"))) - return INVALID_URL; - } - - WebURLRequest request(complete_url); - SetReferrer(&request, referrer_flag); - - request.setHTTPMethod(WebString::fromUTF8(method)); - request.setFirstPartyForCookies( - webframe_->document().firstPartyForCookies()); - if (len > 0) { - if (!SetPostData(&request, buf, len)) { - // Uhoh - we're in trouble. There isn't a good way - // to recover at this point. Break out. - NOTREACHED(); - return ROUTED; - } - } - - container_->loadFrameRequest( - request, target_str, notify_id != 0, reinterpret_cast(notify_id)); - return ROUTED; -} - -NPObject* WebPluginImpl::GetWindowScriptNPObject() { - if (!webframe_) { - NOTREACHED(); - return NULL; - } - return webframe_->windowObject(); -} - -NPObject* WebPluginImpl::GetPluginElement() { - return container_->scriptableObjectForElement(); -} - -void WebPluginImpl::SetCookie(const GURL& url, - const GURL& first_party_for_cookies, - const std::string& cookie) { - if (!page_delegate_) - return; - - WebCookieJar* cookie_jar = page_delegate_->GetCookieJar(); - if (!cookie_jar) { - DLOG(WARNING) << "No cookie jar!"; - return; - } - - cookie_jar->setCookie( - url, first_party_for_cookies, WebString::fromUTF8(cookie)); -} - -std::string WebPluginImpl::GetCookies(const GURL& url, - const GURL& first_party_for_cookies) { - if (!page_delegate_) - return std::string(); - - WebCookieJar* cookie_jar = page_delegate_->GetCookieJar(); - if (!cookie_jar) { - DLOG(WARNING) << "No cookie jar!"; - return std::string(); - } - - return UTF16ToUTF8(cookie_jar->cookies(url, first_party_for_cookies)); -} - -void WebPluginImpl::ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - std::string* json_retval) { - if (page_delegate_) { - page_delegate_->ShowModalHTMLDialogForPlugin( - url, gfx::Size(width, height), json_arguments, json_retval); - } -} - -void WebPluginImpl::OnMissingPluginStatus(int status) { - NOTREACHED(); -} - -void WebPluginImpl::Invalidate() { - if (container_) - container_->invalidate(); -} - -void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { - if (container_) - container_->invalidateRect(rect); -} - -void WebPluginImpl::OnDownloadPluginSrcUrl() { - HandleURLRequestInternal( - plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL); -} - -WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( - WebURLLoader* loader) { - ClientInfo* client_info = GetClientInfoFromLoader(loader); - if (client_info) - return client_info->client; - return NULL; -} - -WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader( - WebURLLoader* loader) { - for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].loader.get() == loader) - return &clients_[i]; - } - - NOTREACHED(); - return 0; -} - -void WebPluginImpl::willSendRequest(WebURLLoader* loader, - WebURLRequest& request, - const WebURLResponse&) { - WebPluginResourceClient* client = GetClientFromLoader(loader); - if (client) - client->WillSendRequest(request.url()); -} - -void WebPluginImpl::didSendData(WebURLLoader* loader, - unsigned long long bytes_sent, - unsigned long long total_bytes_to_be_sent) { -} - -void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, - const WebURLResponse& response) { - static const int kHttpPartialResponseStatusCode = 206; - static const int kHttpResponseSuccessStatusCode = 200; - - WebPluginResourceClient* client = GetClientFromLoader(loader); - if (!client) - return; - - ResponseInfo response_info; - GetResponseInfo(response, &response_info); - - bool request_is_seekable = true; - if (client->IsMultiByteResponseExpected()) { - if (response.httpStatusCode() == kHttpPartialResponseStatusCode) { - HandleHttpMultipartResponse(response, client); - return; - } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) { - // If the client issued a byte range request and the server responds with - // HTTP 200 OK, it indicates that the server does not support byte range - // requests. - // We need to emulate Firefox behavior by doing the following:- - // 1. Destroy the plugin instance in the plugin process. Ensure that - // existing resource requests initiated for the plugin instance - // continue to remain valid. - // 2. Create a new plugin instance and notify it about the response - // received here. - if (!ReinitializePluginForResponse(loader)) { - NOTREACHED(); - return; - } - - // The server does not support byte range requests. No point in creating - // seekable streams. - request_is_seekable = false; - - delete client; - client = NULL; - - // Create a new resource client for this request. - for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].loader.get() == loader) { - WebPluginResourceClient* resource_client = - delegate_->CreateResourceClient(clients_[i].id, plugin_url_, 0); - clients_[i].client = resource_client; - client = resource_client; - break; - } - } - - DCHECK(client != NULL); - } - } - - // Calling into a plugin could result in reentrancy if the plugin yields - // control to the OS like entering a modal loop etc. Prevent this by - // stopping further loading until the plugin notifies us that it is ready to - // accept data - loader->setDefersLoading(true); - - client->DidReceiveResponse( - response_info.mime_type, - GetAllHeaders(response), - response_info.expected_length, - response_info.last_modified, - request_is_seekable); - - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) { - ClientInfo* client_info = GetClientInfoFromLoader(loader); - if (client_info) - devtools_agent->didReceiveResponse(client_info->id, response); - } - - // 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 - // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF - // destroy the stream and invoke the NPP_DestroyStream function on the - // plugin if the HTTP request fails. - const GURL& url = response.url(); - if (url.SchemeIs("http") || url.SchemeIs("https")) { - if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) { - // The plugin instance could be in the process of deletion here. - // Verify if the WebPluginResourceClient instance still exists before - // use. - ClientInfo* client_info = GetClientInfoFromLoader(loader); - if (client_info) { - client_info->pending_failure_notification = true; - } - } - } -} - -void WebPluginImpl::didReceiveData(WebURLLoader* loader, - const char *buffer, - int length) { - WebPluginResourceClient* client = GetClientFromLoader(loader); - if (!client) - return; - - // ClientInfo can be removed from clients_ vector by next statements. - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) { - ClientInfo* client_info = GetClientInfoFromLoader(loader); - if (client_info) - devtools_agent->didReceiveData(client_info->id, length); - } - MultiPartResponseHandlerMap::iterator index = - multi_part_response_map_.find(client); - if (index != multi_part_response_map_.end()) { - MultipartResponseDelegate* multi_part_handler = (*index).second; - DCHECK(multi_part_handler != NULL); - multi_part_handler->OnReceivedData(buffer, length); - } else { - loader->setDefersLoading(true); - client->DidReceiveData(buffer, length, 0); - } -} - -void WebPluginImpl::didFinishLoading(WebURLLoader* loader) { - ClientInfo* client_info = GetClientInfoFromLoader(loader); - if (client_info && client_info->client) { - MultiPartResponseHandlerMap::iterator index = - multi_part_response_map_.find(client_info->client); - if (index != multi_part_response_map_.end()) { - delete (*index).second; - multi_part_response_map_.erase(index); - if (page_delegate_) - page_delegate_->DidStopLoadingForPlugin(); - } - loader->setDefersLoading(true); - WebPluginResourceClient* resource_client = client_info->client; - // The ClientInfo can get deleted in the call to DidFinishLoading below. - // It is not safe to access this structure after that. - client_info->client = NULL; - resource_client->DidFinishLoading(); - - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) - devtools_agent->didFinishLoading(client_info->id); - } -} - -void WebPluginImpl::didFail(WebURLLoader* loader, - const WebURLError& error) { - ClientInfo* client_info = GetClientInfoFromLoader(loader); - if (client_info && client_info->client) { - loader->setDefersLoading(true); - WebPluginResourceClient* resource_client = client_info->client; - // The ClientInfo can get deleted in the call to DidFail below. - // It is not safe to access this structure after that. - client_info->client = NULL; - resource_client->DidFail(); - - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) - devtools_agent->didFailLoading(client_info->id, error); - } -} - -void WebPluginImpl::RemoveClient(size_t i) { - clients_.erase(clients_.begin() + i); -} - -void WebPluginImpl::RemoveClient(WebURLLoader* loader) { - for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].loader.get() == loader) { - RemoveClient(i); - return; - } - } -} - -void WebPluginImpl::SetContainer(WebPluginContainer* container) { - if (!container) - TearDownPluginInstance(NULL); - container_ = container; -} - -void WebPluginImpl::HandleURLRequest(const char* url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - bool popups_allowed) { - // GetURL/PostURL requests initiated explicitly by plugins should specify the - // plugin SRC url as the referrer if it is available. - HandleURLRequestInternal( - url, method, target, buf, len, notify_id, popups_allowed, PLUGIN_SRC); -} - -void WebPluginImpl::HandleURLRequestInternal(const char* url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - bool popups_allowed, - Referrer referrer_flag) { - // For this request, we either route the output to a frame - // because a target has been specified, or we handle the request - // here, i.e. by executing the script if it is a javascript url - // or by initiating a download on the URL, etc. There is one special - // case in that the request is a javascript url and the target is "_self", - // in which case we route the output to the plugin rather than routing it - // to the plugin's frame. - bool is_javascript_url = StartsWithASCII(url, "javascript:", false); - RoutingStatus routing_status = RouteToFrame( - url, is_javascript_url, method, target, buf, len, notify_id, - referrer_flag); - if (routing_status == ROUTED) - return; - - if (is_javascript_url) { - GURL gurl(url); - WebString result = container_->executeScriptURL(gurl, popups_allowed); - - // delegate_ could be NULL because executeScript caused the container to - // be deleted. - if (delegate_) { - delegate_->SendJavaScriptStream( - gurl, result.utf8(), !result.isNull(), notify_id); - } - - return; - } - - unsigned long resource_id = GetNextResourceId(); - if (!resource_id) - return; - - GURL complete_url = CompleteURL(url); - WebPluginResourceClient* resource_client = delegate_->CreateResourceClient( - resource_id, complete_url, notify_id); - if (!resource_client) - return; - - // If the RouteToFrame call returned a failure then inform the result - // back to the plugin asynchronously. - if ((routing_status == INVALID_URL) || - (routing_status == GENERAL_FAILURE)) { - resource_client->DidFail(); - return; - } - - // CreateResourceClient() sends a synchronous IPC message so it's possible - // that TearDownPluginInstance() may have been called in the nested - // message loop. If so, don't start the request. - if (!delegate_) - return; - - InitiateHTTPRequest(resource_id, resource_client, complete_url, method, buf, - len, NULL, referrer_flag); -} - -unsigned long WebPluginImpl::GetNextResourceId() { - if (!webframe_) - return 0; - WebView* view = webframe_->view(); - if (!view) - return 0; - return view->createUniqueIdentifierForRequest(); -} - -bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id, - WebPluginResourceClient* client, - const GURL& url, - const char* method, - const char* buf, - int buf_len, - const char* range_info, - Referrer referrer_flag) { - if (!client) { - NOTREACHED(); - return false; - } - - ClientInfo info; - info.id = resource_id; - info.client = client; - info.request.initialize(); - info.request.setURL(url); - info.request.setFirstPartyForCookies( - webframe_->document().firstPartyForCookies()); - info.request.setRequestorProcessID(delegate_->GetProcessId()); - info.request.setTargetType(WebURLRequest::TargetIsObject); - info.request.setHTTPMethod(WebString::fromUTF8(method)); - info.pending_failure_notification = false; - - if (range_info) { - info.request.addHTTPHeaderField(WebString::fromUTF8("Range"), - WebString::fromUTF8(range_info)); - } - - if (strcmp(method, "POST") == 0) { - // Adds headers or form data to a request. This must be called before - // we initiate the actual request. - SetPostData(&info.request, buf, buf_len); - } - - SetReferrer(&info.request, referrer_flag); - - // Sets the routing id to associate the ResourceRequest with the RenderView. - webframe_->dispatchWillSendRequest(info.request); - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) { - devtools_agent->identifierForInitialRequest(resource_id, webframe_, - info.request); - devtools_agent->willSendRequest(resource_id, info.request); - } - - info.loader.reset(WebKit::webKitClient()->createURLLoader()); - if (!info.loader.get()) - return false; - info.loader->loadAsynchronously(info.request, this); - - clients_.push_back(info); - return true; -} - -void WebPluginImpl::CancelDocumentLoad() { - if (webframe_) { - ignore_response_error_ = true; - webframe_->stopLoading(); - } -} - -void WebPluginImpl::InitiateHTTPRangeRequest( - const char* url, const char* range_info, int range_request_id) { - unsigned long resource_id = GetNextResourceId(); - if (!resource_id) - return; - - GURL complete_url = CompleteURL(url); - - WebPluginResourceClient* resource_client = - delegate_->CreateSeekableResourceClient(resource_id, range_request_id); - InitiateHTTPRequest( - resource_id, resource_client, complete_url, "GET", NULL, 0, range_info, - load_manually_ ? NO_REFERRER : PLUGIN_SRC); -} - -void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id, - bool defer) { - std::vector::iterator client_index = clients_.begin(); - while (client_index != clients_.end()) { - ClientInfo& client_info = *client_index; - - if (client_info.id == resource_id) { - client_info.loader->setDefersLoading(defer); - - // If we determined that the request had failed via the HTTP headers - // in the response then we send out a failure notification to the - // plugin process, as certain plugins don't handle HTTP failure codes - // correctly. - if (!defer && client_info.client && - client_info.pending_failure_notification) { - // The ClientInfo and the iterator can become invalid due to the call - // to DidFail below. - WebPluginResourceClient* resource_client = client_info.client; - client_info.loader->cancel(); - clients_.erase(client_index++); - resource_client->DidFail(); - - // Report that resource loading finished. - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) - devtools_agent->didFinishLoading(resource_id); - } - break; - } - client_index++; - } -} - -void WebPluginImpl::HandleHttpMultipartResponse( - const WebURLResponse& response, WebPluginResourceClient* client) { - std::string multipart_boundary; - if (!MultipartResponseDelegate::ReadMultipartBoundary( - response, &multipart_boundary)) { - NOTREACHED(); - return; - } - - if (page_delegate_) - page_delegate_->DidStartLoadingForPlugin(); - - MultiPartResponseClient* multi_part_response_client = - new MultiPartResponseClient(client); - - MultipartResponseDelegate* multi_part_response_handler = - new MultipartResponseDelegate(multi_part_response_client, NULL, - response, - multipart_boundary); - multi_part_response_map_[client] = multi_part_response_handler; -} - -bool WebPluginImpl::ReinitializePluginForResponse( - WebURLLoader* loader) { - WebFrame* webframe = webframe_; - if (!webframe) - return false; - - WebView* webview = webframe->view(); - if (!webview) - return false; - - WebPluginContainer* container_widget = container_; - - // Destroy the current plugin instance. - TearDownPluginInstance(loader); - - container_ = container_widget; - webframe_ = webframe; - - std::string actual_mime_type; - WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate( - plugin_url_, mime_type_, &actual_mime_type); - - bool ok = plugin_delegate->Initialize( - plugin_url_, arg_names_, arg_values_, this, load_manually_); - - if (!ok) { - container_ = NULL; - // TODO(iyengar) Should we delete the current plugin instance here? - return false; - } - - mime_type_ = actual_mime_type; - delegate_ = plugin_delegate; - - // Force a geometry update to occur to ensure that the plugin becomes - // visible. - container_->reportGeometry(); - - // 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. - container_->invalidate(); - return true; -} - -void WebPluginImpl::TearDownPluginInstance( - WebURLLoader* loader_to_ignore) { - // The container maintains a list of JSObjects which are related to this - // plugin. Tell the frame we're gone so that it can invalidate all of - // those sub JSObjects. - if (container_) - container_->clearScriptObjects(); - - if (delegate_) { - // Call PluginDestroyed() first to prevent the plugin from calling us back - // in the middle of tearing down the render tree. - delegate_->PluginDestroyed(); - delegate_ = NULL; - } - - // Cancel any pending requests because otherwise this deleted object will - // be called by the ResourceDispatcher. - std::vector::iterator client_index = clients_.begin(); - while (client_index != clients_.end()) { - ClientInfo& client_info = *client_index; - - if (loader_to_ignore == client_info.loader) { - client_index++; - continue; - } - - if (client_info.loader.get()) - client_info.loader->cancel(); - - client_index = clients_.erase(client_index); - } - - // This needs to be called now and not in the destructor since the - // webframe_ might not be valid anymore. - webframe_ = NULL; - method_factory_.RevokeAll(); -} - -void WebPluginImpl::SetReferrer(WebKit::WebURLRequest* request, - Referrer referrer_flag) { - switch (referrer_flag) { - case DOCUMENT_URL: - webframe_->setReferrerForRequest(*request, GURL()); - break; - - case PLUGIN_SRC: - webframe_->setReferrerForRequest(*request, plugin_url_); - break; - - default: - break; - } -} - -WebDevToolsAgent* WebPluginImpl::GetDevToolsAgent() { - if (!webframe_) - return NULL; - WebView* view = webframe_->view(); - if (!view) - return NULL; - return view->devToolsAgent(); -} - -} // namespace webkit_glue diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h deleted file mode 100644 index d2eb64b..0000000 --- a/webkit/glue/webplugin_impl.h +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) 2006-2009 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. - -#ifndef WEBKIT_GLUE_WEBPLUGIN_IMPL_H_ -#define WEBKIT_GLUE_WEBPLUGIN_IMPL_H_ - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/linked_ptr.h" -#include "base/task.h" -#include "base/weak_ptr.h" -#include "gfx/native_widget_types.h" -#include "googleurl/src/gurl.h" -#include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h" -#include "third_party/WebKit/WebKit/chromium/public/WebRect.h" -#include "third_party/WebKit/WebKit/chromium/public/WebString.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" -#include "third_party/WebKit/WebKit/chromium/public/WebVector.h" -#include "webkit/glue/webplugin.h" - -class WebViewDelegate; - -namespace WebKit { -class WebDevToolsAgent; -class WebFrame; -class WebPluginContainer; -class WebURLResponse; -class WebURLLoader; -class WebURLRequest; -} - -namespace webkit_glue { - -class MultipartResponseDelegate; -class WebPluginDelegate; -class WebPluginPageDelegate; - -// 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: - WebPluginImpl( - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const base::WeakPtr& page_delegate); - virtual ~WebPluginImpl(); - - // Helper function for sorting post data. - static bool SetPostData(WebKit::WebURLRequest* request, - const char* buf, - uint32 length); - - virtual WebPluginDelegate* delegate() { return delegate_; } - - private: - // WebKit::WebPlugin methods: - virtual bool initialize( - WebKit::WebPluginContainer* container); - 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& cut_outs, bool is_visible); - virtual void updateFocus(bool focused); - virtual void updateVisibility(bool visible); - virtual bool acceptsInputEvents(); - 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); - virtual void didFinishLoadingFrameRequest( - const WebKit::WebURL& url, void* notify_data); - virtual void didFailLoadingFrameRequest( - const WebKit::WebURL& url, void* notify_data, - const WebKit::WebURLError& error); - virtual bool supportsPaginatedPrint(); - virtual int printBegin(const WebKit::WebRect& printable_area, - int printer_dpi); - virtual bool printPage(int page_number, WebKit::WebCanvas* canvas); - virtual void printEnd(); - - // WebPlugin implementation: - void SetWindow(gfx::PluginWindowHandle window); - - // Whether input events should be sent to the delegate. - virtual void SetAcceptsInputEvents(bool accepts) { - accepts_input_events_ = accepts; - } - - void WillDestroyWindow(gfx::PluginWindowHandle window); -#if defined(OS_WIN) - void SetWindowlessPumpEvent(HANDLE pump_messages_event) { } -#endif - - // Given a (maybe partial) url, completes using the base url. - GURL CompleteURL(const char* url); - - // Executes the script passed in. The notify_needed and notify_data arguments - // are passed in by the plugin process. These indicate whether the plugin - // expects a notification on script execution. We pass them back to the - // plugin as is. This avoids having to track the notification arguments in - // the plugin process. - bool ExecuteScript(const std::string& url, const std::wstring& script, - bool notify_needed, intptr_t notify_data, - bool popups_allowed); - - enum RoutingStatus { - ROUTED, - NOT_ROUTED, - INVALID_URL, - GENERAL_FAILURE - }; - - // Determines the referrer value sent along with outgoing HTTP requests - // issued by plugins. - enum Referrer { - PLUGIN_SRC, - DOCUMENT_URL, - NO_REFERRER - }; - - // Given a download request, check if we need to route the output to a frame. - // Returns ROUTED if the load is done and routed to a frame, NOT_ROUTED or - // corresponding error codes otherwise. - RoutingStatus RouteToFrame(const char* url, - bool is_javascript_url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - Referrer referrer_flag); - - // Cancels a pending request. - void CancelResource(unsigned long id); - - // Returns the next avaiable resource id. Returns 0 if the operation fails. - // It may fail if the page has already been closed. - unsigned long GetNextResourceId(); - - // Initiates HTTP GET/POST requests. - // Returns true on success. - bool InitiateHTTPRequest(unsigned long resource_id, - WebPluginResourceClient* client, - const GURL& url, - const char* method, - const char* buf, - int len, - const char* range_info, - Referrer referrer_flag); - - gfx::Rect GetWindowClipRect(const gfx::Rect& rect); - - NPObject* GetWindowScriptNPObject(); - NPObject* GetPluginElement(); - - void SetCookie(const GURL& url, - const GURL& first_party_for_cookies, - const std::string& cookie); - std::string GetCookies(const GURL& url, - const GURL& first_party_for_cookies); - - void ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - std::string* json_retval); - void OnMissingPluginStatus(int status); - void Invalidate(); - void InvalidateRect(const gfx::Rect& rect); - - // Sets the actual Widget for the plugin. - 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); - - // WebURLLoaderClient implementation. We implement this interface in the - // renderer process, and then use the simple WebPluginResourceClient interface - // to relay the callbacks to the plugin. - virtual void willSendRequest(WebKit::WebURLLoader* loader, - WebKit::WebURLRequest& request, - const WebKit::WebURLResponse&); - virtual void didSendData(WebKit::WebURLLoader* loader, - unsigned long long bytes_sent, - unsigned long long total_bytes_to_be_sent); - virtual void didReceiveResponse(WebKit::WebURLLoader* loader, - const WebKit::WebURLResponse& response); - virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer, - int length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader); - virtual void didFail(WebKit::WebURLLoader* loader, const WebKit::WebURLError&); - - // Helper function to remove the stored information about a resource - // request given its index in m_clients. - void RemoveClient(size_t i); - - // Helper function to remove the stored information about a resource - // request given a handle. - void RemoveClient(WebKit::WebURLLoader* loader); - - void HandleURLRequest(const char* url, - const char *method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - bool popups_allowed); - - void CancelDocumentLoad(); - - void InitiateHTTPRangeRequest( - const char* url, const char* range_info, int pending_request_id); - - void SetDeferResourceLoading(unsigned long resource_id, bool defer); - - // Ignore in-process plugins mode for this flag. - bool IsOffTheRecord() { return false; } - - // Handles HTTP multipart responses, i.e. responses received with a HTTP - // status code of 206. - void HandleHttpMultipartResponse(const WebKit::WebURLResponse& response, - WebPluginResourceClient* client); - - void HandleURLRequestInternal(const char* url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - bool popups_allowed, - Referrer referrer_flag); - - // Tears down the existing plugin instance and creates a new plugin instance - // to handle the response identified by the loader parameter. - bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader); - - // Delayed task for downloading the plugin source URL. - void OnDownloadPluginSrcUrl(); - - struct ClientInfo { - unsigned long id; - WebPluginResourceClient* client; - WebKit::WebURLRequest request; - bool pending_failure_notification; - linked_ptr loader; - }; - - // Helper functions - WebPluginResourceClient* GetClientFromLoader(WebKit::WebURLLoader* loader); - ClientInfo* GetClientInfoFromLoader(WebKit::WebURLLoader* loader); - - // Helper function to set the referrer on the request passed in. - void SetReferrer(WebKit::WebURLRequest* request, Referrer referrer_flag); - - // Returns DevToolsAgent for the frame or 0. - WebKit::WebDevToolsAgent* GetDevToolsAgent(); - - std::vector clients_; - - bool windowless_; - gfx::PluginWindowHandle window_; - bool accepts_input_events_; - base::WeakPtr page_delegate_; - WebKit::WebFrame* webframe_; - - WebPluginDelegate* delegate_; - - // This is just a weak reference. - WebKit::WebPluginContainer* container_; - - typedef std::map - MultiPartResponseHandlerMap; - // Tracks HTTP multipart response handlers instantiated for - // a WebPluginResourceClient instance. - MultiPartResponseHandlerMap multi_part_response_map_; - - // The plugin source URL. - GURL plugin_url_; - - // Indicates if the download would be initiated by the plugin or us. - bool load_manually_; - - // 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. - WebPluginGeometry geometry_; - - // The mime type of the plugin. - std::string mime_type_; - - // Holds the list of argument names and values passed to the plugin. We keep - // these so that we can re-initialize the plugin if we need to. - std::vector arg_names_; - std::vector arg_values_; - - ScopedRunnableMethodFactory method_factory_; - - DISALLOW_COPY_AND_ASSIGN(WebPluginImpl); -}; - -} // namespace webkit_glue - -#endif // #ifndef WEBKIT_GLUE_WEBPLUGIN_IMPL_H_ diff --git a/webkit/glue/webplugin_impl_unittest.cc b/webkit/glue/webplugin_impl_unittest.cc deleted file mode 100644 index 4d15e54..0000000 --- a/webkit/glue/webplugin_impl_unittest.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2006-2009 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 "base/string_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/WebKit/chromium/public/WebCString.h" -#include "third_party/WebKit/WebKit/chromium/public/WebString.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" -#include "webkit/glue/webplugin_impl.h" - -using WebKit::WebHTTPBody; -using WebKit::WebString; -using WebKit::WebURLRequest; -using webkit_glue::WebPluginImpl; - -namespace { - -class WebPluginImplTest : public testing::Test { -}; - -} - -static std::string GetHeader(const WebURLRequest& request, const char* name) { - std::string result; - TrimWhitespace( - request.httpHeaderField(WebString::fromUTF8(name)).utf8(), - TRIM_ALL, - &result); - return result; -} - -static std::string GetBodyText(const WebURLRequest& request) { - const WebHTTPBody& body = request.httpBody(); - if (body.isNull()) - return std::string(); - - std::string result; - size_t i = 0; - WebHTTPBody::Element element; - while (body.elementAt(i++, element)) { - if (element.type == WebHTTPBody::Element::TypeData) { - result.append(element.data.data(), element.data.size()); - } else { - NOTREACHED() << "unexpected element type encountered!"; - } - } - return result; -} - -// The Host functions for NPN_PostURL and NPN_PostURLNotify -// need to parse out some HTTP headers. Make sure it works -// with the following tests - -TEST(WebPluginImplTest, PostParserSimple) { - // Test a simple case with headers & data - const char *ex1 = "foo: bar\nContent-length: 10\n\nabcdefghij"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ("bar", GetHeader(request, "foo")); - EXPECT_EQ(0U, GetHeader(request, "bar").length()); - EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); - EXPECT_EQ("abcdefghij", GetBodyText(request)); -} - -TEST(WebPluginImplTest, PostParserLongHeader) { - // Test a simple case with long headers - const char *ex1 = "foo: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\nabcdefghij"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ(100U, GetHeader(request, "foo").length()); -} - -TEST(WebPluginImplTest, PostParserManyHeaders) { - // Test a simple case with long headers - const char *ex1 = "h1:h1\nh2:h2\nh3:h3\nh4:h4\nh5:h5\nh6:h6\nh7:h7\nh8:h8\nh9:h9\nh10:h10\n\nbody"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ("h1", GetHeader(request, "h1")); - EXPECT_EQ("h2", GetHeader(request, "h2")); - EXPECT_EQ("h3", GetHeader(request, "h3")); - EXPECT_EQ("h4", GetHeader(request, "h4")); - EXPECT_EQ("h5", GetHeader(request, "h5")); - EXPECT_EQ("h6", GetHeader(request, "h6")); - EXPECT_EQ("h7", GetHeader(request, "h7")); - EXPECT_EQ("h8", GetHeader(request, "h8")); - EXPECT_EQ("h9", GetHeader(request, "h9")); - EXPECT_EQ("h10", GetHeader(request, "h10")); - EXPECT_EQ("body", GetBodyText(request)); -} - -TEST(WebPluginImplTest, PostParserDuplicateHeaders) { - // Test a simple case with long headers - // What value gets returned doesn't really matter. It shouldn't error - // out. - const char *ex1 = "h1:h1\nh1:h2\n\nbody"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); -} - -TEST(WebPluginImplTest, PostParserNoHeaders) { - // Test a simple case with no headers but with data - const char *ex1 = "\nabcdefghij"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ(0U, GetHeader(request, "foo").length()); - EXPECT_EQ(0U, GetHeader(request, "bar").length()); - EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); - EXPECT_EQ("abcdefghij", GetBodyText(request)); -} - -TEST(WebPluginImplTest, PostParserNoBody) { - // Test a simple case with headers and no body - const char *ex1 = "Foo:bar\n\n"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ("bar", GetHeader(request, "foo")); - EXPECT_EQ(0U, GetHeader(request, "bar").length()); - EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); - EXPECT_EQ(0U, GetBodyText(request).length()); -} - -TEST(WebPluginImplTest, PostParserBodyWithNewLines) { - // Test a simple case with headers and no body - const char *ex1 = "Foo:bar\n\n\n\nabcdefg\n\nabcdefg"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ(GetBodyText(request), "\n\nabcdefg\n\nabcdefg"); -} - -TEST(WebPluginImplTest, PostParserErrorNoBody) { - // Test with headers and no body - const char *ex1 = "Foo:bar\n"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); -} - -TEST(WebPluginImplTest, PostParserErrorEmpty) { - // Test with an empty string - const char *ex1 = ""; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); -} - -TEST(WebPluginImplTest, PostParserEmptyName) { - // Test an error case with an empty header name field - const char *ex1 = "foo:bar\n:blat\n\nbody"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ("bar", GetHeader(request, "foo")); - EXPECT_EQ("body", GetBodyText(request)); -} - -TEST(WebPluginImplTest, PostParserEmptyValue) { - // Test an error case with an empty value field - const char *ex1 = "foo:bar\nbar:\n\nbody"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ("bar", GetHeader(request, "foo")); - EXPECT_EQ(0U, GetHeader(request, "bar").length()); - EXPECT_EQ("body", GetBodyText(request)); -} - -TEST(WebPluginImplTest, PostParserCRLF) { - // Test an error case with an empty value field - const char *ex1 = "foo: bar\r\nbar:\r\n\r\nbody\r\n\r\nbody2"; - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - static_cast(strlen(ex1))); - EXPECT_EQ(true, rv); - EXPECT_EQ("bar", GetHeader(request, "foo")); - EXPECT_EQ(0U, GetHeader(request, "bar").length()); - EXPECT_EQ("body\r\n\r\nbody2", GetBodyText(request)); -} - -TEST(WebPluginImplTest, PostParserBodyWithBinaryData) { - // Test a simple case with headers and binary data. - char ex1[33] = "foo: bar\nContent-length: 10\n\n"; - unsigned int binary_data = 0xFFFFFFF0; - memcpy(ex1 + strlen("foo: bar\nContent-length: 10\n\n"), &binary_data, - sizeof(binary_data)); - - WebURLRequest request; - request.initialize(); - bool rv = WebPluginImpl::SetPostData(&request, ex1, - sizeof(ex1)/sizeof(ex1[0])); - EXPECT_EQ(true, rv); - EXPECT_EQ("bar", GetHeader(request, "foo")); - EXPECT_EQ(0U, GetHeader(request, "bar").length()); - EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); - - std::string body = GetBodyText(request); - - EXPECT_EQ(0xF0, (unsigned char)body[0]); - EXPECT_EQ(0xFF, (unsigned char)body[1]); - EXPECT_EQ(0xFF, (unsigned char)body[2]); - EXPECT_EQ(0xFF, (unsigned char)body[3]); -} diff --git a/webkit/glue/webplugin_page_delegate.h b/webkit/glue/webplugin_page_delegate.h deleted file mode 100644 index 8bc5723..0000000 --- a/webkit/glue/webplugin_page_delegate.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2009 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. - -#ifndef WEBKIT_GLUE_WEBPLUGIN_PAGE_DELEGATE_ -#define WEBKIT_GLUE_WEBPLUGIN_PAGE_DELEGATE_ - -#include "gfx/native_widget_types.h" - -class GURL; - -namespace WebKit { -class WebCookieJar; -} - -namespace webkit_glue { - -class WebPluginDelegate; -struct WebPluginGeometry; - -// Used by the WebPlugin to communicate back to the containing page. -class WebPluginPageDelegate { - public: - // This method is called to create a WebPluginDelegate implementation when a - // new plugin is instanced. See webkit_glue::CreateWebPluginDelegateHelper - // for a default WebPluginDelegate implementation. - virtual WebPluginDelegate* CreatePluginDelegate( - const GURL& url, - const std::string& mime_type, - std::string* actual_mime_type) = 0; - - // Called when a windowed plugin is created. - // Lets the view delegate create anything it is using to wrap the plugin. - virtual void CreatedPluginWindow( - gfx::PluginWindowHandle handle) = 0; - - // Called when a windowed plugin is closing. - // Lets the view delegate shut down anything it is using to wrap the plugin. - virtual void WillDestroyPluginWindow( - gfx::PluginWindowHandle handle) = 0; - - // Keeps track of the necessary window move for a plugin window that resulted - // from a scroll operation. That way, all plugin windows can be moved at the - // same time as each other and the page. - virtual void DidMovePlugin( - const WebPluginGeometry& move) = 0; - - // Notifies the parent view that a load has begun. - virtual void DidStartLoadingForPlugin() = 0; - - // Notifies the parent view that all loads are finished. - virtual void DidStopLoadingForPlugin() = 0; - - // Asks the browser to show a modal HTML dialog. The dialog is passed the - // given arguments as a JSON string, and returns its result as a JSON string - // through json_retval. - virtual void ShowModalHTMLDialogForPlugin( - const GURL& url, - const gfx::Size& size, - const std::string& json_arguments, - std::string* json_retval) = 0; - - // The WebCookieJar to use for this plugin. - virtual WebKit::WebCookieJar* GetCookieJar() = 0; -}; - -} // namespace webkit_glue - -#endif // WEBKIT_GLUE_WEBPLUGIN_PAGE_DELEGATE_H_ diff --git a/webkit/glue/webplugininfo.h b/webkit/glue/webplugininfo.h deleted file mode 100644 index 21f34df..0000000 --- a/webkit/glue/webplugininfo.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef WEBKIT_GLUE_WEBPLUGININFO_H_ -#define WEBKIT_GLUE_WEBPLUGININFO_H_ - -#include -#include - -#include "base/basictypes.h" -#include "base/file_path.h" - -// Describes a mime type entry for a plugin. -struct WebPluginMimeType { - // The name of the mime type (e.g., "application/x-shockwave-flash"). - std::string mime_type; - - // A list of all the file extensions for this mime type. - std::vector file_extensions; - - // Description of the mime type. - std::wstring description; -}; - -// Describes an available NPAPI plugin. -struct WebPluginInfo { - // The name of the plugin (i.e. Flash). - std::wstring name; - - // The path to the plugin file (DLL/bundle/library). - FilePath path; - - // The version number of the plugin file (may be OS-specific) - std::wstring version; - - // A description of the plugin that we get from its version info. - std::wstring desc; - - // A list of all the mime types that this plugin supports. - std::vector mime_types; - - // Whether the plugin is enabled. - bool enabled; -}; - -#endif // WEBKIT_GLUE_WEBPLUGININFO_H_ -- cgit v1.1