1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_PER_CONTEXT_DATA_H_ 32 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_PER_CONTEXT_DATA_H_ 33 34 #include <memory> 35 36 #include "gin/public/context_holder.h" 37 #include "gin/public/gin_embedders.h" 38 #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h" 39 #include "third_party/blink/renderer/platform/bindings/v8_global_value_map.h" 40 #include "third_party/blink/renderer/platform/heap/handle.h" 41 #include "third_party/blink/renderer/platform/heap/persistent.h" 42 #include "third_party/blink/renderer/platform/platform_export.h" 43 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" 44 #include "third_party/blink/renderer/platform/wtf/hash_map.h" 45 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" 46 #include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h" 47 #include "third_party/blink/renderer/platform/wtf/vector.h" 48 #include "v8/include/v8.h" 49 50 namespace blink { 51 52 class V0CustomElementBinding; 53 class V8DOMActivityLogger; 54 class V8PerContextData; 55 struct WrapperTypeInfo; 56 57 // Used to hold data that is associated with a single v8::Context object, and 58 // has a 1:1 relationship with v8::Context. 59 class PLATFORM_EXPORT V8PerContextData final { 60 USING_FAST_MALLOC(V8PerContextData); 61 62 public: 63 explicit V8PerContextData(v8::Local<v8::Context>); 64 65 static V8PerContextData* From(v8::Local<v8::Context>); 66 67 ~V8PerContextData(); 68 GetContext()69 v8::Local<v8::Context> GetContext() { return context_.NewLocal(isolate_); } 70 71 // To create JS Wrapper objects, we create a cache of a 'boiler plate' 72 // object, and then simply Clone that object each time we need a new one. 73 // This is faster than going through the full object creation process. CreateWrapperFromCache(const WrapperTypeInfo * type)74 v8::Local<v8::Object> CreateWrapperFromCache(const WrapperTypeInfo* type) { 75 v8::Local<v8::Object> boilerplate = wrapper_boilerplates_.Get(type); 76 return !boilerplate.IsEmpty() ? boilerplate->Clone() 77 : CreateWrapperFromCacheSlowCase(type); 78 } 79 80 // Returns the interface object that is appropriately initialized (e.g. 81 // context-dependent properties are installed). ConstructorForType(const WrapperTypeInfo * type)82 v8::Local<v8::Function> ConstructorForType(const WrapperTypeInfo* type) { 83 v8::Local<v8::Function> interface_object = constructor_map_.Get(type); 84 return (!interface_object.IsEmpty()) ? interface_object 85 : ConstructorForTypeSlowCase(type); 86 } 87 88 v8::Local<v8::Object> PrototypeForType(const WrapperTypeInfo*); 89 90 // Gets the constructor and prototype for a type, if they have already been 91 // created. Returns true if they exist, and sets the existing values in 92 // |prototypeObject| and |interfaceObject|. Otherwise, returns false, and the 93 // values are set to empty objects (non-null). 94 bool GetExistingConstructorAndPrototypeForType( 95 const WrapperTypeInfo*, 96 v8::Local<v8::Object>* prototype_object, 97 v8::Local<v8::Function>* interface_object); 98 99 void AddCustomElementBinding(std::unique_ptr<V0CustomElementBinding>); 100 101 // Gets a Private to store custom element definition IDs on a 102 // constructor that has been registered as a custom element in this 103 // context. This private has to be per-context because the same 104 // constructor could be simultaneously registered as a custom 105 // element in many contexts and they each need to give it a unique 106 // identifier. GetPrivateCustomElementDefinitionId()107 v8::Local<v8::Private> GetPrivateCustomElementDefinitionId() { 108 if (UNLIKELY(private_custom_element_definition_id_.IsEmpty())) { 109 private_custom_element_definition_id_.Set(isolate_, 110 v8::Private::New(isolate_)); 111 } 112 return private_custom_element_definition_id_.NewLocal(isolate_); 113 } 114 ActivityLogger()115 V8DOMActivityLogger* ActivityLogger() const { return activity_logger_; } SetActivityLogger(V8DOMActivityLogger * activity_logger)116 void SetActivityLogger(V8DOMActivityLogger* activity_logger) { 117 activity_logger_ = activity_logger; 118 } 119 120 // Garbage collected classes that use V8PerContextData to hold an instance 121 // should subclass Data, and use addData / clearData / getData to manage the 122 // instance. 123 class PLATFORM_EXPORT Data : public GarbageCollectedMixin {}; 124 125 void AddData(const char* key, Data*); 126 void ClearData(const char* key); 127 Data* GetData(const char* key); 128 129 private: 130 v8::Local<v8::Object> CreateWrapperFromCacheSlowCase(const WrapperTypeInfo*); 131 v8::Local<v8::Function> ConstructorForTypeSlowCase(const WrapperTypeInfo*); 132 133 v8::Isolate* isolate_; 134 135 // For each possible type of wrapper, we keep a boilerplate object. 136 // The boilerplate is used to create additional wrappers of the same type. 137 V8GlobalValueMap<const WrapperTypeInfo*, v8::Object> wrapper_boilerplates_; 138 139 V8GlobalValueMap<const WrapperTypeInfo*, v8::Function> constructor_map_; 140 141 std::unique_ptr<gin::ContextHolder> context_holder_; 142 143 ScopedPersistent<v8::Context> context_; 144 145 ScopedPersistent<v8::Private> private_custom_element_definition_id_; 146 147 typedef Vector<std::unique_ptr<V0CustomElementBinding>> 148 V0CustomElementBindingList; 149 V0CustomElementBindingList custom_element_bindings_; 150 151 // This is owned by a static hash map in V8DOMActivityLogger. 152 V8DOMActivityLogger* activity_logger_; 153 154 using DataMap = HeapHashMap<const char*, Member<Data>>; 155 Persistent<DataMap> data_map_; 156 157 DISALLOW_COPY_AND_ASSIGN(V8PerContextData); 158 }; 159 160 } // namespace blink 161 162 #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_PER_CONTEXT_DATA_H_ 163