From 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Thu, 2 Jun 2011 12:07:03 +0100 Subject: Merge WebKit at r84325: Initial merge by git. Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b --- Source/WebCore/bindings/v8/DebuggerScript.js | 30 +++--- Source/WebCore/bindings/v8/ScriptDebugServer.cpp | 12 +-- Source/WebCore/bindings/v8/ScriptDebugServer.h | 2 +- Source/WebCore/bindings/v8/ScriptState.cpp | 19 +++- Source/WebCore/bindings/v8/ScriptState.h | 7 +- Source/WebCore/bindings/v8/ScriptValue.cpp | 9 +- .../bindings/v8/V8AbstractEventListener.cpp | 10 +- Source/WebCore/bindings/v8/V8DOMWrapper.cpp | 3 + Source/WebCore/bindings/v8/V8GCController.cpp | 18 ++++ Source/WebCore/bindings/v8/V8Utilities.cpp | 5 + Source/WebCore/bindings/v8/V8Utilities.h | 30 ++++++ .../bindings/v8/WorkerContextExecutionProxy.cpp | 7 +- .../WebCore/bindings/v8/WorkerScriptController.cpp | 25 +++-- .../WebCore/bindings/v8/WorkerScriptController.h | 18 ++-- .../bindings/v8/WorkerScriptDebugServer.cpp | 101 ++++++++++++++++++++- .../WebCore/bindings/v8/WorkerScriptDebugServer.h | 10 +- .../bindings/v8/custom/V8AudioContextCustom.cpp | 29 +++++- .../v8/custom/V8CSSStyleDeclarationCustom.cpp | 20 ++-- .../bindings/v8/custom/V8DOMWindowCustom.cpp | 3 + .../bindings/v8/custom/V8DirectoryEntryCustom.cpp | 18 ++-- .../v8/custom/V8DirectoryEntrySyncCustom.cpp | 14 +-- .../bindings/v8/custom/V8DocumentCustom.cpp | 28 ------ .../WebCore/bindings/v8/custom/V8EventCustom.cpp | 3 + .../bindings/v8/custom/V8GeolocationCustom.cpp | 51 ++--------- .../bindings/v8/custom/V8InjectedScriptManager.cpp | 6 +- .../bindings/v8/custom/V8NavigatorCustom.cpp | 65 +++++++++++++ 26 files changed, 394 insertions(+), 149 deletions(-) (limited to 'Source/WebCore/bindings/v8') diff --git a/Source/WebCore/bindings/v8/DebuggerScript.js b/Source/WebCore/bindings/v8/DebuggerScript.js index fe6e8ab..c6540d7 100644 --- a/Source/WebCore/bindings/v8/DebuggerScript.js +++ b/Source/WebCore/bindings/v8/DebuggerScript.js @@ -38,11 +38,6 @@ DebuggerScript.PauseOnExceptionsState = { PauseOnUncaughtExceptions: 2 }; -DebuggerScript.ScriptWorldType = { - MainWorld : 0, - ExtensionsWorld : 1 -}; - DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; Debug.clearBreakOnException(); Debug.clearBreakOnUncaughtException(); @@ -52,6 +47,21 @@ DebuggerScript.getAfterCompileScript = function(eventData) return DebuggerScript._formatScript(eventData.script_.script_); } +DebuggerScript.getWorkerScripts = function() +{ + var result = []; + var scripts = Debug.scripts(); + for (var i = 0; i < scripts.length; ++i) { + var script = scripts[i]; + // Workers don't share same V8 heap now so there is no need to complicate stuff with + // the context id like we do to discriminate between scripts from different pages. + // However we need to filter out v8 native scripts. + if (script.context_data && script.context_data === "worker") + result.push(DebuggerScript._formatScript(script)); + } + return result; +} + DebuggerScript.getScripts = function(contextData) { var result = []; @@ -76,24 +86,19 @@ DebuggerScript.getScripts = function(contextData) DebuggerScript._formatScript = function(script) { - var scriptWorldType = DebuggerScript.ScriptWorldType.MainWorld; - if (script.context_data && script.context_data.indexOf("injected") == 0) - scriptWorldType = DebuggerScript.ScriptWorldType.ExtensionsWorld; return { id: script.id, name: script.nameOrSourceURL(), source: script.source, lineOffset: script.line_offset, columnOffset: script.column_offset, - scriptWorldType: scriptWorldType + isContentScript: !!script.context_data && script.context_data.indexOf("injected") == 0 }; } DebuggerScript.setBreakpoint = function(execState, args) { - var breakId = Debug.setScriptBreakPointById(args.scriptId, args.lineNumber, args.columnNumber, args.condition); - if (!args.enabled) - Debug.disableScriptBreakPoint(breakId); + var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition); var locations = Debug.findBreakPointActualLocations(breakId); if (!locations.length) @@ -252,7 +257,6 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) "line": location.line, "column": location.column, "functionName": functionName, - "type": "function", "thisObject": thisObject, "scopeChain": scopeChain, "scopeType": scopeType, diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp index 5758639..a0e14f3 100644 --- a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -67,11 +67,10 @@ String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBrea v8::Context::Scope contextScope(debuggerContext); v8::Local args = v8::Object::New(); - args->Set(v8::String::New("scriptId"), v8String(sourceID)); + args->Set(v8::String::New("sourceID"), v8String(sourceID)); args->Set(v8::String::New("lineNumber"), v8::Integer::New(scriptBreakpoint.lineNumber)); args->Set(v8::String::New("columnNumber"), v8::Integer::New(scriptBreakpoint.columnNumber)); args->Set(v8::String::New("condition"), v8String(scriptBreakpoint.condition)); - args->Set(v8::String::New("enabled"), v8::Boolean::New(scriptBreakpoint.enabled)); v8::Handle setBreakpointFunction = v8::Local::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpoint"))); v8::Handle breakpointId = v8::Debug::Call(setBreakpointFunction, args); @@ -212,7 +211,7 @@ void ScriptDebugServer::stepOutOfFunction() continueProgram(); } -bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage) +bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& newContent, String* error) { ensureDebuggerScriptCompiled(); v8::HandleScope scope; @@ -230,11 +229,12 @@ bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& n if (tryCatch.HasCaught()) { v8::Local message = tryCatch.Message(); if (!message.IsEmpty()) - newSourceOrErrorMessage = toWebCoreStringWithNullOrUndefinedCheck(message->Get()); + *error = toWebCoreStringWithNullOrUndefinedCheck(message->Get()); + else + *error = "Unknown error."; return false; } ASSERT(!result.IsEmpty()); - newSourceOrErrorMessage = toWebCoreStringWithNullOrUndefinedCheck(result); // Call stack may have changed after if the edited function was on the stack. if (m_currentCallFrame) @@ -351,7 +351,7 @@ void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8 toWebCoreStringWithNullOrUndefinedCheck(object->Get(v8::String::New("source"))), object->Get(v8::String::New("lineOffset"))->ToInteger()->Value(), object->Get(v8::String::New("columnOffset"))->ToInteger()->Value(), - static_cast(object->Get(v8::String::New("scriptWorldType"))->Int32Value())); + object->Get(v8::String::New("isContentScript"))->ToBoolean()->Value()); } void ScriptDebugServer::ensureDebuggerScriptCompiled() diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.h b/Source/WebCore/bindings/v8/ScriptDebugServer.h index 15004ea..93d897c 100644 --- a/Source/WebCore/bindings/v8/ScriptDebugServer.h +++ b/Source/WebCore/bindings/v8/ScriptDebugServer.h @@ -72,7 +72,7 @@ public: void stepOverStatement(); void stepOutOfFunction(); - bool editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage); + bool editScriptSource(const String& sourceID, const String& newContent, String* error); void recompileAllJSFunctionsSoon() { } void recompileAllJSFunctions(Timer* = 0) { } diff --git a/Source/WebCore/bindings/v8/ScriptState.cpp b/Source/WebCore/bindings/v8/ScriptState.cpp index fac1d26..600a92a 100644 --- a/Source/WebCore/bindings/v8/ScriptState.cpp +++ b/Source/WebCore/bindings/v8/ScriptState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009, 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -37,6 +37,10 @@ #include "ScriptController.h" #include "V8HiddenPropertyName.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" +#include "WorkerScriptController.h" + #include #include @@ -111,4 +115,17 @@ ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page* page) return mainWorldScriptState(page->mainFrame()); } +#if ENABLE(WORKERS) +ScriptState* scriptStateFromWorkerContext(WorkerContext* workerContext) +{ + WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); + if (!proxy) + return 0; + + v8::HandleScope handleScope; + v8::Local context = proxy->context(); + return ScriptState::forContext(context); +} +#endif + } diff --git a/Source/WebCore/bindings/v8/ScriptState.h b/Source/WebCore/bindings/v8/ScriptState.h index 0fecee8..c7dbbb2 100644 --- a/Source/WebCore/bindings/v8/ScriptState.h +++ b/Source/WebCore/bindings/v8/ScriptState.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -41,6 +41,7 @@ class DOMWrapperWorld; class Frame; class Node; class Page; +class WorkerContext; class ScriptState { WTF_MAKE_NONCOPYABLE(ScriptState); @@ -108,6 +109,10 @@ ScriptState* mainWorldScriptState(Frame*); ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); +#if ENABLE(WORKERS) +ScriptState* scriptStateFromWorkerContext(WorkerContext*); +#endif + inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } diff --git a/Source/WebCore/bindings/v8/ScriptValue.cpp b/Source/WebCore/bindings/v8/ScriptValue.cpp index ebe9ccc..3487d39 100644 --- a/Source/WebCore/bindings/v8/ScriptValue.cpp +++ b/Source/WebCore/bindings/v8/ScriptValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -64,7 +64,12 @@ bool ScriptValue::getString(String& result) const String ScriptValue::toString(ScriptState*) const { - return toWebCoreString(m_value); + v8::TryCatch block; + v8::Handle s = m_value->ToString(); + // Handle the case where an exception is thrown as part of invoking toString on the object. + if (block.HasCaught()) + return String(); + return v8StringToWebCoreString(s, DoNotExternalize); } #if ENABLE(INSPECTOR) diff --git a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp index 6dc49fa..f1102c2 100644 --- a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -72,6 +72,10 @@ V8AbstractEventListener::~V8AbstractEventListener() void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event* event) { + // Don't reenter V8 if execution was terminated in this instance of V8. + if (context->isJSExecutionForbidden()) + return; + ASSERT(event); // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. @@ -150,8 +154,12 @@ void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context returnValue = callListenerFunction(context, jsEvent, event); if (tryCatch.HasCaught()) event->target()->uncaughtExceptionInEventHandler(); - if (!tryCatch.CanContinue()) + + if (!tryCatch.CanContinue()) { // Result of TerminateExecution(). + if (context->isWorkerContext()) + static_cast(context)->script()->forbidExecution(); return; + } tryCatch.Reset(); // Restore the old event. This must be done for all exit paths through this method. diff --git a/Source/WebCore/bindings/v8/V8DOMWrapper.cpp b/Source/WebCore/bindings/v8/V8DOMWrapper.cpp index b439274..bef28a2 100644 --- a/Source/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/Source/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -84,6 +84,7 @@ #endif #if ENABLE(WEB_AUDIO) +#include "V8AudioContext.h" #include "V8JavaScriptAudioNode.h" #endif @@ -444,6 +445,8 @@ v8::Handle V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta #if ENABLE(WEB_AUDIO) if (JavaScriptAudioNode* jsAudioNode = target->toJavaScriptAudioNode()) return toV8(jsAudioNode); + if (AudioContext* audioContext = target->toAudioContext()) + return toV8(audioContext); #endif ASSERT(0); diff --git a/Source/WebCore/bindings/v8/V8GCController.cpp b/Source/WebCore/bindings/v8/V8GCController.cpp index 82c9ca4..c9e9dfd 100644 --- a/Source/WebCore/bindings/v8/V8GCController.cpp +++ b/Source/WebCore/bindings/v8/V8GCController.cpp @@ -359,6 +359,24 @@ public: GroupId groupId = calculateGroupId(cssStyleDeclaration); m_grouper.append(GrouperItem(groupId, wrapper)); + // Keep alive "dirty" primitive values (i.e. the ones that + // have user-added properties) by creating implicit + // references between the style declaration and the values + // in it. + if (cssStyleDeclaration->isMutableStyleDeclaration()) { + CSSMutableStyleDeclaration* cssMutableStyleDeclaration = static_cast(cssStyleDeclaration); + Vector > values; + values.reserveCapacity(cssMutableStyleDeclaration->length()); + CSSMutableStyleDeclaration::const_iterator end = cssMutableStyleDeclaration->end(); + for (CSSMutableStyleDeclaration::const_iterator it = cssMutableStyleDeclaration->begin(); it != end; ++it) { + v8::Persistent value = store->domObjectMap().get(it->value()); + if (!value.IsEmpty() && value->IsDirty()) + values.append(value); + } + if (!values.isEmpty()) + v8::V8::AddImplicitReferences(wrapper, values.data(), values.size()); + } + } else if (typeInfo->isSubclass(&V8CSSRuleList::info)) { CSSRuleList* cssRuleList = static_cast(object); GroupId groupId(cssRuleList); diff --git a/Source/WebCore/bindings/v8/V8Utilities.cpp b/Source/WebCore/bindings/v8/V8Utilities.cpp index eebe6b5..b631359 100644 --- a/Source/WebCore/bindings/v8/V8Utilities.cpp +++ b/Source/WebCore/bindings/v8/V8Utilities.cpp @@ -127,4 +127,9 @@ ScriptExecutionContext* getScriptExecutionContext() return 0; } +void throwTypeMismatchException() +{ + V8Proxy::throwError(V8Proxy::GeneralError, "TYPE_MISMATCH_ERR: DOM Exception 17"); +} + } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/V8Utilities.h b/Source/WebCore/bindings/v8/V8Utilities.h index 1892bb7..4a44f3c 100644 --- a/Source/WebCore/bindings/v8/V8Utilities.h +++ b/Source/WebCore/bindings/v8/V8Utilities.h @@ -55,6 +55,36 @@ namespace WebCore { ScriptExecutionContext* getScriptExecutionContext(); + void throwTypeMismatchException(); + + enum CallbackAllowedValueFlag { + CallbackAllowUndefined = 1, + CallbackAllowNull = 1 << 1 + }; + + typedef unsigned CallbackAllowedValueFlags; + + // 'FunctionOnly' is assumed for the created callback. + template + PassRefPtr createFunctionOnlyCallback(v8::Local value, bool& succeeded, CallbackAllowedValueFlags acceptedValues = 0) + { + succeeded = true; + + if (value->IsUndefined() && (acceptedValues & CallbackAllowUndefined)) + return 0; + + if (value->IsNull() && (acceptedValues & CallbackAllowNull)) + return 0; + + if (!value->IsFunction()) { + succeeded = false; + throwTypeMismatchException(); + return 0; + } + + return V8CallbackType::create(value, getScriptExecutionContext()); + } + class AllowAllocation { public: inline AllowAllocation() diff --git a/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index eb7252b..42259d5 100644 --- a/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -150,6 +150,9 @@ bool WorkerContextExecutionProxy::initContextIfNeeded() v8::Context::Scope scope(context); + // Set DebugId for the new context. + context->SetData(v8::String::New("worker")); + // Create a new JS object and use it as the prototype for the shadow global object. WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info; #if ENABLE(SHARED_WORKERS) @@ -200,8 +203,10 @@ ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const St v8::Handle compiledScript = V8Proxy::compileScript(scriptString, fileName, scriptStartPosition); v8::Local result = runScript(compiledScript); - if (!exceptionCatcher.CanContinue()) + if (!exceptionCatcher.CanContinue()) { + m_workerContext->script()->forbidExecution(); return ScriptValue(); + } if (exceptionCatcher.HasCaught()) { v8::Local message = exceptionCatcher.Message(); diff --git a/Source/WebCore/bindings/v8/WorkerScriptController.cpp b/Source/WebCore/bindings/v8/WorkerScriptController.cpp index 42e02e6..214da4e 100644 --- a/Source/WebCore/bindings/v8/WorkerScriptController.cpp +++ b/Source/WebCore/bindings/v8/WorkerScriptController.cpp @@ -68,11 +68,8 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* exception) { - { - MutexLocker lock(m_sharedDataMutex); - if (m_executionForbidden) - return ScriptValue(); - } + if (isExecutionForbidden()) + return ScriptValue(); WorkerContextExecutionState state; ScriptValue result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), WTF::toZeroBasedTextPosition(sourceCode.startPosition()), &state); @@ -86,13 +83,21 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, return result; } -void WorkerScriptController::forbidExecution(ForbidExecutionOption option) +void WorkerScriptController::scheduleExecutionTermination() +{ + v8::V8::TerminateExecution(); +} + +void WorkerScriptController::forbidExecution() { - // This function may be called from another thread. - MutexLocker lock(m_sharedDataMutex); + ASSERT(m_workerContext->isContextThread()); m_executionForbidden = true; - if (option == TerminateRunningScript) - v8::V8::TerminateExecution(); +} + +bool WorkerScriptController::isExecutionForbidden() const +{ + ASSERT(m_workerContext->isContextThread()); + return m_executionForbidden; } void WorkerScriptController::setException(ScriptValue exception) diff --git a/Source/WebCore/bindings/v8/WorkerScriptController.h b/Source/WebCore/bindings/v8/WorkerScriptController.h index 5e3159f..cc4b7c4 100644 --- a/Source/WebCore/bindings/v8/WorkerScriptController.h +++ b/Source/WebCore/bindings/v8/WorkerScriptController.h @@ -48,7 +48,7 @@ namespace WebCore { WorkerScriptController(WorkerContext*); ~WorkerScriptController(); - WorkerContextExecutionProxy* proxy() { return m_executionForbidden ? 0 : m_proxy.get(); } + WorkerContextExecutionProxy* proxy() { return m_proxy.get(); } WorkerContext* workerContext() { return m_workerContext; } ScriptValue evaluate(const ScriptSourceCode&); @@ -56,9 +56,17 @@ namespace WebCore { void setException(ScriptValue); - enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish }; - void forbidExecution(ForbidExecutionOption); - bool isExecutionForbidden() const { return m_executionForbidden; } + // Async request to terminate a future JS execution. Eventually causes termination + // exception raised during JS execution, if the worker thread happens to run JS. + // After JS execution was terminated in this way, the Worker thread has to use + // forbidExecution()/isExecutionForbidden() to guard against reentry into JS. + // Can be called from any thread. + void scheduleExecutionTermination(); + + // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request, + // or by Worker thread termination code to prevent future entry into JS. + void forbidExecution(); + bool isExecutionForbidden() const; // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context. static WorkerScriptController* controllerForContext(); @@ -66,8 +74,6 @@ namespace WebCore { private: WorkerContext* m_workerContext; OwnPtr m_proxy; - - Mutex m_sharedDataMutex; bool m_executionForbidden; }; diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp index 5e2acd2..1887cea 100755 --- a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp +++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp @@ -33,21 +33,118 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) +#include "ScriptDebugListener.h" +#include "V8DOMWrapper.h" +#include "V8DedicatedWorkerContext.h" +#include "V8SharedWorkerContext.h" #include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" +#include "WorkerThread.h" +#include +#include namespace WebCore { +static WorkerContext* retrieveWorkerContext(v8::Handle context) +{ + v8::Handle global = context->Global(); + ASSERT(!global.IsEmpty()); + + v8::Handle prototype = v8::Handle::Cast(global->GetPrototype()); + ASSERT(!prototype.IsEmpty()); + + prototype = v8::Handle::Cast(prototype->GetPrototype()); + ASSERT(!prototype.IsEmpty()); + + WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(prototype); + if (&V8DedicatedWorkerContext::info == typeInfo) + return V8DedicatedWorkerContext::toNative(prototype); + if (&V8SharedWorkerContext::info == typeInfo) + return V8SharedWorkerContext::toNative(prototype); + ASSERT_NOT_REACHED(); + return 0; +} + WorkerScriptDebugServer::WorkerScriptDebugServer() : ScriptDebugServer() + , m_pausedWorkerContext(0) +{ +} + +void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener, WorkerContext* workerContext) +{ + v8::HandleScope scope; + v8::Local debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + if (!m_listenersMap.size()) { + // FIXME: synchronize access to this code. + ensureDebuggerScriptCompiled(); + ASSERT(!m_debuggerScript.get()->IsUndefined()); + v8::Debug::SetDebugEventListener2(&WorkerScriptDebugServer::v8DebugEventCallback, v8::External::New(this)); + } + m_listenersMap.set(workerContext, listener); + + WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); + if (!proxy) + return; + v8::Handle context = proxy->context(); + + v8::Handle getScriptsFunction = v8::Local::Cast(m_debuggerScript.get()->Get(v8::String::New("getWorkerScripts"))); + v8::Handle argv[] = { v8::Handle() }; + v8::Handle value = getScriptsFunction->Call(m_debuggerScript.get(), 0, argv); + if (value.IsEmpty()) + return; + ASSERT(!value->IsUndefined() && value->IsArray()); + v8::Handle scriptsArray = v8::Handle::Cast(value); + for (unsigned i = 0; i < scriptsArray->Length(); ++i) + dispatchDidParseSource(listener, v8::Handle::Cast(scriptsArray->Get(v8::Integer::New(i)))); +} + +void WorkerScriptDebugServer::removeListener(ScriptDebugListener* listener, WorkerContext* workerContext) { + if (!m_listenersMap.contains(workerContext)) + return; + + if (m_pausedWorkerContext == workerContext) + continueProgram(); + + m_listenersMap.remove(workerContext); + + if (m_listenersMap.isEmpty()) + v8::Debug::SetDebugEventListener2(0); } -void WorkerScriptDebugServer::addListener(ScriptDebugListener*, WorkerContext*) +ScriptDebugListener* WorkerScriptDebugServer::getDebugListenerForContext(v8::Handle context) { + WorkerContext* workerContext = retrieveWorkerContext(context); + if (!workerContext) + return 0; + return m_listenersMap.get(workerContext); +} + +void WorkerScriptDebugServer::runMessageLoopOnPause(v8::Handle context) +{ + WorkerContext* workerContext = retrieveWorkerContext(context); + WorkerThread* workerThread = workerContext->thread(); + + m_pausedWorkerContext = workerContext; + + MessageQueueWaitResult result; + do { + result = workerThread->runLoop().runInMode(workerContext, "debugger"); + // Keep waiting until execution is resumed. + } while (result == MessageQueueMessageReceived && isPaused()); + m_pausedWorkerContext = 0; + + // The listener may have been removed in the nested loop. + if (ScriptDebugListener* listener = m_listenersMap.get(workerContext)) + listener->didContinue(); } -void WorkerScriptDebugServer::removeListener(ScriptDebugListener*, WorkerContext*) +void WorkerScriptDebugServer::quitMessageLoopOnPause() { + // FIXME: do exit nested loop when listener is removed on pause. } } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h index fdc47ac..6264c68 100755 --- a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h +++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h @@ -49,9 +49,13 @@ public: void removeListener(ScriptDebugListener*, WorkerContext*); private: - virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle) { return 0; } - virtual void runMessageLoopOnPause(v8::Handle) { } - virtual void quitMessageLoopOnPause() { } + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle); + virtual void runMessageLoopOnPause(v8::Handle); + virtual void quitMessageLoopOnPause(); + + typedef HashMap ListenersMap; + ListenersMap m_listenersMap; + WorkerContext* m_pausedWorkerContext; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp b/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp index 419cd60..f2f8dc0 100644 --- a/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp @@ -51,7 +51,34 @@ v8::Handle V8AudioContext::constructorCallback(const v8::Arguments& a if (!document) return throwError("AudioContext constructor associated document is unavailable", V8Proxy::ReferenceError); - RefPtr audioContext = AudioContext::create(document); + RefPtr audioContext; + + if (!args.Length()) { + // Constructor for default AudioContext which talks to audio hardware. + audioContext = AudioContext::create(document); + } else { + // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer. + // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate); + if (args.Length() < 3) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + + bool ok = false; + + unsigned numberOfChannels = toInt32(args[0], ok); + if (!ok) + return throwError("Invalid number of channels", V8Proxy::SyntaxError); + + unsigned numberOfFrames = toInt32(args[1], ok); + if (!ok) + return throwError("Invalid number of frames", V8Proxy::SyntaxError); + + float sampleRate = toFloat(args[2]); + + audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate); + } + + if (!audioContext.get()) + return throwError("Error creating AudioContext", V8Proxy::SyntaxError); // Transform the holder into a wrapper object for the audio context. V8DOMWrapper::setDOMWrapper(args.Holder(), &info, audioContext.get()); diff --git a/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp index 850ae14..097924b 100644 --- a/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp @@ -40,6 +40,8 @@ #include "V8Binding.h" #include "V8Proxy.h" +#include +#include #include #include #include @@ -107,8 +109,8 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handlev8PropertyName) if (!length) return 0; - Vector name; - name.reserveCapacity(length); + StringBuilder builder; + builder.reserveCapacity(length); unsigned i = 0; @@ -123,23 +125,21 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handlev8PropertyName) } else if (hasCSSPropertyNamePrefix(propertyName, "webkit") || hasCSSPropertyNamePrefix(propertyName, "khtml") || hasCSSPropertyNamePrefix(propertyName, "apple")) - name.append('-'); + builder.append('-'); else if (WTF::isASCIIUpper(propertyName[0])) return 0; - name.append(WTF::toASCIILower(propertyName[i++])); + builder.append(WTF::toASCIILower(propertyName[i++])); for (; i < length; ++i) { UChar c = propertyName[i]; if (!WTF::isASCIIUpper(c)) - name.append(c); - else { - name.append('-'); - name.append(WTF::toASCIILower(c)); - } + builder.append(c); + else + builder.append(makeString('-', toASCIILower(c))); } - String propName = String::adopt(name); + String propName = builder.toString(); int propertyID = cssPropertyID(propName); if (propertyID) { propInfo = new CSSPropertyInfo(); diff --git a/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index 85ae322..43d5a15 100644 --- a/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -32,6 +32,7 @@ #include "V8DOMWindow.h" #include "Chrome.h" +#include "ContentSecurityPolicy.h" #include "DOMTimer.h" #include "DOMWindow.h" #include "ExceptionCode.h" @@ -131,6 +132,8 @@ v8::Handle WindowSetTimeoutImpl(const v8::Arguments& args, bool singl id = DOMTimer::install(scriptContext, action, timeout, singleShot); } else { + if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval()) + return v8::Integer::New(0); id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot); } diff --git a/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp index a44131a..0889451 100644 --- a/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp @@ -39,7 +39,7 @@ #include "V8BindingMacros.h" #include "V8EntryCallback.h" #include "V8ErrorCallback.h" -#include "V8Flags.h" +#include "V8WebKitFlags.h" #include "V8Proxy.h" #include #include @@ -55,10 +55,10 @@ v8::Handle V8DirectoryEntry::getDirectoryCallback(const v8::Arguments imp->getDirectory(path); return v8::Handle(); } - RefPtr flags; - if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8Flags::HasInstance(args[1])) { + RefPtr flags; + if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8WebKitFlags::HasInstance(args[1])) { EXCEPTION_BLOCK(v8::Handle, object, v8::Handle::Cast(args[1])); - flags = Flags::create(); + flags = WebKitFlags::create(); v8::Local v8Create = object->Get(v8::String::New("create")); if (!v8Create.IsEmpty() && !isUndefinedOrNull(v8Create)) { EXCEPTION_BLOCK(bool, isCreate, v8Create->BooleanValue()); @@ -70,7 +70,7 @@ v8::Handle V8DirectoryEntry::getDirectoryCallback(const v8::Arguments flags->setExclusive(isExclusive); } } else { - EXCEPTION_BLOCK(Flags*, tmp_flags, V8Flags::HasInstance(args[1]) ? V8Flags::toNative(v8::Handle::Cast(args[1])) : 0); + EXCEPTION_BLOCK(WebKitFlags*, tmp_flags, V8WebKitFlags::HasInstance(args[1]) ? V8WebKitFlags::toNative(v8::Handle::Cast(args[1])) : 0); flags = tmp_flags; } RefPtr successCallback; @@ -98,10 +98,10 @@ v8::Handle V8DirectoryEntry::getFileCallback(const v8::Arguments& arg imp->getFile(path); return v8::Handle(); } - RefPtr flags; - if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8Flags::HasInstance(args[1])) { + RefPtr flags; + if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8WebKitFlags::HasInstance(args[1])) { EXCEPTION_BLOCK(v8::Handle, object, v8::Handle::Cast(args[1])); - flags = Flags::create(); + flags = WebKitFlags::create(); v8::Local v8Create = object->Get(v8::String::New("create")); if (!v8Create.IsEmpty() && !isUndefinedOrNull(v8Create)) { EXCEPTION_BLOCK(bool, isCreate, v8Create->BooleanValue()); @@ -113,7 +113,7 @@ v8::Handle V8DirectoryEntry::getFileCallback(const v8::Arguments& arg flags->setExclusive(isExclusive); } } else { - EXCEPTION_BLOCK(Flags*, tmp_flags, V8Flags::HasInstance(args[1]) ? V8Flags::toNative(v8::Handle::Cast(args[1])) : 0); + EXCEPTION_BLOCK(WebKitFlags*, tmp_flags, V8WebKitFlags::HasInstance(args[1]) ? V8WebKitFlags::toNative(v8::Handle::Cast(args[1])) : 0); flags = tmp_flags; } RefPtr successCallback; diff --git a/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp index 90b3d13..cd38ca4 100644 --- a/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp @@ -40,7 +40,7 @@ #include "V8EntryCallback.h" #include "V8ErrorCallback.h" #include "V8FileEntrySync.h" -#include "V8Flags.h" +#include "V8WebKitFlags.h" #include "V8Proxy.h" #include #include @@ -62,13 +62,13 @@ static bool extractBooleanValue(const v8::Handle& object, const char return false; } -static PassRefPtr getFlags(const v8::Local& arg, ExceptionCode& ec) +static PassRefPtr getFlags(const v8::Local& arg, ExceptionCode& ec) { ec = 0; if (isUndefinedOrNull(arg) || !arg->IsObject()) return 0; - if (V8Flags::HasInstance(arg)) - return V8Flags::toNative(v8::Handle::Cast(arg)); + if (V8WebKitFlags::HasInstance(arg)) + return V8WebKitFlags::toNative(v8::Handle::Cast(arg)); v8::Handle object; { @@ -87,7 +87,7 @@ static PassRefPtr getFlags(const v8::Local& arg, ExceptionCode if (ec) return 0; - RefPtr flags = Flags::create(); + RefPtr flags = WebKitFlags::create(); flags->setCreate(isCreate); flags->setExclusive(isExclusive); @@ -100,7 +100,7 @@ v8::Handle V8DirectoryEntrySync::getDirectoryCallback(const v8::Argum DirectoryEntrySync* imp = V8DirectoryEntrySync::toNative(args.Holder()); ExceptionCode ec = 0; STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, path, args[0]); - RefPtr flags = getFlags(args[1], ec); + RefPtr flags = getFlags(args[1], ec); if (UNLIKELY(ec)) { V8Proxy::setDOMException(ec); return v8::Handle(); @@ -119,7 +119,7 @@ v8::Handle V8DirectoryEntrySync::getFileCallback(const v8::Arguments& DirectoryEntrySync* imp = V8DirectoryEntrySync::toNative(args.Holder()); ExceptionCode ec = 0; STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, path, args[0]); - RefPtr flags = getFlags(args[1], ec); + RefPtr flags = getFlags(args[1], ec); if (UNLIKELY(ec)) { V8Proxy::setDOMException(ec); return v8::Handle(); diff --git a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index c435863..7cad58e 100644 --- a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -118,34 +118,6 @@ v8::Handle V8Document::getCSSCanvasContextCallback(const v8::Argument return v8::Undefined(); } - -// DOMImplementation is a singleton in WebCore. If we use our normal -// mapping from DOM objects to V8 wrappers, the same wrapper will be -// shared for all frames in the same process. This is a major -// security problem. Therefore, we generate a DOMImplementation -// wrapper per document and store it in an internal field of the -// document. Since the DOMImplementation object is a singleton, we do -// not have to do anything to keep the DOMImplementation object alive -// for the lifetime of the wrapper. -v8::Handle V8Document::implementationAccessorGetter(v8::Local name, const v8::AccessorInfo& info) -{ - ASSERT(info.Holder()->InternalFieldCount() >= internalFieldCount); - - // Check if the internal field already contains a wrapper. - v8::Local implementation = info.Holder()->GetInternalField(V8Document::implementationIndex); - if (!implementation->IsUndefined()) - return implementation; - - // Generate a wrapper. - Document* document = V8Document::toNative(info.Holder()); - v8::Handle wrapper = toV8(document->implementation()); - - // Store the wrapper in the internal field. - info.Holder()->SetInternalField(implementationIndex, wrapper); - - return wrapper; -} - v8::Handle toV8(Document* impl, bool forceNewObject) { if (!impl) diff --git a/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp b/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp index abb7d4c..7e12034 100644 --- a/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -70,6 +70,7 @@ #if ENABLE(WEB_AUDIO) #include "V8AudioProcessingEvent.h" +#include "V8OfflineAudioCompletionEvent.h" #endif namespace WebCore { @@ -169,6 +170,8 @@ v8::Handle toV8(Event* impl) #if ENABLE(WEB_AUDIO) if (impl->isAudioProcessingEvent()) return toV8(static_cast(impl)); + if (impl->isOfflineAudioCompletionEvent()) + return toV8(static_cast(impl)); #endif #if ENABLE(INPUT_SPEECH) if (impl->isSpeechInputEvent()) diff --git a/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp b/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp index 54bd11c..91389d8 100644 --- a/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp @@ -33,52 +33,13 @@ #include "V8Binding.h" #include "V8CustomPositionCallback.h" #include "V8CustomPositionErrorCallback.h" -#include "V8Proxy.h" +#include "V8Utilities.h" using namespace std; using namespace WTF; namespace WebCore { -static const char typeMismatchError[] = "TYPE_MISMATCH_ERR: DOM Exception 17"; - -static void throwTypeMismatchException() -{ - V8Proxy::throwError(V8Proxy::GeneralError, typeMismatchError); -} - -static PassRefPtr createPositionCallback(v8::Local value, bool& succeeded) -{ - succeeded = true; - - // The spec specifies 'FunctionOnly' for this object. - if (!value->IsFunction()) { - succeeded = false; - throwTypeMismatchException(); - return 0; - } - - return V8CustomPositionCallback::create(value, getScriptExecutionContext()); -} - -static PassRefPtr createPositionErrorCallback(v8::Local value, bool& succeeded) -{ - succeeded = true; - - // Argument is optional (hence undefined is allowed), and null is allowed. - if (isUndefinedOrNull(value)) - return 0; - - // The spec specifies 'FunctionOnly' for this object. - if (!value->IsFunction()) { - succeeded = false; - throwTypeMismatchException(); - return 0; - } - - return V8CustomPositionErrorCallback::create(value, getScriptExecutionContext()); -} - static PassRefPtr createPositionOptions(v8::Local value, bool& succeeded) { succeeded = true; @@ -172,12 +133,13 @@ v8::Handle V8Geolocation::getCurrentPositionCallback(const v8::Argume bool succeeded = false; - RefPtr positionCallback = createPositionCallback(args[0], succeeded); + RefPtr positionCallback = createFunctionOnlyCallback(args[0], succeeded); if (!succeeded) return v8::Undefined(); ASSERT(positionCallback); - RefPtr positionErrorCallback = createPositionErrorCallback(args[1], succeeded); + // Argument is optional (hence undefined is allowed), and null is allowed. + RefPtr positionErrorCallback = createFunctionOnlyCallback(args[1], succeeded, CallbackAllowUndefined | CallbackAllowNull); if (!succeeded) return v8::Undefined(); @@ -197,12 +159,13 @@ v8::Handle V8Geolocation::watchPositionCallback(const v8::Arguments& bool succeeded = false; - RefPtr positionCallback = createPositionCallback(args[0], succeeded); + RefPtr positionCallback = createFunctionOnlyCallback(args[0], succeeded); if (!succeeded) return v8::Undefined(); ASSERT(positionCallback); - RefPtr positionErrorCallback = createPositionErrorCallback(args[1], succeeded); + // Argument is optional (hence undefined is allowed), and null is allowed. + RefPtr positionErrorCallback = createFunctionOnlyCallback(args[1], succeeded, CallbackAllowUndefined | CallbackAllowNull); if (!succeeded) return v8::Undefined(); diff --git a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp index f4006b8..8bb4281 100644 --- a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp +++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp @@ -139,13 +139,13 @@ InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* inspectedSc v8::Handle key = V8HiddenPropertyName::devtoolsInjectedScript(); v8::Local val = global->GetHiddenValue(key); if (!val.IsEmpty() && val->IsObject()) - return InjectedScript(ScriptObject(inspectedScriptState, v8::Local::Cast(val))); + return InjectedScript(ScriptObject(inspectedScriptState, v8::Local::Cast(val)), m_inspectedStateAccessCheck); - if (!canAccessInspectedWindow(inspectedScriptState)) + if (!m_inspectedStateAccessCheck(inspectedScriptState)) return InjectedScript(); pair injectedScript = injectScript(injectedScriptSource(), inspectedScriptState); - InjectedScript result(injectedScript.second); + InjectedScript result(injectedScript.second, m_inspectedStateAccessCheck); m_idToInjectedScript.set(injectedScript.first, result); global->SetHiddenValue(key, injectedScript.second.v8Object()); return result; diff --git a/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp b/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp index e5a6909..16e8cfe 100644 --- a/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp @@ -1,4 +1,5 @@ /* +<<<<<<< HEAD * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,11 +27,35 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +======= + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +>>>>>>> WebKit.org at r84325 */ #include "config.h" #include "V8Navigator.h" +<<<<<<< HEAD #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) #include "ExceptionCode.h" @@ -77,9 +102,49 @@ v8::Handle V8Navigator::isApplicationInstalledCallback(const v8::Argu if (!navigator->isApplicationInstalled(toWebCoreString(args[0]), callback.release())) return throwError(INVALID_STATE_ERR); +======= +#if ENABLE(MEDIA_STREAM) + +#include "Navigator.h" +#include "V8Binding.h" +#include "V8NavigatorUserMediaErrorCallback.h" +#include "V8NavigatorUserMediaSuccessCallback.h" +#include "V8Utilities.h" + +using namespace WTF; + +namespace WebCore { + +v8::Handle V8Navigator::webkitGetUserMediaCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.Navigator.webkitGetUserMedia()"); + + v8::TryCatch exceptionCatcher; + String options = toWebCoreString(args[0]); + if (exceptionCatcher.HasCaught()) + return throwError(exceptionCatcher.Exception()); + + bool succeeded = false; + + RefPtr successCallback = createFunctionOnlyCallback(args[1], succeeded); + if (!succeeded) + return v8::Undefined(); + + // Argument is optional, hence undefined is allowed. + RefPtr errorCallback = createFunctionOnlyCallback(args[2], succeeded, CallbackAllowUndefined); + if (!succeeded) + return v8::Undefined(); + + Navigator* navigator = V8Navigator::toNative(args.Holder()); + navigator->webkitGetUserMedia(options, successCallback.release(), errorCallback.release()); +>>>>>>> WebKit.org at r84325 return v8::Undefined(); } } // namespace WebCore +<<<<<<< HEAD #endif // PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) +======= +#endif // ENABLE(MEDIA_STREAM) +>>>>>>> WebKit.org at r84325 -- cgit v1.1