| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2008, 2009 Google Inc. All rights reserved. | |
| 3 * Copyright (C) 2009 Apple Inc. All rights reserved. | |
| 4 * Copyright (C) 2014 Opera Software ASA. All rights reserved. | |
| 5 * | |
| 6 * Redistribution and use in source and binary forms, with or without | |
| 7 * modification, are permitted provided that the following conditions are | |
| 8 * met: | |
| 9 * | |
| 10 * * Redistributions of source code must retain the above copyright | |
| 11 * notice, this list of conditions and the following disclaimer. | |
| 12 * * Redistributions in binary form must reproduce the above | |
| 13 * copyright notice, this list of conditions and the following disclaimer | |
| 14 * in the documentation and/or other materials provided with the | |
| 15 * distribution. | |
| 16 * * Neither the name of Google Inc. nor the names of its | |
| 17 * contributors may be used to endorse or promote products derived from | |
| 18 * this software without specific prior written permission. | |
| 19 * | |
| 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 31 */ | |
| 32 | |
| 33 #include "sky/engine/config.h" | |
| 34 #include "sky/engine/bindings/core/v8/ScriptController.h" | |
| 35 | |
| 36 #include "bindings/core/v8/V8Event.h" | |
| 37 #include "bindings/core/v8/V8HTMLElement.h" | |
| 38 #include "bindings/core/v8/V8Window.h" | |
| 39 #include "sky/engine/bindings/core/v8/BindingSecurity.h" | |
| 40 #include "sky/engine/bindings/core/v8/ScriptCallStackFactory.h" | |
| 41 #include "sky/engine/bindings/core/v8/ScriptSourceCode.h" | |
| 42 #include "sky/engine/bindings/core/v8/ScriptValue.h" | |
| 43 #include "sky/engine/bindings/core/v8/V8Binding.h" | |
| 44 #include "sky/engine/bindings/core/v8/V8GCController.h" | |
| 45 #include "sky/engine/bindings/core/v8/V8PerContextData.h" | |
| 46 #include "sky/engine/bindings/core/v8/V8ScriptRunner.h" | |
| 47 #include "sky/engine/bindings/core/v8/WindowProxy.h" | |
| 48 #include "sky/engine/core/app/Module.h" | |
| 49 #include "sky/engine/core/dom/Document.h" | |
| 50 #include "sky/engine/core/dom/Node.h" | |
| 51 #include "sky/engine/core/events/Event.h" | |
| 52 #include "sky/engine/core/events/EventListener.h" | |
| 53 #include "sky/engine/core/frame/LocalDOMWindow.h" | |
| 54 #include "sky/engine/core/frame/LocalFrame.h" | |
| 55 #include "sky/engine/core/frame/Settings.h" | |
| 56 #include "sky/engine/core/html/imports/HTMLImportChild.h" | |
| 57 #include "sky/engine/core/html/imports/HTMLImportLoader.h" | |
| 58 #include "sky/engine/core/html/parser/HTMLDocumentParser.h" | |
| 59 #include "sky/engine/core/loader/FrameLoaderClient.h" | |
| 60 #include "sky/engine/platform/NotImplemented.h" | |
| 61 #include "sky/engine/platform/TraceEvent.h" | |
| 62 #include "sky/engine/platform/Widget.h" | |
| 63 #include "sky/engine/public/platform/Platform.h" | |
| 64 #include "sky/engine/core/inspector/ScriptCallStack.h" | |
| 65 #include "sky/engine/wtf/CurrentTime.h" | |
| 66 #include "sky/engine/wtf/StdLibExtras.h" | |
| 67 #include "sky/engine/wtf/StringExtras.h" | |
| 68 #include "sky/engine/wtf/text/CString.h" | |
| 69 #include "sky/engine/wtf/text/StringBuilder.h" | |
| 70 #include "sky/engine/wtf/text/TextPosition.h" | |
| 71 | |
| 72 namespace blink { | |
| 73 | |
| 74 bool ScriptController::canAccessFromCurrentOrigin(LocalFrame *frame) | |
| 75 { | |
| 76 if (!frame) | |
| 77 return false; | |
| 78 v8::Isolate* isolate = toIsolate(frame); | |
| 79 return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(is
olate, frame); | |
| 80 } | |
| 81 | |
| 82 ScriptController::ScriptController(LocalFrame* frame) | |
| 83 : m_frame(frame) | |
| 84 , m_sourceURL(0) | |
| 85 , m_isolate(v8::Isolate::GetCurrent()) | |
| 86 , m_windowProxy(WindowProxy::create(frame, DOMWrapperWorld::mainWorld(), m_i
solate)) | |
| 87 { | |
| 88 } | |
| 89 | |
| 90 ScriptController::~ScriptController() | |
| 91 { | |
| 92 // WindowProxy::clearForClose() must be invoked before destruction starts. | |
| 93 ASSERT(!m_windowProxy->isContextInitialized()); | |
| 94 } | |
| 95 | |
| 96 void ScriptController::clearForClose() | |
| 97 { | |
| 98 double start = currentTime(); | |
| 99 m_windowProxy->clearForClose(); | |
| 100 for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_i
solatedWorlds.end(); ++iter) | |
| 101 iter->value->clearForClose(); | |
| 102 blink::Platform::current()->histogramCustomCounts("WebCore.ScriptController.
clearForClose", (currentTime() - start) * 1000, 0, 10000, 50); | |
| 103 } | |
| 104 | |
| 105 v8::Local<v8::Value> ScriptController::callFunction(v8::Handle<v8::Function> fun
ction, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]) | |
| 106 { | |
| 107 // Keep LocalFrame (and therefore ScriptController) alive. | |
| 108 RefPtr<LocalFrame> protect(m_frame); | |
| 109 return ScriptController::callFunction(m_frame->document(), function, receive
r, argc, info, m_isolate); | |
| 110 } | |
| 111 | |
| 112 v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v
8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::
Handle<v8::Value> info[], v8::Isolate* isolate) | |
| 113 { | |
| 114 return V8ScriptRunner::callFunction(function, context, receiver, argc, info,
isolate); | |
| 115 } | |
| 116 | |
| 117 v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8
::Context> context, const ScriptSourceCode& source) | |
| 118 { | |
| 119 v8::Local<v8::Value> result; | |
| 120 { | |
| 121 V8CacheOptions v8CacheOptions(V8CacheOptionsOff); | |
| 122 if (m_frame->settings()) | |
| 123 v8CacheOptions = m_frame->settings()->v8CacheOptions(); | |
| 124 | |
| 125 // Isolate exceptions that occur when compiling and executing | |
| 126 // the code. These exceptions should not interfere with | |
| 127 // javascript code we might evaluate from C++ when returning | |
| 128 // from here. | |
| 129 v8::TryCatch tryCatch; | |
| 130 tryCatch.SetVerbose(true); | |
| 131 | |
| 132 v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, m_
isolate, v8CacheOptions); | |
| 133 | |
| 134 // Keep LocalFrame (and therefore ScriptController) alive. | |
| 135 RefPtr<LocalFrame> protect(m_frame); | |
| 136 result = V8ScriptRunner::runCompiledScript(script, m_frame->document(),
m_isolate); | |
| 137 ASSERT(!tryCatch.HasCaught() || result.IsEmpty()); | |
| 138 } | |
| 139 | |
| 140 return result; | |
| 141 } | |
| 142 | |
| 143 bool ScriptController::initializeMainWorld() | |
| 144 { | |
| 145 if (m_windowProxy->isContextInitialized()) | |
| 146 return false; | |
| 147 return windowProxy(DOMWrapperWorld::mainWorld())->isContextInitialized(); | |
| 148 } | |
| 149 | |
| 150 WindowProxy* ScriptController::existingWindowProxy(DOMWrapperWorld& world) | |
| 151 { | |
| 152 if (world.isMainWorld()) | |
| 153 return m_windowProxy->isContextInitialized() ? m_windowProxy.get() : 0; | |
| 154 return 0; | |
| 155 } | |
| 156 | |
| 157 WindowProxy* ScriptController::windowProxy(DOMWrapperWorld& world) | |
| 158 { | |
| 159 m_windowProxy->initializeIfNeeded(); | |
| 160 return m_windowProxy.get(); | |
| 161 } | |
| 162 | |
| 163 V8Extensions& ScriptController::registeredExtensions() | |
| 164 { | |
| 165 DEFINE_STATIC_LOCAL(V8Extensions, extensions, ()); | |
| 166 return extensions; | |
| 167 } | |
| 168 | |
| 169 void ScriptController::registerExtensionIfNeeded(v8::Extension* extension) | |
| 170 { | |
| 171 const V8Extensions& extensions = registeredExtensions(); | |
| 172 for (size_t i = 0; i < extensions.size(); ++i) { | |
| 173 if (extensions[i] == extension) | |
| 174 return; | |
| 175 } | |
| 176 v8::RegisterExtension(extension); | |
| 177 registeredExtensions().append(extension); | |
| 178 } | |
| 179 | |
| 180 void ScriptController::clearWindowProxy() | |
| 181 { | |
| 182 double start = currentTime(); | |
| 183 // V8 binding expects ScriptController::clearWindowProxy only be called | |
| 184 // when a frame is loading a new page. This creates a new context for the ne
w page. | |
| 185 | |
| 186 m_windowProxy->clearForNavigation(); | |
| 187 for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_i
solatedWorlds.end(); ++iter) | |
| 188 iter->value->clearForNavigation(); | |
| 189 blink::Platform::current()->histogramCustomCounts("WebCore.ScriptController.
clearWindowProxy", (currentTime() - start) * 1000, 0, 10000, 50); | |
| 190 } | |
| 191 | |
| 192 void ScriptController::setCaptureCallStackForUncaughtExceptions(bool value) | |
| 193 { | |
| 194 v8::V8::SetCaptureStackTraceForUncaughtExceptions(value, ScriptCallStack::ma
xCallStackSizeToCapture, stackTraceOptions); | |
| 195 } | |
| 196 | |
| 197 void ScriptController::setWorldDebugId(int debuggerId) | |
| 198 { | |
| 199 ASSERT(debuggerId > 0); | |
| 200 if (!m_windowProxy || !m_windowProxy->isContextInitialized()) | |
| 201 return; | |
| 202 v8::HandleScope scope(m_isolate); | |
| 203 v8::Local<v8::Context> context = m_windowProxy->context(); | |
| 204 V8PerContextDebugData::setContextDebugData(context, "page", debuggerId); | |
| 205 } | |
| 206 | |
| 207 void ScriptController::updateDocument() | |
| 208 { | |
| 209 // For an uninitialized main window windowProxy, do not incur the cost of co
ntext initialization. | |
| 210 if (!m_windowProxy->isGlobalInitialized()) | |
| 211 return; | |
| 212 | |
| 213 if (!initializeMainWorld()) | |
| 214 windowProxy(DOMWrapperWorld::mainWorld())->updateDocument(); | |
| 215 } | |
| 216 | |
| 217 void ScriptController::executeScriptInMainWorld(const String& script) | |
| 218 { | |
| 219 v8::HandleScope handleScope(m_isolate); | |
| 220 evaluateScriptInMainWorld(ScriptSourceCode(script)); | |
| 221 } | |
| 222 | |
| 223 void ScriptController::executeScriptInMainWorld(const ScriptSourceCode& sourceCo
de) | |
| 224 { | |
| 225 v8::HandleScope handleScope(m_isolate); | |
| 226 evaluateScriptInMainWorld(sourceCode); | |
| 227 } | |
| 228 | |
| 229 v8::Local<v8::Value> ScriptController::executeScriptInMainWorldAndReturnValue(co
nst ScriptSourceCode& sourceCode) | |
| 230 { | |
| 231 return evaluateScriptInMainWorld(sourceCode); | |
| 232 } | |
| 233 | |
| 234 v8::Local<v8::Value> ScriptController::evaluateScriptInMainWorld(const ScriptSou
rceCode& sourceCode) | |
| 235 { | |
| 236 String sourceURL = sourceCode.url(); | |
| 237 const String* savedSourceURL = m_sourceURL; | |
| 238 m_sourceURL = &sourceURL; | |
| 239 | |
| 240 v8::EscapableHandleScope handleScope(m_isolate); | |
| 241 v8::Handle<v8::Context> context = toV8Context(m_frame, DOMWrapperWorld::main
World()); | |
| 242 if (context.IsEmpty()) | |
| 243 return v8::Local<v8::Value>(); | |
| 244 | |
| 245 ScriptState* scriptState = ScriptState::from(context); | |
| 246 ScriptState::Scope scope(scriptState); | |
| 247 | |
| 248 RefPtr<LocalFrame> protect(m_frame); | |
| 249 | |
| 250 v8::Local<v8::Value> object = executeScriptAndReturnValue(scriptState->conte
xt(), sourceCode); | |
| 251 m_sourceURL = savedSourceURL; | |
| 252 | |
| 253 if (object.IsEmpty()) | |
| 254 return v8::Local<v8::Value>(); | |
| 255 | |
| 256 return handleScope.Escape(object); | |
| 257 } | |
| 258 | |
| 259 void ScriptController::executeModuleScript(AbstractModule& module, const String&
source, const TextPosition& textPosition) | |
| 260 { | |
| 261 v8::HandleScope handleScope(m_isolate); | |
| 262 v8::Handle<v8::Context> context = toV8Context(m_frame, DOMWrapperWorld::main
World()); | |
| 263 if (context.IsEmpty()) | |
| 264 return; | |
| 265 | |
| 266 ScriptState* scriptState = ScriptState::from(context); | |
| 267 ScriptState::Scope scope(scriptState); | |
| 268 | |
| 269 RefPtr<LocalFrame> protect(m_frame); | |
| 270 | |
| 271 v8::TryCatch tryCatch; | |
| 272 tryCatch.SetVerbose(true); | |
| 273 | |
| 274 V8ScriptModule scriptModule; | |
| 275 scriptModule.resourceName = module.url(); | |
| 276 scriptModule.textPosition = textPosition; | |
| 277 scriptModule.moduleObject = toV8(&module, context->Global(), m_isolate); | |
| 278 scriptModule.source = source; | |
| 279 | |
| 280 if (HTMLImport* parent = module.document()->import()) { | |
| 281 for (HTMLImportChild* child = static_cast<HTMLImportChild*>(parent->firs
tChild()); | |
| 282 child; child = static_cast<HTMLImportChild*>(child->next())) { | |
| 283 if (Element* link = child->link()) { | |
| 284 String name = link->getAttribute(HTMLNames::asAttr); | |
| 285 if (!name.isEmpty()) { | |
| 286 scriptModule.formalDependencies.append(name); | |
| 287 v8::Handle<v8::Value> actual; | |
| 288 if (Module* childModule = child->module()) | |
| 289 actual = childModule->exports(scriptState).v8Value(); | |
| 290 if (actual.IsEmpty()) | |
| 291 actual = v8::Undefined(m_isolate); | |
| 292 scriptModule.resolvedDependencies.append(actual); | |
| 293 } | |
| 294 } | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 V8ScriptRunner::runModule(m_isolate, m_frame->document(), scriptModule); | |
| 299 } | |
| 300 | |
| 301 } // namespace blink | |
| OLD | NEW |