*/
#include "config.h"
-#include "WebSharedWorkerImpl.h"
-
-#include "DatabaseClientImpl.h"
-#include "LocalFileSystemClient.h"
-#include "WebDataSourceImpl.h"
-#include "WebFrame.h"
-#include "WebFrameImpl.h"
-#include "WebRuntimeFeatures.h"
-#include "WebSettings.h"
-#include "WebView.h"
-#include "WorkerPermissionClient.h"
+#include "web/WebSharedWorkerImpl.h"
+
+#include "RuntimeEnabledFeatures.h"
#include "core/dom/CrossThreadTask.h"
#include "core/dom/Document.h"
#include "core/events/MessageEvent.h"
#include "core/html/HTMLFormElement.h"
+#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/WorkerDebuggerAgent.h"
#include "core/inspector/WorkerInspectorController.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoader.h"
#include "core/page/Page.h"
-#include "core/page/PageGroup.h"
#include "core/workers/SharedWorkerGlobalScope.h"
#include "core/workers/SharedWorkerThread.h"
#include "core/workers/WorkerClients.h"
#include "core/workers/WorkerGlobalScope.h"
+#include "core/workers/WorkerScriptLoader.h"
#include "core/workers/WorkerThreadStartupData.h"
#include "modules/webdatabase/DatabaseTask.h"
+#include "platform/heap/Handle.h"
+#include "platform/network/ContentSecurityPolicyParsers.h"
+#include "platform/network/ResourceResponse.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/WebFileError.h"
#include "public/platform/WebMessagePortChannel.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"
+#include "public/web/WebFrame.h"
+#include "public/web/WebSettings.h"
+#include "public/web/WebView.h"
#include "public/web/WebWorkerPermissionClientProxy.h"
+#include "web/DatabaseClientImpl.h"
+#include "web/LocalFileSystemClient.h"
+#include "web/WebDataSourceImpl.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/WorkerPermissionClient.h"
#include "wtf/Functional.h"
#include "wtf/MainThread.h"
namespace blink {
+// A thin wrapper for one-off script loading.
+class WebSharedWorkerImpl::Loader : public WorkerScriptLoaderClient {
+public:
+ static PassOwnPtr<Loader> create()
+ {
+ return adoptPtr(new Loader());
+ }
+
+ virtual ~Loader()
+ {
+ m_scriptLoader->setClient(0);
+ }
+
+ void load(ExecutionContext* loadingContext, const KURL& scriptURL, const Closure& receiveResponseCallback, const Closure& finishCallback)
+ {
+ ASSERT(loadingContext);
+ m_receiveResponseCallback = receiveResponseCallback;
+ m_finishCallback = finishCallback;
+ m_scriptLoader->setTargetType(ResourceRequest::TargetIsSharedWorker);
+ m_scriptLoader->loadAsynchronously(
+ *loadingContext, scriptURL, DenyCrossOriginRequests, this);
+ }
+
+ void didReceiveResponse(unsigned long identifier, const ResourceResponse& response) OVERRIDE
+ {
+ m_identifier = identifier;
+ m_appCacheID = response.appCacheID();
+ m_receiveResponseCallback();
+ }
+
+ virtual void notifyFinished() OVERRIDE
+ {
+ m_finishCallback();
+ }
+
+ void cancel()
+ {
+ m_scriptLoader->cancel();
+ }
+
+ bool failed() const { return m_scriptLoader->failed(); }
+ const KURL& url() const { return m_scriptLoader->responseURL(); }
+ String script() const { return m_scriptLoader->script(); }
+ unsigned long identifier() const { return m_identifier; }
+ long long appCacheID() const { return m_appCacheID; }
+
+private:
+ Loader() : m_scriptLoader(WorkerScriptLoader::create()), m_identifier(0), m_appCacheID(0)
+ {
+ }
+
+ RefPtr<WorkerScriptLoader> m_scriptLoader;
+ unsigned long m_identifier;
+ long long m_appCacheID;
+ Closure m_receiveResponseCallback;
+ Closure m_finishCallback;
+};
+
// This function is called on the main thread to force to initialize some static
// values used in WebKit before any worker thread is started. This is because in
// our worker processs, we do not run any WebKit code in main thread and thus
, m_client(WeakReference<WebSharedWorkerClient>::create(client))
, m_clientWeakPtr(WeakPtr<WebSharedWorkerClient>(m_client))
, m_pauseWorkerContextOnStart(false)
+ , m_attachDevToolsOnStart(false)
{
initializeWebKitStaticValues();
}
{
ASSERT(m_webView);
// Detach the client before closing the view to avoid getting called back.
- toWebFrameImpl(m_mainFrame)->setClient(0);
+ toWebLocalFrameImpl(m_mainFrame)->setClient(0);
m_webView->close();
m_mainFrame->close();
if (m_askedToTerminate)
return;
m_askedToTerminate = true;
+ if (m_mainScriptLoader)
+ m_mainScriptLoader->cancel();
if (m_workerThread)
m_workerThread->stop();
}
// infrastructure.
ASSERT(!m_webView);
m_webView = WebView::create(0);
- m_webView->settings()->setOfflineWebApplicationCacheEnabled(WebRuntimeFeatures::isApplicationCacheEnabled());
+ m_webView->settings()->setOfflineWebApplicationCacheEnabled(RuntimeEnabledFeatures::applicationCacheEnabled());
// FIXME: Settings information should be passed to the Worker process from Browser process when the worker
// is created (similar to RenderThread::OnCreateNewView).
- m_mainFrame = WebFrame::create(this);
+ m_mainFrame = WebLocalFrame::create(this);
m_webView->setMainFrame(m_mainFrame);
- WebFrameImpl* webFrame = toWebFrameImpl(m_webView->mainFrame());
+ WebLocalFrameImpl* webFrame = toWebLocalFrameImpl(m_webView->mainFrame());
// 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.
webFrame->frame()->loader().load(FrameLoadRequest(0, ResourceRequest(url), SubstituteData(buffer, "text/html", "UTF-8", KURL())));
}
-WebApplicationCacheHost* WebSharedWorkerImpl::createApplicationCacheHost(WebFrame*, WebApplicationCacheHostClient* appcacheHostClient)
+WebApplicationCacheHost* WebSharedWorkerImpl::createApplicationCacheHost(WebLocalFrame*, WebApplicationCacheHostClient* appcacheHostClient)
{
if (client())
return client()->createApplicationCacheHost(appcacheHostClient);
return 0;
}
+void WebSharedWorkerImpl::didFinishDocumentLoad(WebLocalFrame* frame)
+{
+ ASSERT(!m_loadingDocument);
+ ASSERT(!m_mainScriptLoader);
+ m_mainScriptLoader = Loader::create();
+ m_loadingDocument = toWebLocalFrameImpl(frame)->frame()->document();
+ m_mainScriptLoader->load(
+ m_loadingDocument.get(),
+ m_url,
+ bind(&WebSharedWorkerImpl::didReceiveScriptLoaderResponse, this),
+ bind(&WebSharedWorkerImpl::onScriptLoaderFinished, this));
+}
+
// WorkerReportingProxy --------------------------------------------------------
void WebSharedWorkerImpl::reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL)
void WebSharedWorkerImpl::postMessageToPageInspector(const String& message)
{
- callOnMainThread(bind(&WebSharedWorkerClient::dispatchDevToolsMessage, m_clientWeakPtr, message.isolatedCopy()));
+ // Note that we need to keep the closure creation on a separate line so
+ // that the temporary created by isolatedCopy() will always be destroyed
+ // before the copy in the closure is used on the main thread.
+ const Closure& boundFunction = bind(&WebSharedWorkerClient::dispatchDevToolsMessage, m_clientWeakPtr, message.isolatedCopy());
+ callOnMainThread(boundFunction);
}
void WebSharedWorkerImpl::updateInspectorStateCookie(const String& cookie)
{
- callOnMainThread(bind(&WebSharedWorkerClient::saveDevToolsAgentState, m_clientWeakPtr, cookie.isolatedCopy()));
+ // Note that we need to keep the closure creation on a separate line so
+ // that the temporary created by isolatedCopy() will always be destroyed
+ // before the copy in the closure is used on the main thread.
+ const Closure& boundFunction = bind(&WebSharedWorkerClient::saveDevToolsAgentState, m_clientWeakPtr, cookie.isolatedCopy());
+ callOnMainThread(boundFunction);
}
void WebSharedWorkerImpl::workerGlobalScopeClosed()
void WebSharedWorkerImpl::postTaskToLoader(PassOwnPtr<ExecutionContextTask> task)
{
- toWebFrameImpl(m_mainFrame)->frame()->document()->postTask(task);
+ toWebLocalFrameImpl(m_mainFrame)->frame()->document()->postTask(task);
}
-bool WebSharedWorkerImpl::postTaskForModeToWorkerGlobalScope(
- PassOwnPtr<ExecutionContextTask> task, const String& mode)
+bool WebSharedWorkerImpl::postTaskToWorkerGlobalScope(PassOwnPtr<ExecutionContextTask> task)
{
- m_workerThread->runLoop().postTaskForMode(task, mode);
+ m_workerThread->runLoop().postTask(task);
return true;
}
workerGlobalScope->dispatchEvent(createConnectEvent(port));
}
-void WebSharedWorkerImpl::startWorkerContext(const WebURL& url, const WebString& name, const WebString& userAgent, const WebString& sourceCode, const WebString& contentSecurityPolicy, WebContentSecurityPolicyType policyType, long long)
+void WebSharedWorkerImpl::startWorkerContext(const WebURL& url, const WebString& name, const WebString& contentSecurityPolicy, WebContentSecurityPolicyType policyType)
{
+ m_url = url;
+ m_name = name;
+ m_contentSecurityPolicy = contentSecurityPolicy;
+ m_policyType = policyType;
initializeLoader(url);
+}
+
+void WebSharedWorkerImpl::didReceiveScriptLoaderResponse()
+{
+ InspectorInstrumentation::didReceiveScriptResponse(m_loadingDocument.get(), m_mainScriptLoader->identifier());
+ if (client())
+ client()->selectAppCacheID(m_mainScriptLoader->appCacheID());
+}
+
+static void connectToWorkerContextInspectorTask(ExecutionContext* context, bool)
+{
+ toWorkerGlobalScope(context)->workerInspectorController()->connectFrontend();
+}
+void WebSharedWorkerImpl::onScriptLoaderFinished()
+{
+ ASSERT(m_loadingDocument);
+ ASSERT(m_mainScriptLoader);
+ if (m_mainScriptLoader->failed() || m_askedToTerminate) {
+ m_mainScriptLoader.clear();
+ if (client())
+ client()->workerScriptLoadFailed();
+ return;
+ }
WorkerThreadStartMode startMode = m_pauseWorkerContextOnStart ? PauseWorkerGlobalScopeOnStart : DontPauseWorkerGlobalScopeOnStart;
- OwnPtr<WorkerClients> workerClients = WorkerClients::create();
+ OwnPtrWillBeRawPtr<WorkerClients> workerClients = WorkerClients::create();
provideLocalFileSystemToWorker(workerClients.get(), LocalFileSystemClient::create());
provideDatabaseClientToWorker(workerClients.get(), DatabaseClientImpl::create());
- // We can't get the SecurityOrigin from the Document, because the Document will be created asynchronously.
- // Normally it's not safe to create a new SecurityOrigin from the same url and assume it will be the same, but the
- // cases where that's risky aren't applicable here. They involve being in an iframe (e.g., sandbox origin or
- // about:blank in a new iframe), and this codepath is always working with a main frame.
- WebSecurityOrigin webSecurityOrigin = WebSecurityOrigin::create(url);
+ WebSecurityOrigin webSecurityOrigin(m_loadingDocument->securityOrigin());
providePermissionClientToWorker(workerClients.get(), adoptPtr(client()->createWorkerPermissionClientProxy(webSecurityOrigin)));
- OwnPtr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create(url, userAgent, sourceCode, startMode, contentSecurityPolicy, static_cast<WebCore::ContentSecurityPolicy::HeaderType>(policyType), workerClients.release());
- setWorkerThread(SharedWorkerThread::create(name, *this, *this, startupData.release()));
+ OwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create(m_url, m_loadingDocument->userAgent(m_url), m_mainScriptLoader->script(), startMode, m_contentSecurityPolicy, static_cast<WebCore::ContentSecurityPolicyHeaderType>(m_policyType), workerClients.release());
+ setWorkerThread(SharedWorkerThread::create(m_name, *this, *this, startupData.release()));
+ InspectorInstrumentation::scriptImported(m_loadingDocument.get(), m_mainScriptLoader->identifier(), m_mainScriptLoader->script());
+ m_mainScriptLoader.clear();
+
+ if (m_attachDevToolsOnStart)
+ workerThread()->runLoop().postDebuggerTask(createCallbackTask(connectToWorkerContextInspectorTask, true));
workerThread()->start();
- // FIXME(horo): This call will be moved when we implement script loading in WebSharedWorkerImpl.
if (client())
client()->workerScriptLoaded();
}
{
m_pauseWorkerContextOnStart = false;
if (workerThread())
- workerThread()->runLoop().postTaskForMode(createCallbackTask(resumeWorkerContextTask, true), WorkerDebuggerAgent::debuggerTaskMode);
-}
-
-static void connectToWorkerContextInspectorTask(ExecutionContext* context, bool)
-{
- toWorkerGlobalScope(context)->workerInspectorController()->connectFrontend();
+ workerThread()->runLoop().postDebuggerTask(createCallbackTask(resumeWorkerContextTask, true));
}
void WebSharedWorkerImpl::attachDevTools()
{
- workerThread()->runLoop().postTaskForMode(createCallbackTask(connectToWorkerContextInspectorTask, true), WorkerDebuggerAgent::debuggerTaskMode);
+ if (workerThread())
+ workerThread()->runLoop().postDebuggerTask(createCallbackTask(connectToWorkerContextInspectorTask, true));
+ else
+ m_attachDevToolsOnStart = true;
}
static void reconnectToWorkerContextInspectorTask(ExecutionContext* context, const String& savedState)
void WebSharedWorkerImpl::reattachDevTools(const WebString& savedState)
{
- workerThread()->runLoop().postTaskForMode(createCallbackTask(reconnectToWorkerContextInspectorTask, String(savedState)), WorkerDebuggerAgent::debuggerTaskMode);
+ workerThread()->runLoop().postDebuggerTask(createCallbackTask(reconnectToWorkerContextInspectorTask, String(savedState)));
}
static void disconnectFromWorkerContextInspectorTask(ExecutionContext* context, bool)
void WebSharedWorkerImpl::detachDevTools()
{
- workerThread()->runLoop().postTaskForMode(createCallbackTask(disconnectFromWorkerContextInspectorTask, true), WorkerDebuggerAgent::debuggerTaskMode);
+ m_attachDevToolsOnStart = false;
+ workerThread()->runLoop().postDebuggerTask(createCallbackTask(disconnectFromWorkerContextInspectorTask, true));
}
static void dispatchOnInspectorBackendTask(ExecutionContext* context, const String& message)
void WebSharedWorkerImpl::dispatchDevToolsMessage(const WebString& message)
{
- workerThread()->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode);
+ workerThread()->runLoop().postDebuggerTask(createCallbackTask(dispatchOnInspectorBackendTask, String(message)));
WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(workerThread());
}