summaryrefslogtreecommitdiffstats
path: root/chrome/plugin/webplugin_delegate_stub.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/plugin/webplugin_delegate_stub.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/plugin/webplugin_delegate_stub.cc')
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc462
1 files changed, 462 insertions, 0 deletions
diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc
new file mode 100644
index 0000000..0678b14
--- /dev/null
+++ b/chrome/plugin/webplugin_delegate_stub.cc
@@ -0,0 +1,462 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/plugin/webplugin_delegate_stub.h"
+
+#include "base/command_line.h"
+#include "base/time.h"
+#include "base/gfx/bitmap_header.h"
+#include "base/gfx/platform_device.h"
+#include "bindings/npapi.h"
+#include "bindings/npruntime.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/gfx/emf.h"
+#include "chrome/common/plugin_messages.h"
+#include "chrome/common/win_util.h"
+#include "chrome/plugin/npobject_stub.h"
+#include "chrome/plugin/plugin_channel.h"
+#include "chrome/plugin/plugin_thread.h"
+#include "chrome/plugin/webplugin_proxy.h"
+#include "webkit/glue/plugins/webplugin_delegate_impl.h"
+#include "webkit/glue/webcursor.h"
+
+class FinishDestructionTask : public Task {
+ public:
+ FinishDestructionTask(WebPluginDelegate* delegate, WebPlugin* webplugin)
+ : delegate_(delegate), webplugin_(webplugin) { }
+
+ void Run() {
+ // WebPlugin must outlive WebPluginDelegate.
+ if (delegate_)
+ delegate_->PluginDestroyed();
+
+ delete webplugin_;
+ }
+
+ private:
+ WebPluginDelegate* delegate_;
+ WebPlugin* webplugin_;
+};
+
+WebPluginDelegateStub::WebPluginDelegateStub(
+ const std::string& mime_type, int instance_id, PluginChannel* channel) :
+ mime_type_(mime_type),
+ instance_id_(instance_id),
+ channel_(channel),
+ delegate_(NULL),
+ webplugin_(NULL) {
+ DCHECK(channel);
+}
+
+WebPluginDelegateStub::~WebPluginDelegateStub() {
+ if (channel_->in_send()) {
+ // The delegate or an npobject is in the callstack, so don't delete it
+ // right away.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ new FinishDestructionTask(delegate_, webplugin_));
+ } else {
+ // Safe to delete right away.
+ if (delegate_)
+ delegate_->PluginDestroyed();
+
+ delete webplugin_;
+ }
+}
+
+void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) {
+ // A plugin can execute a script to delete itself in any of its NPP methods.
+ // Hold an extra reference to ourself so that if this does occur and we're
+ // handling a sync message, we don't crash when attempting to send a reply.
+ AddRef();
+
+ IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateStub, msg)
+ IPC_MESSAGE_HANDLER(PluginMsg_Init, OnInit)
+ IPC_MESSAGE_HANDLER(PluginMsg_WillSendRequest, OnWillSendRequest)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveResponse, OnDidReceiveResponse)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveData, OnDidReceiveData)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidFinishLoading, OnDidFinishLoading)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidFail, OnDidFail)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidFinishLoadWithReason,
+ OnDidFinishLoadWithReason)
+ IPC_MESSAGE_HANDLER(PluginMsg_SetFocus, OnSetFocus)
+ IPC_MESSAGE_HANDLER(PluginMsg_HandleEvent, OnHandleEvent)
+ IPC_MESSAGE_HANDLER(PluginMsg_Paint, OnPaint)
+ IPC_MESSAGE_HANDLER(PluginMsg_Print, OnPrint)
+ IPC_MESSAGE_HANDLER(PluginMsg_PaintIntoSharedMemory,
+ OnPaintIntoSharedMemory)
+ IPC_MESSAGE_HANDLER(PluginMsg_GetPluginScriptableObject,
+ OnGetPluginScriptableObject)
+ IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometry, OnUpdateGeometry)
+ IPC_MESSAGE_HANDLER(PluginMsg_SendJavaScriptStream,
+ OnSendJavaScriptStream)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualResponse,
+ OnDidReceiveManualResponse)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveManualData, OnDidReceiveManualData)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidFinishManualLoading,
+ OnDidFinishManualLoading)
+ IPC_MESSAGE_HANDLER(PluginMsg_DidManualLoadFail, OnDidManualLoadFail)
+ IPC_MESSAGE_HANDLER(PluginMsg_InstallMissingPlugin, OnInstallMissingPlugin)
+ IPC_MESSAGE_HANDLER(PluginMsg_HandleURLRequestReply, OnHandleURLRequestReply)
+ IPC_MESSAGE_HANDLER(PluginMsg_URLRequestRouted, OnURLRequestRouted)
+ IPC_MESSAGE_UNHANDLED_ERROR()
+ IPC_END_MESSAGE_MAP()
+
+ Release();
+}
+
+bool WebPluginDelegateStub::Send(IPC::Message* msg) {
+ return channel_->Send(msg);
+}
+
+void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params,
+ bool* result) {
+ *result = false;
+ int argc = static_cast<int>(params.arg_names.size());
+ if (argc != static_cast<int>(params.arg_values.size())) {
+ NOTREACHED();
+ return;
+ }
+
+ char **argn = new char*[argc];
+ char **argv = new char*[argc];
+ for (int i = 0; i < argc; ++i) {
+ argn[i] = const_cast<char*>(params.arg_names[i].c_str());
+ argv[i] = const_cast<char*>(params.arg_values[i].c_str());
+ }
+
+ CommandLine command_line;
+ std::wstring path = command_line.GetSwitchValue(switches::kPluginPath);
+ delegate_ = WebPluginDelegateImpl::Create(
+ path, mime_type_, params.containing_window);
+ if (delegate_) {
+ webplugin_ = new WebPluginProxy(
+ channel_, instance_id_, delegate_, params.modal_dialog_event);
+ *result = delegate_->Initialize(
+ params.url, argn, argv, argc, webplugin_, params.load_manually);
+ }
+
+ delete[] argn;
+ delete[] argv;
+}
+
+void WebPluginDelegateStub::OnWillSendRequest(int id, const GURL& url) {
+ WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
+ if (!client)
+ return;
+
+ client->WillSendRequest(url);
+}
+
+void WebPluginDelegateStub::OnDidReceiveResponse(
+ const PluginMsg_DidReceiveResponseParams& params, bool* cancel) {
+ *cancel = false;
+ WebPluginResourceClient* client = webplugin_->GetResourceClient(params.id);
+ if (!client)
+ return;
+
+ client->DidReceiveResponse(params.mime_type,
+ params.headers,
+ params.expected_length,
+ params.last_modified,
+ cancel);
+}
+
+void WebPluginDelegateStub::OnDidReceiveData(int id,
+ const std::vector<char>& buffer) {
+ WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
+ if (!client)
+ return;
+
+ client->DidReceiveData(&buffer.front(), static_cast<int>(buffer.size()));
+}
+
+void WebPluginDelegateStub::OnDidFinishLoading(int id) {
+ WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
+ if (!client)
+ return;
+
+ client->DidFinishLoading();
+}
+
+void WebPluginDelegateStub::OnDidFail(int id) {
+ WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
+ if (!client)
+ return;
+
+ client->DidFail();
+}
+
+void WebPluginDelegateStub::OnDidFinishLoadWithReason(int reason) {
+ delegate_->DidFinishLoadWithReason(reason);
+}
+
+void WebPluginDelegateStub::OnSetFocus() {
+ delegate_->SetFocus();
+}
+
+void WebPluginDelegateStub::OnHandleEvent(const NPEvent& event,
+ bool* handled,
+ WebCursor* cursor) {
+ *handled = delegate_->HandleEvent(const_cast<NPEvent*>(&event), cursor);
+}
+
+void WebPluginDelegateStub::OnPaint(const PluginMsg_Paint_Params& params) {
+ // Convert the shared memory handle to a handle that works in our process,
+ // and then use that to create an HDC.
+ win_util::ScopedHandle shared_section(win_util::GetSectionFromProcess(
+ params.shared_memory, channel_->renderer_handle(), false));
+
+ if (shared_section == NULL) {
+ NOTREACHED();
+ return;
+ }
+
+ void* data = NULL;
+ HDC screen_dc = GetDC(NULL);
+ BITMAPINFOHEADER bitmap_header;
+ gfx::CreateBitmapHeader(params.size.width(), params.size.height(),
+ &bitmap_header);
+ win_util::ScopedBitmap hbitmap(CreateDIBSection(
+ screen_dc, reinterpret_cast<const BITMAPINFO*>(&bitmap_header),
+ DIB_RGB_COLORS, &data,
+ shared_section, 0));
+ ReleaseDC(NULL, screen_dc);
+ if (hbitmap == NULL) {
+ NOTREACHED();
+ return;
+ }
+
+ win_util::ScopedHDC hdc(CreateCompatibleDC(NULL));
+ if (hdc == NULL) {
+ NOTREACHED();
+ return;
+ }
+ gfx::PlatformDevice::InitializeDC(hdc);
+ SelectObject(hdc, hbitmap);
+ SetWorldTransform(hdc, &params.xf);
+
+ win_util::ScopedHRGN hrgn(CreateRectRgnIndirect(&params.clip_rect.ToRECT()));
+ SelectClipRgn(hdc, hrgn);
+ webplugin_->WillPaint();
+ delegate_->Paint(hdc, params.damaged_rect);
+}
+
+void WebPluginDelegateStub::OnPrint(PluginMsg_PrintResponse_Params* params) {
+ gfx::Emf emf;
+ if (!emf.CreateDc(NULL, NULL)) {
+ NOTREACHED();
+ return;
+ }
+ HDC hdc = emf.hdc();
+ gfx::PlatformDevice::InitializeDC(hdc);
+ delegate_->Print(hdc);
+ if (!emf.CloseDc()) {
+ NOTREACHED();
+ return;
+ }
+
+ size_t size = emf.GetDataSize();
+ DCHECK(size);
+ params->size = size;
+ SharedMemory shared_buf;
+ CreateSharedBuffer(size, &shared_buf, &params->shared_memory);
+
+ // Retrieve a copy of the data.
+ bool success = emf.GetData(shared_buf.memory(), size);
+ DCHECK(success);
+}
+
+void WebPluginDelegateStub::OnPaintIntoSharedMemory(
+ const PluginMsg_Paint_Params& params,
+ SharedMemoryHandle* emf_buffer,
+ size_t* bytes) {
+ *emf_buffer = NULL;
+ *bytes = 0;
+
+ gfx::Emf emf;
+ if (!emf.CreateDc(NULL, NULL)) {
+ NOTREACHED();
+ return;
+ }
+ HDC hdc = emf.hdc();
+ gfx::PlatformDevice::InitializeDC(hdc);
+
+ if (delegate_->windowless()) {
+ WindowlessPaint(hdc, params);
+ } else {
+ WindowedPaint(hdc, params.damaged_rect);
+ }
+
+ // Need to send back the data as shared memory.
+ if (!emf.CloseDc()) {
+ NOTREACHED();
+ return;
+ }
+
+ size_t size = emf.GetDataSize();
+ DCHECK(size);
+ *bytes = size;
+ SharedMemory shared_buf;
+ CreateSharedBuffer(size, &shared_buf, emf_buffer);
+
+ // Retrieve a copy of the data.
+ bool success = emf.GetData(shared_buf.memory(), size);
+ DCHECK(success);
+}
+
+void WebPluginDelegateStub::WindowedPaint(HDC hdc,
+ const gfx::Rect& window_rect) {
+ // Use the NPAPI print() function to render the plugin.
+ delegate_->Print(hdc);
+}
+
+void WebPluginDelegateStub::WindowlessPaint(
+ HDC hdc,
+ const PluginMsg_Paint_Params& params) {
+ void* data = NULL;
+ HDC screen_dc = GetDC(NULL);
+ BITMAPINFOHEADER bitmap_header;
+ gfx::CreateBitmapHeader(params.size.width(), params.size.height(),
+ &bitmap_header);
+ win_util::ScopedBitmap hbitmap(CreateDIBSection(
+ screen_dc, reinterpret_cast<const BITMAPINFO*>(&bitmap_header),
+ DIB_RGB_COLORS, &data, NULL, 0));
+ ReleaseDC(NULL, screen_dc);
+ if (hbitmap == NULL) {
+ NOTREACHED();
+ return;
+ }
+ SelectObject(hdc, hbitmap);
+
+ // Apply transform and clipping.
+ SetWorldTransform(hdc, &params.xf);
+ win_util::ScopedHRGN hrgn(CreateRectRgnIndirect(&params.clip_rect.ToRECT()));
+ SelectClipRgn(hdc, hrgn);
+ webplugin_->WillPaint();
+ delegate_->Paint(hdc, params.damaged_rect);
+}
+
+void WebPluginDelegateStub::OnUpdateGeometry(const gfx::Rect& window_rect,
+ const gfx::Rect& clip_rect,
+ bool visible) {
+ delegate_->UpdateGeometry(window_rect, clip_rect, visible);
+}
+
+void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id,
+ void** npobject_ptr) {
+ NPObject* object = delegate_->GetPluginScriptableObject();
+ if (!object) {
+ *route_id = MSG_ROUTING_NONE;
+ return;
+ }
+
+ *route_id = channel_->GenerateRouteID();
+ *npobject_ptr = object;
+ // The stub will delete itself when the proxy tells it that it's released, or
+ // otherwise when the channel is closed.
+ NPObjectStub* stub = new NPObjectStub(object, channel_.get(), *route_id);
+
+ // Release ref added by GetPluginScriptableObject (our stub holds its own).
+ NPN_ReleaseObject(object);
+}
+
+void WebPluginDelegateStub::OnSendJavaScriptStream(const std::string& url,
+ const std::wstring& result,
+ bool success,
+ bool notify_needed,
+ int notify_data) {
+ delegate_->SendJavaScriptStream(url, result, success, notify_needed,
+ notify_data);
+}
+
+void WebPluginDelegateStub::OnDidReceiveManualResponse(
+ const std::string& url,
+ const PluginMsg_DidReceiveResponseParams& params) {
+ delegate_->DidReceiveManualResponse(url, params.mime_type, params.headers,
+ params.expected_length,
+ params.last_modified);
+}
+
+void WebPluginDelegateStub::OnDidReceiveManualData(
+ const std::vector<char>& buffer) {
+ delegate_->DidReceiveManualData(&buffer.front(),
+ static_cast<int>(buffer.size()));
+}
+
+void WebPluginDelegateStub::OnDidFinishManualLoading() {
+ delegate_->DidFinishManualLoading();
+}
+
+void WebPluginDelegateStub::OnDidManualLoadFail() {
+ delegate_->DidManualLoadFail();
+}
+
+void WebPluginDelegateStub::OnInstallMissingPlugin() {
+ delegate_->InstallMissingPlugin();
+}
+
+void WebPluginDelegateStub::CreateSharedBuffer(
+ size_t size,
+ SharedMemory* shared_buf,
+ SharedMemoryHandle* remote_handle) {
+ if (!shared_buf->Create(std::wstring(), false, false, size)) {
+ NOTREACHED();
+ return;
+ }
+ if (!shared_buf->Map(size)) {
+ NOTREACHED();
+ shared_buf->Close();
+ return;
+ }
+
+ BOOL result = DuplicateHandle(GetCurrentProcess(),
+ shared_buf->handle(),
+ channel_->renderer_handle(),
+ remote_handle, 0, FALSE,
+ DUPLICATE_SAME_ACCESS);
+ DCHECK_NE(result, 0);
+ // If the calling function's shared_buf is on the stack, its destructor will
+ // close the shared memory buffer handle. This is fine since we already
+ // duplicated the handle to the renderer process so it will stay "alive".
+}
+
+void WebPluginDelegateStub::OnHandleURLRequestReply(
+ const PluginMsg_URLRequestReply_Params& params) {
+ WebPluginResourceClient* resource_client =
+ delegate_->CreateResourceClient(params.resource_id, params.url,
+ params.notify_needed,
+ params.notify_data);
+ webplugin_->OnResourceCreated(params.resource_id, resource_client);
+}
+
+void WebPluginDelegateStub::OnURLRequestRouted(const std::string& url,
+ bool notify_needed,
+ HANDLE notify_data) {
+ delegate_->URLRequestRouted(url, notify_needed, notify_data);
+}