Source/WebCore/ChangeLog

 12017-08-30 Brady Eidson <beidson@apple.com>
 2
 3 Implement all of "Register" right up until where the script is fetched.
 4 https://bugs.webkit.org/show_bug.cgi?id=176082
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Test: http/tests/workers/service/basic-register-exceptions.html
 9
 10 This patch implements every detail of the "Register" and "Update" algorithms right up to
 11 where we would actually fetch the service worker script file.
 12
 13 It also includes miscellaneous refactoring and cleanup along the way.
 14
 15 * CMakeLists.txt:
 16 * WebCore.xcodeproj/project.pbxproj:
 17
 18 * page/SecurityOrigin.cpp:
 19 (WebCore::shouldTreatAsPotentiallyTrustworthy): Expose in the header for other files to use.
 20 * page/SecurityOrigin.h:
 21
 22 * workers/service/ServiceWorkerContainer.cpp:
 23 (WebCore::ServiceWorkerContainer::addRegistration): Add some more exception cases from the spec.
 24 (WebCore::ServiceWorkerContainer::scheduleJob): Use the correct job identifier.
 25 (WebCore::ServiceWorkerContainer::jobFailedWithException):
 26 (WebCore::ServiceWorkerContainer::jobResolvedWithRegistration):
 27 (WebCore::ServiceWorkerContainer::jobDidFinish):
 28 * workers/service/ServiceWorkerContainer.h:
 29
 30 * workers/service/ServiceWorkerJob.cpp:
 31 (WebCore::ServiceWorkerJob::ServiceWorkerJob):
 32 (WebCore::ServiceWorkerJob::failedWithException): Call through to the client to handle the failure.
 33 (WebCore::ServiceWorkerJob::resolvedWithRegistration): Call through to the client to handle success.
 34 * workers/service/ServiceWorkerJob.h:
 35 (WebCore::ServiceWorkerJob::promise):
 36 (WebCore::ServiceWorkerJob::identifier const): Deleted. Rely on the identifier from the JobData.
 37
 38 * workers/service/ServiceWorkerJobClient.h:
 39
 40 * workers/service/ServiceWorkerJobData.cpp:
 41 (WebCore::ServiceWorkerJobData::ServiceWorkerJobData):
 42 (WebCore::ServiceWorkerJobData::isolatedCopy const):
 43 * workers/service/ServiceWorkerJobData.h:
 44 (WebCore::ServiceWorkerJobData::identifier const):
 45 (WebCore::ServiceWorkerJobData::encode const):
 46 (WebCore::ServiceWorkerJobData::decode):
 47 (WebCore::ServiceWorkerJobData::jobIdentifier const): Deleted.
 48
 49 * workers/service/ServiceWorkerRegistration.cpp:
 50 (WebCore::ServiceWorkerRegistration::ServiceWorkerRegistration): Make this class an ActiveDOMObject
 51 both because it *is* an active DOM object and because we need to get at the ScriptExecutionContext.
 52 * workers/service/ServiceWorkerRegistration.h:
 53
 54 Add a class to encapsulate everything about a registration for encode/decode/crossthread:
 55 * workers/service/ServiceWorkerRegistrationData.cpp:
 56 (WebCore::ServiceWorkerRegistrationData::isolatedCopy const):
 57 * workers/service/ServiceWorkerRegistrationData.h:
 58 (WebCore::ServiceWorkerRegistrationData::encode const):
 59 (WebCore::ServiceWorkerRegistrationData::decode):
 60
 61 * workers/service/ServiceWorkerRegistrationKey.cpp:
 62 (WebCore::ServiceWorkerRegistrationKey::isolatedCopy const):
 63 * workers/service/ServiceWorkerRegistrationKey.h:
 64 (WebCore::ServiceWorkerRegistrationKey::encode const):
 65 (WebCore::ServiceWorkerRegistrationKey::decode):
 66
 67 * workers/service/server/SWClientConnection.cpp:
 68 (WebCore::SWClientConnection::scheduleJob):
 69 (WebCore::SWClientConnection::jobResolvedInServer):
 70 * workers/service/server/SWClientConnection.h:
 71
 72 * workers/service/server/SWServer.cpp:
 73 (WebCore::SWServer::~SWServer):
 74 (WebCore::SWServer::Connection::scheduleJobInServer):
 75 (WebCore::SWServer::scheduleJob):
 76 (WebCore::SWServer::rejectJob):
 77 (WebCore::SWServer::resolveJob):
 78 * workers/service/server/SWServer.h:
 79
 80 * workers/service/server/SWServerRegistration.cpp:
 81 (WebCore::SWServerRegistration::SWServerRegistration):
 82 (WebCore::SWServerRegistration::startNextJob):
 83 (WebCore::SWServerRegistration::isEmpty):
 84 (WebCore::SWServerRegistration::getNewestWorker): Implement "Get Newest Worker" algorithm.
 85 (WebCore::SWServerRegistration::runRegisterJob): Implement the rest of the "Register" algorithm.
 86 (WebCore::SWServerRegistration::runUpdateJob): Implement every part of "Update" up to where we would fetch.
 87 (WebCore::SWServerRegistration::rejectWithExceptionOnMainThread):
 88 (WebCore::SWServerRegistration::resolveWithRegistrationOnMainThread):
 89 (WebCore::SWServerRegistration::resolveCurrentJob):
 90 (WebCore::SWServerRegistration::data const):
 91 (WebCore::SWServerRegistration::performCurrentJob): Deleted.
 92 * workers/service/server/SWServerRegistration.h:
 93 (WebCore::SWServerRegistration::identifier const):
 94
 95 Add a stub class to represent "active service workers" in the SWServer:
 96 * workers/service/server/SWServerWorker.cpp:
 97 (WebCore::SWServerWorker::SWServerWorker):
 98 (WebCore::SWServerWorker::~SWServerWorker):
 99 * workers/service/server/SWServerWorker.h:
 100 (WebCore::SWServerWorker::scriptURL const):
 101
11022017-08-29 Wenson Hsieh <wenson_hsieh@apple.com>
2103
3104 REGRESSION(r210287) On drop, event.dataTransfer.getData("text") returns an empty string when dragging an image

Source/WebKit/ChangeLog

 12017-08-30 Brady Eidson <beidson@apple.com>
 2
 3 Implement all of "Register" right up until where the script is fetched.
 4 https://bugs.webkit.org/show_bug.cgi?id=176082
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * StorageProcess/ServiceWorker/WebSWServerConnection.cpp:
 9 (WebKit::WebSWServerConnection::resolveJobInClient):
 10 * StorageProcess/ServiceWorker/WebSWServerConnection.h:
 11 * WebProcess/Storage/WebSWClientConnection.messages.in:
 12
1132017-08-30 Carlos Alberto Lopez Perez <clopez@igalia.com>
214
315 [WPE] Enable MEMORY_SAMPLER

Source/WebCore/CMakeLists.txt

