Blink: Move isolated world CSP handling to the core layer.

This CL moves the isolated world CSP handling from DOMWrapperWorld (at the
platform/bindings/layer) to the IsolatedWorldCSP singleton instance (at the
bindings/core layer). The platform/bindings layer doesn't know the concept of a
CSP, hence move it to the bindings/core/ layer. Furthermore, DOMWrapperWorld is
per world, hence it shouldn't necessarily store isolated world specific data.

This is required to store ContentSecurityPolicy instances for isolated worlds to
add CSP support for the isolated worlds. This CL should have no behavior change.

BUG=896041

Change-Id: I0ac995dbae549379934bfadeed148d4ca91c8706
Reviewed-on: https://chromium-review.googlesource.com/c/1354567
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Commit-Queue: Karan Bhatia <karandeepb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612355}
diff --git a/third_party/blink/renderer/bindings/DEPS b/third_party/blink/renderer/bindings/DEPS
index d06b67f..daac63b 100644
--- a/third_party/blink/renderer/bindings/DEPS
+++ b/third_party/blink/renderer/bindings/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+    "+base/logging.h",
     "+base/memory/scoped_refptr.h",
     "+base/process/process_metrics.h",
     "+gin/public",
diff --git a/third_party/blink/renderer/bindings/bindings.gni b/third_party/blink/renderer/bindings/bindings.gni
index bbbd6e8b..104cce2c 100644
--- a/third_party/blink/renderer/bindings/bindings.gni
+++ b/third_party/blink/renderer/bindings/bindings.gni
@@ -70,6 +70,8 @@
                     "core/v8/scheduled_action.h",
                     "core/v8/script_controller.cc",
                     "core/v8/script_controller.h",
+                    "core/v8/isolated_world_csp.cc",
+                    "core/v8/isolated_world_csp.h",
                     "core/v8/script_custom_element_definition.cc",
                     "core/v8/script_custom_element_definition.h",
                     "core/v8/script_custom_element_definition_builder.cc",
