diff options
author | dimich@google.com <dimich@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-16 00:37:09 +0000 |
---|---|---|
committer | dimich@google.com <dimich@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-16 00:37:09 +0000 |
commit | f2330fe08ed5e92b52c6c90d2230fe678e07eb17 (patch) | |
tree | 20a25568b86dfe7c59a925f8ef9b273e449532e6 | |
parent | 8b3833e7804b92c2a2fab6f91ba08367ab103bb0 (diff) | |
download | chromium_src-f2330fe08ed5e92b52c6c90d2230fe678e07eb17.zip chromium_src-f2330fe08ed5e92b52c6c90d2230fe678e07eb17.tar.gz chromium_src-f2330fe08ed5e92b52c6c90d2230fe678e07eb17.tar.bz2 |
Make XHR work in Workers. Creates a 'shadow page' in a worker process to proxy the loading requests through.
BUG=4361
TEST=none
Review URL: http://codereview.chromium.org/126070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18465 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/common/child_thread.h | 6 | ||||
-rw-r--r-- | chrome/renderer/renderer_glue.cc | 4 | ||||
-rw-r--r-- | webkit/glue/webworker_impl.cc | 96 | ||||
-rw-r--r-- | webkit/glue/webworker_impl.h | 7 |
4 files changed, 105 insertions, 8 deletions
diff --git a/chrome/common/child_thread.h b/chrome/common/child_thread.h index f612c35..cc4abaa 100644 --- a/chrome/common/child_thread.h +++ b/chrome/common/child_thread.h @@ -34,6 +34,9 @@ class ChildThread : public IPC::Channel::Listener, return resource_dispatcher_.get(); } + // Returns the one child thread. + static ChildThread* current(); + protected: friend class ChildProcess; @@ -52,9 +55,6 @@ class ChildThread : public IPC::Channel::Listener, virtual void OnControlMessageReceived(const IPC::Message& msg) { } - // Returns the one child thread. - static ChildThread* current(); - IPC::SyncChannel* channel() { return channel_.get(); } // Thread implementation. diff --git a/chrome/renderer/renderer_glue.cc b/chrome/renderer/renderer_glue.cc index be7893d..5f31444 100644 --- a/chrome/renderer/renderer_glue.cc +++ b/chrome/renderer/renderer_glue.cc @@ -225,7 +225,7 @@ ResourceLoaderBridge* ResourceLoaderBridge::Create( ResourceType::Type resource_type, int app_cache_context_id, int routing_id) { - ResourceDispatcher* dispatch = RenderThread::current()->resource_dispatcher(); + ResourceDispatcher* dispatch = ChildThread::current()->resource_dispatcher(); return dispatch->CreateBridge(method, url, first_party_for_cookies, referrer, frame_origin, main_frame_origin, headers, load_flags, origin_pid, resource_type, 0, @@ -236,7 +236,7 @@ void NotifyCacheStats() { // Update the browser about our cache // NOTE: Since this can be called from the plugin process, we might not have // a RenderThread. Do nothing in that case. - if (!IsPluginProcess()) + if (RenderThread::current()) RenderThread::current()->InformHostOfCacheStatsLater(); } diff --git a/webkit/glue/webworker_impl.cc b/webkit/glue/webworker_impl.cc index bee7f44..1328dd6 100644 --- a/webkit/glue/webworker_impl.cc +++ b/webkit/glue/webworker_impl.cc @@ -10,6 +10,7 @@ #include "KURL.h" #include "ScriptExecutionContext.h" #include "SecurityOrigin.h" +#include "SubstituteData.h" #include "WorkerContext.h" #include "WorkerThread.h" #include <wtf/MainThread.h> @@ -18,10 +19,16 @@ #undef LOG #include "base/logging.h" +#include "webkit/api/public/WebScreenInfo.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebURL.h" #include "webkit/api/public/WebWorkerClient.h" #include "webkit/glue/glue_util.h" +#include "webkit/glue/webdatasource_impl.h" +#include "webkit/glue/webframe_impl.h" +#include "webkit/glue/webpreferences.h" +#include "webkit/glue/webview.h" +#include "webkit/glue/webview_delegate.h" #include "webkit/glue/webworker_impl.h" using WebKit::WebWorker; @@ -31,6 +38,58 @@ using WebKit::WebURL; #if ENABLE(WORKERS) +// Dummy WebViewDelegate - we only need it in Worker process to load a +// 'shadow page' which will initialize WebCore loader. +class WorkerWebViewDelegate : public WebViewDelegate { + public: + WorkerWebViewDelegate() {} + virtual void AddRef() { } + virtual void Release() { } + virtual void Blur(WebWidget *webwidget) { } + virtual void CloseWidgetSoon(WebWidget *webwidget) { } + virtual void DidInvalidateRect(WebWidget *webwidget, + const WebKit::WebRect &rect) { } + virtual void DidMove(WebWidget *webwidget, const WebPluginGeometry &move) { } + virtual void DidScrollRect(WebWidget *webwidget, int dx, int dy, + const WebKit::WebRect &clip_rect) { } + virtual void Focus(WebWidget *webwidget) { } + virtual gfx::NativeViewId GetContainingView(WebWidget *webwidget) { + return gfx::NativeViewId(); + } + virtual void GetRootWindowRect(WebWidget *webwidget, + WebKit::WebRect *rect) { } + virtual void GetRootWindowResizerRect(WebWidget *webwidget, + WebKit::WebRect *rect) { } + virtual WebKit::WebScreenInfo GetScreenInfo(WebWidget *webwidget) { + WebKit::WebScreenInfo info; + return info; + } + virtual void GetWindowRect(WebWidget *webwidget, WebKit::WebRect *rect) { } + virtual bool IsHidden(WebWidget *webwidget) { return true; } + virtual void RunModal(WebWidget *webwidget) { } + virtual void SetCursor(WebWidget *webwidget, const WebCursor &cursor) { } + virtual void SetWindowRect(WebWidget *webwidget, + const WebKit::WebRect &rect) { } + virtual void Show(WebWidget *webwidget, WindowOpenDisposition disposition) { } + virtual void ShowAsPopupWithItems(WebWidget *webwidget, + const WebKit::WebRect &bounds, + int item_height, + int selected_index, + const std::vector<WebMenuItem> &items) { } + // Tell the loader to load the data into the 'shadow page' synchronously, + // so we can grab the resulting Document right after load. + virtual void DidCreateDataSource(WebFrame* frame, WebDataSource* ds) { + static_cast<WebDataSourceImpl*>(ds)->setDeferMainResourceDataLoad(false); + } + // Lazy allocate and leak this instance. + static WorkerWebViewDelegate* worker_delegate() { + static WorkerWebViewDelegate* worker_delegate = new WorkerWebViewDelegate(); + return worker_delegate; + } + private: + DISALLOW_COPY_AND_ASSIGN(WorkerWebViewDelegate); +}; + namespace WebKit { WebWorker* WebWorker::create(WebWorkerClient* client) { @@ -56,11 +115,14 @@ void InitializeWebKitStaticValues() { } } -WebWorkerImpl::WebWorkerImpl(WebWorkerClient* client) : client_(client) { +WebWorkerImpl::WebWorkerImpl(WebWorkerClient* client) + : client_(client), + web_view_(NULL) { InitializeWebKitStaticValues(); } WebWorkerImpl::~WebWorkerImpl() { + web_view_->Close(); } void WebWorkerImpl::PostMessageToWorkerContextTask( @@ -81,6 +143,33 @@ void WebWorkerImpl::PostMessageToWorkerContextTask( void WebWorkerImpl::startWorkerContext(const WebURL& script_url, const WebString& user_agent, const WebString& source_code) { + // Create 'shadow page'. This page is never displayed, it is used to proxy the + // loading requests from the worker context to the rest of WebKit and Chromium + // infrastructure. + DCHECK(!web_view_); + web_view_ = WebView::Create(WorkerWebViewDelegate::worker_delegate(), + WebPreferences()); + + WebFrameImpl* web_frame = + static_cast<WebFrameImpl*>(web_view_->GetMainFrame()); + + // Construct substitute data source for the 'shadow page'. We only need it + // to have same origin as the worker so the loading checks work correctly. + WebCore::CString content("Shadow page"); + int len = static_cast<int>(content.length()); + RefPtr<WebCore::SharedBuffer> buf( + WebCore::SharedBuffer::create(content.data(), len)); + WebCore::SubstituteData subst_data(buf, + WebCore::String("text/html"), + WebCore::String("UTF-8"), + WebCore::KURL()); + WebCore::ResourceRequest request(webkit_glue::GURLToKURL(script_url), + WebCore::CString()); + web_frame->frame()->loader()->load(request, subst_data, false); + + // This document will be used as 'loading context' for the worker. + loading_document_ = web_frame->frame()->document(); + worker_thread_ = WebCore::WorkerThread::create( webkit_glue::WebURLToKURL(script_url), webkit_glue::WebStringToString(user_agent), @@ -235,13 +324,14 @@ void WebWorkerImpl::workerContextDestroyed() { void WebWorkerImpl::postTaskToLoader( PassRefPtr<WebCore::ScriptExecutionContext::Task> task) { - NOTIMPLEMENTED(); + ASSERT(loading_document_->isDocument()); + loading_document_->postTask(task); } void WebWorkerImpl::postTaskForModeToWorkerContext( PassRefPtr<WebCore::ScriptExecutionContext::Task> task, const WebCore::String& mode) { - NOTIMPLEMENTED(); + worker_thread_->runLoop().postTaskForMode(task, mode); } void WebWorkerImpl::WorkerContextDestroyedTask( diff --git a/webkit/glue/webworker_impl.h b/webkit/glue/webworker_impl.h index 8c87d48..db12c09 100644 --- a/webkit/glue/webworker_impl.h +++ b/webkit/glue/webworker_impl.h @@ -19,6 +19,8 @@ class Strng; class WorkerThread; }; +class WebView; + // This class is used by the worker process code to talk to the WebCore::Worker // implementation. It can't use it directly since it uses WebKit types, so this // class converts the data types. When the WebCore::Worker object wants to call @@ -113,6 +115,11 @@ class WebWorkerImpl: public WebCore::WorkerObjectProxy, WebWorkerImpl* this_ptr); WebKit::WebWorkerClient* client_; + + // 'shadow page' - created to proxy loading requests from the worker. + WTF::RefPtr<WebCore::ScriptExecutionContext> loading_document_; + WebView* web_view_; + WTF::RefPtr<WebCore::WorkerThread> worker_thread_; DISALLOW_COPY_AND_ASSIGN(WebWorkerImpl); |