@@set(WebCore_SOURCES
30193019 workers/service/ServiceWorkerJobData.cpp
30203020 workers/service/ServiceWorkerProvider.cpp
30213021 workers/service/ServiceWorkerRegistration.cpp
 3022 workers/service/ServiceWorkerRegistrationData.cpp
30223023 workers/service/ServiceWorkerRegistrationKey.cpp
30233024 workers/service/ServiceWorkerRegistrationOptions.cpp
30243025
30253026 workers/service/server/SWClientConnection.cpp
30263027 workers/service/server/SWServer.cpp
30273028 workers/service/server/SWServerRegistration.cpp
 3029 workers/service/server/SWServerWorker.cpp
30283030
30293031 xml/DOMParser.cpp
30303032 xml/NativeXPathNSResolver.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

23012301 517A53251F4B905500DCDC0A /* ServiceWorkerJobData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517A53241F4B904A00DCDC0A /* ServiceWorkerJobData.cpp */; };
23022302 517A53281F4B90B900DCDC0A /* ServiceWorkerRegistrationKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517A53271F4B90B200DCDC0A /* ServiceWorkerRegistrationKey.cpp */; };
23032303 517A53291F4B90B900DCDC0A /* ServiceWorkerRegistrationKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 517A53261F4B90B200DCDC0A /* ServiceWorkerRegistrationKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2304 517A53451F50C17F00DCDC0A /* SWServerWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517A53431F50C16100DCDC0A /* SWServerWorker.cpp */; };
 2305 517A53461F50C17F00DCDC0A /* SWServerWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 517A53421F50C16100DCDC0A /* SWServerWorker.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2306 517A534E1F54A8BA00DCDC0A /* ServiceWorkerRegistrationData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517A534B1F549D4A00DCDC0A /* ServiceWorkerRegistrationData.cpp */; };
 2307 517A534F1F54A8BA00DCDC0A /* ServiceWorkerRegistrationData.h in Headers */ = {isa = PBXBuildFile; fileRef = 517A534C1F549D4A00DCDC0A /* ServiceWorkerRegistrationData.h */; settings = {ATTRIBUTES = (Private, ); }; };
23042308 517A63C31B74318700E7DCDC /* KeyedDecoderCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517A63BF1B74317E00E7DCDC /* KeyedDecoderCF.cpp */; };
23052309 517A63C41B74318B00E7DCDC /* KeyedEncoderCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517A63C11B74317E00E7DCDC /* KeyedEncoderCF.cpp */; };
23062310 517A63C51B74318F00E7DCDC /* KeyedDecoderCF.h in Headers */ = {isa = PBXBuildFile; fileRef = 517A63C01B74317E00E7DCDC /* KeyedDecoderCF.h */; settings = {ATTRIBUTES = (Private, ); }; };

1012210126 517A53241F4B904A00DCDC0A /* ServiceWorkerJobData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerJobData.cpp; sourceTree = "<group>"; };
1012310127 517A53261F4B90B200DCDC0A /* ServiceWorkerRegistrationKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerRegistrationKey.h; sourceTree = "<group>"; };
1012410128 517A53271F4B90B200DCDC0A /* ServiceWorkerRegistrationKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerRegistrationKey.cpp; sourceTree = "<group>"; };
 10129 517A53421F50C16100DCDC0A /* SWServerWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWServerWorker.h; sourceTree = "<group>"; };
 10130 517A53431F50C16100DCDC0A /* SWServerWorker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWServerWorker.cpp; sourceTree = "<group>"; };
 10131 517A534B1F549D4A00DCDC0A /* ServiceWorkerRegistrationData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerRegistrationData.cpp; sourceTree = "<group>"; };
 10132 517A534C1F549D4A00DCDC0A /* ServiceWorkerRegistrationData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerRegistrationData.h; sourceTree = "<group>"; };
1012510133 517A63BF1B74317E00E7DCDC /* KeyedDecoderCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyedDecoderCF.cpp; sourceTree = "<group>"; };
1012610134 517A63C01B74317E00E7DCDC /* KeyedDecoderCF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyedDecoderCF.h; sourceTree = "<group>"; };
1012710135 517A63C11B74317E00E7DCDC /* KeyedEncoderCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyedEncoderCF.cpp; sourceTree = "<group>"; };

1875818766 517A52EE1F47535900DCDC0A /* SWServer.h */,
1875918767 51F645951F4A686100B54DED /* SWServerRegistration.cpp */,
1876018768 51F645941F4A684F00B54DED /* SWServerRegistration.h */,
 18769 517A53431F50C16100DCDC0A /* SWServerWorker.cpp */,
 18770 517A53421F50C16100DCDC0A /* SWServerWorker.h */,
1876118771 );
1876218772 path = server;
1876318773 sourceTree = "<group>";

1886318873 51F1754D1F3EBC0C00C74950 /* ServiceWorkerRegistration.cpp */,
1886418874 51F1754C1F3EBC0C00C74950 /* ServiceWorkerRegistration.h */,
1886518875 51F1754B1F3EBC0C00C74950 /* ServiceWorkerRegistration.idl */,
 18876 517A534B1F549D4A00DCDC0A /* ServiceWorkerRegistrationData.cpp */,
 18877 517A534C1F549D4A00DCDC0A /* ServiceWorkerRegistrationData.h */,
1886618878 517A53271F4B90B200DCDC0A /* ServiceWorkerRegistrationKey.cpp */,
1886718879 517A53261F4B90B200DCDC0A /* ServiceWorkerRegistrationKey.h */,
1886818880 51F645A01F4BF51600B54DED /* ServiceWorkerRegistrationOptions.cpp */,

2970929721 51F6456A1F4539C000B54DED /* ServiceWorkerJobType.h in Headers */,
2971029722 51F175661F3EBC8300C74950 /* ServiceWorkerProvider.h in Headers */,
2971129723 51F175681F3EBC8300C74950 /* ServiceWorkerRegistration.h in Headers */,
 29724 517A534F1F54A8BA00DCDC0A /* ServiceWorkerRegistrationData.h in Headers */,
2971229725 517A53291F4B90B900DCDC0A /* ServiceWorkerRegistrationKey.h in Headers */,
2971329726 51F175691F3EBC8300C74950 /* ServiceWorkerRegistrationOptions.h in Headers */,
2971429727 51F1756C1F3EBC8300C74950 /* ServiceWorkerUpdateViaCache.h in Headers */,

3013030143 517A531D1F4B53B100DCDC0A /* SWClientConnection.h in Headers */,
3013130144 517A52F01F47535B00DCDC0A /* SWServer.h in Headers */,
3013230145 51F645971F4A686F00B54DED /* SWServerRegistration.h in Headers */,
 30146 517A53461F50C17F00DCDC0A /* SWServerWorker.h in Headers */,
3013330147 E180811716FCF9CB00B80D07 /* SynchronousLoaderClient.h in Headers */,
3013430148 26FAE4CF1852E3A5004C8C46 /* SynchronousResourceHandleCFURLConnectionDelegate.h in Headers */,
3013530149 0F03C0741884695E00A5F8CA /* SystemMemory.h in Headers */,

3360033614 517A53251F4B905500DCDC0A /* ServiceWorkerJobData.cpp in Sources */,
3360133615 51F175651F3EBC8300C74950 /* ServiceWorkerProvider.cpp in Sources */,
3360233616 51F175671F3EBC8300C74950 /* ServiceWorkerRegistration.cpp in Sources */,
 33617 517A534E1F54A8BA00DCDC0A /* ServiceWorkerRegistrationData.cpp in Sources */,