diff --git a/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc b/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc
new file mode 100644
index 0000000..c82ca3e
--- /dev/null
+++ b/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc
@@ -0,0 +1,42 @@
+// Copyright 2018 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 "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
+
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+
+// static
+IsolatedWorldCSP& IsolatedWorldCSP::Get() {
+  DCHECK(IsMainThread());
+  DEFINE_STATIC_LOCAL(IsolatedWorldCSP, g_isolated_world_csp, ());
+  return g_isolated_world_csp;
+}
+
+void IsolatedWorldCSP::SetContentSecurityPolicy(int world_id,
+                                                const String& policy) {
+  DCHECK(IsMainThread());
+  DCHECK(DOMWrapperWorld::IsIsolatedWorldId(world_id));
+
+  if (policy.IsEmpty())
+    csp_map_.erase(world_id);
+  else
+    csp_map_.Set(world_id, true);
+}
+
+bool IsolatedWorldCSP::HasContentSecurityPolicy(int world_id) const {
+  DCHECK(IsMainThread());
+  DCHECK(DOMWrapperWorld::IsIsolatedWorldId(world_id));
+
+  auto it = csp_map_.find(world_id);
+  return it != csp_map_.end() ? it->value : false;
+}
+
+IsolatedWorldCSP::IsolatedWorldCSP() = default;
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h b/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h
new file mode 100644
index 0000000..99c61b6
--- /dev/null
+++ b/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h
@@ -0,0 +1,43 @@
+// Copyright 2018 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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ISOLATED_WORLD_CSP_H_
+#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ISOLATED_WORLD_CSP_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// A singleton storing content security policy for each isolated world.
+class CORE_EXPORT IsolatedWorldCSP {
+ public:
+  static IsolatedWorldCSP& Get();
+
+  // Associated an isolated world with a Content Security Policy. Resources
+  // embedded into the main world's DOM from script executed in an isolated
+  // world should be restricted based on the isolated world's DOM, not the
+  // main world's.
+  //
+  // FIXME: Right now, resource injection simply bypasses the main world's
+  // DOM. More work is necessary to allow the isolated world's policy to be
+  // applied correctly.
+  void SetContentSecurityPolicy(int world_id, const String& policy);
+  bool HasContentSecurityPolicy(int world_id) const;
+
+ private:
+  IsolatedWorldCSP();
+
+  // Map from the isolated world |world_id| to a bool denoting if it has a CSP
+  // defined.
+  HashMap<int, bool> csp_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(IsolatedWorldCSP);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ISOLATED_WORLD_CSP_H_
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc
index c090869..f20a13b 100644
--- a/third_party/blink/renderer/core/dom/document_test.cc
+++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -37,6 +37,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/web_application_cache_host.h"
+#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/core/dom/document_fragment.h"
@@ -980,17 +981,19 @@
   ScriptState* isolated_world_without_csp_script_state =
       ToScriptState(frame, *world_without_csp);
   ASSERT_TRUE(world_without_csp->IsIsolatedWorld());
-  EXPECT_FALSE(world_without_csp->IsolatedWorldHasContentSecurityPolicy());
+  EXPECT_FALSE(IsolatedWorldCSP::Get().HasContentSecurityPolicy(
+      kIsolatedWorldWithoutCSPId));
 
   constexpr int kIsolatedWorldWithCSPId = 2;
   scoped_refptr<DOMWrapperWorld> world_with_csp =
       DOMWrapperWorld::EnsureIsolatedWorld(isolate, kIsolatedWorldWithCSPId);
-  DOMWrapperWorld::SetIsolatedWorldContentSecurityPolicy(
+  IsolatedWorldCSP::Get().SetContentSecurityPolicy(
       kIsolatedWorldWithCSPId, String::FromUTF8("script-src *"));
   ScriptState* isolated_world_with_csp_script_state =
       ToScriptState(frame, *world_with_csp);
   ASSERT_TRUE(world_with_csp->IsIsolatedWorld());
-  EXPECT_TRUE(world_with_csp->IsolatedWorldHasContentSecurityPolicy());
+  EXPECT_TRUE(IsolatedWorldCSP::Get().HasContentSecurityPolicy(
+      kIsolatedWorldWithCSPId));
 
   {
     // Since the page is sandboxed, main world script execution shouldn't be
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 67feebb3..18113741 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -32,6 +32,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -1696,7 +1697,7 @@
   if (!world.IsIsolatedWorld())
     return false;
 
-  return world.IsolatedWorldHasContentSecurityPolicy();
+  return IsolatedWorldCSP::Get().HasContentSecurityPolicy(world.GetWorldId());
 }
 
 bool ContentSecurityPolicy::ShouldSendViolationReport(
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 40e1f65..6f286a3 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -133,6 +133,7 @@
 #include "third_party/blink/public/web/web_text_direction.h"
 #include "third_party/blink/public/web/web_tree_scope_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
+#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
 #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
@@ -727,7 +728,7 @@
     int world_id,
     const WebString& policy) {
   DCHECK(GetFrame());
-  DOMWrapperWorld::SetIsolatedWorldContentSecurityPolicy(world_id, policy);
+  IsolatedWorldCSP::Get().SetContentSecurityPolicy(world_id, policy);
 }
 
 void WebLocalFrameImpl::SetIsolatedWorldHumanReadableName(
diff --git a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
index 09177ea..0777e2c 100644
--- a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
+++ b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
@@ -54,11 +54,6 @@
 }
 
 #if DCHECK_IS_ON()
-static bool IsIsolatedWorldId(int world_id) {
-  return DOMWrapperWorld::kMainWorldId < world_id &&
-         world_id < DOMWrapperWorld::kDOMWrapperWorldIsolatedWorldIdLimit;
-}
-
 static bool IsMainWorldId(int world_id) {
   return world_id == DOMWrapperWorld::kMainWorldId;
 }
@@ -212,35 +207,6 @@
   IsolatedWorldHumanReadableNames().Set(world_id, human_readable_name);
 }
 
-typedef HashMap<int, bool> IsolatedWorldContentSecurityPolicyMap;
-static IsolatedWorldContentSecurityPolicyMap&
-IsolatedWorldContentSecurityPolicies() {
-  DCHECK(IsMainThread());
-  DEFINE_STATIC_LOCAL(IsolatedWorldContentSecurityPolicyMap, map, ());
-  return map;
-}
-
-bool DOMWrapperWorld::IsolatedWorldHasContentSecurityPolicy() {
-  DCHECK(this->IsIsolatedWorld());
-  IsolatedWorldContentSecurityPolicyMap& policies =
-      IsolatedWorldContentSecurityPolicies();
-  IsolatedWorldContentSecurityPolicyMap::iterator it =
-      policies.find(GetWorldId());
-  return it == policies.end() ? false : it->value;
-}
-
-void DOMWrapperWorld::SetIsolatedWorldContentSecurityPolicy(
-    int world_id,
-    const String& policy) {
-#if DCHECK_IS_ON()
-  DCHECK(IsIsolatedWorldId(world_id));
-#endif
-  if (!policy.IsEmpty())
-    IsolatedWorldContentSecurityPolicies().Set(world_id, true);
-  else
-    IsolatedWorldContentSecurityPolicies().erase(world_id);
-}
-
 void DOMWrapperWorld::RegisterDOMObjectHolderInternal(
     std::unique_ptr<DOMObjectHolderBase> holder_base) {
   DCHECK(!dom_object_holders_.Contains(holder_base.get()));
diff --git a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
index 76f79ae..fca6477 100644
--- a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
+++ b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
@@ -79,6 +79,11 @@
     kWorker,
   };
 
+  static bool IsIsolatedWorldId(int world_id) {
+    return DOMWrapperWorld::kMainWorldId < world_id &&
+           world_id < DOMWrapperWorld::kDOMWrapperWorldIsolatedWorldIdLimit;
+  }
+
   // Creates a world other than IsolatedWorld. Note this can return nullptr if
   // GenerateWorldIdForType fails to allocate a valid id.
   static scoped_refptr<DOMWrapperWorld> Create(v8::Isolate*, WorldType);
@@ -121,18 +126,6 @@
                                              scoped_refptr<SecurityOrigin>);
   SecurityOrigin* IsolatedWorldSecurityOrigin();
 
-  // Associated an isolated world with a Content Security Policy. Resources
-  // embedded into the main world's DOM from script executed in an isolated
-  // world should be restricted based on the isolated world's DOM, not the
-  // main world's.
-  //
-  // FIXME: Right now, resource injection simply bypasses the main world's
-  // DOM. More work is necessary to allow the isolated world's policy to be
-  // applied correctly.
-  static void SetIsolatedWorldContentSecurityPolicy(int world_id,
-                                                    const String& policy);
-  bool IsolatedWorldHasContentSecurityPolicy();
-
   static bool HasWrapperInAnyWorldInMainThread(ScriptWrappable*);
 
   bool IsMainWorld() const { return world_type_ == WorldType::kMain; }