| // Copyright 2022 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef COBALT_WORKER_SERVICE_WORKER_OBJECT_H_ |
| #define COBALT_WORKER_SERVICE_WORKER_OBJECT_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <utility> |
| |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/message_loop/message_loop_current.h" |
| #include "cobalt/web/agent.h" |
| #include "cobalt/web/context.h" |
| #include "cobalt/worker/service_worker_state.h" |
| #include "cobalt/worker/worker_global_scope.h" |
| #include "starboard/atomic.h" |
| #include "url/gurl.h" |
| |
| #if defined(ENABLE_DEBUGGER) |
| #include "cobalt/debug/backend/debug_module.h" // nogncheck |
| #endif // defined(ENABLE_DEBUGGER) |
| |
| namespace cobalt { |
| namespace worker { |
| class ServiceWorkerRegistrationObject; |
| |
| // This class represents the 'service worker'. |
| // https://w3c.github.io/ServiceWorker/#dfn-service-worker |
| // Not to be confused with the ServiceWorker JavaScript object, this represents |
| // the service worker in the browser, independent from the JavaScript realm. |
| // The lifetime of a service worker is tied to the execution lifetime of events |
| // and not references held by service worker clients to the ServiceWorker |
| // object. A user agent may terminate service workers at any time it has no |
| // event to handle, or detects abnormal operation. |
| // https://w3c.github.io/ServiceWorker/#service-worker-lifetime |
| class ServiceWorkerObject |
| : public base::RefCountedThreadSafe<ServiceWorkerObject>, |
| public base::SupportsWeakPtr<ServiceWorkerObject>, |
| public base::MessageLoop::DestructionObserver { |
| public: |
| // Worker Options needed at thread run time. |
| struct Options { |
| explicit Options( |
| const std::string& name, network::NetworkModule* network_module, |
| ServiceWorkerRegistrationObject* containing_service_worker_registration) |
| : web_options(name), |
| containing_service_worker_registration( |
| containing_service_worker_registration) { |
| web_options.network_module = network_module; |
| } |
| |
| web::Agent::Options web_options; |
| ServiceWorkerRegistrationObject* containing_service_worker_registration; |
| }; |
| |
| explicit ServiceWorkerObject(const Options& options); |
| ~ServiceWorkerObject(); |
| ServiceWorkerObject(const ServiceWorkerObject&) = delete; |
| ServiceWorkerObject& operator=(const ServiceWorkerObject&) = delete; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-state |
| void set_state(ServiceWorkerState state) { state_ = state; } |
| ServiceWorkerState state() const { return state_; } |
| // https://w3c.github.io/ServiceWorker/#dfn-script-url |
| void set_script_url(const GURL& script_url) { script_url_ = script_url; } |
| const GURL& script_url() const { return script_url_; } |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-containing-service-worker-registration |
| ServiceWorkerRegistrationObject* containing_service_worker_registration() { |
| return options_.containing_service_worker_registration; |
| } |
| // https://w3c.github.io/ServiceWorker/#dfn-skip-waiting-flag |
| void set_skip_waiting() { skip_waiting_ = true; } |
| bool skip_waiting() const { return skip_waiting_; } |
| |
| // https://w3c.github.io/ServiceWoScriptResourceMaprker/#dfn-classic-scripts-imported-flag |
| void set_classic_scripts_imported() { classic_scripts_imported_ = true; } |
| bool classic_scripts_imported() { return classic_scripts_imported_; } |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-set-of-used-scripts |
| void AppendToSetOfUsedScripts(const GURL& url) { |
| set_of_used_scripts_.insert(url); |
| } |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-script-resource-map |
| void set_script_resource_map(ScriptResourceMap&& resource_map) { |
| script_resource_map_ = std::move(resource_map); |
| } |
| void SetScriptResource(const GURL& url, std::string* resource); |
| bool HasScriptResource() const; |
| std::string* LookupScriptResource(const GURL& url) const; |
| |
| // Steps 13-15 of Algorithm for Install. |
| // https://w3c.github.io/ServiceWorker/#installation-algorithm |
| void PurgeScriptResourceMap(); |
| const ScriptResourceMap& script_resource_map() { |
| return script_resource_map_; |
| } |
| |
| // https://w3c.github.io/ServiceWorker/#service-worker-start-status |
| void set_start_status(std::string* start_status) { |
| start_status_.reset(start_status); |
| } |
| std::string* start_status() const { return start_status_.get(); } |
| |
| void Abort(); |
| bool is_running() { return web_agent_.get() != nullptr; } |
| web::Agent* web_agent() const { return web_agent_.get(); } |
| |
| const scoped_refptr<WorkerGlobalScope>& worker_global_scope() const { |
| return worker_global_scope_; |
| } |
| |
| // From base::MessageLoop::DestructionObserver. |
| void WillDestroyCurrentMessageLoop() override; |
| |
| void store_start_failed(bool value) { start_failed_.store(value); } |
| bool load_start_failed() { return start_failed_.load(); } |
| |
| void ObtainWebAgentAndWaitUntilDone(); |
| |
| private: |
| // Called by ObtainWebAgentAndWaitUntilDone to perform initialization required |
| // on the dedicated thread. |
| // https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm |
| void Initialize(web::Context* context); |
| |
| // The message loop this object is running on. |
| base::MessageLoop* message_loop() const { |
| return web_agent_ ? web_agent_->message_loop() : nullptr; |
| } |
| |
| #if defined(ENABLE_DEBUGGER) |
| // The core of the debugging system. |
| std::unique_ptr<debug::backend::DebugModule> debug_module_; |
| #endif // defined(ENABLE_DEBUGGER) |
| |
| // The Web Context includes the Script Agent and Realm. |
| std::unique_ptr<web::Agent> web_agent_; |
| |
| web::Context* web_context_ = nullptr; |
| |
| Options options_; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-state |
| ServiceWorkerState state_; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-script-url |
| GURL script_url_; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-script-resource-map |
| ScriptResourceMap script_resource_map_; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-set-of-used-scripts |
| std::set<GURL> set_of_used_scripts_; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-skip-waiting-flag |
| bool skip_waiting_ = false; |
| |
| // https://w3c.github.io/ServiceWorker/#dfn-classic-scripts-imported-flag |
| bool classic_scripts_imported_ = false; |
| |
| // https://w3c.github.io/ServiceWorker/#service-worker-start-status |
| std::unique_ptr<std::string> start_status_; |
| |
| starboard::atomic_bool start_failed_; |
| |
| scoped_refptr<WorkerGlobalScope> worker_global_scope_; |
| }; |
| |
| } // namespace worker |
| } // namespace cobalt |
| |
| #endif // COBALT_WORKER_SERVICE_WORKER_OBJECT_H_ |