Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebSharedWorkerImpl.cpp
index 0a0b1c9..8abbaa7 100644 (file)
  */
 
 #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"
 
@@ -70,6 +74,64 @@ using namespace WebCore;
 
 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
@@ -95,6 +157,7 @@ WebSharedWorkerImpl::WebSharedWorkerImpl(WebSharedWorkerClient* client)
     , m_client(WeakReference<WebSharedWorkerClient>::create(client))
     , m_clientWeakPtr(WeakPtr<WebSharedWorkerClient>(m_client))
     , m_pauseWorkerContextOnStart(false)
+    , m_attachDevToolsOnStart(false)
 {
     initializeWebKitStaticValues();
 }
@@ -103,7 +166,7 @@ WebSharedWorkerImpl::~WebSharedWorkerImpl()
 {
     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();
@@ -114,6 +177,8 @@ void WebSharedWorkerImpl::stopWorkerThread()
     if (m_askedToTerminate)
         return;
     m_askedToTerminate = true;
+    if (m_mainScriptLoader)
+        m_mainScriptLoader->cancel();
     if (m_workerThread)
         m_workerThread->stop();
 }
@@ -125,13 +190,13 @@ void WebSharedWorkerImpl::initializeLoader(const WebURL& url)
     // 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.
@@ -141,13 +206,26 @@ void WebSharedWorkerImpl::initializeLoader(const WebURL& url)
     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)
@@ -162,12 +240,20 @@ void WebSharedWorkerImpl::reportConsoleMessage(MessageSource source, MessageLeve
 
 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()
@@ -204,13 +290,12 @@ void WebSharedWorkerImpl::workerGlobalScopeDestroyedOnMainThread()
 
 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;
 }
 
@@ -230,25 +315,52 @@ void WebSharedWorkerImpl::connectTask(ExecutionContext* context, PassOwnPtr<WebM
     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();
 }
@@ -277,17 +389,15 @@ void WebSharedWorkerImpl::resumeWorkerContext()
 {
     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)
@@ -299,7 +409,7 @@ static void reconnectToWorkerContextInspectorTask(ExecutionContext* context, con
 
 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)
@@ -309,7 +419,8 @@ static void disconnectFromWorkerContextInspectorTask(ExecutionContext* context,
 
 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)
@@ -319,7 +430,7 @@ static void dispatchOnInspectorBackendTask(ExecutionContext* context, const Stri
 
 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());
 }