worker_script_context_set.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "extensions/renderer/worker_script_context_set.h"
  5. #include <algorithm>
  6. #include <utility>
  7. #include "extensions/renderer/dispatcher.h"
  8. #include "extensions/renderer/script_context.h"
  9. #include "extensions/renderer/worker_thread_util.h"
  10. #include "v8/include/v8-context.h"
  11. namespace extensions {
  12. using ContextVector = std::vector<std::unique_ptr<ScriptContext>>;
  13. namespace {
  14. // Returns an iterator to the ScriptContext associated with |v8_context| from
  15. // |contexts|, or |contexts|->end() if not found.
  16. ContextVector::iterator FindContext(ContextVector* contexts,
  17. v8::Local<v8::Context> v8_context) {
  18. auto context_matches =
  19. [&v8_context](const std::unique_ptr<ScriptContext>& context) {
  20. v8::HandleScope handle_scope(context->isolate());
  21. v8::Context::Scope context_scope(context->v8_context());
  22. return context->v8_context() == v8_context;
  23. };
  24. return std::find_if(contexts->begin(), contexts->end(), context_matches);
  25. }
  26. } // namespace
  27. WorkerScriptContextSet::WorkerScriptContextSet() {}
  28. WorkerScriptContextSet::~WorkerScriptContextSet() {}
  29. void WorkerScriptContextSet::ForEach(
  30. const std::string& extension_id,
  31. content::RenderFrame* render_frame,
  32. const base::RepeatingCallback<void(ScriptContext*)>& callback) {
  33. DCHECK(!render_frame);
  34. ContextVector* contexts = contexts_tls_.Get();
  35. for (const std::unique_ptr<ScriptContext>& context : *contexts) {
  36. DCHECK(!context->GetRenderFrame());
  37. if (!extension_id.empty() && context->GetExtensionID() != extension_id)
  38. continue;
  39. callback.Run(context.get());
  40. }
  41. }
  42. void WorkerScriptContextSet::Insert(std::unique_ptr<ScriptContext> context) {
  43. DCHECK(worker_thread_util::IsWorkerThread())
  44. << "Must be called on a worker thread";
  45. ContextVector* contexts = contexts_tls_.Get();
  46. if (!contexts) {
  47. // First context added for this thread. Create a new set, then wait for
  48. // this thread's shutdown.
  49. contexts = new ContextVector();
  50. contexts_tls_.Set(contexts);
  51. content::WorkerThread::AddObserver(this);
  52. }
  53. CHECK(FindContext(contexts, context->v8_context()) == contexts->end())
  54. << "Worker for " << context->url() << " is already in this set";
  55. contexts->push_back(std::move(context));
  56. }
  57. // static
  58. ScriptContext* WorkerScriptContextSet::GetContextByV8Context(
  59. v8::Local<v8::Context> v8_context) {
  60. DCHECK(worker_thread_util::IsWorkerThread())
  61. << "Must be called on a worker thread";
  62. ContextVector* contexts = contexts_tls_.Get();
  63. if (!contexts)
  64. return nullptr;
  65. auto context_it = FindContext(contexts, v8_context);
  66. return context_it == contexts->end() ? nullptr : context_it->get();
  67. }
  68. void WorkerScriptContextSet::Remove(v8::Local<v8::Context> v8_context,
  69. const GURL& url) {
  70. DCHECK(worker_thread_util::IsWorkerThread())
  71. << "Must be called on a worker thread";
  72. ContextVector* contexts = contexts_tls_.Get();
  73. if (!contexts) {
  74. // Thread has already been torn down, and |v8_context| removed. I'm not
  75. // sure this can actually happen (depends on in what order blink fires
  76. // events), but SW lifetime has bitten us before, so be cautious.
  77. return;
  78. }
  79. auto context_it = FindContext(contexts, v8_context);
  80. CHECK(context_it != contexts->end()) << "Worker for " << url
  81. << " is not in this set";
  82. DCHECK_EQ(url, (*context_it)->url());
  83. (*context_it)->Invalidate();
  84. contexts->erase(context_it);
  85. }
  86. void WorkerScriptContextSet::WillStopCurrentWorkerThread() {
  87. content::WorkerThread::RemoveObserver(this);
  88. ContextVector* contexts = contexts_tls_.Get();
  89. DCHECK(contexts);
  90. for (const auto& context : *contexts)
  91. context->Invalidate();
  92. contexts_tls_.Set(nullptr);
  93. delete contexts;
  94. }
  95. } // namespace extensions