| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <map> |
| #include <memory> |
| |
| #include "base/memory/ref_counted.h" |
| #include "base/synchronization/condition_variable.h" |
| #include "base/synchronization/lock.h" |
| #include "content/common/content_export.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" |
| |
| #ifndef CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_ |
| #define CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_ |
| |
| namespace content { |
| |
| // ThreadSafeScriptContainer stores the scripts of a service worker for |
| // startup. This container is created for each service worker. The IO thread |
| // adds scripts to the container, and the worker thread takes the scripts. |
| // |
| // This class uses explicit synchronization because it needs to support |
| // synchronous importScripts() from the worker thread. |
| // |
| // This class is RefCounted because there is no ordering guarantee of lifetime |
| // of its owners, i.e. WebServiceWorkerInstalledScriptsManagerImpl and its |
| // Internal class. WebSWInstalledScriptsManagerImpl is destroyed earlier than |
| // Internal if the worker is terminated before all scripts are streamed, and |
| // Internal is destroyed earlier if all of scripts are received before finishing |
| // script evaluation. |
| class CONTENT_EXPORT ThreadSafeScriptContainer |
| : public base::RefCountedThreadSafe<ThreadSafeScriptContainer> { |
| public: |
| using Data = blink::WebServiceWorkerInstalledScriptsManager::RawScriptData; |
| |
| REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); |
| ThreadSafeScriptContainer(); |
| |
| // Called on the IO thread. |
| void AddOnIOThread(const GURL& url, std::unique_ptr<Data> data); |
| |
| // Called on the worker thread. |
| bool ExistsOnWorkerThread(const GURL& url); |
| |
| // Waits until the script is added. The thread is blocked until the script is |
| // available. Returns false if an error happens and the waiting script won't |
| // be available forever. |
| // Called on the worker thread. |
| bool WaitOnIOThread(const GURL& url); |
| |
| // Returns nullptr if the script has already been taken. |
| // Called on the worker thread. |
| std::unique_ptr<Data> TakeOnWorkerThread(const GURL& url); |
| |
| // Called if no more data will be added. |
| // Called on the IO thread. |
| void OnAllDataAddedOnIOThread(); |
| |
| private: |
| friend class base::RefCountedThreadSafe<ThreadSafeScriptContainer>; |
| ~ThreadSafeScriptContainer(); |
| |
| // |lock_| protects |waiting_cv_|, |script_data_|, |waiting_url_| and |
| // |are_all_data_added_|. |
| base::Lock lock_; |
| // |waiting_cv_| is signaled when a script whose url matches to |waiting_url| |
| // is added, or OnAllDataAdded is called. The worker thread waits on this, and |
| // the IO thread signals it. |
| base::ConditionVariable waiting_cv_; |
| std::map<GURL, std::unique_ptr<Data>> script_data_; |
| GURL waiting_url_; |
| bool are_all_data_added_; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_ |