2 * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
34 #include "CSSMutableStyleDeclaration.h"
35 #include "CachedMetadata.h"
37 #include "DateExtension.h"
39 #include "DocumentLoader.h"
41 #include "FrameLoaderClient.h"
42 #include "IDBDatabaseException.h"
43 #include "IDBFactoryBackendInterface.h"
44 #include "IDBPendingTransactionMonitor.h"
45 #include "InspectorInstrumentation.h"
47 #include "PageGroup.h"
48 #include "PlatformSupport.h"
49 #include "ScriptSourceCode.h"
50 #include "SecurityOrigin.h"
52 #include "StorageNamespace.h"
53 #include "V8Binding.h"
54 #include "V8BindingState.h"
55 #include "V8Collection.h"
56 #include "V8DOMCoreException.h"
58 #include "V8DOMWindow.h"
59 #include "V8EventException.h"
60 #include "V8FileException.h"
61 #include "V8HiddenPropertyName.h"
62 #include "V8IsolatedContext.h"
63 #include "V8OperationNotAllowedException.h"
64 #include "V8RangeException.h"
65 #include "V8SQLException.h"
66 #include "V8XMLHttpRequestException.h"
67 #include "V8XPathException.h"
68 #include "WorkerContext.h"
69 #include "WorkerContextExecutionProxy.h"
71 #if ENABLE(INDEXED_DATABASE)
72 #include "V8IDBDatabaseException.h"
76 #include "V8SVGException.h"
82 #include <wtf/Assertions.h>
83 #include <wtf/OwnArrayPtr.h>
84 #include <wtf/OwnPtr.h>
85 #include <wtf/StdLibExtras.h>
86 #include <wtf/StringExtras.h>
87 #include <wtf/UnusedParam.h>
88 #include <wtf/text/WTFString.h>
92 // Static list of registered extensions
93 V8Extensions V8Proxy::m_extensions;
95 void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate> instance,
96 v8::Handle<v8::ObjectTemplate> proto,
97 const BatchedAttribute* attributes,
98 size_t attributeCount)
100 for (size_t i = 0; i < attributeCount; ++i)
101 configureAttribute(instance, proto, attributes[i]);
104 void batchConfigureCallbacks(v8::Handle<v8::ObjectTemplate> proto,
105 v8::Handle<v8::Signature> signature,
106 v8::PropertyAttribute attributes,
107 const BatchedCallback* callbacks,
108 size_t callbackCount)
110 for (size_t i = 0; i < callbackCount; ++i) {
111 proto->Set(v8::String::New(callbacks[i].name),
112 v8::FunctionTemplate::New(callbacks[i].callback,
113 v8::Handle<v8::Value>(),
119 void batchConfigureConstants(v8::Handle<v8::FunctionTemplate> functionDescriptor,
120 v8::Handle<v8::ObjectTemplate> proto,
121 const BatchedConstant* constants,
122 size_t constantCount)
124 for (size_t i = 0; i < constantCount; ++i) {
125 const BatchedConstant* constant = &constants[i];
126 functionDescriptor->Set(v8::String::New(constant->name), v8::Integer::New(constant->value), v8::ReadOnly);
127 proto->Set(v8::String::New(constant->name), v8::Integer::New(constant->value), v8::ReadOnly);
131 typedef HashMap<Node*, v8::Object*> DOMNodeMap;
132 typedef HashMap<void*, v8::Object*> DOMObjectMap;
133 typedef HashMap<int, v8::FunctionTemplate*> FunctionTemplateMap;
135 static void addMessageToConsole(Page* page, const String& message, const String& sourceID, unsigned lineNumber)
138 Console* console = page->mainFrame()->domWindow()->console();
139 console->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, lineNumber, sourceID);
142 void logInfo(Frame* frame, const String& message, const String& url)
144 Page* page = frame->page();
147 addMessageToConsole(page, message, url, 0);
150 void V8Proxy::reportUnsafeAccessTo(Frame* target)
153 Document* targetDocument = target->document();
157 Frame* source = V8Proxy::retrieveFrameForEnteredContext();
160 Page* page = source->page();
164 Document* sourceDocument = source->document();
166 return; // Ignore error if the source document is gone.
168 // FIXME: This error message should contain more specifics of why the same
169 // origin check has failed.
170 String str = "Unsafe JavaScript attempt to access frame with URL " + targetDocument->url().string() +
171 " from frame with URL " + sourceDocument->url().string() + ". Domains, protocols and ports must match.\n";
173 // Build a console message with fake source ID and line number.
174 const String kSourceID = "";
175 const int kLineNumber = 1;
177 // NOTE: Safari prints the message in the target page, but it seems like
178 // it should be in the source page. Even for delayed messages, we put it in
180 addMessageToConsole(page, str, kSourceID, kLineNumber);
183 static void handleFatalErrorInV8()
185 // FIXME: We temporarily deal with V8 internal error situations
186 // such as out-of-memory by crashing the renderer.
190 V8Proxy::V8Proxy(Frame* frame)
192 , m_windowShell(V8DOMWindowShell::create(frame))
193 , m_inlineCode(false)
201 windowShell()->destroyGlobal();
204 v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* scriptData)
206 const uint16_t* fileNameString = fromWebCoreString(fileName);
207 v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length());
208 v8::Handle<v8::Integer> line = v8::Integer::New(scriptStartPosition.m_line.zeroBasedInt());
209 v8::Handle<v8::Integer> column = v8::Integer::New(scriptStartPosition.m_column.zeroBasedInt());
210 v8::ScriptOrigin origin(name, line, column);
211 v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin, scriptData);
215 bool V8Proxy::handleOutOfMemory()
217 v8::Local<v8::Context> context = v8::Context::GetCurrent();
219 if (!context->HasOutOfMemoryException())
222 // Warning, error, disable JS for this frame?
223 Frame* frame = V8Proxy::retrieveFrame(context);
225 V8Proxy* proxy = V8Proxy::retrieve(frame);
227 // Clean m_context, and event handlers.
228 proxy->clearForClose();
230 proxy->windowShell()->destroyGlobal();
233 #if PLATFORM(CHROMIUM)
234 PlatformSupport::notifyJSOutOfMemory(frame);
238 Settings* settings = frame->settings();
240 settings->setJavaScriptEnabled(false);
245 void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup)
247 // FIXME: This will need to get reorganized once we have a windowShell for the isolated world.
248 windowShell()->initContextIfNeeded();
250 v8::HandleScope handleScope;
251 V8IsolatedContext* isolatedContext = 0;
254 IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID);
255 if (iter != m_isolatedWorlds.end()) {
256 isolatedContext = iter->second;
258 isolatedContext = new V8IsolatedContext(this, extensionGroup, worldID);
259 if (isolatedContext->context().IsEmpty()) {
260 delete isolatedContext;
264 // FIXME: We should change this to using window shells to match JSC.
265 m_isolatedWorlds.set(worldID, isolatedContext);
267 // Setup context id for JS debugger.
268 if (!setInjectedScriptContextDebugId(isolatedContext->context())) {
269 m_isolatedWorlds.take(worldID);
270 delete isolatedContext;
275 IsolatedWorldSecurityOriginMap::iterator securityOriginIter = m_isolatedWorldSecurityOrigins.find(worldID);
276 if (securityOriginIter != m_isolatedWorldSecurityOrigins.end())
277 isolatedContext->setSecurityOrigin(securityOriginIter->second);
279 isolatedContext = new V8IsolatedContext(this, extensionGroup, worldID);
280 if (isolatedContext->context().IsEmpty()) {
281 delete isolatedContext;
286 v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolatedContext->context());
287 v8::Context::Scope context_scope(context);
288 for (size_t i = 0; i < sources.size(); ++i)
289 evaluate(sources[i], 0);
292 isolatedContext->destroy();
295 void V8Proxy::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> prpSecurityOriginIn)
298 RefPtr<SecurityOrigin> securityOrigin = prpSecurityOriginIn;
299 m_isolatedWorldSecurityOrigins.set(worldID, securityOrigin);
300 IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID);
301 if (iter != m_isolatedWorlds.end())
302 iter->second->setSecurityOrigin(securityOrigin);
305 bool V8Proxy::setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext)
307 // Setup context id for JS debugger.
308 v8::Context::Scope contextScope(targetContext);
309 v8::Handle<v8::Context> context = windowShell()->context();
310 if (context.IsEmpty())
312 int debugId = contextDebugId(context);
316 snprintf(buffer, sizeof(buffer), "injected");
318 snprintf(buffer, sizeof(buffer), "injected,%d", debugId);
319 targetContext->SetData(v8::String::New(buffer));
324 PassOwnPtr<v8::ScriptData> V8Proxy::precompileScript(v8::Handle<v8::String> code, CachedScript* cachedScript)
326 // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from
327 // the CachedScript. If the format changes, this ID should be changed too.
328 static const unsigned dataTypeID = 0xECC13BD7;
330 // Very small scripts are not worth the effort to preparse.
331 static const int minPreparseLength = 1024;
333 if (!cachedScript || code->Length() < minPreparseLength)
336 CachedMetadata* cachedMetadata = cachedScript->cachedMetadata(dataTypeID);
338 return adoptPtr(v8::ScriptData::New(cachedMetadata->data(), cachedMetadata->size()));
340 OwnPtr<v8::ScriptData> scriptData = adoptPtr(v8::ScriptData::PreCompile(code));
341 cachedScript->setCachedMetadata(dataTypeID, scriptData->Data(), scriptData->Length());
343 return scriptData.release();
346 bool V8Proxy::executingScript() const
351 v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* node)
353 ASSERT(v8::Context::InContext());
355 V8GCController::checkMemoryUsage();
357 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, source.url().isNull() ? String() : source.url().string(), source.startLine());
359 v8::Local<v8::Value> result;
361 // Isolate exceptions that occur when compiling and executing
362 // the code. These exceptions should not interfere with
363 // javascript code we might evaluate from C++ when returning
365 v8::TryCatch tryCatch;
366 tryCatch.SetVerbose(true);
368 // Compile the script.
369 v8::Local<v8::String> code = v8ExternalString(source.source());
370 #if PLATFORM(CHROMIUM)
371 PlatformSupport::traceEventBegin("v8.compile", node, "");
373 OwnPtr<v8::ScriptData> scriptData = precompileScript(code, source.cachedScript());
375 // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
376 // 1, whereas v8 starts at 0.
377 v8::Handle<v8::Script> script = compileScript(code, source.url(), WTF::toZeroBasedTextPosition(source.startPosition()), scriptData.get());
378 #if PLATFORM(CHROMIUM)
379 PlatformSupport::traceEventEnd("v8.compile", node, "");
381 PlatformSupport::traceEventBegin("v8.run", node, "");
383 // Set inlineCode to true for <a href="javascript:doSomething()">
384 // and false for <script>doSomething</script>. We make a rough guess at
385 // this based on whether the script source has a URL.
386 result = runScript(script, source.url().string().isNull());
388 #if PLATFORM(CHROMIUM)
389 PlatformSupport::traceEventEnd("v8.run", node, "");
392 InspectorInstrumentation::didEvaluateScript(cookie);
397 v8::Local<v8::Value> V8Proxy::runScript(v8::Handle<v8::Script> script, bool isInlineCode)
399 if (script.IsEmpty())
400 return notHandledByInterceptor();
402 V8GCController::checkMemoryUsage();
403 // Compute the source string and prevent against infinite recursion.
404 if (m_recursion >= kMaxRecursionDepth) {
405 v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')");
406 // FIXME: Ideally, we should be able to re-use the origin of the
407 // script passed to us as the argument instead of using an empty string
409 script = compileScript(code, "", TextPosition0::minimumPosition());
412 if (handleOutOfMemory())
413 ASSERT(script.IsEmpty());
415 if (script.IsEmpty())
416 return notHandledByInterceptor();
418 // Save the previous value of the inlineCode flag and update the flag for
419 // the duration of the script invocation.
420 bool previousInlineCode = inlineCode();
421 setInlineCode(isInlineCode);
423 // Keep Frame (and therefore ScriptController and V8Proxy) alive.
424 RefPtr<Frame> protect(frame());
426 // Run the script and keep track of the current recursion depth.
427 v8::Local<v8::Value> result;
428 v8::TryCatch tryCatch;
429 tryCatch.SetVerbose(true);
432 result = script->Run();
436 // Release the storage mutex if applicable.
437 didLeaveScriptContext();
439 if (handleOutOfMemory())
440 ASSERT(result.IsEmpty());
442 // Handle V8 internal error situation (Out-of-memory).
443 if (tryCatch.HasCaught()) {
444 ASSERT(result.IsEmpty());
445 return notHandledByInterceptor();
448 if (result.IsEmpty())
449 return notHandledByInterceptor();
451 // Restore inlineCode flag.
452 setInlineCode(previousInlineCode);
454 if (v8::V8::IsDead())
455 handleFatalErrorInV8();
460 v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
462 V8GCController::checkMemoryUsage();
464 // Keep Frame (and therefore ScriptController and V8Proxy) alive.
465 RefPtr<Frame> protect(frame());
467 v8::Local<v8::Value> result;
469 if (m_recursion >= kMaxRecursionDepth) {
470 v8::Local<v8::String> code = v8::String::New("throw new RangeError('Maximum call stack size exceeded.')");
473 v8::Local<v8::Script> script = v8::Script::Compile(code);
474 if (script.IsEmpty())
481 result = V8Proxy::instrumentedCallFunction(m_frame->page(), function, receiver, argc, args);
485 // Release the storage mutex if applicable.
486 didLeaveScriptContext();
488 if (v8::V8::IsDead())
489 handleFatalErrorInV8();
494 v8::Local<v8::Value> V8Proxy::callFunctionWithoutFrame(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
496 V8GCController::checkMemoryUsage();
497 v8::Local<v8::Value> result = function->Call(receiver, argc, args);
499 if (v8::V8::IsDead())
500 handleFatalErrorInV8();
505 v8::Local<v8::Value> V8Proxy::instrumentedCallFunction(Page* page, v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
507 InspectorInstrumentationCookie cookie;
508 if (InspectorInstrumentation::hasFrontends()) {
509 String resourceName("undefined");
511 v8::ScriptOrigin origin = function->GetScriptOrigin();
512 if (!origin.ResourceName().IsEmpty()) {
513 resourceName = toWebCoreString(origin.ResourceName());
514 lineNumber = function->GetScriptLineNumber() + 1;
516 cookie = InspectorInstrumentation::willCallFunction(page, resourceName, lineNumber);
518 v8::Local<v8::Value> result = function->Call(receiver, argc, args);
519 InspectorInstrumentation::didCallFunction(cookie);
523 v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor, int argc, v8::Handle<v8::Value> args[])
525 // No artificial limitations on the depth of recursion, see comment in
526 // V8Proxy::callFunction.
527 v8::Local<v8::Value> result;
529 result = constructor->NewInstance(argc, args);
532 if (v8::V8::IsDead())
533 handleFatalErrorInV8();
538 DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context)
540 v8::Handle<v8::Object> global = context->Global();
541 ASSERT(!global.IsEmpty());
542 global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global);
543 ASSERT(!global.IsEmpty());
544 return V8DOMWindow::toNative(global);
547 Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context)
549 DOMWindow* window = retrieveWindow(context);
550 Frame* frame = window->frame();
551 if (frame && frame->domWindow() == window)
553 // We return 0 here because |context| is detached from the Frame. If we
554 // did return |frame| we could get in trouble because the frame could be
555 // navigated to another security origin.
559 Frame* V8Proxy::retrieveFrameForEnteredContext()
561 v8::Handle<v8::Context> context = v8::Context::GetEntered();
562 if (context.IsEmpty())
564 return retrieveFrame(context);
567 Frame* V8Proxy::retrieveFrameForCurrentContext()
569 v8::Handle<v8::Context> context = v8::Context::GetCurrent();
570 if (context.IsEmpty())
572 return retrieveFrame(context);
575 Frame* V8Proxy::retrieveFrameForCallingContext()
577 v8::Handle<v8::Context> context = v8::Context::GetCalling();
578 if (context.IsEmpty())
580 return retrieveFrame(context);
583 V8Proxy* V8Proxy::retrieve()
585 DOMWindow* window = retrieveWindow(currentContext());
587 return retrieve(window->frame());
590 V8Proxy* V8Proxy::retrieve(Frame* frame)
594 return frame->script()->canExecuteScripts(NotAboutToExecuteScript) ? frame->script()->proxy() : 0;
597 V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context)
599 if (!context || !context->isDocument())
601 return retrieve(static_cast<Document*>(context)->frame());
604 void V8Proxy::didLeaveScriptContext()
606 Page* page = m_frame->page();
609 // If we've just left a top level script context and local storage has been
610 // instantiated, we must ensure that any storage locks have been freed.
611 // Per http://dev.w3.org/html5/spec/Overview.html#storage-mutex
614 #if ENABLE(INDEXED_DATABASE)
615 // If we've just left a script context and indexed database has been
616 // instantiated, we must let its transaction coordinator know so it can terminate
617 // any not-yet-started transactions.
618 IDBPendingTransactionMonitor::abortPendingTransactions();
619 #endif // ENABLE(INDEXED_DATABASE)
620 if (page->group().hasLocalStorage())
621 page->group().localStorage()->unlock();
624 void V8Proxy::resetIsolatedWorlds()
626 for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin();
627 iter != m_isolatedWorlds.end(); ++iter) {
628 iter->second->destroy();
630 m_isolatedWorlds.clear();
631 m_isolatedWorldSecurityOrigins.clear();
634 void V8Proxy::clearForClose()
636 resetIsolatedWorlds();
637 windowShell()->clearForClose();
640 void V8Proxy::clearForNavigation()
642 resetIsolatedWorlds();
643 windowShell()->clearForNavigation();
646 void V8Proxy::setDOMException(int exceptionCode)
648 if (exceptionCode <= 0)
651 ExceptionCodeDescription description;
652 getExceptionCodeDescription(exceptionCode, description);
654 v8::Handle<v8::Value> exception;
655 switch (description.type) {
656 case DOMExceptionType:
657 exception = toV8(DOMCoreException::create(description));
659 case RangeExceptionType:
660 exception = toV8(RangeException::create(description));
662 case EventExceptionType:
663 exception = toV8(EventException::create(description));
665 case XMLHttpRequestExceptionType:
666 exception = toV8(XMLHttpRequestException::create(description));
669 case SVGExceptionType:
670 exception = toV8(SVGException::create(description));
674 case XPathExceptionType:
675 exception = toV8(XPathException::create(description));
679 case SQLExceptionType:
680 exception = toV8(SQLException::create(description));
683 #if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
684 case FileExceptionType:
685 exception = toV8(FileException::create(description));
687 case OperationNotAllowedExceptionType:
688 exception = toV8(OperationNotAllowedException::create(description));
691 #if ENABLE(INDEXED_DATABASE)
692 case IDBDatabaseExceptionType:
693 exception = toV8(IDBDatabaseException::create(description));
697 ASSERT_NOT_REACHED();
700 if (!exception.IsEmpty())
701 v8::ThrowException(exception);
704 v8::Handle<v8::Value> V8Proxy::throwError(ErrorType type, const char* message)
708 return v8::ThrowException(v8::Exception::RangeError(v8String(message)));
710 return v8::ThrowException(v8::Exception::ReferenceError(v8String(message)));
712 return v8::ThrowException(v8::Exception::SyntaxError(v8String(message)));
714 return v8::ThrowException(v8::Exception::TypeError(v8String(message)));
716 return v8::ThrowException(v8::Exception::Error(v8String(message)));
718 ASSERT_NOT_REACHED();
719 return notHandledByInterceptor();
723 v8::Handle<v8::Value> V8Proxy::throwTypeError()
725 return throwError(TypeError, "Type error");
728 v8::Handle<v8::Value> V8Proxy::throwSyntaxError()
730 return throwError(SyntaxError, "Syntax error");
733 v8::Local<v8::Context> V8Proxy::context(Frame* frame)
735 v8::Local<v8::Context> context = V8Proxy::mainWorldContext(frame);
736 if (context.IsEmpty())
737 return v8::Local<v8::Context>();
739 if (V8IsolatedContext* isolatedContext = V8IsolatedContext::getEntered()) {
740 context = v8::Local<v8::Context>::New(isolatedContext->context());
741 if (frame != V8Proxy::retrieveFrame(context))
742 return v8::Local<v8::Context>();
748 v8::Local<v8::Context> V8Proxy::context()
750 if (V8IsolatedContext* isolatedContext = V8IsolatedContext::getEntered()) {
751 RefPtr<SharedPersistent<v8::Context> > context = isolatedContext->sharedContext();
752 if (m_frame != V8Proxy::retrieveFrame(context->get()))
753 return v8::Local<v8::Context>();
754 return v8::Local<v8::Context>::New(context->get());
756 return mainWorldContext();
759 v8::Local<v8::Context> V8Proxy::mainWorldContext()
761 windowShell()->initContextIfNeeded();
762 return v8::Local<v8::Context>::New(windowShell()->context());
765 v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame)
767 V8Proxy* proxy = retrieve(frame);
769 return v8::Local<v8::Context>();
771 return proxy->mainWorldContext();
774 v8::Local<v8::Context> V8Proxy::currentContext()
776 return v8::Context::GetCurrent();
779 v8::Handle<v8::Value> V8Proxy::checkNewLegal(const v8::Arguments& args)
781 if (!AllowAllocation::current())
782 return throwError(TypeError, "Illegal constructor");
787 void V8Proxy::registerExtensionWithV8(v8::Extension* extension)
789 // If the extension exists in our list, it was already registered with V8.
790 if (!registeredExtensionWithV8(extension))
791 v8::RegisterExtension(extension);
794 bool V8Proxy::registeredExtensionWithV8(v8::Extension* extension)
796 for (size_t i = 0; i < m_extensions.size(); ++i) {
797 if (m_extensions[i] == extension)
804 void V8Proxy::registerExtension(v8::Extension* extension)
806 registerExtensionWithV8(extension);
807 m_extensions.append(extension);
810 bool V8Proxy::setContextDebugId(int debugId)
813 v8::HandleScope scope;
814 v8::Handle<v8::Context> context = windowShell()->context();
815 if (context.IsEmpty())
817 if (!context->GetData()->IsUndefined())
820 v8::Context::Scope contextScope(context);
823 snprintf(buffer, sizeof(buffer), "page,%d", debugId);
824 context->SetData(v8::String::New(buffer));
829 int V8Proxy::contextDebugId(v8::Handle<v8::Context> context)
831 v8::HandleScope scope;
832 if (!context->GetData()->IsString())
834 v8::String::AsciiValue ascii(context->GetData());
835 char* comma = strnstr(*ascii, ",", ascii.length());
838 return atoi(comma + 1);
841 v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, const WorldContextHandle& worldContext)
843 if (context->isDocument()) {
844 if (V8Proxy* proxy = V8Proxy::retrieve(context))
845 return worldContext.adjustedContext(proxy);
847 } else if (context->isWorkerContext()) {
848 if (WorkerContextExecutionProxy* proxy = static_cast<WorkerContext*>(context)->script()->proxy())
849 return proxy->context();
852 return v8::Local<v8::Context>();
855 } // namespace WebCore