1b930c3d550a63a53e0edbdee1be682c779e5a6a
[WebKit-https.git] / Source / WebCore / workers / service / ServiceWorkerJob.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ServiceWorkerJob.h"
28
29 #if ENABLE(SERVICE_WORKER)
30
31 #include "JSDOMPromiseDeferred.h"
32 #include "MIMETypeRegistry.h"
33 #include "ResourceError.h"
34 #include "ResourceResponse.h"
35 #include "ServiceWorkerJobData.h"
36 #include "ServiceWorkerRegistration.h"
37
38 namespace WebCore {
39
40 ServiceWorkerJob::ServiceWorkerJob(ServiceWorkerJobClient& client, Ref<DeferredPromise>&& promise, ServiceWorkerJobData&& jobData)
41     : m_client(client)
42     , m_jobData(WTFMove(jobData))
43     , m_promise(WTFMove(promise))
44     , m_contextIdentifier(client.contextIdentifier())
45 {
46 }
47
48 ServiceWorkerJob::~ServiceWorkerJob()
49 {
50     ASSERT(m_creationThread.ptr() == &Thread::current());
51 }
52
53 void ServiceWorkerJob::failedWithException(const Exception& exception)
54 {
55     ASSERT(m_creationThread.ptr() == &Thread::current());
56     ASSERT(!m_completed);
57
58     m_completed = true;
59     m_client->jobFailedWithException(*this, exception);
60 }
61
62 void ServiceWorkerJob::resolvedWithRegistration(ServiceWorkerRegistrationData&& data, ShouldNotifyWhenResolved shouldNotifyWhenResolved)
63 {
64     ASSERT(m_creationThread.ptr() == &Thread::current());
65     ASSERT(!m_completed);
66
67     m_completed = true;
68     m_client->jobResolvedWithRegistration(*this, WTFMove(data), shouldNotifyWhenResolved);
69 }
70
71 void ServiceWorkerJob::resolvedWithUnregistrationResult(bool unregistrationResult)
72 {
73     ASSERT(m_creationThread.ptr() == &Thread::current());
74     ASSERT(!m_completed);
75
76     m_completed = true;
77     m_client->jobResolvedWithUnregistrationResult(*this, unregistrationResult);
78 }
79
80 void ServiceWorkerJob::startScriptFetch(FetchOptions::Cache cachePolicy)
81 {
82     ASSERT(m_creationThread.ptr() == &Thread::current());
83     ASSERT(!m_completed);
84
85     m_client->startScriptFetchForJob(*this, cachePolicy);
86 }
87
88 void ServiceWorkerJob::fetchScriptWithContext(ScriptExecutionContext& context, FetchOptions::Cache cachePolicy)
89 {
90     ASSERT(m_creationThread.ptr() == &Thread::current());
91     ASSERT(!m_completed);
92
93     // FIXME: WorkerScriptLoader is the wrong loader class to use here, but there's nothing else better right now.
94     m_scriptLoader = WorkerScriptLoader::create();
95
96     ResourceRequest request { m_jobData.scriptURL };
97     request.setInitiatorIdentifier("serviceWorkerScriptLoad:");
98     request.addHTTPHeaderField(ASCIILiteral("Service-Worker"), ASCIILiteral("script"));
99
100     m_scriptLoader->loadAsynchronously(context, WTFMove(request), FetchOptions::Mode::SameOrigin, cachePolicy, ContentSecurityPolicyEnforcement::DoNotEnforce, *this);
101 }
102
103 void ServiceWorkerJob::didReceiveResponse(unsigned long, const ResourceResponse& response)
104 {
105     ASSERT(m_creationThread.ptr() == &Thread::current());
106     ASSERT(!m_completed);
107     ASSERT(m_scriptLoader);
108
109     m_lastResponse = response;
110     // Extract a MIME type from the response's header list. If this MIME type (ignoring parameters) is not a JavaScript MIME type, then:
111     if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(response.mimeType())) {
112         // Invoke Reject Job Promise with job and "SecurityError" DOMException.
113         Exception exception { SecurityError, ASCIILiteral("MIME Type is not a JavaScript MIME type") };
114         // Asynchronously complete these steps with a network error.
115         ResourceError error { errorDomainWebKitInternal, 0, response.url(), ASCIILiteral("Unexpected MIME type") };
116         m_client->jobFailedLoadingScript(*this, WTFMove(error), WTFMove(exception));
117         m_scriptLoader = nullptr;
118     }
119 }
120
121 void ServiceWorkerJob::notifyFinished()
122 {
123     ASSERT(m_creationThread.ptr() == &Thread::current());
124     ASSERT(m_scriptLoader);
125     
126     if (!m_scriptLoader->failed())
127         m_client->jobFinishedLoadingScript(*this, m_scriptLoader->script());
128     else {
129         auto& error =  m_scriptLoader->error();
130         ASSERT(!error.isNull());
131         m_client->jobFailedLoadingScript(*this, error, std::nullopt);
132     }
133
134     m_scriptLoader = nullptr;
135 }
136
137 } // namespace WebCore
138
139 #endif // ENABLE(SERVICE_WORKER)