3360333618 517A53281F4B90B900DCDC0A /* ServiceWorkerRegistrationKey.cpp in Sources */,
3360433619 51F645A21F4BF53C00B54DED /* ServiceWorkerRegistrationOptions.cpp in Sources */,
3360533620 93309E0F099E64920056E581 /* SetNodeAttributeCommand.cpp in Sources */,

3390733922 517A531C1F4B53B100DCDC0A /* SWClientConnection.cpp in Sources */,
3390833923 517A52F11F4754E700DCDC0A /* SWServer.cpp in Sources */,
3390933924 51F645961F4A686F00B54DED /* SWServerRegistration.cpp in Sources */,
 33925 517A53451F50C17F00DCDC0A /* SWServerWorker.cpp in Sources */,
3391033926 E180811216FCF42F00B80D07 /* SynchronousLoaderClient.cpp in Sources */,
3391133927 E180811616FCF9CB00B80D07 /* SynchronousLoaderClient.mm in Sources */,
3391233928 442ABCD617D9262F00D30715 /* SynchronousLoaderClientCFNet.cpp in Sources */,

Source/WebCore/page/SecurityOrigin.cpp

@@static bool isLoopbackIPAddress(const URL& url)
123123}
124124
125125// https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy (Editor's Draft, 17 November 2016)
126 static bool shouldTreatAsPotentiallyTrustworthy(const URL& url)
 126bool shouldTreatAsPotentiallyTrustworthy(const URL& url)
127127{
128128 if (!url.isValid())
129129 return false;

Source/WebCore/page/SecurityOrigin.h

@@private:
234234 bool m_isPotentiallyTrustworthy { false };
235235};
236236
 237bool shouldTreatAsPotentiallyTrustworthy(const URL&);
 238
237239// Returns true if the Origin header values serialized from these two origins would be the same.
238240bool originsMatch(const SecurityOrigin&, const SecurityOrigin&);
239241bool originsMatch(const SecurityOrigin*, const SecurityOrigin*);

Source/WebCore/workers/service/ServiceWorkerContainer.cpp

2929#if ENABLE(SERVICE_WORKER)
3030
3131#include "Exception.h"
 32#include "IDLTypes.h"
3233#include "JSDOMPromiseDeferred.h"
 34#include "JSServiceWorkerRegistration.h"
3335#include "NavigatorBase.h"
 36#include "ScopeGuard.h"
3437#include "ScriptExecutionContext.h"
3538#include "SecurityOrigin.h"
3639#include "ServiceWorkerJob.h"

