blob: bfd6d99f7117e327d2a8d4321c3f07b7a22a3c66 [file] [log] [blame]
// 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_