diff options
author | mpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-15 18:36:46 +0000 |
---|---|---|
committer | mpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-15 18:36:46 +0000 |
commit | 173de1be12780200c62bae5c01965d51ac0eaa31 (patch) | |
tree | 5ab851b72e8012f49a4d80b281744a6b64d40753 /chrome | |
parent | 1f2763de9d897fc2b0e6da4c2323b7d8ab70c687 (diff) | |
download | chromium_src-173de1be12780200c62bae5c01965d51ac0eaa31.zip chromium_src-173de1be12780200c62bae5c01965d51ac0eaa31.tar.gz chromium_src-173de1be12780200c62bae5c01965d51ac0eaa31.tar.bz2 |
Step 1 at making Gears run in the renderer process (enabled by switch
"--gears-in-renderer"). Requires some changes to gears to work. Most things
work if you disable the sandbox. One major hole is that update tasks don't
report status to the appropriate renderer.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@954 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/chrome_plugin_host.cc | 8 | ||||
-rw-r--r-- | chrome/browser/render_process_host.cc | 3 | ||||
-rw-r--r-- | chrome/browser/resource_message_filter.cc | 20 | ||||
-rw-r--r-- | chrome/browser/resource_message_filter.h | 4 | ||||
-rw-r--r-- | chrome/common/chrome_plugin_api.h | 1 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 2 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 10 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 3 | ||||
-rw-r--r-- | chrome/renderer/SConscript | 1 | ||||
-rw-r--r-- | chrome/renderer/chrome_plugin_host.cc | 573 | ||||
-rw-r--r-- | chrome/renderer/chrome_plugin_host.h | 38 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 3 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 21 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 8 | ||||
-rw-r--r-- | chrome/renderer/renderer.vcproj | 8 |
17 files changed, 704 insertions, 7 deletions
diff --git a/chrome/browser/chrome_plugin_host.cc b/chrome/browser/chrome_plugin_host.cc index 65600b8..ed6c6f5 100644 --- a/chrome/browser/chrome_plugin_host.cc +++ b/chrome/browser/chrome_plugin_host.cc @@ -31,6 +31,7 @@ #include <set> +#include "base/command_line.h" #include "base/file_util.h" #include "base/histogram.h" #include "base/message_loop.h" @@ -52,6 +53,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_plugin_lib.h" #include "chrome/common/chrome_plugin_util.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/net/url_request_intercept_job.h" #include "chrome/common/plugin_messages.h" @@ -658,6 +660,12 @@ CPProcessType STDCALL CPB_GetProcessType(CPID id) { } CPError STDCALL CPB_SendMessage(CPID id, const void *data, uint32 data_len) { + CommandLine cmd; + if (cmd.HasSwitch(switches::kGearsInRenderer)) { + // TODO(mpcomplete): figure out what to do here. + return CPERR_FAILURE; + } + CHECK(ChromePluginLib::IsPluginThread()); ChromePluginLib* plugin = ChromePluginLib::FromCPID(id); CHECK(plugin); diff --git a/chrome/browser/render_process_host.cc b/chrome/browser/render_process_host.cc index 558a161..aff2ba0 100644 --- a/chrome/browser/render_process_host.cc +++ b/chrome/browser/render_process_host.cc @@ -289,7 +289,8 @@ bool RenderProcessHost::Init() { switches::kEnableDCHECK, switches::kSilentDumpOnDCHECK, switches::kDisablePopupBlocking, - switches::kUseLowFragHeapCrt + switches::kUseLowFragHeapCrt, + switches::kGearsInRenderer, }; for (int i = 0; i < arraysize(switch_names); ++i) { diff --git a/chrome/browser/resource_message_filter.cc b/chrome/browser/resource_message_filter.cc index d5234a8..99b188c 100644 --- a/chrome/browser/resource_message_filter.cc +++ b/chrome/browser/resource_message_filter.cc @@ -41,6 +41,7 @@ #include "chrome/browser/render_process_host.h" #include "chrome/browser/render_widget_helper.h" #include "chrome/browser/spellchecker.h" +#include "chrome/common/chrome_plugin_lib.h" #include "chrome/common/clipboard_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" @@ -167,6 +168,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie) IPC_MESSAGE_HANDLER(ViewHostMsg_GetCookies, OnGetCookies) + IPC_MESSAGE_HANDLER(ViewHostMsg_GetDataDir, OnGetDataDir) + IPC_MESSAGE_HANDLER(ViewHostMsg_PluginMessage, OnPluginMessage) IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont) IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorInfoForWindow, OnGetMonitorInfoForWindow) @@ -362,6 +365,23 @@ void ResourceMessageFilter::OnGetCookies(const GURL& url, *cookies = request_context_->cookie_store()->GetCookies(url); } +void ResourceMessageFilter::OnGetDataDir(std::wstring* data_dir) { + *data_dir = plugin_service_->GetChromePluginDataDir(); +} + +void ResourceMessageFilter::OnPluginMessage(const std::wstring& dll_path, + const std::vector<uint8>& data) { + DCHECK(MessageLoop::current() == + ChromeThread::GetMessageLoop(ChromeThread::IO)); + + ChromePluginLib *chrome_plugin = ChromePluginLib::Find(dll_path); + if (chrome_plugin) { + void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0])); + uint32 data_len = static_cast<uint32>(data.size()); + chrome_plugin->functions().on_message(data_ptr, data_len); + } +} + void ResourceMessageFilter::OnGetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { plugin_service_->GetPlugins(refresh, plugins); diff --git a/chrome/browser/resource_message_filter.h b/chrome/browser/resource_message_filter.h index a5525e7..31dff65 100644 --- a/chrome/browser/resource_message_filter.h +++ b/chrome/browser/resource_message_filter.h @@ -103,6 +103,10 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, const std::string& cookie); void OnGetCookies(const GURL& url, const GURL& policy_url, std::string* cookies); + void OnGetDataDir(std::wstring* data_dir); + void OnPluginMessage(const std::wstring& dll_path, + const std::vector<uint8>& message); + // Cache fonts for the renderer. See ResourceMessageFilter::OnLoadFont // implementation for more details void OnLoadFont(LOGFONT font); diff --git a/chrome/common/chrome_plugin_api.h b/chrome/common/chrome_plugin_api.h index 1dd08727..af21699 100644 --- a/chrome/common/chrome_plugin_api.h +++ b/chrome/common/chrome_plugin_api.h @@ -67,6 +67,7 @@ typedef unsigned char CPBool; typedef enum { CP_PROCESS_BROWSER = 0, CP_PROCESS_PLUGIN, + CP_PROCESS_RENDERER, } CPProcessType; // Return codes. Error values are negative. diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 47f3080..c36d710 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -330,6 +330,9 @@ const wchar_t kUseLowFragHeapCrt[] = L"use-lf-heap"; const wchar_t kGearsPluginPathOverride[] = L"gears-plugin-path"; #endif +// Switch to load Gears in the renderer process. +const wchar_t kGearsInRenderer[] = L"gears-in-renderer"; + // Enable new HTTP stack. const wchar_t kUseNewHttp[] = L"new-http"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index fbffc88..11ce1bc 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -137,6 +137,8 @@ extern const wchar_t kUseLowFragHeapCrt[]; extern const wchar_t kGearsPluginPathOverride[]; #endif +extern const wchar_t kGearsInRenderer[]; + extern const wchar_t kUseNewHttp[]; extern const wchar_t kJavaScriptDebuggerPath[]; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 334b902..841f661 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -650,6 +650,16 @@ IPC_BEGIN_MESSAGES(ViewHost, 2) std::wstring /* filename */, std::string /* actual mime type for url */) + // Retrieve the data directory associated with the renderer's profile. + IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetDataDir, + std::wstring /* data_dir_retval */) + + // Allows a chrome plugin loaded in a renderer process to send arbitrary + // data to an instance of the same plugin loaded in the browser process. + IPC_MESSAGE_CONTROL2(ViewHostMsg_PluginMessage, + std::wstring /* dll_path of plugin */, + std::vector<uint8> /* opaque data */) + // Requests spellcheck for a word. IPC_SYNC_MESSAGE_ROUTED1_2(ViewHostMsg_SpellCheck, std::wstring /* word to check */, diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index 6c862e1..de0a771 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -60,6 +60,9 @@ class WebPluginProxy : public WebPlugin { void InvalidateRect(const gfx::Rect& rect); NPObject* GetWindowScriptNPObject(); NPObject* GetPluginElement(); + WebFrame* GetWebFrame() { + return NULL; // doesn't make sense in the plugin process. + } void SetCookie(const GURL& url, const GURL& policy_url, const std::string& cookie); diff --git a/chrome/renderer/SConscript b/chrome/renderer/SConscript index f801236..a10793e 100644 --- a/chrome/renderer/SConscript +++ b/chrome/renderer/SConscript @@ -61,6 +61,7 @@ env.Append( input_files = [ 'about_handler.cc', 'automation/dom_automation_controller.cc', + 'chrome_plugin_host.cc', 'debug_message_handler.cc', 'dom_ui_bindings.cc', 'external_js_object.cc', diff --git a/chrome/renderer/chrome_plugin_host.cc b/chrome/renderer/chrome_plugin_host.cc new file mode 100644 index 0000000..cf80816 --- /dev/null +++ b/chrome/renderer/chrome_plugin_host.cc @@ -0,0 +1,573 @@ +// 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/chrome_plugin_host.h" + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_plugin_lib.h" +#include "chrome/common/chrome_plugin_util.h" +#include "chrome/common/resource_dispatcher.h" +#include "chrome/renderer/render_view.h" +#include "net/base/data_url.h" +#include "net/base/upload_data.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/resource_loader_bridge.h" +#include "webkit/glue/resource_type.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/webframe.h" + +namespace { + +using webkit_glue::ResourceLoaderBridge; + +// This class manages a network request made by the plugin, handling the +// data as it comes in from the ResourceLoaderBridge and is requested by the +// plugin. +// NOTE: All methods must be called on the Plugin thread. +class PluginRequestHandlerProxy + : public PluginHelper, public ResourceLoaderBridge::Peer { + public: + static PluginRequestHandlerProxy* FromCPRequest(CPRequest* request) { + return ScopableCPRequest::GetData<PluginRequestHandlerProxy*>(request); + } + + PluginRequestHandlerProxy(ChromePluginLib* plugin, + ScopableCPRequest* cprequest, + WebFrame* webframe) + : PluginHelper(plugin), cprequest_(cprequest), response_data_offset_(0), + completed_(false), sync_(false), read_buffer_(NULL), + webframe_(webframe) { + load_flags_ = PluginResponseUtils::CPLoadFlagsToNetFlags(0); + cprequest_->data = this; // see FromCPRequest(). + } + + ~PluginRequestHandlerProxy() { + if (bridge_.get() && !completed_) { + bridge_->Cancel(); + } + } + + // ResourceLoaderBridge::Peer + virtual void OnUploadProgress(uint64 position, uint64 size) { + CPRR_UploadProgressFunc upload_progress = + plugin_->functions().response_funcs->upload_progress; + if (upload_progress) + upload_progress(cprequest_.get(), position, size); + } + + virtual void OnReceivedRedirect(const GURL& new_url) { + plugin_->functions().response_funcs->received_redirect( + cprequest_.get(), new_url.spec().c_str()); + } + + virtual void OnReceivedResponse( + const ResourceLoaderBridge::ResponseInfo& info) { + response_headers_ = info.headers; + plugin_->functions().response_funcs->start_completed( + cprequest_.get(), CPERR_SUCCESS); + } + + virtual void OnReceivedData(const char* data, int len) { + response_data_.append(data, len); + if (read_buffer_) { + // If we had an asynchronous operation pending, read into that buffer + // and inform the plugin. + int rv = Read(read_buffer_, read_buffer_size_); + DCHECK(rv != CPERR_IO_PENDING); + read_buffer_ = NULL; + plugin_->functions().response_funcs->read_completed( + cprequest_.get(), rv); + } + } + + virtual void OnCompletedRequest(const URLRequestStatus& status) { + completed_ = true; + + if (!status.is_success()) { + // TODO(mpcomplete): better error codes + // Inform the plugin, calling the right function depending on whether + // we got the start_completed event or not. + if (response_headers_) { + plugin_->functions().response_funcs->start_completed( + cprequest_.get(), CPERR_FAILURE); + } else { + plugin_->functions().response_funcs->read_completed( + cprequest_.get(), CPERR_FAILURE); + } + } else if (read_buffer_) { + // The plugin was waiting for more data. Inform him we're done. + read_buffer_ = NULL; + plugin_->functions().response_funcs->read_completed( + cprequest_.get(), CPERR_SUCCESS); + } + } + + virtual std::string GetURLForDebugging() { + return cprequest_->url; + } + + void set_extra_headers(const std::string& headers) { + extra_headers_ = headers; + } + void set_load_flags(uint32 flags) { + load_flags_ = flags; + } + void set_sync(bool sync) { + sync_ = sync; + } + void AppendDataToUpload(const char* bytes, int bytes_len) { + upload_content_.push_back(net::UploadData::Element()); + upload_content_.back().SetToBytes(bytes, bytes_len); + } + + void AppendFileToUpload(const std::wstring &filepath) { + AppendFileRangeToUpload(filepath, 0, kuint64max); + } + + void AppendFileRangeToUpload(const std::wstring &filepath, + uint64 offset, uint64 length) { + upload_content_.push_back(net::UploadData::Element()); + upload_content_.back().SetToFilePathRange(filepath, offset, length); + } + + CPError Start() { + bridge_.reset( + webkit_glue::ResourceLoaderBridge::Create( + webframe_, + cprequest_->method, + GURL(cprequest_->url), + GURL(cprequest_->url), // TODO(jackson): policy url? + GURL(), // TODO(mpcomplete): referrer? + extra_headers_, + load_flags_, + GetCurrentProcessId(), + ResourceType::OBJECT, + false)); // TODO (jcampan): mixed-content? + if (!bridge_.get()) + return CPERR_FAILURE; + + for (size_t i = 0; i < upload_content_.size(); ++i) { + switch (upload_content_[i].type()) { + case net::UploadData::TYPE_BYTES: { + const std::vector<char>& bytes = upload_content_[i].bytes(); + bridge_->AppendDataToUpload(&bytes[0], + static_cast<int>(bytes.size())); + break; + } + case net::UploadData::TYPE_FILE: { + bridge_->AppendFileRangeToUpload( + upload_content_[i].file_path(), + upload_content_[i].file_range_offset(), + upload_content_[i].file_range_length()); + break; + } + default: { + NOTREACHED() << "Unknown UploadData::Element type"; + } + } + } + + if (sync_) { + ResourceLoaderBridge::SyncLoadResponse response; + bridge_->SyncLoad(&response); + response_headers_ = response.headers; + response_data_ = response.data; + completed_ = true; + return response.status.is_success() ? CPERR_SUCCESS : CPERR_FAILURE; + } else { + if (!bridge_->Start(this)) { + bridge_.reset(); + return CPERR_FAILURE; + } + return CPERR_IO_PENDING; + } + } + + int GetResponseInfo(CPResponseInfoType type, void* buf, uint32 buf_size) { + return PluginResponseUtils::GetResponseInfo( + response_headers_, type, buf, buf_size); + } + + int Read(void* buf, uint32 buf_size) { + uint32 avail = + static_cast<uint32>(response_data_.size()) - response_data_offset_; + uint32 count = buf_size; + if (count > avail) + count = avail; + + int rv = CPERR_FAILURE; + if (count) { + // Data is ready now. + memcpy(buf, &response_data_[0] + response_data_offset_, count); + response_data_offset_ += count; + } else if (!completed_) { + read_buffer_ = buf; + read_buffer_size_ = buf_size; + DCHECK(!sync_); + return CPERR_IO_PENDING; + } + + if (response_data_.size() == response_data_offset_) { + // Simple optimization for large requests. Generally the consumer will + // read the data faster than it comes in, so we can clear our buffer + // any time it has all been read. + response_data_.clear(); + response_data_offset_ = 0; + } + + read_buffer_ = NULL; + return count; + } + + private: + scoped_ptr<ScopableCPRequest> cprequest_; + WebFrame* webframe_; + scoped_ptr<ResourceLoaderBridge> bridge_; + std::vector<net::UploadData::Element> upload_content_; + std::string extra_headers_; + uint32 load_flags_; + bool sync_; + + scoped_refptr<net::HttpResponseHeaders> response_headers_; + std::string response_data_; + int response_data_offset_; + bool completed_; + void* read_buffer_; + uint32 read_buffer_size_; +}; + +// +// Generic functions +// + +// TODO(mpcomplete): call up to browser to ask for a valid browsing context. +WebPlugin* WebPluginFromContext(CPBrowsingContext context) { + return reinterpret_cast<WebPlugin*>(static_cast<LONG_PTR>(context)); +} + +CPBrowsingContext ContextFromWebPlugin(WebPlugin* webplugin) { + return static_cast<CPBrowsingContext>(reinterpret_cast<LONG_PTR>(webplugin)); +} + +void STDCALL CPB_SetKeepProcessAlive(CPID id, CPBool keep_alive) { + // Doesn't apply in the renderer process. +} + +CPError STDCALL CPB_GetCookies(CPID id, CPBrowsingContext context, + const char* url, char** cookies) { + CHECK(ChromePluginLib::IsPluginThread()); + std::string cookies_str = webkit_glue::GetCookies(GURL(url), GURL(url)); + *cookies = CPB_StringDup(CPB_Alloc, cookies_str); + return CPERR_SUCCESS; +} + +CPError STDCALL CPB_ShowHtmlDialogModal( + CPID id, CPBrowsingContext context, const char* url, int width, int height, + const char* json_arguments, char** json_retval) { + CHECK(ChromePluginLib::IsPluginThread()); + + WebPlugin* webplugin = WebPluginFromContext(context); + if (!webplugin) + return CPERR_INVALID_PARAMETER; + + std::string retval_str; + webplugin->ShowModalHTMLDialog( + GURL(url), width, height, json_arguments, &retval_str); + *json_retval = CPB_StringDup(CPB_Alloc, retval_str); + return CPERR_SUCCESS; +} + +CPError STDCALL CPB_ShowHtmlDialog( + CPID id, CPBrowsingContext context, const char* url, int width, int height, + const char* json_arguments, void* plugin_context) { + // TODO(mpcomplete): support non-modal dialogs. + return CPERR_FAILURE; +} + +CPError STDCALL CPB_GetCommandLineArguments( + CPID id, CPBrowsingContext context, const char* url, char** arguments) { + CHECK(ChromePluginLib::IsPluginThread()); + std::string arguments_str; + CPError rv = CPB_GetCommandLineArgumentsCommon(url, &arguments_str); + if (rv == CPERR_SUCCESS) + *arguments = CPB_StringDup(CPB_Alloc, arguments_str); + return rv; +} + +CPBrowsingContext STDCALL CPB_GetBrowsingContextFromNPP(NPP npp) { + if (!npp) + return CPERR_INVALID_PARAMETER; + + NPAPI::PluginInstance* instance = + static_cast<NPAPI::PluginInstance *>(npp->ndata); + return ContextFromWebPlugin(instance->webplugin()); +} + +int STDCALL CPB_GetBrowsingContextInfo( + CPID id, CPBrowsingContext context, CPBrowsingContextInfoType type, + void* buf, uint32 buf_size) { + CHECK(ChromePluginLib::IsPluginThread()); + + switch (type) { + case CPBROWSINGCONTEXT_DATA_DIR_PTR: { + if (buf_size < sizeof(char*)) + return sizeof(char*); + + std::wstring wretval; + if (!RenderThread::current()->Send(new ViewHostMsg_GetDataDir(&wretval))) + return CPERR_FAILURE; + file_util::AppendToPath(&wretval, chrome::kChromePluginDataDirname); + *static_cast<char**>(buf) = CPB_StringDup(CPB_Alloc, WideToUTF8(wretval)); + return CPERR_SUCCESS; + } + case CPBROWSINGCONTEXT_UI_LOCALE_PTR: { + if (buf_size < sizeof(char*)) + return sizeof(char*); + + std::wstring wretval = webkit_glue::GetWebKitLocale(); + *static_cast<char**>(buf) = CPB_StringDup(CPB_Alloc, WideToUTF8(wretval)); + return CPERR_SUCCESS; + } + } + + return CPERR_FAILURE; +} + +CPError STDCALL CPB_AddUICommand(CPID id, int command) { + // Not implemented in the renderer process + return CPERR_FAILURE; +} + +CPError STDCALL CPB_HandleCommand( + CPID id, CPBrowsingContext context, int command, void *data) { + // Not implemented in the renderer process + return CPERR_FAILURE; +} + +// +// Functions related to network interception +// + +void STDCALL CPB_EnableRequestIntercept( + CPID id, const char** schemes, uint32 num_schemes) { + // We ignore requests by the plugin to intercept from this process. That's + // handled in the browser process. +} + +void STDCALL CPRR_ReceivedRedirect(CPRequest* request, const char* new_url) { + NOTREACHED() << "Network interception should not happen in renderer process."; +} + +void STDCALL CPRR_StartCompleted(CPRequest* request, CPError result) { + NOTREACHED() << "Network interception should not happen in renderer process."; +} + +void STDCALL CPRR_ReadCompleted(CPRequest* request, int bytes_read) { + NOTREACHED() << "Network interception should not happen in renderer process."; +} + +void STDCALL CPRR_UploadProgress(CPRequest* request, uint64 pos, uint64 size) { + NOTREACHED() << "Network interception should not happen in renderer process."; +} + +// +// Functions related to serving network requests to the plugin +// + +CPError STDCALL CPB_CreateRequest(CPID id, CPBrowsingContext context, + const char* method, const char* url, + CPRequest** request) { + CHECK(ChromePluginLib::IsPluginThread()); + ChromePluginLib* plugin = ChromePluginLib::FromCPID(id); + CHECK(plugin); + + WebPlugin* webplugin = WebPluginFromContext(context); + WebFrame* webframe = webplugin->GetWebFrame(); + ScopableCPRequest* cprequest = new ScopableCPRequest(url, method, context); + PluginRequestHandlerProxy* handler = + new PluginRequestHandlerProxy(plugin, cprequest, webframe); + + *request = cprequest; + return CPERR_SUCCESS; +} + +CPError STDCALL CPR_StartRequest(CPRequest* request) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + return handler->Start(); +} + +void STDCALL CPR_EndRequest(CPRequest* request, CPError reason) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + delete handler; +} + +void STDCALL CPR_SetExtraRequestHeaders(CPRequest* request, + const char* headers) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + handler->set_extra_headers(headers); +} + +void STDCALL CPR_SetRequestLoadFlags(CPRequest* request, uint32 flags) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + + if (flags & CPREQUESTLOAD_SYNCHRONOUS) { + handler->set_sync(true); + } + + uint32 net_flags = PluginResponseUtils::CPLoadFlagsToNetFlags(flags); + handler->set_load_flags(net_flags); +} + +void STDCALL CPR_AppendDataToUpload(CPRequest* request, const char* bytes, + int bytes_len) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + handler->AppendDataToUpload(bytes, bytes_len); +} + +CPError STDCALL CPR_AppendFileToUpload(CPRequest* request, const char* filepath, + uint64 offset, uint64 length) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + + if (!length) length = kuint64max; + std::wstring wfilepath(UTF8ToWide(filepath)); + handler->AppendFileRangeToUpload(wfilepath, offset, length); + return CPERR_SUCCESS; +} + +int STDCALL CPR_GetResponseInfo(CPRequest* request, CPResponseInfoType type, + void* buf, uint32 buf_size) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + return handler->GetResponseInfo(type, buf, buf_size); +} + +int STDCALL CPR_Read(CPRequest* request, void* buf, uint32 buf_size) { + CHECK(ChromePluginLib::IsPluginThread()); + PluginRequestHandlerProxy* handler = + PluginRequestHandlerProxy::FromCPRequest(request); + CHECK(handler); + return handler->Read(buf, buf_size); +} + +CPBool STDCALL CPB_IsPluginProcessRunning(CPID id) { + CHECK(ChromePluginLib::IsPluginThread()); + return true; +} + +CPProcessType STDCALL CPB_GetProcessType(CPID id) { + CHECK(ChromePluginLib::IsPluginThread()); + return CP_PROCESS_RENDERER; +} + +CPError STDCALL CPB_SendMessage(CPID id, const void *data, uint32 data_len) { + CHECK(ChromePluginLib::IsPluginThread()); + ChromePluginLib* plugin = ChromePluginLib::FromCPID(id); + CHECK(plugin); + + const uint8* data_ptr = static_cast<const uint8*>(data); + std::vector<uint8> v(data_ptr, data_ptr + data_len); + if (!RenderThread::current()->Send(new ViewHostMsg_PluginMessage( + plugin->filename(), v))) { + return CPERR_FAILURE; + } + return CPERR_SUCCESS; +} + +} // namespace + +CPBrowserFuncs* GetCPBrowserFuncsForRenderer() { + static CPBrowserFuncs browser_funcs; + static CPRequestFuncs request_funcs; + static CPResponseFuncs response_funcs; + static bool initialized = false; + if (!initialized) { + initialized = true; + + browser_funcs.size = sizeof(browser_funcs); + browser_funcs.version = CP_VERSION; + browser_funcs.enable_request_intercept = CPB_EnableRequestIntercept; + browser_funcs.create_request = CPB_CreateRequest; + browser_funcs.get_cookies = CPB_GetCookies; + browser_funcs.alloc = CPB_Alloc; + browser_funcs.free = CPB_Free; + browser_funcs.set_keep_process_alive = CPB_SetKeepProcessAlive; + browser_funcs.show_html_dialog = CPB_ShowHtmlDialog; + browser_funcs.show_html_dialog_modal = CPB_ShowHtmlDialogModal; + browser_funcs.is_plugin_process_running = CPB_IsPluginProcessRunning; + browser_funcs.get_process_type = CPB_GetProcessType; + browser_funcs.send_message = CPB_SendMessage; + browser_funcs.get_browsing_context_from_npp = CPB_GetBrowsingContextFromNPP; + browser_funcs.get_browsing_context_info = CPB_GetBrowsingContextInfo; + browser_funcs.get_command_line_arguments = CPB_GetCommandLineArguments; + browser_funcs.add_ui_command = CPB_AddUICommand; + browser_funcs.handle_command = CPB_HandleCommand; + + browser_funcs.request_funcs = &request_funcs; + browser_funcs.response_funcs = &response_funcs; + + request_funcs.size = sizeof(request_funcs); + request_funcs.start_request = CPR_StartRequest; + request_funcs.end_request = CPR_EndRequest; + request_funcs.set_extra_request_headers = CPR_SetExtraRequestHeaders; + request_funcs.set_request_load_flags = CPR_SetRequestLoadFlags; + request_funcs.append_data_to_upload = CPR_AppendDataToUpload; + request_funcs.get_response_info = CPR_GetResponseInfo; + request_funcs.read = CPR_Read; + request_funcs.append_file_to_upload = CPR_AppendFileToUpload; + + response_funcs.size = sizeof(response_funcs); + response_funcs.received_redirect = CPRR_ReceivedRedirect; + response_funcs.start_completed = CPRR_StartCompleted; + response_funcs.read_completed = CPRR_ReadCompleted; + response_funcs.upload_progress = CPRR_UploadProgress; + } + + return &browser_funcs; +} diff --git a/chrome/renderer/chrome_plugin_host.h b/chrome/renderer/chrome_plugin_host.h new file mode 100644 index 0000000..4587ded --- /dev/null +++ b/chrome/renderer/chrome_plugin_host.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef CHROME_RENDERER_CHROME_PLUGIN_HOST_H__ +#define CHROME_RENDERER_CHROME_PLUGIN_HOST_H__ + +#include "chrome/common/chrome_plugin_api.h" + +// Returns the table of browser functions for use from the renderer process. +CPBrowserFuncs* GetCPBrowserFuncsForRenderer(); + +#endif // CHROME_RENDERER_CHROME_PLUGIN_HOST_H__ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 5282cad..b37cf454 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -34,6 +34,7 @@ #include "base/shared_memory.h" #include "chrome/common/ipc_logging.h" +#include "chrome/common/notification_service.h" #include "chrome/plugin/plugin_channel.h" #include "chrome/renderer/net/render_dns_master.h" #include "chrome/renderer/render_process.h" @@ -108,6 +109,8 @@ void RenderThread::Init() { DCHECK(tls_index_) << "static initializer failed"; DCHECK(!current()) << "should only have one RenderThread per thread"; + notification_service_.reset(new NotificationService); + cache_stats_factory_.reset( new ScopedRunnableMethodFactory<RenderThread>(this)); @@ -145,6 +148,8 @@ void RenderThread::CleanUp() { IPC::Logging::current()->SetIPCSender(NULL); #endif + notification_service_.reset(); + delete visited_link_slave_; visited_link_slave_ = NULL; diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index ca022671..9463a20 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -43,6 +43,7 @@ class Task; class VisitedLinkSlave; struct WebPreferences; class RenderDnsMaster; +class NotificationService; // The RenderThread class represents a background thread where RenderView // instances live. The RenderThread supports an API that is used by its @@ -137,6 +138,8 @@ class RenderThread : public IPC::Channel::Listener, scoped_ptr<ScopedRunnableMethodFactory<RenderThread> > cache_stats_factory_; + scoped_ptr<NotificationService> notification_service_; + int in_send_; DISALLOW_EVIL_CONSTRUCTORS(RenderThread); diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 2d93886..0d57727 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -52,7 +52,9 @@ #include "chrome/common/resource_bundle.h" #include "chrome/common/text_zoom.h" #include "chrome/common/thumbnail_score.h" +#include "chrome/common/chrome_plugin_lib.h" #include "chrome/renderer/about_handler.h" +#include "chrome/renderer/chrome_plugin_host.h" #include "chrome/renderer/debug_message_handler.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/renderer_resources.h" @@ -1659,13 +1661,28 @@ WebWidget* RenderView::CreatePopupWidget(WebView* webview) { return widget->webwidget(); } +static bool ShouldLoadPluginInProcess(const std::string& mime_type, + bool* is_gears) { + if (RenderProcess::ShouldLoadPluginsInProcess()) + return true; + + if (mime_type == "application/x-googlegears") { + *is_gears = true; + CommandLine cmd; + return cmd.HasSwitch(switches::kGearsInRenderer); + } + + return false; +} + WebPluginDelegate* RenderView::CreatePluginDelegate( WebView* webview, const GURL& url, const std::string& mime_type, const std::string& clsid, std::string* actual_mime_type) { - if (RenderProcess::ShouldLoadPluginsInProcess()) { + bool is_gears = false; + if (ShouldLoadPluginInProcess(mime_type, &is_gears)) { std::wstring path; RenderThread::current()->Send( new ViewHostMsg_GetPluginPath(url, mime_type, clsid, &path, @@ -1679,6 +1696,8 @@ WebPluginDelegate* RenderView::CreatePluginDelegate( else mime_type_to_use = mime_type; + if (is_gears) + ChromePluginLib::Create(path, GetCPBrowserFuncsForRenderer()); return WebPluginDelegateImpl::Create(path, mime_type_to_use, host_window_); } diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index c04be51..cf3c0d1 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -116,6 +116,9 @@ class RenderView : public RenderWidget, public WebViewDelegate, virtual void OnMessageReceived(const IPC::Message& msg); // WebViewDelegate + virtual void ShowModalHTMLDialog(const GURL& url, int width, int height, + const std::string& json_arguments, + std::string* json_retval); virtual void RunJavaScriptAlert(WebView* webview, const std::wstring& message); virtual bool RunJavaScriptConfirm(WebView* webview, @@ -276,11 +279,6 @@ class RenderView : public RenderWidget, public WebViewDelegate, // Called when a plugin is crashed. void PluginCrashed(const std::wstring& plugin_path); - // Shows a modal HTML dialog. - void ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - std::string* json_retval); - // Called from JavaScript window.external.AddSearchProvider() to add a // keyword for a provider described in the given OpenSearch document. void AddSearchProvider(const std::string& url); diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index 7f867bd..753f517 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -162,6 +162,14 @@ > </File> <File + RelativePath=".\chrome_plugin_host.cc" + > + </File> + <File + RelativePath=".\chrome_plugin_host.h" + > + </File> + <File RelativePath=".\debug_message_handler.cc" > </File> |