@@void ServiceWorkerContainer::addRegistration(const String& relativeScriptURL, co
104107
105108 String path = jobData.scriptURL.path();
106109 if (path.containsIgnoringASCIICase("%2f") || path.containsIgnoringASCIICase("%5c")) {
107  promise->reject(Exception { TypeError, ASCIILiteral("serviceWorker.register() must be called with a script URL whose path does not contain '%%2f' or '%%5c'") });
 110 promise->reject(Exception { TypeError, ASCIILiteral("serviceWorker.register() must be called with a script URL whose path does not contain '%2f' or '%5c'") });
108111 return;
109112 }
110113

@@void ServiceWorkerContainer::addRegistration(const String& relativeScriptURL, co
112115 if (!scope.isEmpty())
113116 jobData.scopeURL = context->completeURL(scope);
114117
 118 if (!jobData.scopeURL.isNull() && !jobData.scopeURL.protocolIsInHTTPFamily()) {
 119 promise->reject(Exception { TypeError, ASCIILiteral("Scope URL provided to serviceWorker.register() must be either HTTP or HTTPS") });
 120 return;
 121 }
 122
 123 path = jobData.scopeURL.path();
 124 if (path.containsIgnoringASCIICase("%2f") || path.containsIgnoringASCIICase("%5c")) {
 125 promise->reject(Exception { TypeError, ASCIILiteral("Scope URL provided to serviceWorker.register() cannot have a path that contains '%2f' or '%5c'") });
 126 return;
 127 }
 128
115129 jobData.clientCreationURL = context->url();
116130 jobData.topOrigin = SecurityOriginData::fromSecurityOrigin(context->topOrigin());
117131 jobData.type = ServiceWorkerJobType::Register;
118  jobData.registrationOptions = std::make_unique<RegistrationOptions>(options);
 132 jobData.registrationOptions = options;
119133
120134 scheduleJob(ServiceWorkerJob::create(*this, WTFMove(promise), WTFMove(jobData)));
121135}

@@void ServiceWorkerContainer::scheduleJob(Ref<ServiceWorkerJob>&& job)
125139 ASSERT(m_swConnection);
126140
127141 ServiceWorkerJob& rawJob = job.get();
128  auto result = m_jobMap.add(rawJob.identifier(), WTFMove(job));
 142 auto result = m_jobMap.add(rawJob.data().identifier(), WTFMove(job));
129143 ASSERT_UNUSED(result, result.isNewEntry);
130144
131145 m_swConnection->scheduleJob(rawJob);

@@void ServiceWorkerContainer::startMessages()
145159{
146160}
147161
 162void ServiceWorkerContainer::jobFailedWithException(ServiceWorkerJob& job, const Exception& exception)
 163{
 164 job.promise().reject(exception);
 165 jobDidFinish(job);
 166}
 167
 168void ServiceWorkerContainer::jobResolvedWithRegistration(ServiceWorkerJob& job, const ServiceWorkerRegistrationData& data)
 169{
 170 ScopeGuard guard([this, job = &job] {
 171 jobDidFinish(*job);
 172 });
 173
 174 auto* context = scriptExecutionContext();
 175 if (!context) {
 176 LOG_ERROR("ServiceWorkerContainer::jobResolvedWithRegistration called but the containers ScriptExecutionContext is gone");
 177 return;
 178 }
 179
 180 auto registration = ServiceWorkerRegistration::create(*context, data);
 181 job.promise().resolve<IDLInterface<ServiceWorkerRegistration>>(registration.get());
 182}
 183
148184void ServiceWorkerContainer::jobDidFinish(ServiceWorkerJob& job)
149185{
150  auto taken = m_jobMap.take(job.identifier());
 186 auto taken = m_jobMap.take(job.data().identifier());
151187 ASSERT_UNUSED(taken, taken.get() == &job);
152188}
153189

Source/WebCore/workers/service/ServiceWorkerContainer.h

@@public:
7070
7171private:
7272 void scheduleJob(Ref<ServiceWorkerJob>&&);
73  void jobDidFinish(ServiceWorkerJob&) final;
 73
 74 void jobFailedWithException(ServiceWorkerJob&, const Exception&) final;
 75 void jobResolvedWithRegistration(ServiceWorkerJob&, const ServiceWorkerRegistrationData&) final;
 76 void jobDidFinish(ServiceWorkerJob&);
 77
7478 uint64_t connectionIdentifier() final;
7579
7680 const char* activeDOMObjectName() const final;

Source/WebCore/workers/service/ServiceWorkerJob.cpp

3030
3131#include "JSDOMPromiseDeferred.h"
3232#include "ServiceWorkerJobData.h"
 33#include "ServiceWorkerRegistration.h"
3334
3435namespace WebCore {
3536
36 static std::atomic<uint64_t> currentIdentifier;
37 
3837ServiceWorkerJob::ServiceWorkerJob(ServiceWorkerJobClient& client, Ref<DeferredPromise>&& promise, ServiceWorkerJobData&& jobData)
3938 : m_client(client)
4039 , m_jobData(WTFMove(jobData))
4140 , m_promise(WTFMove(promise))
42  , m_identifier(++currentIdentifier)
4341{
4442}
4543

@@ServiceWorkerJob::~ServiceWorkerJob()
5149void ServiceWorkerJob::failedWithException(const Exception& exception)
5250{
5351 ASSERT(currentThread() == m_creationThread);
54 
5552 ASSERT(!m_completed);
56  m_promise->reject(exception);
 53
5754 m_completed = true;
 55 m_client->jobFailedWithException(*this, exception);
 56}
5857
59  // Can cause this to be deleted.
60  m_client->jobDidFinish(*this);
 58void ServiceWorkerJob::resolvedWithRegistration(const ServiceWorkerRegistrationData& data)
 59{
 60 ASSERT(currentThread() == m_creationThread);
 61 ASSERT(!m_completed);
 62
 63 m_completed = true;
 64 m_client->jobResolvedWithRegistration(*this, data);
6165}
6266
6367} // namespace WebCore

Source/WebCore/workers/service/ServiceWorkerJob.h

@@namespace WebCore {
3939class DeferredPromise;
4040class Exception;
4141enum class ServiceWorkerJobType;
 42struct ServiceWorkerRegistrationData;
4243
4344class ServiceWorkerJob : public ThreadSafeRefCounted<ServiceWorkerJob> {
4445public:

@@public:
4950
5051 WEBCORE_EXPORT ~ServiceWorkerJob();
5152
52  WEBCORE_EXPORT void failedWithException(const Exception&);
53 
54  uint64_t identifier() const { return m_identifier; }
 53 void failedWithException(const Exception&);
 54 void resolvedWithRegistration(const ServiceWorkerRegistrationData&);
5555
5656 ServiceWorkerJobData data() const { return m_jobData; }
 57 DeferredPromise& promise() { return m_promise.get(); }
5758
5859private:
5960 ServiceWorkerJob(ServiceWorkerJobClient&, Ref<DeferredPromise>&&, ServiceWorkerJobData&&);

@@private:
6364 Ref<DeferredPromise> m_promise;
6465
6566 bool m_completed { false };
66  uint64_t m_identifier;
6767
6868 Ref<RunLoop> m_runLoop { RunLoop::current() };
6969

Source/WebCore/workers/service/ServiceWorkerJobClient.h

2929
3030namespace WebCore {
3131
 32class Exception;
3233class ServiceWorkerJob;
 34struct ServiceWorkerRegistrationData;
3335
3436class ServiceWorkerJobClient {
3537public:
3638 virtual ~ServiceWorkerJobClient() { };
3739
38  virtual void jobDidFinish(ServiceWorkerJob&) = 0;
 40 virtual void jobFailedWithException(ServiceWorkerJob&, const Exception&) = 0;
 41 virtual void jobResolvedWithRegistration(ServiceWorkerJob&, const ServiceWorkerRegistrationData&) = 0;
 42
3943 virtual uint64_t connectionIdentifier() = 0;
4044
4145 virtual void ref() = 0;

Source/WebCore/workers/service/ServiceWorkerJobData.cpp

@@ServiceWorkerJobData::ServiceWorkerJobData(const ServiceWorkerJobData& other)
4747 topOrigin = other.topOrigin;
4848 scopeURL = other.scopeURL;
4949 type = other.type;
50 
51  if (other.registrationOptions)
52  registrationOptions = std::make_unique<RegistrationOptions>(*other.registrationOptions);
 50 registrationOptions = other.registrationOptions;
5351}
5452
5553ServiceWorkerRegistrationKey ServiceWorkerJobData::registrationKey() const

@@ServiceWorkerJobData ServiceWorkerJobData::isolatedCopy() const
6866 result.clientCreationURL = clientCreationURL.isolatedCopy();
6967 result.topOrigin = topOrigin.isolatedCopy();
7068 result.scopeURL = scopeURL.isolatedCopy();
 69 result.registrationOptions = registrationOptions.isolatedCopy();
7170
72  if (registrationOptions)
73  result.registrationOptions = std::make_unique<RegistrationOptions>(registrationOptions->isolatedCopy());
7471 return result;
7572}
7673

Source/WebCore/workers/service/ServiceWorkerJobData.h

@@public:
4141 ServiceWorkerJobData(const ServiceWorkerJobData&);
4242 ServiceWorkerJobData() = default;
4343
44  uint64_t jobIdentifier() const { return m_jobIdentifier; }
 44 uint64_t identifier() const { return m_jobIdentifier; }
4545 uint64_t connectionIdentifier() const { return m_connectionIdentifier; }
4646
4747 URL scriptURL;

@@public:
5050 URL scopeURL;
5151 ServiceWorkerJobType type;
5252
53  std::unique_ptr<RegistrationOptions> registrationOptions;
 53 RegistrationOptions registrationOptions;
5454
5555 ServiceWorkerRegistrationKey registrationKey() const;
5656 ServiceWorkerJobData isolatedCopy() const;

@@void ServiceWorkerJobData::encode(Encoder& encoder) const
7070 encoder.encodeEnum(type);
7171 switch (type) {
7272 case ServiceWorkerJobType::Register:
73  RELEASE_ASSERT(registrationOptions);
74  encoder << *registrationOptions;
 73 encoder << registrationOptions;
7574 break;
7675 }
7776}

@@bool ServiceWorkerJobData::decode(Decoder& decoder, ServiceWorkerJobData& jobDat
9695
9796 switch (jobData.type) {
9897 case ServiceWorkerJobType::Register:
99  jobData.registrationOptions = std::make_unique<RegistrationOptions>();
100  if (!decoder.decode(*jobData.registrationOptions))
 98 if (!decoder.decode(jobData.registrationOptions))
10199 return false;
102100 break;
103101 }

Source/WebCore/workers/service/ServiceWorkerRegistration.cpp

3030
3131namespace WebCore {
3232
 33ServiceWorkerRegistration::ServiceWorkerRegistration(ScriptExecutionContext& context, const ServiceWorkerRegistrationData& registrationData)
 34 : ActiveDOMObject(&context)
 35 , m_registrationData(registrationData)
 36{
 37}
 38
3339ServiceWorker* ServiceWorkerRegistration::installing()
3440{
3541 return nullptr;

Source/WebCore/workers/service/ServiceWorkerRegistration.h

2727
2828#if ENABLE(SERVICE_WORKER)
2929
 30#include "ActiveDOMObject.h"
3031#include "EventTarget.h"
3132#include "JSDOMPromiseDeferred.h"
 33#include "ServiceWorkerRegistrationData.h"
3234
3335namespace WebCore {
3436
35 class Frame;
 37class ScriptExecutionContext;
3638class ServiceWorker;
3739
38 class ServiceWorkerRegistration final : public EventTargetWithInlineData {
 40class ServiceWorkerRegistration final : public EventTargetWithInlineData, public ActiveDOMObject {
3941public:
4042 enum class UpdateViaCache {
4143 Imports,

@@public:
4345 None,
4446 };
4547
46  static Ref<ServiceWorkerRegistration> create(Frame& frame) { return adoptRef(*new ServiceWorkerRegistration(frame)); }
 48 static Ref<ServiceWorkerRegistration> create(ScriptExecutionContext& context, const ServiceWorkerRegistrationData& data)
 49 {
 50 return adoptRef(*new ServiceWorkerRegistration(context, data));
 51 }
 52
4753 virtual ~ServiceWorkerRegistration() = default;
4854
4955 ServiceWorker* installing();

@@public:
5763 void unregister(Ref<DeferredPromise>&&);
5864
5965private:
60  explicit ServiceWorkerRegistration(Frame&);
 66 ServiceWorkerRegistration(ScriptExecutionContext&, const ServiceWorkerRegistrationData&);
6167
6268 virtual EventTargetInterface eventTargetInterface() const;
6369 virtual ScriptExecutionContext* scriptExecutionContext() const;
6470 void refEventTarget() final { ref(); }
6571 void derefEventTarget() final { deref(); }
 72
 73 const char* activeDOMObjectName() const { return "ServiceWorkerRegistration"; }
 74 bool canSuspendForDocumentSuspension() const { return false; }
 75
 76 ServiceWorkerRegistrationData m_registrationData;
6677};
6778
6879} // namespace WebCore

Source/WebCore/workers/service/ServiceWorkerRegistrationData.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 "ServiceWorkerRegistrationData.h"
 28
 29#if ENABLE(SERVICE_WORKER)
 30
 31namespace WebCore {
 32
 33ServiceWorkerRegistrationData ServiceWorkerRegistrationData::isolatedCopy() const
 34{
 35 ServiceWorkerRegistrationData result;
 36 result.key = key.isolatedCopy();
 37 result.identifier = identifier;
 38 return result;
 39}
 40
 41} // namespace WTF
 42
 43#endif // ENABLE(SERVICE_WORKER)

Source/WebCore/workers/service/ServiceWorkerRegistrationData.h

 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#pragma once
 27
 28#if ENABLE(SERVICE_WORKER)
 29
 30#include "ServiceWorkerRegistrationKey.h"
 31
 32namespace WebCore {
 33
 34struct ServiceWorkerRegistrationData {
 35 ServiceWorkerRegistrationKey key;
 36 uint64_t identifier;
 37
 38 ServiceWorkerRegistrationData isolatedCopy() const;
 39
 40 template<class Encoder> void encode(Encoder&) const;
 41 template<class Decoder> static bool decode(Decoder&, ServiceWorkerRegistrationData&);
 42};
 43
 44
 45template<class Encoder>
 46void ServiceWorkerRegistrationData::encode(Encoder& encoder) const
 47{
 48 encoder << key << identifier;
 49}
 50
 51template<class Decoder>
 52bool ServiceWorkerRegistrationData::decode(Decoder& decoder, ServiceWorkerRegistrationData& data)
 53{
 54 if (!decoder.decode(data.key))
 55 return false;
 56 if (!decoder.decodeEnum(data.identifier))
 57 return false;
 58
 59 return true;
 60}
 61
 62} // namespace WTF
 63
 64#endif // ENABLE(SERVICE_WORKER)

Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp

@@bool ServiceWorkerRegistrationKey::operator==(const ServiceWorkerRegistrationKey
5151 return clientCreationURL == other.clientCreationURL && topOrigin == other.topOrigin;
5252}
5353
 54ServiceWorkerRegistrationKey ServiceWorkerRegistrationKey::isolatedCopy() const
 55{
 56 ServiceWorkerRegistrationKey result;
 57 result.clientCreationURL = clientCreationURL.isolatedCopy();
 58 result.topOrigin = topOrigin.isolatedCopy();
 59 return result;
 60}
 61
5462} // namespace WebCore
5563
5664#endif // ENABLE(SERVICE_WORKER)

Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h

@@struct ServiceWorkerRegistrationKey {
4040 unsigned hash() const;
4141
4242 bool operator==(const ServiceWorkerRegistrationKey&) const;
 43
 44 ServiceWorkerRegistrationKey isolatedCopy() const;
 45
 46 template<class Encoder> void encode(Encoder&) const;
 47 template<class Decoder> static bool decode(Decoder&, ServiceWorkerRegistrationKey&);
4348};
4449
 50template<class Encoder>
 51void ServiceWorkerRegistrationKey::encode(Encoder& encoder) const
 52{
 53 encoder << clientCreationURL << topOrigin;
 54}
 55
 56template<class Decoder>
 57bool ServiceWorkerRegistrationKey::decode(Decoder& decoder, ServiceWorkerRegistrationKey& key)
 58{
 59 if (!decoder.decode(key.clientCreationURL))
 60 return false;
 61 if (!decoder.decode(key.topOrigin))
 62 return false;
 63
 64 return true;
 65}
 66
4567} // namespace WebCore
4668
4769namespace WTF {

Source/WebCore/workers/service/server/SWClientConnection.cpp

@@SWClientConnection::~SWClientConnection()
4343
4444void SWClientConnection::scheduleJob(ServiceWorkerJob& job)
4545{
46  auto addResult = m_scheduledJobs.add(job.identifier(), &job);
 46 auto addResult = m_scheduledJobs.add(job.data().identifier(), &job);
4747 ASSERT_UNUSED(addResult, addResult.isNewEntry);
4848
4949 scheduleJobInServer(job.data());

@@void SWClientConnection::jobRejectedInServer(uint64_t jobIdentifier, const Excep
6060 job->failedWithException(exceptionData.toException());
6161}
6262
 63void SWClientConnection::jobResolvedInServer(uint64_t jobIdentifier, const ServiceWorkerRegistrationData& registrationData)
 64{
 65 auto job = m_scheduledJobs.take(jobIdentifier);
 66 if (!job) {
 67 LOG_ERROR("Job %" PRIu64 " resolved in server, but was not found", jobIdentifier);
 68 return;
 69 }
 70
 71 job->resolvedWithRegistration(registrationData);
 72}
 73
6374} // namespace WebCore
6475
6576#endif // ENABLE(SERVICE_WORKER)

Source/WebCore/workers/service/server/SWClientConnection.h

3434namespace WebCore {
3535
3636struct ExceptionData;
 37struct ServiceWorkerRegistrationData;
3738
3839class SWClientConnection : public ThreadSafeRefCounted<SWClientConnection> {
3940public:

@@public:
4647
4748protected:
4849 WEBCORE_EXPORT void jobRejectedInServer(uint64_t jobIdentifier, const ExceptionData&);
 50 WEBCORE_EXPORT void jobResolvedInServer(uint64_t jobIdentifier, const ServiceWorkerRegistrationData&);
4951
5052private:
5153 virtual void scheduleJobInServer(const ServiceWorkerJobData&) = 0;

Source/WebCore/workers/service/server/SWServer.cpp

@@SWServer::~SWServer()
5454 RELEASE_ASSERT(m_connections.isEmpty());
5555 RELEASE_ASSERT(m_registrations.isEmpty());
5656
 57 ASSERT(m_taskQueue.isEmpty());
 58 ASSERT(m_taskReplyQueue.isEmpty());
 59
5760 // For a SWServer to be cleanly shut down its thread must have finished and gone away.
5861 // At this stage in development of the feature that actually never happens.
5962 // But once it does start happening, this ASSERT will catch us doing it wrong.

@@SWServer::~SWServer()
6366
6467void SWServer::Connection::scheduleJobInServer(const ServiceWorkerJobData& jobData)
6568{
66  LOG(ServiceWorker, "Scheduling ServiceWorker job %" PRIu64 "-%" PRIu64 " in server", jobData.connectionIdentifier(), jobData.jobIdentifier());
 69 LOG(ServiceWorker, "Scheduling ServiceWorker job %" PRIu64 "-%" PRIu64 " in server", jobData.connectionIdentifier(), jobData.identifier());
6770 ASSERT(identifier() == jobData.connectionIdentifier());
6871
6972 m_server.scheduleJob(jobData);

@@void SWServer::scheduleJob(const ServiceWorkerJobData& jobData)
8285
8386 auto result = m_registrations.add(jobData.registrationKey(), nullptr);
8487 if (result.isNewEntry)
85  result.iterator->value = std::make_unique<SWServerRegistration>(*this);
 88 result.iterator->value = std::make_unique<SWServerRegistration>(*this, jobData.registrationKey());
8689
8790 ASSERT(result.iterator->value);
8891

@@void SWServer::scheduleJob(const ServiceWorkerJobData& jobData)
9194
9295void SWServer::rejectJob(const ServiceWorkerJobData& jobData, const ExceptionData& exceptionData)
9396{
94  LOG(ServiceWorker, "Rejected ServiceWorker job %" PRIu64 "-%" PRIu64 " in server", jobData.connectionIdentifier(), jobData.jobIdentifier());
 97 LOG(ServiceWorker, "Rejected ServiceWorker job %" PRIu64 "-%" PRIu64 " in server", jobData.connectionIdentifier(), jobData.identifier());
 98 auto* connection = m_connections.get(jobData.connectionIdentifier());
 99 if (!connection)
 100 return;
 101
 102 connection->rejectJobInClient(jobData.identifier(), exceptionData);
 103}
 104
 105void SWServer::resolveJob(const ServiceWorkerJobData& jobData, const ServiceWorkerRegistrationData& registrationData)
 106{
 107 LOG(ServiceWorker, "Resolved ServiceWorker job %" PRIu64 "-%" PRIu64 " in server with registration %" PRIu64, jobData.connectionIdentifier(), jobData.identifier(), registrationData.identifier);
95108 auto* connection = m_connections.get(jobData.connectionIdentifier());
96109 if (!connection)
97110 return;
98111
99  connection->rejectJobInClient(jobData.jobIdentifier(), exceptionData);
 112 connection->resolveJobInClient(jobData.identifier(), registrationData);
100113}
101114
102115void SWServer::taskThreadEntryPoint()

Source/WebCore/workers/service/server/SWServer.h

@@namespace WebCore {
4242
4343class SWServerRegistration;
4444struct ExceptionData;
 45struct ServiceWorkerRegistrationData;
4546
4647class SWServer {
4748public:

@@public:
6061
6162 private:
6263 virtual void rejectJobInClient(uint64_t jobIdentifier, const ExceptionData&) = 0;
 64 virtual void resolveJobInClient(uint64_t jobIdentifier, const ServiceWorkerRegistrationData&) = 0;
6365
6466 SWServer& m_server;
6567 uint64_t m_identifier;

@@public:
7072
7173 void scheduleJob(const ServiceWorkerJobData&);
7274 void rejectJob(const ServiceWorkerJobData&, const ExceptionData&);
73 
 75 void resolveJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationData&);
7476 void postTask(CrossThreadTask&&);
7577 void postTaskReply(CrossThreadTask&&);
7678

Source/WebCore/workers/service/server/SWServerRegistration.cpp

3030
3131#include "ExceptionData.h"
3232#include "SWServer.h"
 33#include "SWServerWorker.h"
 34#include "SecurityOrigin.h"
 35#include "ServiceWorkerRegistrationData.h"
 36#include "WorkerType.h"
3337
3438namespace WebCore {
3539
36 SWServerRegistration::SWServerRegistration(SWServer& server)
 40static std::atomic<uint64_t> currentIdentifier;
 41
 42SWServerRegistration::SWServerRegistration(SWServer& server, const ServiceWorkerRegistrationKey& key)
3743 : m_jobTimer(*this, &SWServerRegistration::startNextJob)
3844 , m_server(server)
 45 , m_identifier(++currentIdentifier)
 46 , m_registrationKey(key)
3947{
4048}
4149

@@void SWServerRegistration::startNextJob()
6573 ASSERT(!m_jobQueue.isEmpty());
6674
6775 m_currentJob = std::make_unique<ServiceWorkerJobData>(m_jobQueue.takeFirst().isolatedCopy());
68  m_server.postTask(createCrossThreadTask(*this, &SWServerRegistration::performCurrentJob));
 76
 77 switch (m_currentJob->type) {
 78 case ServiceWorkerJobType::Register:
 79 m_server.postTask(createCrossThreadTask(*this, &SWServerRegistration::runRegisterJob, *m_currentJob));
 80 return;
 81 }
 82
 83 RELEASE_ASSERT_NOT_REACHED();
 84}
 85
 86bool SWServerRegistration::isEmpty()
 87{
 88 ASSERT(!isMainThread());
 89
 90 // Having or not-having an m_updateViaCache flag is currently
 91 // the signal as to whether or not this is an empty (i.e. "new") registration.
 92 // There will be a more explicit signal in the near future.
 93 return !m_updateViaCache;
6994}
7095
71 void SWServerRegistration::performCurrentJob()
 96SWServerWorker* SWServerRegistration::getNewestWorker()
7297{
7398 ASSERT(!isMainThread());
 99 if (m_installingWorker)
 100 return m_installingWorker.get();
 101 if (m_waitingWorker)
 102 return m_waitingWorker.get();
 103
 104 return m_activeWorker.get();
 105}
 106
 107void SWServerRegistration::runRegisterJob(const ServiceWorkerJobData& job)
 108{
 109 ASSERT(!isMainThread());
 110 ASSERT(job.type == ServiceWorkerJobType::Register);
 111
 112 if (!shouldTreatAsPotentiallyTrustworthy(job.scriptURL))
 113 return rejectWithExceptionOnMainThread(ExceptionData { SecurityError, ASCIILiteral("Script URL is not potentially trustworthy") });
 114
 115 // If the origin of job’s script url is not job’s referrer's origin, then:
 116 if (!protocolHostAndPortAreEqual(job.scriptURL, job.clientCreationURL))
 117 return rejectWithExceptionOnMainThread(ExceptionData { SecurityError, ASCIILiteral("Script origin does not match the registering client's origin") });
 118
 119 // If the origin of job’s scope url is not job’s referrer's origin, then:
 120 if (!protocolHostAndPortAreEqual(job.scopeURL, job.clientCreationURL))
 121 return rejectWithExceptionOnMainThread(ExceptionData { SecurityError, ASCIILiteral("Scope origin does not match the registering client's origin") });
 122
 123 // If registration is not null (in our parlance "empty"), then:
 124 if (!isEmpty()) {
 125 ASSERT(m_updateViaCache);
 126
 127 m_uninstalling = false;
 128 auto* newestWorker = getNewestWorker();
 129 if (newestWorker && equalIgnoringFragmentIdentifier(job.scriptURL, newestWorker->scriptURL()) && job.registrationOptions.updateViaCache == *m_updateViaCache) {
 130 resolveWithRegistrationOnMainThread();
 131 return;
 132 }
 133 } else {
 134 m_scopeURL = job.scopeURL.isolatedCopy();
 135 m_scopeURL.removeFragmentIdentifier();
 136 m_updateViaCache = job.registrationOptions.updateViaCache;
 137 }
 138
 139 runUpdateJob(job);
 140}
 141
 142void SWServerRegistration::runUpdateJob(const ServiceWorkerJobData& job)
 143{
 144 // If registration is null (in our parlance "empty") or registration’s uninstalling flag is set, then:
 145 if (isEmpty())
 146 return rejectWithExceptionOnMainThread(ExceptionData { TypeError, ASCIILiteral("Cannot update a null/nonexistent service worker registration") });
 147 if (m_uninstalling)
 148 return rejectWithExceptionOnMainThread(ExceptionData { TypeError, ASCIILiteral("Cannot update a service worker registration that is uninstalling") });
 149
 150 // If job’s job type is update, and newestWorker’s script url does not equal job’s script url with the exclude fragments flag set, then:
 151 auto* newestWorker = getNewestWorker();
 152 if (newestWorker && !equalIgnoringFragmentIdentifier(job.scriptURL, newestWorker->scriptURL()))
 153 return rejectWithExceptionOnMainThread(ExceptionData { TypeError, ASCIILiteral("Cannot update a service worker with a requested script URL whose newest worker has a different script URL") });
 154
 155 // FIXME: At this point we are ready to actually fetch the script for the worker in the registering context.
 156 // For now we're still hard coding the same rejection we have so far.
 157 rejectWithExceptionOnMainThread(ExceptionData { UnknownError, ASCIILiteral("serviceWorker job scheduling is not yet implemented") });
 158}
74159
75  auto exception = ExceptionData { UnknownError, ASCIILiteral("serviceWorker job scheduling is not yet implemented") };
 160void SWServerRegistration::rejectWithExceptionOnMainThread(const ExceptionData& exception)
 161{
 162 ASSERT(!isMainThread());
76163 m_server.postTaskReply(createCrossThreadTask(*this, &SWServerRegistration::rejectCurrentJob, exception));
77164}
78165
 166void SWServerRegistration::resolveWithRegistrationOnMainThread()
 167{
 168 ASSERT(!isMainThread());
 169 m_server.postTaskReply(createCrossThreadTask(*this, &SWServerRegistration::resolveCurrentJob, data()));
 170}
 171
79172void SWServerRegistration::rejectCurrentJob(const ExceptionData& exceptionData)
80173{
81174 ASSERT(isMainThread());

@@void SWServerRegistration::rejectCurrentJob(const ExceptionData& exceptionData)
86179 finishCurrentJob();
87180}
88181
 182void SWServerRegistration::resolveCurrentJob(const ServiceWorkerRegistrationData& data)
 183{
 184 ASSERT(isMainThread());
 185 ASSERT(m_currentJob);
 186
 187 m_server.resolveJob(*m_currentJob, data);
 188
 189 finishCurrentJob();
 190}
 191
89192void SWServerRegistration::finishCurrentJob()
90193{
91194 ASSERT(m_currentJob);

@@void SWServerRegistration::finishCurrentJob()
98201 startNextJob();
99202}
100203
 204ServiceWorkerRegistrationData SWServerRegistration::data() const
 205{
 206 return { m_registrationKey, m_identifier };
 207}
 208
 209
101210} // namespace WebCore
102211
103212#endif // ENABLE(SERVICE_WORKER)

Source/WebCore/workers/service/server/SWServerRegistration.h

2828#if ENABLE(SERVICE_WORKER)
2929
3030#include "ServiceWorkerJobData.h"
 31#include "ServiceWorkerRegistrationData.h"
3132#include "Timer.h"
3233#include <wtf/Deque.h>
3334
3435namespace WebCore {
3536
3637class SWServer;
 38class SWServerWorker;
3739struct ExceptionData;
3840
3941class SWServerRegistration {
4042public:
41  explicit SWServerRegistration(SWServer&);
 43 explicit SWServerRegistration(SWServer&, const ServiceWorkerRegistrationKey&);
4244 SWServerRegistration(const SWServerRegistration&) = delete;
4345 ~SWServerRegistration();
4446
4547 void enqueueJob(const ServiceWorkerJobData&);
4648
 49 uint64_t identifier() const { return m_identifier; }
 50 ServiceWorkerRegistrationData data() const;
 51
4752private:
4853 void jobTimerFired();
49  void performCurrentJob();
50  void rejectCurrentJob(const ExceptionData&);
51 
5254 void startNextJob();
 55 void rejectCurrentJob(const ExceptionData&);
 56 void resolveCurrentJob(const ServiceWorkerRegistrationData&);
5357 void finishCurrentJob();
5458
 59 void runRegisterJob(const ServiceWorkerJobData&);
 60 void runUpdateJob(const ServiceWorkerJobData&);
 61
 62 void rejectWithExceptionOnMainThread(const ExceptionData&);
 63 void resolveWithRegistrationOnMainThread();
 64 bool isEmpty();
 65 SWServerWorker* getNewestWorker();
 66
5567 Deque<ServiceWorkerJobData> m_jobQueue;
5668 std::unique_ptr<ServiceWorkerJobData> m_currentJob;
5769
 70 bool m_uninstalling { false };
 71 std::unique_ptr<SWServerWorker> m_installingWorker;
 72 std::unique_ptr<SWServerWorker> m_waitingWorker;
 73 std::unique_ptr<SWServerWorker> m_activeWorker;
 74 URL m_scopeURL;
 75 std::optional<ServiceWorkerUpdateViaCache> m_updateViaCache;
 76
5877 Timer m_jobTimer;
5978 SWServer& m_server;
 79 uint64_t m_identifier;
 80 ServiceWorkerRegistrationKey m_registrationKey;
6081};
6182
6283} // namespace WebCore

Source/WebCore/workers/service/server/SWServerWorker.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 "SWServerWorker.h"
 28
 29#if ENABLE(SERVICE_WORKER)
 30
 31#include <wtf/MainThread.h>
 32
 33namespace WebCore {
 34
 35SWServerWorker::SWServerWorker(const URL& url)
 36 : m_scriptURL(url)
 37{
 38 ASSERT(!isMainThread());
 39}
 40
 41SWServerWorker::~SWServerWorker()
 42{
 43 ASSERT(!isMainThread());
 44}
 45
 46} // namespace WebCore
 47
 48#endif // ENABLE(SERVICE_WORKER)

Source/WebCore/workers/service/server/SWServerWorker.h

 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#pragma once
 27
 28#if ENABLE(SERVICE_WORKER)
 29
 30#include "URL.h"
 31
 32namespace WebCore {
 33
 34class SWServerWorker {
 35public:
 36 SWServerWorker(const URL&);
 37 SWServerWorker(const SWServerWorker&) = delete;
 38 ~SWServerWorker();
 39 const URL& scriptURL() const { return m_scriptURL; }
 40
 41private:
 42 URL m_scriptURL;
 43};
 44
 45} // namespace WebCore
 46
 47#endif // ENABLE(SERVICE_WORKER)

Source/WebKit/StorageProcess/ServiceWorker/WebSWServerConnection.cpp

@@void WebSWServerConnection::rejectJobInClient(uint64_t jobIdentifier, const Exce
6565 send(Messages::WebSWClientConnection::JobRejectedInServer(jobIdentifier, exceptionData));
6666}
6767
 68void WebSWServerConnection::resolveJobInClient(uint64_t jobIdentifier, const ServiceWorkerRegistrationData& registrationData)
 69{
 70 send(Messages::WebSWClientConnection::JobResolvedInServer(jobIdentifier, registrationData));
 71}
 72
6873} // namespace WebKit
6974
7075#endif // ENABLE(SERVICE_WORKER)

Source/WebKit/StorageProcess/ServiceWorker/WebSWServerConnection.h

@@public:
5050private:
5151 // Implement SWServer::Connection
5252 void rejectJobInClient(uint64_t jobIdentifier, const WebCore::ExceptionData&) final;
 53 void resolveJobInClient(uint64_t jobIdentifier, const WebCore::ServiceWorkerRegistrationData&) final;
5354
5455 IPC::Connection* messageSenderConnection() final { return m_connection.ptr(); }
5556 uint64_t messageSenderDestinationID() final { return identifier(); }

Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in

2525messages -> WebSWClientConnection {
2626 # When possible, these messages can be implemented directly by WebCore::SWServer::Connection
2727 JobRejectedInServer(uint64_t identifier, struct WebCore::ExceptionData exception)
 28 JobResolvedInServer(uint64_t identifier, struct WebCore::ServiceWorkerRegistrationData registration)
2829}
2930
3031#endif // ENABLE(SERVICE_WORKER)

LayoutTests/ChangeLog

 12017-08-30 Brady Eidson <beidson@apple.com>
 2
 3 Implement all of "Register" right up until where the script is fetched.
 4 https://bugs.webkit.org/show_bug.cgi?id=176082
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * http/tests/workers/service/basic-register-exceptions-expected.txt: Added.
 9 * http/tests/workers/service/basic-register-exceptions.html: Added.
 10 * http/tests/workers/service/resources/basic-register-exceptions.js: Added.
 11
1122017-08-30 Per Arne Vollan <pvollan@apple.com>
213
314 The test imported/w3c/web-platform-tests/dom/traversal/NodeFilter-constants.html is slow on Windows.

LayoutTests/http/tests/workers/service/basic-register-exceptions-expected.txt

 1CONSOLE MESSAGE: line 10: Registration failed with error: TypeError: serviceWorker.register() cannot be called with an empty script URL
 2CONSOLE MESSAGE: line 20: Registration failed with error: TypeError: serviceWorker.register() must be called with a valid relative script URL
 3CONSOLE MESSAGE: line 30: Registration failed with error: TypeError: serviceWorker.register() must be called with a script URL whose protocol is either HTTP or HTTPS
 4CONSOLE MESSAGE: line 40: Registration failed with error: TypeError: serviceWorker.register() must be called with a script URL whose path does not contain '%2f' or '%5c'
 5CONSOLE MESSAGE: line 50: Registration failed with error: TypeError: Scope URL provided to serviceWorker.register() must be either HTTP or HTTPS
 6CONSOLE MESSAGE: line 60: Registration failed with error: TypeError: Scope URL provided to serviceWorker.register() cannot have a path that contains '%2f' or '%5c'
 7CONSOLE MESSAGE: line 70: Registration failed with error: SecurityError: Script origin does not match the registering client's origin
 8CONSOLE MESSAGE: line 81: Registration failed with error: SecurityError: Scope origin does not match the registering client's origin
 9

LayoutTests/http/tests/workers/service/basic-register-exceptions.html

 1<html>
 2<head>
 3<script src="resources/sw-test-pre.js"></script>
 4</head>
 5<body>
 6
 7<script src="resources/basic-register-exceptions.js"></script>
 8</body>
 9</html>

LayoutTests/http/tests/workers/service/resources/basic-register-exceptions.js

 1function done()
 2{
 3 finishSWTest();
 4}
 5
 6navigator.serviceWorker.register("", { })
 7.then(function(r) {
 8 console.log("Registered! (unexpectedly)");
 9}, function(e) {
 10 console.log("Registration failed with error: " + e);
 11})
 12.catch(function(e) {
 13 console.log("Exception registering: " + e);
 14});
 15
 16navigator.serviceWorker.register("http://127.0.0.1:abc", { })
 17.then(function(r) {
 18 console.log("Registered! (unexpectedly)");
 19}, function(e) {
 20 console.log("Registration failed with error: " + e);
 21})
 22.catch(function(e) {
 23 console.log("Exception registering: " + e);
 24});
 25
 26navigator.serviceWorker.register("somescheme://script.js", { })
 27.then(function(r) {
 28 console.log("Registered! (unexpectedly)");
 29}, function(e) {
 30 console.log("Registration failed with error: " + e);
 31})
 32.catch(function(e) {
 33 console.log("Exception registering: " + e);
 34});
 35
 36navigator.serviceWorker.register("resources/%2fscript.js", { })
 37.then(function(r) {
 38 console.log("Registered! (unexpectedly)");
 39}, function(e) {
 40 console.log("Registration failed with error: " + e);
 41})
 42.catch(function(e) {
 43 console.log("Exception registering: " + e);
 44});
 45
 46navigator.serviceWorker.register("resources/script.js", { scope: "somescheme://script.js" })
 47.then(function(r) {
 48 console.log("Registered! (unexpectedly)");
 49}, function(e) {
 50 console.log("Registration failed with error: " + e);
 51})
 52.catch(function(e) {
 53 console.log("Exception registering: " + e);
 54});
 55
 56navigator.serviceWorker.register("resources/script.js", { scope: "%2fscript.js" })
 57.then(function(r) {
 58 console.log("Registered! (unexpectedly)");
 59}, function(e) {
 60 console.log("Registration failed with error: " + e);
 61})
 62.catch(function(e) {
 63 console.log("Exception registering: " + e);
 64});
 65
 66navigator.serviceWorker.register("http://localhost:8000/workers/service/resources/empty-worker.js", { })
 67.then(function(r) {
 68 console.log("Registered! (unexpectedly)");
 69}, function(e) {
 70 console.log("Registration failed with error: " + e);
 71})
 72.catch(function(e) {
 73 console.log("Exception registering: " + e);
 74});
 75
 76navigator.serviceWorker.register("resources/empty-worker.js", { scope: "http://localhost:8000/workers/service/" })
 77.then(function(r) {
 78 console.log("Registered! (unexpectedly)");
 79 done();
 80}, function(e) {
 81 console.log("Registration failed with error: " + e);
 82 done();
 83})
 84.catch(function(e) {
 85 console.log("Exception registering: " + e);
 86 done();
 87});