зеркало из https://github.com/mozilla/gecko-dev.git
Merge last green changeset from mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
e3d3e25769
|
@ -282,11 +282,11 @@ nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
|
|||
|
||||
nsCOMPtr<nsIToolkitProfileService> profileSvc
|
||||
(do_GetService(NS_PROFILESERVICE_CONTRACTID));
|
||||
NS_ENSURE_TRUE(profileSvc, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(profileSvc, PR_FALSE);
|
||||
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
(do_GetService("@mozilla.org/file/directory_service;1"));
|
||||
NS_ENSURE_TRUE(dirService, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(dirService, PR_FALSE);
|
||||
|
||||
nsCOMPtr<nsILocalFile> regFile;
|
||||
#ifdef XP_WIN
|
||||
|
|
|
@ -383,7 +383,7 @@ class JarMaker(object):
|
|||
src = src[1:]
|
||||
else:
|
||||
# use srcdirs and the objdir (current working dir) for relative paths
|
||||
src_base = sourcedirs + ['.']
|
||||
src_base = sourcedirs + [os.getcwd()]
|
||||
# check if the source file exists
|
||||
realsrc = None
|
||||
for _srcdir in src_base:
|
||||
|
|
15
configure.in
15
configure.in
|
@ -7913,7 +7913,11 @@ dnl done during packaging with omnijar.
|
|||
if test "$MOZ_CHROME_FILE_FORMAT" = "omni"; then
|
||||
MOZ_OMNIJAR=1
|
||||
AC_DEFINE(MOZ_OMNIJAR)
|
||||
MOZ_CHROME_FILE_FORMAT=flat
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
MOZ_CHROME_FILE_FORMAT=flat
|
||||
else
|
||||
MOZ_CHROME_FILE_FORMAT=symlink
|
||||
fi
|
||||
elif test "$MOZ_CHROME_FILE_FORMAT" = "jar"; then
|
||||
AC_DEFINE(MOZ_CHROME_FILE_FORMAT_JAR)
|
||||
fi
|
||||
|
@ -9384,9 +9388,13 @@ if test -n "$_NON_GLOBAL_ACDEFINES"; then
|
|||
done
|
||||
fi
|
||||
_EGREP_PATTERN="${_EGREP_PATTERN}dummy_never_defined)"
|
||||
|
||||
|
||||
sort confdefs.h | egrep -v "$_EGREP_PATTERN" >> $_CONFIG_TMP
|
||||
|
||||
if test "$?" != 0; then
|
||||
AC_MSG_ERROR([Error outputting config definitions])
|
||||
fi
|
||||
|
||||
cat >> $_CONFIG_TMP <<\EOF
|
||||
|
||||
#endif /* _MOZILLA_CONFIG_H_ */
|
||||
|
@ -9408,6 +9416,9 @@ dnl Probably shouldn't call this manually but we always want the output of DEFS
|
|||
rm -f confdefs.h.save
|
||||
mv confdefs.h confdefs.h.save
|
||||
egrep -v "$_EGREP_PATTERN" confdefs.h.save > confdefs.h
|
||||
if test "$?" != 0; then
|
||||
AC_MSG_ERROR([Error outputting confdefs.h])
|
||||
fi
|
||||
AC_OUTPUT_MAKE_DEFS()
|
||||
MOZ_DEFINES=$DEFS
|
||||
AC_SUBST(MOZ_DEFINES)
|
||||
|
|
|
@ -2492,9 +2492,7 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
|
|||
}
|
||||
}
|
||||
|
||||
PRUint16 state;
|
||||
rv = GetReadyState(&state);
|
||||
if (NS_FAILED(rv) || state != OPENED)
|
||||
if (!(mState & XML_HTTP_REQUEST_OPENED))
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
|
||||
if (!mChannel) // open() initializes mChannel, and open()
|
||||
|
|
|
@ -58,6 +58,11 @@ function headerCheckHandler(metadata, response) {
|
|||
} catch(e) {
|
||||
do_throw("No header present after redirect");
|
||||
}
|
||||
try {
|
||||
metadata.getHeader("X-Unwanted-Header");
|
||||
do_throw("Unwanted header present after redirect");
|
||||
} catch (x) {
|
||||
}
|
||||
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/plain");
|
||||
response.write("");
|
||||
|
@ -72,11 +77,18 @@ function run_test() {
|
|||
do_test_pending();
|
||||
var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Components.interfaces.nsIXMLHttpRequest);
|
||||
request.open("GET", redirectURL, false);
|
||||
request.open("GET", redirectURL, true);
|
||||
request.setRequestHeader("X-Custom-Header", "present");
|
||||
request.send(null);
|
||||
|
||||
do_check_eq(request.status, 200);
|
||||
|
||||
server.stop(do_test_finished);
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState == 4) {
|
||||
do_check_eq(request.status, 200);
|
||||
server.stop(do_test_finished);
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
try {
|
||||
request.setRequestHeader("X-Unwanted-Header", "present");
|
||||
do_throw("Shouldn't be able to set a header after send");
|
||||
} catch (x) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -599,7 +599,7 @@ WebGLContext::InitAndValidateGL()
|
|||
}
|
||||
|
||||
// Check the shader validator pref
|
||||
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(Preferences::GetRootBranch(), PR_FALSE);
|
||||
|
||||
mShaderValidation =
|
||||
Preferences::GetBool("webgl.shader_validator", mShaderValidation);
|
||||
|
|
|
@ -328,7 +328,10 @@ nsIMEStateManager::SetIMEState(PRUint32 aState,
|
|||
willSubmit = PR_TRUE;
|
||||
}
|
||||
}
|
||||
context.mActionHint.Assign(willSubmit ? NS_LITERAL_STRING("go") : NS_LITERAL_STRING("next"));
|
||||
context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
|
||||
? NS_LITERAL_STRING("search")
|
||||
: NS_LITERAL_STRING("go")
|
||||
: NS_LITERAL_STRING("next"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<script type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.documentElement.appendChild(document.getElementById("a"));
|
||||
}
|
||||
|
||||
window.addEventListener("load", boom, false);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<animate end="a.begin" id="a"/>
|
||||
<animate end="a.begin" id="a"/>
|
||||
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 333 B |
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<script type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function boom()
|
||||
{
|
||||
var a = document.getElementById("a");
|
||||
a.removeAttribute("end");
|
||||
a.setAttribute("end", "a.begin");
|
||||
}
|
||||
|
||||
window.addEventListener("load", boom, false);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<animate end="0" id="a" onend="boom()"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 343 B |
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="reftest-wait">
|
||||
<script type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function boom()
|
||||
{
|
||||
try {
|
||||
document.getElementById("x").beginElementAt(36028797018963970);
|
||||
} catch (e) { }
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
window.addEventListener("load", boom, false);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
<animate id="x" begin="a" />
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 397 B |
|
@ -35,3 +35,6 @@ load 611927-1.svg
|
|||
load 615002-1.svg
|
||||
load 615872-1.svg
|
||||
load 665334-1.svg
|
||||
load 669225-1.svg
|
||||
load 670313-1.svg
|
||||
load 669225-2.svg
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "prtime.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -143,7 +144,7 @@ namespace
|
|||
// If several of these objects are allocated on the stack, the update will not
|
||||
// be performed until the last object for a given nsSMILTimedElement is
|
||||
// destroyed.
|
||||
NS_STACK_CLASS class nsSMILTimedElement::AutoIntervalUpdateBatcher
|
||||
class NS_STACK_CLASS nsSMILTimedElement::AutoIntervalUpdateBatcher
|
||||
{
|
||||
public:
|
||||
AutoIntervalUpdateBatcher(nsSMILTimedElement& aTimedElement)
|
||||
|
@ -185,6 +186,18 @@ nsSMILTimedElement::RemoveInstanceTimes(InstanceTimeList& aArray,
|
|||
for (PRUint32 i = 0; i < aArray.Length(); ++i) {
|
||||
nsSMILInstanceTime* item = aArray[i].get();
|
||||
if (aTest(item, i)) {
|
||||
// As per bugs 665334 and 669225 we should be careful not to remove the
|
||||
// instance time that corresponds to the previous interval's end time.
|
||||
//
|
||||
// Most functors supplied here fulfil this condition by checking if the
|
||||
// instance time is marked as "ShouldPreserve" and if so, not deleting it.
|
||||
//
|
||||
// However, when filtering instance times, we sometimes need to drop even
|
||||
// instance times marked as "ShouldPreserve". In that case we take special
|
||||
// care not to delete the end instance time of the previous interval.
|
||||
NS_ABORT_IF_FALSE(!GetPreviousInterval() ||
|
||||
item != GetPreviousInterval()->End(),
|
||||
"Removing end instance time of previous interval");
|
||||
item->Unlink();
|
||||
} else {
|
||||
newArray.AppendElement(item);
|
||||
|
@ -262,13 +275,7 @@ nsSMILTimedElement::~nsSMILTimedElement()
|
|||
// Notify anyone listening to our intervals that they're gone
|
||||
// (We shouldn't get any callbacks from this because all our instance times
|
||||
// are now disassociated with any intervals)
|
||||
mElementState = STATE_POSTACTIVE;
|
||||
ResetCurrentInterval();
|
||||
|
||||
for (PRInt32 i = mOldIntervals.Length() - 1; i >= 0; --i) {
|
||||
mOldIntervals[i]->Unlink();
|
||||
}
|
||||
mOldIntervals.Clear();
|
||||
ClearIntervals();
|
||||
|
||||
// The following assertions are important in their own right (for checking
|
||||
// correct behavior) but also because AutoIntervalUpdateBatcher holds pointers
|
||||
|
@ -320,9 +327,7 @@ nsSMILTimedElement::BeginElementAt(double aOffsetSeconds)
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsSMILTime currentTime = container->GetCurrentTime();
|
||||
AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
return AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -333,9 +338,7 @@ nsSMILTimedElement::EndElementAt(double aOffsetSeconds)
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsSMILTime currentTime = container->GetCurrentTime();
|
||||
AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
return AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_FALSE);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -422,10 +425,15 @@ nsSMILTimedElement::RemoveInstanceTime(nsSMILInstanceTime* aInstanceTime,
|
|||
{
|
||||
NS_ABORT_IF_FALSE(aInstanceTime, "Attempting to remove null instance time");
|
||||
|
||||
// If the instance time should be kept (because it is or was the fixed end
|
||||
// point of an interval) then just disassociate it from the creator.
|
||||
if (aInstanceTime->ShouldPreserve()) {
|
||||
aInstanceTime->Unlink();
|
||||
return;
|
||||
}
|
||||
|
||||
InstanceTimeList& instanceList = aIsBegin ? mBeginInstances : mEndInstances;
|
||||
#ifdef DEBUG
|
||||
PRBool found =
|
||||
#endif
|
||||
mozilla::DebugOnly<PRBool> found =
|
||||
instanceList.RemoveElementSorted(aInstanceTime, InstanceTimeComparator());
|
||||
NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete");
|
||||
|
||||
|
@ -434,7 +442,7 @@ nsSMILTimedElement::RemoveInstanceTime(nsSMILInstanceTime* aInstanceTime,
|
|||
|
||||
namespace
|
||||
{
|
||||
class RemoveByCreator
|
||||
class NS_STACK_CLASS RemoveByCreator
|
||||
{
|
||||
public:
|
||||
RemoveByCreator(const nsSMILTimeValueSpec* aCreator) : mCreator(aCreator)
|
||||
|
@ -721,7 +729,7 @@ namespace
|
|||
NS_ABORT_IF_FALSE(!aInstanceTime->IsDynamic() ||
|
||||
!aInstanceTime->GetCreator(),
|
||||
"Dynamic instance time should be unlinked from its creator");
|
||||
return !aInstanceTime->IsDynamic();
|
||||
return !aInstanceTime->IsDynamic() && !aInstanceTime->ShouldPreserve();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,7 +758,10 @@ nsSMILTimedElement::Rewind()
|
|||
mSeekState == SEEK_BACKWARD_FROM_ACTIVE,
|
||||
"Rewind in the middle of a forwards seek?");
|
||||
|
||||
ClearIntervalProgress();
|
||||
ClearIntervals();
|
||||
// ClearIntervals puts us in to the POSTACTIVE state but we're doing a full
|
||||
// rewind so go back to the startup state
|
||||
mElementState = STATE_STARTUP;
|
||||
|
||||
UnsetBeginSpec(RemoveNonDynamic);
|
||||
UnsetEndSpec(RemoveNonDynamic);
|
||||
|
@ -780,7 +791,7 @@ namespace
|
|||
PRBool
|
||||
RemoveNonDOM(nsSMILInstanceTime* aInstanceTime)
|
||||
{
|
||||
return !aInstanceTime->FromDOM();
|
||||
return !aInstanceTime->FromDOM() && !aInstanceTime->ShouldPreserve();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1226,6 +1237,7 @@ nsSMILTimedElement::Unlink()
|
|||
{
|
||||
AutoIntervalUpdateBatcher updateBatcher(*this);
|
||||
|
||||
// Remove dependencies on other elements
|
||||
PRUint32 count = mBeginSpecs.Length();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i];
|
||||
|
@ -1240,6 +1252,11 @@ nsSMILTimedElement::Unlink()
|
|||
NS_ABORT_IF_FALSE(endSpec, "null nsSMILTimeValueSpec in list of end specs");
|
||||
endSpec->Unlink();
|
||||
}
|
||||
|
||||
ClearIntervals();
|
||||
|
||||
// Make sure we don't notify other elements of new intervals
|
||||
mTimeDependents.Clear();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -1287,7 +1304,7 @@ namespace
|
|||
// pointers instead.
|
||||
// Without this we'd have to either templatize ClearSpecs and all its callers
|
||||
// or pass bool flags around to specify which removal function to use here.
|
||||
class RemoveByFunction
|
||||
class NS_STACK_CLASS RemoveByFunction
|
||||
{
|
||||
public:
|
||||
RemoveByFunction(nsSMILTimedElement::RemovalTestFunction aFunction)
|
||||
|
@ -1313,9 +1330,9 @@ nsSMILTimedElement::ClearSpecs(TimeValueSpecList& aSpecs,
|
|||
}
|
||||
|
||||
void
|
||||
nsSMILTimedElement::ClearIntervalProgress()
|
||||
nsSMILTimedElement::ClearIntervals()
|
||||
{
|
||||
mElementState = STATE_STARTUP;
|
||||
mElementState = STATE_POSTACTIVE;
|
||||
mCurrentRepeatIteration = 0;
|
||||
ResetCurrentInterval();
|
||||
|
||||
|
@ -1357,7 +1374,7 @@ nsSMILTimedElement::ApplyEarlyEnd(const nsSMILTimeValue& aSampleTime)
|
|||
|
||||
namespace
|
||||
{
|
||||
class RemoveReset
|
||||
class NS_STACK_CLASS RemoveReset
|
||||
{
|
||||
public:
|
||||
RemoveReset(const nsSMILInstanceTime* aCurrentIntervalBegin)
|
||||
|
@ -1505,7 +1522,7 @@ nsSMILTimedElement::FilterIntervals()
|
|||
|
||||
namespace
|
||||
{
|
||||
class RemoveFiltered
|
||||
class NS_STACK_CLASS RemoveFiltered
|
||||
{
|
||||
public:
|
||||
RemoveFiltered(nsSMILTimeValue aCutoff) : mCutoff(aCutoff) { }
|
||||
|
@ -1525,21 +1542,21 @@ namespace
|
|||
nsSMILTimeValue mCutoff;
|
||||
};
|
||||
|
||||
class RemoveBelowThreshold
|
||||
class NS_STACK_CLASS RemoveBelowThreshold
|
||||
{
|
||||
public:
|
||||
RemoveBelowThreshold(PRUint32 aThreshold,
|
||||
const nsSMILInstanceTime* aCurrentIntervalBegin)
|
||||
nsTArray<const nsSMILInstanceTime *>& aTimesToKeep)
|
||||
: mThreshold(aThreshold),
|
||||
mCurrentIntervalBegin(aCurrentIntervalBegin) { }
|
||||
mTimesToKeep(aTimesToKeep) { }
|
||||
PRBool operator()(nsSMILInstanceTime* aInstanceTime, PRUint32 aIndex)
|
||||
{
|
||||
return aInstanceTime != mCurrentIntervalBegin && aIndex < mThreshold;
|
||||
return aIndex < mThreshold && !mTimesToKeep.Contains(aInstanceTime);
|
||||
}
|
||||
|
||||
private:
|
||||
PRUint32 mThreshold;
|
||||
const nsSMILInstanceTime* mCurrentIntervalBegin;
|
||||
nsTArray<const nsSMILInstanceTime *>& mTimesToKeep;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1559,10 +1576,18 @@ nsSMILTimedElement::FilterInstanceTimes(InstanceTimeList& aList)
|
|||
// a hard cutoff at which point we just drop the oldest instance times.
|
||||
if (aList.Length() > sMaxNumInstanceTimes) {
|
||||
PRUint32 threshold = aList.Length() - sMaxNumInstanceTimes;
|
||||
// We should still preserve the current interval begin time however
|
||||
const nsSMILInstanceTime* currentIntervalBegin = mCurrentInterval ?
|
||||
mCurrentInterval->Begin() : nsnull;
|
||||
RemoveBelowThreshold removeBelowThreshold(threshold, currentIntervalBegin);
|
||||
// There are a few instance times we should keep though, notably:
|
||||
// - the current interval begin time,
|
||||
// - the previous interval end time (see note in RemoveInstanceTimes)
|
||||
nsTArray<const nsSMILInstanceTime *> timesToKeep;
|
||||
if (mCurrentInterval) {
|
||||
timesToKeep.AppendElement(mCurrentInterval->Begin());
|
||||
}
|
||||
const nsSMILInterval* prevInterval = GetPreviousInterval();
|
||||
if (prevInterval) {
|
||||
timesToKeep.AppendElement(prevInterval->End());
|
||||
}
|
||||
RemoveBelowThreshold removeBelowThreshold(threshold, timesToKeep);
|
||||
RemoveInstanceTimes(aList, removeBelowThreshold);
|
||||
}
|
||||
}
|
||||
|
@ -2024,19 +2049,24 @@ nsSMILTimedElement::SampleFillValue()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsSMILTimedElement::AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
|
||||
double aOffsetSeconds, PRBool aIsBegin)
|
||||
{
|
||||
double offset = aOffsetSeconds * PR_MSEC_PER_SEC;
|
||||
nsSMILTime timeWithOffset = aCurrentTime + PRInt64(NS_round(offset));
|
||||
|
||||
nsSMILTimeValue timeVal(timeWithOffset);
|
||||
// Check we won't overflow the range of nsSMILTime
|
||||
if (aCurrentTime + NS_round(offset) > LL_MAXINT)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
nsSMILTimeValue timeVal(aCurrentTime + PRInt64(NS_round(offset)));
|
||||
|
||||
nsRefPtr<nsSMILInstanceTime> instanceTime =
|
||||
new nsSMILInstanceTime(timeVal, nsSMILInstanceTime::SOURCE_DOM);
|
||||
|
||||
AddInstanceTime(instanceTime, aIsBegin);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -409,7 +409,7 @@ protected:
|
|||
void ClearSpecs(TimeValueSpecList& aSpecs,
|
||||
InstanceTimeList& aInstances,
|
||||
RemovalTestFunction aRemove);
|
||||
void ClearIntervalProgress();
|
||||
void ClearIntervals();
|
||||
void DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly);
|
||||
|
||||
/**
|
||||
|
@ -505,7 +505,7 @@ protected:
|
|||
void UpdateCurrentInterval(PRBool aForceChangeNotice = PR_FALSE);
|
||||
void SampleSimpleTime(nsSMILTime aActiveTime);
|
||||
void SampleFillValue();
|
||||
void AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
|
||||
nsresult AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
|
||||
double aOffsetSeconds, PRBool aIsBegin);
|
||||
void RegisterMilestone();
|
||||
PRBool GetNextMilestone(nsSMILMilestone& aNextMilestone) const;
|
||||
|
|
|
@ -62,7 +62,6 @@ DIRS = \
|
|||
interfaces/json \
|
||||
interfaces/offline \
|
||||
interfaces/geolocation \
|
||||
interfaces/threads \
|
||||
interfaces/notification \
|
||||
interfaces/svg \
|
||||
$(NULL)
|
||||
|
@ -81,6 +80,7 @@ DIRS += \
|
|||
indexedDB \
|
||||
system \
|
||||
ipc \
|
||||
workers \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
|
|
@ -459,7 +459,7 @@
|
|||
#include "nsIDOMGeoPositionError.h"
|
||||
|
||||
// Workers
|
||||
#include "nsDOMWorker.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsDOMFileReader.h"
|
||||
|
@ -598,9 +598,6 @@ DOMCI_DATA(ContentFrameMessageManager, void)
|
|||
DOMCI_DATA(DOMPrototype, void)
|
||||
DOMCI_DATA(DOMConstructor, void)
|
||||
|
||||
DOMCI_DATA(Worker, void)
|
||||
DOMCI_DATA(ChromeWorker, void)
|
||||
|
||||
#define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper, \
|
||||
_flags) \
|
||||
{ #_name, \
|
||||
|
@ -1428,11 +1425,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
NS_DEFINE_CLASSINFO_DATA_WITH_NAME(MathMLElement, Element, nsElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Worker, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeWorker, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLRenderingContext, nsWebGLViewportHandlerSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLBuffer, nsDOMGenericSH,
|
||||
|
@ -1569,8 +1561,6 @@ struct nsConstructorFuncMapData
|
|||
|
||||
static const nsConstructorFuncMapData kConstructorFuncMap[] =
|
||||
{
|
||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
|
||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
|
||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
|
||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
|
||||
};
|
||||
|
@ -4136,18 +4126,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(Worker, nsIWorker)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(ChromeWorker, nsIWorker)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(WebGLRenderingContext, nsIDOMWebGLRenderingContext)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWebGLRenderingContext)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -6058,10 +6036,32 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
const nsGlobalNameStruct *name_struct;
|
||||
rv = GetNameStruct(NS_ConvertASCIItoUTF16(dom_class->name), &name_struct);
|
||||
if (!name_struct) {
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!name_struct) {
|
||||
// This isn't a normal DOM object, see if this constructor lives on its
|
||||
// prototype chain.
|
||||
jsval val;
|
||||
if (!JS_GetProperty(cx, obj, "prototype", &val)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(val));
|
||||
JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
|
||||
|
||||
JSObject *proto = JS_GetPrototype(cx, dom_obj);
|
||||
for ( ; proto; proto = JS_GetPrototype(cx, proto)) {
|
||||
if (proto == dot_prototype) {
|
||||
*bp = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
|
||||
name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo &&
|
||||
name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
|
@ -6694,6 +6694,10 @@ ContentWindowGetter(JSContext *cx, uintN argc, jsval *vp)
|
|||
return ::JS_GetProperty(cx, obj, "content", vp);
|
||||
}
|
||||
|
||||
static JSNewResolveOp sOtherResolveFuncs[] = {
|
||||
mozilla::dom::workers::ResolveWorkerClasses
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
|
@ -6920,6 +6924,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
if (!(flags & JSRESOLVE_ASSIGNING)) {
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// Resolve special classes.
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sOtherResolveFuncs); i++) {
|
||||
if (!sOtherResolveFuncs[i](cx, obj, id, flags, objp)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (*objp) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Call GlobalResolve() after we call FindChildWithName() so
|
||||
// that named child frames will override external properties
|
||||
// which have been registered with the script namespace manager.
|
||||
|
|
|
@ -461,9 +461,6 @@ DOMCI_CLASS(MozTouchEvent)
|
|||
|
||||
DOMCI_CLASS(MathMLElement)
|
||||
|
||||
DOMCI_CLASS(Worker)
|
||||
DOMCI_CLASS(ChromeWorker)
|
||||
|
||||
// WebGL
|
||||
DOMCI_CLASS(WebGLRenderingContext)
|
||||
DOMCI_CLASS(WebGLBuffer)
|
||||
|
|
|
@ -91,9 +91,9 @@
|
|||
#include "nsLayoutStatics.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "nsDOMMediaQueryList.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
// Interfaces Needed
|
||||
#include "nsIFrame.h"
|
||||
|
@ -1244,18 +1244,11 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
|
|||
NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
|
||||
|
||||
// Kill all of the workers for this window.
|
||||
nsDOMThreadService* dts = nsDOMThreadService::get();
|
||||
if (dts) {
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
|
||||
JSContext *cx = scx ? (JSContext *)scx->GetNativeContext() : nsnull;
|
||||
|
||||
// Have to suspend this request here because CancelWorkersForGlobal will
|
||||
// lock until the worker has died and that could cause a deadlock.
|
||||
JSAutoSuspendRequest asr(cx);
|
||||
|
||||
dts->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
|
||||
}
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
JSContext *cx = scx ?
|
||||
static_cast<JSContext*>(scx->GetNativeContext()) :
|
||||
nsnull;
|
||||
mozilla::dom::workers::CancelWorkersForWindow(cx, this);
|
||||
|
||||
// Close all IndexedDB databases for this window.
|
||||
indexedDB::IndexedDatabaseManager* idbManager =
|
||||
|
@ -9928,11 +9921,13 @@ nsGlobalWindow::SuspendTimeouts(PRUint32 aIncrease,
|
|||
if (!suspended) {
|
||||
DisableDeviceMotionUpdates();
|
||||
|
||||
nsDOMThreadService* dts = nsDOMThreadService::get();
|
||||
if (dts) {
|
||||
dts->SuspendWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
|
||||
}
|
||||
|
||||
// Suspend all of the workers for this window.
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
JSContext *cx = scx ?
|
||||
static_cast<JSContext*>(scx->GetNativeContext()) :
|
||||
nsnull;
|
||||
mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
|
||||
// Set mTimeRemaining to be the time remaining for this timer.
|
||||
|
@ -10004,10 +9999,12 @@ nsGlobalWindow::ResumeTimeouts(PRBool aThawChildren)
|
|||
if (shouldResume) {
|
||||
EnableDeviceMotionUpdates();
|
||||
|
||||
nsDOMThreadService* dts = nsDOMThreadService::get();
|
||||
if (dts) {
|
||||
dts->ResumeWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
|
||||
}
|
||||
// Resume all of the workers for this window.
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
JSContext *cx = scx ?
|
||||
static_cast<JSContext*>(scx->GetNativeContext()) :
|
||||
nsnull;
|
||||
mozilla::dom::workers::ResumeWorkersForWindow(cx, this);
|
||||
|
||||
// Restore all of the timeouts, using the stored time remaining
|
||||
// (stored in timeout->mTimeRemaining).
|
||||
|
|
|
@ -3694,32 +3694,32 @@ ObjectPrincipalFinder(JSContext *cx, JSObject *obj)
|
|||
return jsPrincipals;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
DOMReadStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneReader* reader,
|
||||
uint32 tag,
|
||||
uint32 data,
|
||||
void* closure)
|
||||
JSObject*
|
||||
NS_DOMReadStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneReader* reader,
|
||||
uint32 tag,
|
||||
uint32 data,
|
||||
void* closure)
|
||||
{
|
||||
// We don't currently support any extensions to structured cloning.
|
||||
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DOMWriteStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneWriter* writer,
|
||||
JSObject* obj,
|
||||
void *closure)
|
||||
JSBool
|
||||
NS_DOMWriteStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneWriter* writer,
|
||||
JSObject* obj,
|
||||
void *closure)
|
||||
{
|
||||
// We don't currently support any extensions to structured cloning.
|
||||
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
DOMStructuredCloneError(JSContext* cx,
|
||||
uint32 errorid)
|
||||
void
|
||||
NS_DOMStructuredCloneError(JSContext* cx,
|
||||
uint32 errorid)
|
||||
{
|
||||
// We don't currently support any extensions to structured cloning.
|
||||
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
|
@ -3763,9 +3763,9 @@ nsJSRuntime::Init()
|
|||
|
||||
// Set up the structured clone callbacks.
|
||||
static JSStructuredCloneCallbacks cloneCallbacks = {
|
||||
DOMReadStructuredClone,
|
||||
DOMWriteStructuredClone,
|
||||
DOMStructuredCloneError
|
||||
NS_DOMReadStructuredClone,
|
||||
NS_DOMWriteStructuredClone,
|
||||
NS_DOMStructuredCloneError
|
||||
};
|
||||
JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks);
|
||||
|
||||
|
|
|
@ -363,4 +363,14 @@ nsresult NS_CreateJSRuntime(nsIScriptRuntime **aRuntime);
|
|||
/* prototypes */
|
||||
void NS_ScriptErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
JSObject* NS_DOMReadStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneReader* reader, uint32 tag,
|
||||
uint32 data, void* closure);
|
||||
|
||||
JSBool NS_DOMWriteStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneWriter* writer,
|
||||
JSObject* obj, void *closure);
|
||||
|
||||
void NS_DOMStructuredCloneError(JSContext* cx, uint32 errorid);
|
||||
|
||||
#endif /* nsJSEnvironment_h___ */
|
||||
|
|
|
@ -7,7 +7,7 @@ DOM_SRCDIRS = \
|
|||
dom/src/offline \
|
||||
dom/src/geolocation \
|
||||
dom/src/notification \
|
||||
dom/src/threads \
|
||||
dom/workers \
|
||||
content/xbl/src \
|
||||
content/xul/document/src \
|
||||
content/events/src \
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* From http://www.whatwg.org/specs/web-workers/current-work
|
||||
*/
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
interface nsIDOMEventListener;
|
||||
|
||||
[scriptable, uuid(ab3725b8-3fca-40cc-a42c-92fb154ef01d)]
|
||||
interface nsIWorkerMessagePort : nsISupports
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
};
|
||||
|
||||
[scriptable, uuid(508f2d49-e9a0-4fe8-bd33-321820173b4a)]
|
||||
interface nsIWorkerMessageEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString data;
|
||||
readonly attribute DOMString origin;
|
||||
|
||||
readonly attribute nsISupports source;
|
||||
|
||||
void initMessageEvent(in DOMString aTypeArg,
|
||||
in boolean aCanBubbleArg,
|
||||
in boolean aCancelableArg,
|
||||
in DOMString aDataArg,
|
||||
in DOMString aOriginArg,
|
||||
in nsISupports aSourceArg);
|
||||
};
|
||||
|
||||
[scriptable, uuid(73d82c1d-05de-49c9-a23b-7121ff09a67a)]
|
||||
interface nsIWorkerErrorEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString message;
|
||||
readonly attribute DOMString filename;
|
||||
|
||||
readonly attribute unsigned long lineno;
|
||||
|
||||
void initErrorEvent(in DOMString aTypeArg,
|
||||
in boolean aCanBubbleArg,
|
||||
in boolean aCancelableArg,
|
||||
in DOMString aMessageArg,
|
||||
in DOMString aFilenameArg,
|
||||
in unsigned long aLinenoArg);
|
||||
};
|
||||
|
||||
[scriptable, uuid(17a005c3-4f2f-4bb6-b169-c181fa6873de)]
|
||||
interface nsIWorkerLocation : nsISupports
|
||||
{
|
||||
readonly attribute AUTF8String href;
|
||||
readonly attribute AUTF8String protocol;
|
||||
readonly attribute AUTF8String host;
|
||||
readonly attribute AUTF8String hostname;
|
||||
readonly attribute AUTF8String port;
|
||||
readonly attribute AUTF8String pathname;
|
||||
readonly attribute AUTF8String search;
|
||||
readonly attribute AUTF8String hash;
|
||||
|
||||
AUTF8String toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(74fb665a-e477-4ce2-b3c6-c58b1b28b6c3)]
|
||||
interface nsIWorkerNavigator : nsISupports
|
||||
{
|
||||
readonly attribute DOMString appName;
|
||||
readonly attribute DOMString appVersion;
|
||||
readonly attribute DOMString platform;
|
||||
readonly attribute DOMString userAgent;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c111e7d3-8044-4458-aa7b-637696ffb841)]
|
||||
interface nsIWorkerGlobalScope : nsISupports
|
||||
{
|
||||
readonly attribute nsIWorkerGlobalScope self;
|
||||
readonly attribute nsIWorkerNavigator navigator;
|
||||
readonly attribute nsIWorkerLocation location;
|
||||
|
||||
attribute nsIDOMEventListener onerror;
|
||||
};
|
||||
|
||||
[scriptable, uuid(5c55ea4b-e4ac-4ceb-bfeb-46bd5e521b8a)]
|
||||
interface nsIWorkerScope : nsIWorkerGlobalScope
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
|
||||
void close();
|
||||
|
||||
attribute nsIDOMEventListener onmessage;
|
||||
attribute nsIDOMEventListener onclose;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(b90b7561-b5e2-4545-84b0-280dbaaa94ea)]
|
||||
interface nsIAbstractWorker : nsIDOMEventTarget
|
||||
{
|
||||
attribute nsIDOMEventListener onerror;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(daf945c3-8d29-4724-8939-dd383f7d27a7)]
|
||||
interface nsIWorker : nsIAbstractWorker
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
|
||||
attribute nsIDOMEventListener onmessage;
|
||||
|
||||
void terminate();
|
||||
};
|
||||
|
||||
[scriptable, uuid(cfc4bb32-ca83-4d58-9b6f-66f8054a333a)]
|
||||
interface nsIWorkerFactory : nsISupports
|
||||
{
|
||||
nsIWorker newChromeWorker(/* in DOMString aScriptURL */);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_WORKERFACTORY_CONTRACTID \
|
||||
"@mozilla.org/threads/workerfactory;1"
|
||||
%}
|
|
@ -891,8 +891,7 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
|
|||
PRBool
|
||||
nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi)
|
||||
{
|
||||
|
||||
NS_ENSURE_ARG_POINTER(psi);
|
||||
NS_ENSURE_TRUE(psi, PR_FALSE);
|
||||
|
||||
if (psi->mLength == mLength &&
|
||||
psi->mModified == mModified &&
|
||||
|
|
|
@ -1973,7 +1973,7 @@ PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor
|
|||
argv,
|
||||
0);
|
||||
if (NPERR_NO_ERROR != *rv) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX) && defined(__i386__)
|
||||
|
|
|
@ -42,6 +42,6 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = jsurl events storage offline json geolocation threads notification
|
||||
DIRS = jsurl events storage offline json geolocation notification foo
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -12,10 +11,11 @@
|
|||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
# The Original Code is worker threads.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Corporation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
@ -23,8 +23,8 @@
|
|||
# Ben Turner <bent.mozilla@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
|
@ -36,17 +36,20 @@
|
|||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = dom/src/foo
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dom
|
||||
XPIDL_MODULE = dom_threads
|
||||
GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = nsIDOMWorkers.idl
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
test_foo.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
|
@ -1,15 +1,16 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads
|
||||
Tests of DOM Worker Threads XHR(Bug 450452 )
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads Recursion</title>
|
||||
<title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -17,20 +18,10 @@ Tests of DOM Worker Threads
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var worker = new Worker("functionHandlers_worker.js");
|
||||
|
||||
var message = "hello!";
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
is(event.data, "uncaught exception: " + message, "Bad message!");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
worker.postMessage(message);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
ok(true, "passed");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,212 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMTHREADSERVICE_H__
|
||||
#define __NSDOMTHREADSERVICE_H__
|
||||
|
||||
// Interfaces
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIThreadPool.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTPtrArray.h"
|
||||
|
||||
#include "prlog.h"
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gDOMThreadsLog;
|
||||
#endif
|
||||
|
||||
class nsDOMWorker;
|
||||
class nsDOMWorkerPool;
|
||||
class nsDOMWorkerRunnable;
|
||||
class nsDOMWorkerTimeout;
|
||||
class nsIJSRuntimeService;
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIThreadJSContextStack;
|
||||
class nsIXPConnect;
|
||||
class nsIXPCSecurityManager;
|
||||
|
||||
enum ThreadsafeStatus
|
||||
{
|
||||
Threadsafe,
|
||||
NotThreadsafe,
|
||||
Unknown
|
||||
};
|
||||
|
||||
class nsDOMThreadService : public nsIEventTarget,
|
||||
public nsIObserver,
|
||||
public nsIThreadPoolListener
|
||||
{
|
||||
friend class nsDOMWorker;
|
||||
friend class nsDOMWorkerNavigator;
|
||||
friend class nsDOMWorkerPool;
|
||||
friend class nsDOMWorkerRunnable;
|
||||
friend class nsDOMWorkerThread;
|
||||
friend class nsDOMWorkerTimeout;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsLayoutStatics;
|
||||
friend class nsReportErrorRunnable;
|
||||
|
||||
friend void DOMWorkerErrorReporter(JSContext* aCx,
|
||||
const char* aMessage,
|
||||
JSErrorReport* aReport);
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIEVENTTARGET
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSITHREADPOOLLISTENER
|
||||
|
||||
// Any DOM consumers that need access to this service should use this method.
|
||||
static already_AddRefed<nsDOMThreadService> GetOrInitService();
|
||||
|
||||
// Simple getter for this service. This does not create the service if it
|
||||
// hasn't been created already, and it never AddRef's!
|
||||
static nsDOMThreadService* get();
|
||||
|
||||
static JSContext* GetCurrentContext();
|
||||
|
||||
// Easy access to the services we care about.
|
||||
static nsIJSRuntimeService* JSRuntimeService();
|
||||
static nsIThreadJSContextStack* ThreadJSContextStack();
|
||||
static nsIXPCSecurityManager* WorkerSecurityManager();
|
||||
|
||||
void CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
void SuspendWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
void ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
|
||||
nsresult ChangeThreadPoolMaxThreads(PRInt16 aDelta);
|
||||
|
||||
void NoteThreadsafeContractId(const nsACString& aContractId,
|
||||
PRBool aIsThreadsafe);
|
||||
|
||||
ThreadsafeStatus GetContractIdThreadsafeStatus(const nsACString& aContractId);
|
||||
|
||||
private:
|
||||
nsDOMThreadService();
|
||||
~nsDOMThreadService();
|
||||
|
||||
nsresult Init();
|
||||
void Cleanup();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
nsresult Dispatch(nsDOMWorker* aWorker,
|
||||
nsIRunnable* aRunnable,
|
||||
PRIntervalTime aTimeoutInterval = 0,
|
||||
PRBool aClearQueue = PR_FALSE);
|
||||
|
||||
void SetWorkerTimeout(nsDOMWorker* aWorker,
|
||||
PRIntervalTime aTimeoutInterval);
|
||||
|
||||
void WorkerComplete(nsDOMWorkerRunnable* aRunnable);
|
||||
|
||||
static JSContext* CreateJSContext();
|
||||
|
||||
already_AddRefed<nsDOMWorkerPool>
|
||||
GetPoolForGlobal(nsIScriptGlobalObject* aGlobalObject,
|
||||
PRBool aRemove);
|
||||
|
||||
void TriggerOperationCallbackForPool(nsDOMWorkerPool* aPool);
|
||||
void RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
void NoteEmptyPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
void TimeoutReady(nsDOMWorkerTimeout* aTimeout);
|
||||
|
||||
nsresult RegisterWorker(nsDOMWorker* aWorker,
|
||||
nsIScriptGlobalObject* aGlobalObject);
|
||||
|
||||
void GetAppName(nsAString& aAppName);
|
||||
void GetAppVersion(nsAString& aAppVersion);
|
||||
void GetPlatform(nsAString& aPlatform);
|
||||
void GetUserAgent(nsAString& aUserAgent);
|
||||
|
||||
void RegisterPrefCallbacks();
|
||||
void UnregisterPrefCallbacks();
|
||||
|
||||
static int PrefCallback(const char* aPrefName,
|
||||
void* aClosure);
|
||||
|
||||
static PRUint32 GetWorkerCloseHandlerTimeoutMS();
|
||||
|
||||
PRBool QueueSuspendedWorker(nsDOMWorkerRunnable* aRunnable);
|
||||
|
||||
// Our internal thread pool.
|
||||
nsCOMPtr<nsIThreadPool> mThreadPool;
|
||||
|
||||
// Maps nsIScriptGlobalObject* to nsDOMWorkerPool.
|
||||
nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerPool> mPools;
|
||||
|
||||
// mReentrantMonitor protects all access to mWorkersInProgress and
|
||||
// mCreationsInProgress.
|
||||
mozilla::ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
// A map from nsDOMWorkerThread to nsDOMWorkerRunnable.
|
||||
nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerRunnable> mWorkersInProgress;
|
||||
|
||||
// A list of active JSContexts that we've created. Always protected with
|
||||
// mReentrantMonitor.
|
||||
nsTArray<JSContext*> mJSContexts;
|
||||
|
||||
// A list of worker runnables that were never started because the worker was
|
||||
// suspended. Always protected with mReentrantMonitor.
|
||||
nsTArray<nsDOMWorkerRunnable*> mSuspendedWorkers;
|
||||
|
||||
// Always protected with mReentrantMonitor.
|
||||
nsDataHashtable<nsCStringHashKey, PRBool> mThreadsafeContractIDs;
|
||||
|
||||
nsString mAppName;
|
||||
nsString mAppVersion;
|
||||
nsString mPlatform;
|
||||
nsString mUserAgent;
|
||||
|
||||
PRBool mNavigatorStringsLoaded;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMTHREADSERVICE_H__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,471 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKER_H__
|
||||
#define __NSDOMWORKER_H__
|
||||
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTPtrArray.h"
|
||||
|
||||
#include "nsDOMWorkerMessageHandler.h"
|
||||
|
||||
// {1295EFB5-8644-42B2-8B8E-80EEF56E4284}
|
||||
#define NS_WORKERFACTORY_CID \
|
||||
{0x1295efb5, 0x8644, 0x42b2, \
|
||||
{0x8b, 0x8e, 0x80, 0xee, 0xf5, 0x6e, 0x42, 0x84} }
|
||||
|
||||
class nsDOMWorker;
|
||||
class nsDOMWorkerFeature;
|
||||
class nsDOMWorkerMessageHandler;
|
||||
class nsDOMWorkerNavigator;
|
||||
class nsDOMWorkerPool;
|
||||
class nsDOMWorkerTimeout;
|
||||
class nsICancelable;
|
||||
class nsIDOMEventListener;
|
||||
class nsIEventTarget;
|
||||
class nsIRunnable;
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIXPConnectWrappedNative;
|
||||
|
||||
class nsDOMWorkerScope : public nsDOMWorkerMessageHandler,
|
||||
public nsIWorkerScope,
|
||||
public nsIXPCScriptable
|
||||
{
|
||||
friend class nsDOMWorker;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMEventHandler
|
||||
NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
NS_IMETHOD RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval);
|
||||
NS_DECL_NSIWORKERGLOBALSCOPE
|
||||
NS_DECL_NSIWORKERSCOPE
|
||||
NS_DECL_NSIXPCSCRIPTABLE
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
typedef NS_STDCALL_FUNCPROTO(nsresult, SetListenerFunc, nsDOMWorkerScope,
|
||||
SetOnmessage, (nsIDOMEventListener*));
|
||||
|
||||
nsDOMWorkerScope(nsDOMWorker* aWorker);
|
||||
|
||||
protected:
|
||||
already_AddRefed<nsIXPConnectWrappedNative> GetWrappedNative();
|
||||
|
||||
private:
|
||||
nsDOMWorker* mWorker;
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
nsRefPtr<nsDOMWorkerNavigator> mNavigator;
|
||||
|
||||
PRPackedBool mHasOnerror;
|
||||
};
|
||||
|
||||
class nsLazyAutoRequest
|
||||
{
|
||||
public:
|
||||
nsLazyAutoRequest() : mCx(nsnull) {}
|
||||
|
||||
~nsLazyAutoRequest() {
|
||||
if (mCx)
|
||||
JS_EndRequest(mCx);
|
||||
}
|
||||
|
||||
void enter(JSContext *aCx) {
|
||||
JS_BeginRequest(aCx);
|
||||
mCx = aCx;
|
||||
}
|
||||
|
||||
bool entered() const { return mCx != nsnull; }
|
||||
|
||||
void swap(nsLazyAutoRequest &other) {
|
||||
JSContext *tmp = mCx;
|
||||
mCx = other.mCx;
|
||||
other.mCx = tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
JSContext *mCx;
|
||||
};
|
||||
|
||||
class nsDOMWorker : public nsDOMWorkerMessageHandler,
|
||||
public nsIWorker,
|
||||
public nsITimerCallback,
|
||||
public nsIJSNativeInitializer,
|
||||
public nsIXPCScriptable
|
||||
{
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
friend class nsDOMWorkerFeature;
|
||||
friend class nsDOMWorkerFunctions;
|
||||
friend class nsDOMWorkerScope;
|
||||
friend class nsDOMWorkerScriptLoader;
|
||||
friend class nsDOMWorkerTimeout;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsReportErrorRunnable;
|
||||
friend class nsDOMFireEventRunnable;
|
||||
|
||||
friend JSBool DOMWorkerOperationCallback(JSContext* aCx);
|
||||
friend void DOMWorkerErrorReporter(JSContext* aCx,
|
||||
const char* aMessage,
|
||||
JSErrorReport* aReport);
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMEventHandler
|
||||
NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
NS_IMETHOD RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval);
|
||||
|
||||
NS_DECL_NSIABSTRACTWORKER
|
||||
NS_DECL_NSIWORKER
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSICLASSINFO
|
||||
NS_DECL_NSIXPCSCRIPTABLE
|
||||
|
||||
static nsresult NewWorker(nsISupports** aNewObject);
|
||||
static nsresult NewChromeWorker(nsISupports** aNewObject);
|
||||
static nsresult NewChromeDOMWorker(nsDOMWorker** aNewObject);
|
||||
|
||||
enum WorkerPrivilegeModel { CONTENT, CHROME };
|
||||
|
||||
nsDOMWorker(nsDOMWorker* aParent,
|
||||
nsIXPConnectWrappedNative* aParentWN,
|
||||
WorkerPrivilegeModel aModel);
|
||||
|
||||
NS_IMETHOD Initialize(nsISupports* aOwner,
|
||||
JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
PRUint32 aArgc,
|
||||
jsval* aArgv);
|
||||
|
||||
nsresult InitializeInternal(nsIScriptGlobalObject* aOwner,
|
||||
JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
PRUint32 aArgc,
|
||||
jsval* aArgv);
|
||||
|
||||
void Cancel();
|
||||
void Kill();
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
||||
// This just calls IsCanceledNoLock with an autolock around the call.
|
||||
PRBool IsCanceled();
|
||||
|
||||
PRBool IsClosing();
|
||||
PRBool IsSuspended();
|
||||
|
||||
PRBool SetGlobalForContext(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoEnterCompartment *aComp);
|
||||
|
||||
void SetPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
nsDOMWorkerPool* Pool() {
|
||||
return mPool;
|
||||
}
|
||||
|
||||
Mutex& GetLock() {
|
||||
return mLock;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIXPConnectWrappedNative> GetWrappedNative();
|
||||
already_AddRefed<nsDOMWorker> GetParent();
|
||||
|
||||
nsDOMWorkerScope* GetInnerScope() {
|
||||
return mInnerScope;
|
||||
}
|
||||
|
||||
void SetExpirationTime(PRIntervalTime aExpirationTime);
|
||||
#ifdef DEBUG
|
||||
PRIntervalTime GetExpirationTime();
|
||||
#endif
|
||||
|
||||
PRBool IsPrivileged() {
|
||||
return mPrivilegeModel == CHROME;
|
||||
}
|
||||
|
||||
static JSObject* ReadStructuredClone(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32 aTag,
|
||||
uint32 aData,
|
||||
void* aClosure);
|
||||
|
||||
/**
|
||||
* Use this chart to help figure out behavior during each of the closing
|
||||
* statuses. Details below.
|
||||
*
|
||||
* +=============+=============+=================+=======================+
|
||||
* | status | clear queue | abort execution | close handler timeout |
|
||||
* +=============+=============+=================+=======================+
|
||||
* | eClosed | yes | no | no |
|
||||
* +-------------+-------------+-----------------+-----------------------+
|
||||
* | eTerminated | yes | yes | no |
|
||||
* +-------------+-------------+-----------------+-----------------------+
|
||||
* | eCanceled | yes | yes | yes |
|
||||
* +-------------+-------------+-----------------+-----------------------+
|
||||
*
|
||||
*/
|
||||
|
||||
enum DOMWorkerStatus {
|
||||
// This status means that the close handler has not yet been scheduled.
|
||||
eRunning = 0,
|
||||
|
||||
// Inner script called Close() on the worker global scope. Setting this
|
||||
// status causes the worker to clear its queue of events but does not abort
|
||||
// the currently running script. The close handler is also scheduled with
|
||||
// no expiration time. This status may be superseded by 'eTerminated' in
|
||||
// which case the currently running script will be aborted as detailed
|
||||
// below. It may also be superseded by 'eCanceled' at which point the close
|
||||
// handler will be assigned an expiration time. Once the close handler has
|
||||
// completed or timed out the status will be changed to 'eKilled'.
|
||||
eClosed,
|
||||
|
||||
// Outer script called Terminate() on the worker or the worker object was
|
||||
// garbage collected in its outer script. Setting this status causes the
|
||||
// worker to abort immediately, clear its queue of events, and schedules the
|
||||
// close handler with no expiration time. This status may be superseded by
|
||||
// 'eCanceled' at which point the close handler will have an expiration time
|
||||
// assigned. Once the close handler has completed or timed out the status
|
||||
// will be changed to 'eKilled'.
|
||||
eTerminated,
|
||||
|
||||
// Either the user navigated away from the owning page, the owning page fell
|
||||
// out of bfcache, or the user quit the application. Setting this status
|
||||
// causes the worker to abort immediately and schedules the close handler
|
||||
// with an expiration time. Since the page has gone away the worker may not
|
||||
// post any messages. Once the close handler has completed or timed out the
|
||||
// status will be changed to 'eKilled'.
|
||||
eCanceled,
|
||||
|
||||
// The close handler has run and the worker is effectively dead.
|
||||
eKilled
|
||||
};
|
||||
|
||||
private:
|
||||
~nsDOMWorker();
|
||||
|
||||
nsresult PostMessageInternal(PRBool aToInner);
|
||||
|
||||
PRBool CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoEnterCompartment *aComp);
|
||||
|
||||
PRUint32 NextTimeoutId() {
|
||||
return ++mNextTimeoutId;
|
||||
}
|
||||
|
||||
nsresult AddFeature(nsDOMWorkerFeature* aFeature,
|
||||
JSContext* aCx);
|
||||
void RemoveFeature(nsDOMWorkerFeature* aFeature,
|
||||
JSContext* aCx);
|
||||
void CancelTimeoutWithId(PRUint32 aId);
|
||||
void SuspendFeatures();
|
||||
void ResumeFeatures();
|
||||
|
||||
nsIPrincipal* GetPrincipal() {
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
void SetPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
nsIURI* GetBaseURI() {
|
||||
return mBaseURI;
|
||||
}
|
||||
|
||||
nsresult SetBaseURI(nsIURI* aURI);
|
||||
|
||||
void ClearBaseURI();
|
||||
|
||||
nsresult FireCloseRunnable(PRIntervalTime aTimeoutInterval,
|
||||
PRBool aClearQueue,
|
||||
PRBool aFromFinalize);
|
||||
nsresult Close();
|
||||
|
||||
nsresult TerminateInternal(PRBool aFromFinalize);
|
||||
|
||||
nsIWorkerLocation* GetLocation() {
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
PRBool QueueSuspendedRunnable(nsIRunnable* aRunnable);
|
||||
|
||||
// Determines if the worker should be considered "canceled". See the large
|
||||
// comment in the implementation for more details.
|
||||
PRBool IsCanceledNoLock();
|
||||
|
||||
private:
|
||||
|
||||
// mParent will live as long as mParentWN but only mParentWN will keep the JS
|
||||
// reflection alive, so we only hold one strong reference to mParentWN.
|
||||
nsDOMWorker* mParent;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mParentWN;
|
||||
|
||||
// Whether or not this worker has chrome privileges. Never changed after the
|
||||
// worker is created.
|
||||
WorkerPrivilegeModel mPrivilegeModel;
|
||||
|
||||
Mutex mLock;
|
||||
|
||||
nsRefPtr<nsDOMWorkerPool> mPool;
|
||||
|
||||
nsDOMWorkerScope* mInnerScope;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mScopeWN;
|
||||
JSObject* mGlobal;
|
||||
|
||||
PRUint32 mNextTimeoutId;
|
||||
|
||||
nsTArray<nsDOMWorkerFeature*> mFeatures;
|
||||
PRUint32 mFeatureSuspendDepth;
|
||||
|
||||
nsString mScriptURL;
|
||||
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
|
||||
PRInt32 mErrorHandlerRecursionCount;
|
||||
|
||||
// Always protected by mLock
|
||||
DOMWorkerStatus mStatus;
|
||||
|
||||
// Always protected by mLock
|
||||
PRIntervalTime mExpirationTime;
|
||||
|
||||
nsCOMPtr<nsITimer> mKillTimer;
|
||||
|
||||
nsCOMPtr<nsIWorkerLocation> mLocation;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > mQueuedRunnables;
|
||||
|
||||
PRPackedBool mSuspended;
|
||||
PRPackedBool mCompileAttempted;
|
||||
};
|
||||
|
||||
/**
|
||||
* A worker "feature" holds the worker alive yet can be canceled, paused, and
|
||||
* resumed by the worker. It is up to each derived class to implement these
|
||||
* methods. This class uses a custom implementation of Release in order to
|
||||
* ensure no races between Cancel and object destruction can occur, so derived
|
||||
* classes must use the ISUPPORTS_INHERITED macros.
|
||||
*
|
||||
* To use this class you should inherit it and use the ISUPPORTS_INHERITED
|
||||
* macros. Then add or remove an instance to the worker using the
|
||||
* AddFeature/RemoveFeature functions.
|
||||
*/
|
||||
class nsDOMWorkerFeature : public nsISupports
|
||||
{
|
||||
friend class nsDOMWorker;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDOMWorkerFeature(nsDOMWorker* aWorker)
|
||||
: mWorker(aWorker), mWorkerWN(aWorker->GetWrappedNative()), mId(0),
|
||||
mHasId(PR_FALSE), mFreeToDie(PR_TRUE) { }
|
||||
|
||||
nsDOMWorkerFeature(nsDOMWorker* aWorker, PRUint32 aId)
|
||||
: mWorker(aWorker), mWorkerWN(aWorker->GetWrappedNative()), mId(aId),
|
||||
mHasId(PR_TRUE), mFreeToDie(PR_TRUE) { }
|
||||
|
||||
virtual void Cancel() = 0;
|
||||
virtual void Suspend() { }
|
||||
virtual void Resume() { }
|
||||
|
||||
PRUint32 GetId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
PRBool HasId() {
|
||||
return mHasId;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerFeature() { }
|
||||
|
||||
private:
|
||||
void FreeToDie(PRBool aFreeToDie) {
|
||||
mFreeToDie = aFreeToDie;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsDOMWorker> mWorker;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mWorkerWN;
|
||||
PRUint32 mId;
|
||||
|
||||
private:
|
||||
PRPackedBool mHasId;
|
||||
PRPackedBool mFreeToDie;
|
||||
};
|
||||
|
||||
class nsWorkerFactory : public nsIWorkerFactory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWORKERFACTORY
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKER_H__ */
|
|
@ -1,635 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerEvents.h"
|
||||
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsDOMWorkerMessageHandler.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMWorkerPrivateEvent,
|
||||
NS_IDOMWORKERPRIVATEEVENT_IID)
|
||||
|
||||
nsDOMWorkerPrivateEvent::nsDOMWorkerPrivateEvent(nsIDOMEvent* aEvent)
|
||||
: mEvent(aEvent),
|
||||
mProgressEvent(do_QueryInterface(aEvent)),
|
||||
mMessageEvent(do_QueryInterface(aEvent)),
|
||||
mErrorEvent(do_QueryInterface(aEvent)),
|
||||
mPreventDefaultCalled(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(aEvent, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerPrivateEvent)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerPrivateEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEvent, nsIDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMWorkerPrivateEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMProgressEvent, mProgressEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIWorkerMessageEvent, mMessageEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIWorkerErrorEvent, mErrorEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerPrivateEvent, nsIDOMEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_HELPER(nsDOMWorkerPrivateEvent)
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerPrivateEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::GetInterfaces(PRUint32* aCount, nsIID*** aArray)
|
||||
{
|
||||
nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(mEvent));
|
||||
if (ci) {
|
||||
return ci->GetInterfaces(aCount, aArray);
|
||||
}
|
||||
return NS_CI_INTERFACE_GETTER_NAME(nsDOMWorkerPrivateEvent)(aCount, aArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::PreventDefault()
|
||||
{
|
||||
PRBool cancelable = PR_FALSE;
|
||||
mEvent->GetCancelable(&cancelable);
|
||||
|
||||
if (cancelable) {
|
||||
mPreventDefaultCalled = PR_TRUE;
|
||||
}
|
||||
|
||||
return mEvent->PreventDefault();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::GetDefaultPrevented(PRBool* aRetVal)
|
||||
{
|
||||
*aRetVal = mPreventDefaultCalled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitEvent(const nsAString& aEventType,
|
||||
PRBool aCanBubble,
|
||||
PRBool aCancelable)
|
||||
{
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mEvent->InitEvent(aEventType, aCanBubble, aCancelable);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitProgressEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
PRBool aLengthComputableArg,
|
||||
PRUint64 aLoadedArg,
|
||||
PRUint64 aTotalArg)
|
||||
{
|
||||
NS_ASSERTION(mProgressEvent, "Impossible!");
|
||||
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mProgressEvent->InitProgressEvent(aTypeArg, aCanBubbleArg,
|
||||
aCancelableArg, aLengthComputableArg,
|
||||
aLoadedArg, aTotalArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitMessageEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aDataArg,
|
||||
const nsAString& aOriginArg,
|
||||
nsISupports* aSourceArg)
|
||||
{
|
||||
NS_ASSERTION(mMessageEvent, "Impossible!");
|
||||
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mMessageEvent->InitMessageEvent(aTypeArg, aCanBubbleArg,
|
||||
aCancelableArg, aDataArg, aOriginArg,
|
||||
aSourceArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPrivateEvent::InitErrorEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aMessageArg,
|
||||
const nsAString& aFilenameArg,
|
||||
PRUint32 aLinenoArg)
|
||||
{
|
||||
NS_ASSERTION(mErrorEvent, "Impossible!");
|
||||
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mErrorEvent->InitErrorEvent(aTypeArg, aCanBubbleArg, aCancelableArg,
|
||||
aMessageArg, aFilenameArg, aLinenoArg);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorkerPrivateEvent::PreventDefaultCalled()
|
||||
{
|
||||
return mPreventDefaultCalled;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerEvent, nsIDOMEvent,
|
||||
nsIClassInfo)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerEvent, nsIDOMEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI(nsDOMWorkerEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetType(nsAString& aType)
|
||||
{
|
||||
aType.Assign(mType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetTarget(nsIDOMEventTarget** aTarget)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTarget);
|
||||
NS_IF_ADDREF(*aTarget = mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCurrentTarget);
|
||||
NS_IF_ADDREF(*aCurrentTarget = mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetEventPhase(PRUint16* aEventPhase)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEventPhase);
|
||||
*aEventPhase = mEventPhase;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetBubbles(PRBool* aBubbles)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aBubbles);
|
||||
*aBubbles = mBubbles;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetCancelable(PRBool* aCancelable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCancelable);
|
||||
*aCancelable = mCancelable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetTimeStamp(DOMTimeStamp* aTimeStamp)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTimeStamp);
|
||||
*aTimeStamp = mTimeStamp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::StopPropagation()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::PreventDefault()
|
||||
{
|
||||
mPreventDefaultCalled = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::GetDefaultPrevented(PRBool* aRetVal)
|
||||
{
|
||||
*aRetVal = mPreventDefaultCalled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerEvent::InitEvent(const nsAString& aEventTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg)
|
||||
{
|
||||
NS_ENSURE_FALSE(aEventTypeArg.IsEmpty(), NS_ERROR_INVALID_ARG);
|
||||
|
||||
mType.Assign(aEventTypeArg);
|
||||
mBubbles = aCanBubbleArg;
|
||||
mCancelable = aCancelableArg;
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
mTimeStamp = PR_Now();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerMessageEvent::~nsDOMWorkerMessageEvent()
|
||||
{
|
||||
if (mData) {
|
||||
JSContext* cx = nsDOMThreadService::GetCurrentContext();
|
||||
if (cx) {
|
||||
JS_free(cx, mData);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Failed to get safe JSContext, leaking event data!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerMessageEvent, nsDOMWorkerEvent,
|
||||
nsIWorkerMessageEvent)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
|
||||
nsIWorkerMessageEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageEvent::SetJSData(
|
||||
JSContext* aCx,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
nsTArray<nsCOMPtr<nsISupports> >& aWrappedNatives)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
|
||||
if (!mDataVal.Hold(aCx)) {
|
||||
NS_WARNING("Failed to hold jsval!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mWrappedNatives.SwapElements(aWrappedNatives)) {
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
|
||||
aBuffer.steal(&mData, &mDataLen);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::GetData(nsAString& aData)
|
||||
{
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAXPCNativeCallContext* cc;
|
||||
nsresult rv = xpc->GetCurrentNativeCallContext(&cc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (mData) {
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
buffer.adopt(cx, mData, mDataLen);
|
||||
mData = nsnull;
|
||||
mDataLen = 0;
|
||||
|
||||
JSStructuredCloneCallbacks callbacks = {
|
||||
nsDOMWorker::ReadStructuredClone, nsnull, nsnull
|
||||
};
|
||||
|
||||
JSBool ok = buffer.read(mDataVal.ToJSValPtr(), cx, &callbacks);
|
||||
|
||||
// Release wrapped natives now, regardless of whether or not the deserialize
|
||||
// succeeded.
|
||||
mWrappedNatives.Clear();
|
||||
|
||||
if (!ok) {
|
||||
NS_WARNING("Failed to deserialize!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
jsval* retval;
|
||||
rv = cc->GetRetValPtr(&retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
*retval = mDataVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::GetOrigin(nsAString& aOrigin)
|
||||
{
|
||||
aOrigin.Assign(mOrigin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::GetSource(nsISupports** aSource)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSource);
|
||||
NS_IF_ADDREF(*aSource = mSource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageEvent::InitMessageEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aDataArg,
|
||||
const nsAString& aOriginArg,
|
||||
nsISupports* aSourceArg)
|
||||
{
|
||||
mOrigin.Assign(aOriginArg);
|
||||
mSource = aSourceArg;
|
||||
return nsDOMWorkerEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerProgressEvent, nsDOMWorkerEvent,
|
||||
nsIDOMProgressEvent)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerProgressEvent, nsIDOMEvent,
|
||||
nsIDOMProgressEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerProgressEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::GetLengthComputable(PRBool* aLengthComputable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLengthComputable);
|
||||
*aLengthComputable = mLengthComputable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::GetLoaded(PRUint64* aLoaded)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoaded);
|
||||
*aLoaded = mLoaded;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::GetTotal(PRUint64* aTotal)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTotal);
|
||||
*aTotal = mTotal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerProgressEvent::InitProgressEvent(const nsAString_internal& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
PRBool aLengthComputableArg,
|
||||
PRUint64 aLoadedArg,
|
||||
PRUint64 aTotalArg)
|
||||
{
|
||||
mLengthComputable = aLengthComputableArg;
|
||||
mLoaded = aLoadedArg;
|
||||
mTotal = aTotalArg;
|
||||
return nsDOMWorkerEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerXHRState)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerXHRState)
|
||||
|
||||
nsDOMWorkerXHREvent::nsDOMWorkerXHREvent(nsDOMWorkerXHRProxy* aXHRProxy)
|
||||
: mXHRProxy(aXHRProxy),
|
||||
mXHREventType(PR_UINT32_MAX),
|
||||
mChannelID(-1),
|
||||
mUploadEvent(PR_FALSE),
|
||||
mProgressEvent(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(aXHRProxy, "Can't be null!");
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMWorkerXHREvent, nsDOMWorkerProgressEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMWorkerXHREvent, nsDOMWorkerProgressEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMWorkerXHREvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMProgressEvent, mProgressEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMWorkerEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREvent::GetInterfaces(PRUint32* aCount,
|
||||
nsIID*** aArray)
|
||||
{
|
||||
PRUint32 count = *aCount = mProgressEvent ? 2 : 1;
|
||||
|
||||
*aArray = (nsIID**)nsMemory::Alloc(sizeof(nsIID*) * count);
|
||||
|
||||
if (mProgressEvent) {
|
||||
(*aArray)[--count] =
|
||||
(nsIID*)nsMemory::Clone(&NS_GET_IID(nsIDOMProgressEvent), sizeof(nsIID));
|
||||
}
|
||||
|
||||
(*aArray)[--count] =
|
||||
(nsIID *)nsMemory::Clone(&NS_GET_IID(nsIDOMEvent), sizeof(nsIID));
|
||||
|
||||
NS_ASSERTION(!count, "Bad math!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHREvent::Init(PRUint32 aXHREventType,
|
||||
const nsAString& aType,
|
||||
nsIDOMEvent* aEvent,
|
||||
SnapshotChoice aSnapshot)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aEvent, "Don't pass null here!");
|
||||
|
||||
mXHREventType = aXHREventType;
|
||||
|
||||
// Only set a channel id if we're not going to be run immediately.
|
||||
mChannelID = mXHRProxy->mSyncEventQueue ? -1 : mXHRProxy->ChannelID();
|
||||
|
||||
mTarget = static_cast<nsDOMWorkerMessageHandler*>(mXHRProxy->mWorkerXHR);
|
||||
NS_ENSURE_TRUE(mTarget, NS_ERROR_UNEXPECTED);
|
||||
|
||||
mXHRWN = mXHRProxy->mWorkerXHR->GetWrappedNative();
|
||||
NS_ENSURE_STATE(mXHRWN);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> mainThreadTarget;
|
||||
nsresult rv = aEvent->GetTarget(getter_AddRefs(mainThreadTarget));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(mainThreadTarget);
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequestUpload> upload(do_QueryInterface(mainThreadTarget));
|
||||
if (upload) {
|
||||
mUploadEvent = PR_TRUE;
|
||||
mTarget =
|
||||
static_cast<nsDOMWorkerMessageHandler*>(mXHRProxy->mWorkerXHR->mUpload);
|
||||
}
|
||||
else {
|
||||
mUploadEvent = PR_FALSE;
|
||||
mTarget = static_cast<nsDOMWorkerMessageHandler*>(mXHRProxy->mWorkerXHR);
|
||||
}
|
||||
NS_ASSERTION(mTarget, "Null target!");
|
||||
|
||||
PRBool bubbles;
|
||||
rv = aEvent->GetBubbles(&bubbles);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool cancelable;
|
||||
rv = aEvent->GetCancelable(&cancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aEvent->GetTimeStamp(&mTimeStamp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aEvent->GetEventPhase(&mEventPhase);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(mEventPhase == nsIDOMEvent::AT_TARGET, "Unsupported phase!");
|
||||
|
||||
nsCOMPtr<nsIDOMProgressEvent> progressEvent(do_QueryInterface(aEvent));
|
||||
if (progressEvent) {
|
||||
mProgressEvent = PR_TRUE;
|
||||
|
||||
PRBool lengthComputable;
|
||||
rv = progressEvent->GetLengthComputable(&lengthComputable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint64 loaded;
|
||||
rv = progressEvent->GetLoaded(&loaded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint64 total;
|
||||
rv = progressEvent->GetTotal(&total);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = InitProgressEvent(aType, bubbles, cancelable, lengthComputable, loaded,
|
||||
total);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
mProgressEvent = PR_FALSE;
|
||||
|
||||
rv = InitEvent(aType, bubbles, cancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mState = new nsDOMWorkerXHRState();
|
||||
NS_ENSURE_TRUE(mState, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (aSnapshot == SNAPSHOT) {
|
||||
SnapshotXHRState(mXHRProxy->mXHR, mState);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsDOMWorkerXHREvent::SnapshotXHRState(nsIXMLHttpRequest* aXHR,
|
||||
nsDOMWorkerXHRState* aState)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aXHR && aState, "Don't pass null here!");
|
||||
|
||||
aState->responseTextResult = aXHR->GetResponseText(aState->responseText);
|
||||
aState->statusTextResult = aXHR->GetStatusText(aState->statusText);
|
||||
aState->statusResult = aXHR->GetStatus(&aState->status);
|
||||
aState->readyStateResult = aXHR->GetReadyState(&aState->readyState);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREvent::Run()
|
||||
{
|
||||
nsresult rv = mXHRProxy->HandleWorkerEvent(this, mUploadEvent);
|
||||
|
||||
// Prevent reference cycles by releasing this here.
|
||||
mXHRProxy = nsnull;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerErrorEvent, nsDOMWorkerEvent,
|
||||
nsIWorkerErrorEvent)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerErrorEvent, nsIDOMEvent,
|
||||
nsIWorkerErrorEvent)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerErrorEvent)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::GetMessage(nsAString& aMessage)
|
||||
{
|
||||
aMessage.Assign(mMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::GetFilename(nsAString& aFilename)
|
||||
{
|
||||
aFilename.Assign(mFilename);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::GetLineno(PRUint32* aLineno)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLineno);
|
||||
*aLineno = mLineno;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerErrorEvent::InitErrorEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aMessageArg,
|
||||
const nsAString& aFilenameArg,
|
||||
PRUint32 aLinenoArg)
|
||||
{
|
||||
mMessage.Assign(aMessageArg);
|
||||
mFilename.Assign(aFilenameArg);
|
||||
mLineno = aLinenoArg;
|
||||
return InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
}
|
|
@ -1,340 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKEREVENTS_H__
|
||||
#define __NSDOMWORKEREVENTS_H__
|
||||
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMProgressEvent.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsutil.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#include "nsDOMWorkerMacros.h"
|
||||
|
||||
class nsDOMWorkerXHRProxy;
|
||||
class nsIXMLHttpRequest;
|
||||
class nsIXPConnectWrappedNative;
|
||||
|
||||
/* 4d5794d6-98ab-4a6b-ad5a-8ed1fa1d4839 */
|
||||
#define NS_IDOMWORKERPRIVATEEVENT_IID \
|
||||
{ \
|
||||
0x4d5794d6, \
|
||||
0x98ab, \
|
||||
0x4a6b, \
|
||||
{ 0xad, 0x5a, 0x8e, 0xd1, 0xfa, 0x1d, 0x48, 0x39 } \
|
||||
}
|
||||
|
||||
class nsIDOMWorkerPrivateEvent : public nsIDOMEvent
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMWORKERPRIVATEEVENT_IID)
|
||||
virtual PRBool PreventDefaultCalled() = 0;
|
||||
};
|
||||
|
||||
#define NS_FORWARD_NSIDOMEVENT_SPECIAL \
|
||||
NS_IMETHOD GetType(nsAString& aType) \
|
||||
{ return mEvent->GetType(aType); } \
|
||||
NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) \
|
||||
{ return mEvent->GetTarget(aTarget); } \
|
||||
NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) \
|
||||
{ return mEvent->GetCurrentTarget(aCurrentTarget); } \
|
||||
NS_IMETHOD GetEventPhase(PRUint16* aEventPhase) \
|
||||
{ return mEvent->GetEventPhase(aEventPhase); } \
|
||||
NS_IMETHOD GetBubbles(PRBool* aBubbles) \
|
||||
{ return mEvent->GetBubbles(aBubbles); } \
|
||||
NS_IMETHOD GetCancelable(PRBool* aCancelable) \
|
||||
{ return mEvent->GetCancelable(aCancelable); } \
|
||||
NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) \
|
||||
{ return mEvent->GetTimeStamp(aTimeStamp); } \
|
||||
NS_IMETHOD StopPropagation() \
|
||||
{ return mEvent->StopPropagation(); }
|
||||
|
||||
#define NS_FORWARD_NSIDOMPROGRESSEVENT_SPECIAL \
|
||||
NS_IMETHOD GetLengthComputable(PRBool* aLengthComputable) \
|
||||
{ return mProgressEvent->GetLengthComputable(aLengthComputable); } \
|
||||
NS_IMETHOD GetLoaded(PRUint64* aLoaded) \
|
||||
{ return mProgressEvent->GetLoaded(aLoaded); } \
|
||||
NS_IMETHOD GetTotal(PRUint64* aTotal) \
|
||||
{ return mProgressEvent->GetTotal(aTotal); }
|
||||
|
||||
#define NS_FORWARD_NSIWORKERMESSAGEEVENT_SPECIAL \
|
||||
NS_IMETHOD GetData(nsAString& aData) \
|
||||
{ return mMessageEvent->GetData(aData); } \
|
||||
NS_IMETHOD GetOrigin(nsAString& aOrigin) \
|
||||
{ return mMessageEvent->GetOrigin(aOrigin); } \
|
||||
NS_IMETHOD GetSource(nsISupports** aSource) \
|
||||
{ return mMessageEvent->GetSource(aSource); }
|
||||
|
||||
#define NS_FORWARD_NSIWORKERERROREVENT_SPECIAL \
|
||||
NS_IMETHOD GetMessage(nsAString& aMessage) \
|
||||
{ return mErrorEvent->GetMessage(aMessage); } \
|
||||
NS_IMETHOD GetFilename(nsAString& aFilename) \
|
||||
{ return mErrorEvent->GetFilename(aFilename); } \
|
||||
NS_IMETHOD GetLineno(PRUint32* aLineno) \
|
||||
{ return mErrorEvent->GetLineno(aLineno); }
|
||||
|
||||
class nsDOMWorkerPrivateEvent : public nsIDOMWorkerPrivateEvent,
|
||||
public nsIDOMProgressEvent,
|
||||
public nsIWorkerMessageEvent,
|
||||
public nsIWorkerErrorEvent,
|
||||
public nsIClassInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIDOMEVENT_SPECIAL
|
||||
NS_FORWARD_NSIWORKERMESSAGEEVENT_SPECIAL
|
||||
NS_FORWARD_NSIDOMPROGRESSEVENT_SPECIAL
|
||||
NS_FORWARD_NSIWORKERERROREVENT_SPECIAL
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
nsDOMWorkerPrivateEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
NS_IMETHOD PreventDefault();
|
||||
|
||||
NS_IMETHOD InitEvent(const nsAString& aEventType,
|
||||
PRBool aCanBubble,
|
||||
PRBool aCancelable);
|
||||
|
||||
NS_IMETHOD InitProgressEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
PRBool aLengthComputableArg,
|
||||
PRUint64 aLoadedArg,
|
||||
PRUint64 aTotalArg);
|
||||
|
||||
NS_IMETHOD InitMessageEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aDataArg,
|
||||
const nsAString& aOriginArg,
|
||||
nsISupports* aSourceArg);
|
||||
|
||||
NS_IMETHOD InitErrorEvent(const nsAString& aTypeArg,
|
||||
PRBool aCanBubbleArg,
|
||||
PRBool aCancelableArg,
|
||||
const nsAString& aMessageArg,
|
||||
const nsAString& aFilenameArg,
|
||||
PRUint32 aLinenoArg);
|
||||
|
||||
NS_IMETHOD GetDefaultPrevented(PRBool* aRetVal);
|
||||
|
||||
virtual PRBool PreventDefaultCalled();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMEvent> mEvent;
|
||||
nsCOMPtr<nsIDOMProgressEvent> mProgressEvent;
|
||||
nsCOMPtr<nsIWorkerMessageEvent> mMessageEvent;
|
||||
nsCOMPtr<nsIWorkerErrorEvent> mErrorEvent;
|
||||
PRBool mPreventDefaultCalled;
|
||||
};
|
||||
|
||||
class nsDOMWorkerEvent : public nsIDOMEvent,
|
||||
public nsIClassInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENT
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
nsDOMWorkerEvent()
|
||||
: mEventPhase(nsIDOMEvent::AT_TARGET), mTimeStamp(0), mBubbles(PR_FALSE),
|
||||
mCancelable(PR_FALSE), mPreventDefaultCalled(PR_FALSE) { }
|
||||
|
||||
void SetTarget(nsIDOMEventTarget* aTarget) {
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
PRBool PreventDefaultCalled() {
|
||||
return PRBool(mPreventDefaultCalled);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerEvent() { }
|
||||
|
||||
nsString mType;
|
||||
nsCOMPtr<nsIDOMEventTarget> mTarget;
|
||||
PRUint16 mEventPhase;
|
||||
DOMTimeStamp mTimeStamp;
|
||||
PRPackedBool mBubbles;
|
||||
PRPackedBool mCancelable;
|
||||
PRPackedBool mPreventDefaultCalled;
|
||||
};
|
||||
|
||||
class nsDOMWorkerMessageEvent : public nsDOMWorkerEvent,
|
||||
public nsIWorkerMessageEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
|
||||
NS_DECL_NSIWORKERMESSAGEEVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerMessageEvent() : mData(nsnull) { }
|
||||
~nsDOMWorkerMessageEvent();
|
||||
|
||||
nsresult SetJSData(JSContext* aCx,
|
||||
JSAutoStructuredCloneBuffer& aBuffer,
|
||||
nsTArray<nsCOMPtr<nsISupports> >& aWrappedNatives);
|
||||
|
||||
protected:
|
||||
nsString mOrigin;
|
||||
nsCOMPtr<nsISupports> mSource;
|
||||
|
||||
nsAutoJSValHolder mDataVal;
|
||||
uint64* mData;
|
||||
size_t mDataLen;
|
||||
nsTArray<nsCOMPtr<nsISupports> > mWrappedNatives;
|
||||
};
|
||||
|
||||
class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,
|
||||
public nsIDOMProgressEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
|
||||
NS_DECL_NSIDOMPROGRESSEVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerProgressEvent()
|
||||
: mLoaded(0), mTotal(0), mLengthComputable(PR_FALSE) { }
|
||||
|
||||
protected:
|
||||
PRUint64 mLoaded;
|
||||
PRUint64 mTotal;
|
||||
PRBool mLengthComputable;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHRState
|
||||
{
|
||||
public:
|
||||
nsDOMWorkerXHRState()
|
||||
: responseTextResult(NS_OK), statusTextResult(NS_OK), status(NS_OK),
|
||||
statusResult(NS_OK), readyState(0), readyStateResult(NS_OK) { }
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
nsString responseText;
|
||||
nsresult responseTextResult;
|
||||
|
||||
nsCString statusText;
|
||||
nsresult statusTextResult;
|
||||
|
||||
nsresult status;
|
||||
nsresult statusResult;
|
||||
|
||||
PRUint16 readyState;
|
||||
nsresult readyStateResult;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHRState() { }
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHREvent : public nsDOMWorkerProgressEvent,
|
||||
public nsIRunnable
|
||||
{
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
enum SnapshotChoice {
|
||||
SNAPSHOT,
|
||||
NO_SNAPSHOT
|
||||
};
|
||||
|
||||
nsDOMWorkerXHREvent(nsDOMWorkerXHRProxy* aXHRProxy);
|
||||
|
||||
nsresult Init(PRUint32 aXHREventType,
|
||||
const nsAString& aType,
|
||||
nsIDOMEvent* aEvent,
|
||||
SnapshotChoice = SNAPSHOT);
|
||||
|
||||
static void SnapshotXHRState(nsIXMLHttpRequest* aXHR,
|
||||
nsDOMWorkerXHRState* aState);
|
||||
|
||||
already_AddRefed<nsDOMWorkerXHRState> ForgetState() {
|
||||
return mState.forget();
|
||||
}
|
||||
|
||||
protected:
|
||||
nsDOMWorkerXHRState* GetState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHRProxy;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mXHRWN;
|
||||
nsRefPtr<nsDOMWorkerXHRState> mState;
|
||||
PRUint32 mXHREventType;
|
||||
PRInt32 mChannelID;
|
||||
PRPackedBool mUploadEvent;
|
||||
PRPackedBool mProgressEvent;
|
||||
};
|
||||
|
||||
class nsDOMWorkerErrorEvent : public nsDOMWorkerEvent,
|
||||
public nsIWorkerErrorEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
|
||||
NS_DECL_NSIWORKERERROREVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerErrorEvent()
|
||||
: mLineno(0) { }
|
||||
|
||||
protected:
|
||||
nsString mMessage;
|
||||
nsString mFilename;
|
||||
PRUint32 mLineno;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKEREVENTS_H__ */
|
|
@ -1,223 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerLocation.h"
|
||||
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsITextToSubURI.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#include "nsDOMWorkerMacros.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#define XPC_MAP_CLASSNAME nsDOMWorkerLocation
|
||||
#define XPC_MAP_QUOTED_CLASSNAME "WorkerLocation"
|
||||
|
||||
#define XPC_MAP_FLAGS \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY | \
|
||||
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
|
||||
|
||||
#include "xpc_map_end.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsDOMWorkerLocation, nsIWorkerLocation,
|
||||
nsIClassInfo,
|
||||
nsIXPCScriptable)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerLocation, nsIWorkerLocation)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerLocation)
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerLocation)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetHelperForLanguage(PRUint32 aLanguage,
|
||||
nsISupports** _retval)
|
||||
{
|
||||
if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
NS_ADDREF(*_retval = NS_ISUPPORTS_CAST(nsIWorkerLocation*, this));
|
||||
}
|
||||
else {
|
||||
*_retval = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIWorkerLocation>
|
||||
nsDOMWorkerLocation::NewLocation(nsIURL* aURL)
|
||||
{
|
||||
NS_ASSERTION(aURL, "Don't hand me a null pointer!");
|
||||
|
||||
nsAutoPtr<nsDOMWorkerLocation> location(new nsDOMWorkerLocation());
|
||||
NS_ENSURE_TRUE(location, nsnull);
|
||||
|
||||
nsresult rv = aURL->GetSpec(location->mHref);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
rv = aURL->GetHost(location->mHostname);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
rv = aURL->GetPath(location->mPathname);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
nsCString temp;
|
||||
|
||||
rv = aURL->GetQuery(temp);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
if (!temp.IsEmpty()) {
|
||||
location->mSearch.AssignLiteral("?");
|
||||
location->mSearch.Append(temp);
|
||||
}
|
||||
|
||||
rv = aURL->GetRef(temp);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
if (!temp.IsEmpty()) {
|
||||
nsAutoString unicodeRef;
|
||||
|
||||
nsCOMPtr<nsITextToSubURI> converter =
|
||||
do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCString charset;
|
||||
rv = aURL->GetOriginCharset(charset);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = converter->UnEscapeURIForUI(charset, temp, unicodeRef);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
location->mHash.AssignLiteral("#");
|
||||
location->mHash.Append(NS_ConvertUTF16toUTF8(unicodeRef));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
location->mHash.AssignLiteral("#");
|
||||
location->mHash.Append(temp);
|
||||
}
|
||||
}
|
||||
|
||||
rv = aURL->GetScheme(location->mProtocol);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
location->mProtocol.AppendLiteral(":");
|
||||
|
||||
PRInt32 port;
|
||||
rv = aURL->GetPort(&port);
|
||||
if (NS_SUCCEEDED(rv) && port != -1) {
|
||||
location->mPort.AppendInt(port);
|
||||
|
||||
nsCAutoString host(location->mHostname);
|
||||
host.AppendLiteral(":");
|
||||
host.Append(location->mPort);
|
||||
|
||||
location->mHost.Assign(host);
|
||||
}
|
||||
else {
|
||||
location->mHost.Assign(location->mHostname);
|
||||
}
|
||||
|
||||
NS_ADDREF(location);
|
||||
return location.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetHref(nsACString& aHref)
|
||||
{
|
||||
aHref.Assign(mHref);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetProtocol(nsACString& aProtocol)
|
||||
{
|
||||
aProtocol.Assign(mProtocol);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetHost(nsACString& aHost)
|
||||
{
|
||||
aHost.Assign(mHost);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetHostname(nsACString& aHostname)
|
||||
{
|
||||
aHostname.Assign(mHostname);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetPort(nsACString& aPort)
|
||||
{
|
||||
aPort.Assign(mPort);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetPathname(nsACString& aPathname)
|
||||
{
|
||||
aPathname.Assign(mPathname);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetSearch(nsACString& aSearch)
|
||||
{
|
||||
aSearch.Assign(mSearch);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::GetHash(nsACString& aHash)
|
||||
{
|
||||
aHash.Assign(mHash);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerLocation::ToString(nsACString& _retval)
|
||||
{
|
||||
return GetHref(_retval);
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERMACROS_H__
|
||||
#define __NSDOMWORKERMACROS_H__
|
||||
|
||||
// Macro to generate nsIClassInfo methods for these threadsafe DOM classes
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetInterfaces(PRUint32* _count, nsIID*** _array) \
|
||||
{ \
|
||||
return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \
|
||||
} \
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_HELPER(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetHelperForLanguage(PRUint32 _language, nsISupports** _retval) \
|
||||
{ \
|
||||
*_retval = nsnull; \
|
||||
return NS_OK; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetContractID(char** _contractID) \
|
||||
{ \
|
||||
*_contractID = nsnull; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetClassDescription(char** _classDescription) \
|
||||
{ \
|
||||
*_classDescription = nsnull; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetClassID(nsCID** _classID) \
|
||||
{ \
|
||||
*_classID = nsnull; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetImplementationLanguage(PRUint32* _language) \
|
||||
{ \
|
||||
*_language = nsIProgrammingLanguage::CPLUSPLUS; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetFlags(PRUint32* _flags) \
|
||||
{ \
|
||||
*_flags = nsIClassInfo::THREADSAFE | nsIClassInfo::DOM_OBJECT; \
|
||||
return NS_OK; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
_class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
|
||||
{ \
|
||||
return NS_ERROR_NOT_AVAILABLE; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_HELPER(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_class)
|
||||
|
||||
#define NS_FORWARD_NSICLASSINFO_NOGETINTERFACES(_to) \
|
||||
NS_IMETHOD GetHelperForLanguage(PRUint32 aLanguage, nsISupports** _retval) \
|
||||
{ return _to GetHelperForLanguage(aLanguage, _retval); } \
|
||||
NS_IMETHOD GetContractID(char** aContractID) \
|
||||
{ return _to GetContractID(aContractID); } \
|
||||
NS_IMETHOD GetClassDescription(char** aClassDescription) \
|
||||
{ return _to GetClassDescription(aClassDescription); } \
|
||||
NS_IMETHOD GetClassID(nsCID** aClassID) \
|
||||
{ return _to GetClassID(aClassID); } \
|
||||
NS_IMETHOD GetImplementationLanguage(PRUint32* aImplementationLanguage) \
|
||||
{ return _to GetImplementationLanguage(aImplementationLanguage); } \
|
||||
NS_IMETHOD GetFlags(PRUint32* aFlags) \
|
||||
{ return _to GetFlags(aFlags); } \
|
||||
NS_IMETHOD GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) \
|
||||
{ return _to GetClassIDNoAlloc(aClassIDNoAlloc); }
|
||||
|
||||
#define NS_DECL_NSICLASSINFO_GETINTERFACES \
|
||||
NS_IMETHOD GetInterfaces(PRUint32* aCount, nsIID*** aArray);
|
||||
|
||||
// Don't know why nsISupports.idl defines this out...
|
||||
#define NS_FORWARD_NSISUPPORTS(_to) \
|
||||
NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) { \
|
||||
return _to QueryInterface(uuid, result); \
|
||||
} \
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) { return _to AddRef(); } \
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) { return _to Release(); }
|
||||
|
||||
#define JSON_PRIMITIVE_PROPNAME \
|
||||
"primitive"
|
||||
|
||||
#endif /* __NSDOMWORKERMACROS_H__ */
|
|
@ -1,440 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerMessageHandler.h"
|
||||
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerEvents.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerEventListenerBase)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerEventListenerBase)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerWeakEventListener::Init(nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(aListener));
|
||||
NS_ENSURE_TRUE(wrappedJS, NS_NOINTERFACE);
|
||||
|
||||
JSObject* obj;
|
||||
nsresult rv = wrappedJS->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mObj = obj;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
nsDOMWorkerWeakEventListener::GetListener()
|
||||
{
|
||||
JSContext* cx = nsDOMThreadService::GetCurrentContext();
|
||||
NS_ENSURE_TRUE(cx, nsnull);
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
nsresult rv = xpc->WrapJS(cx, mObj, NS_GET_IID(nsIDOMEventListener),
|
||||
getter_AddRefs(listener));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
return listener.forget();
|
||||
}
|
||||
|
||||
nsDOMWorkerWrappedWeakEventListener::
|
||||
nsDOMWorkerWrappedWeakEventListener(nsDOMWorkerWeakEventListener* aInner)
|
||||
: mInner(aInner)
|
||||
{
|
||||
NS_ASSERTION(aInner, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerMessageHandler,
|
||||
nsIDOMEventTarget,
|
||||
nsIClassInfo)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerMessageHandler,
|
||||
nsIDOMEventTarget)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI(nsDOMWorkerMessageHandler)
|
||||
|
||||
const nsDOMWorkerMessageHandler::ListenerCollection*
|
||||
nsDOMWorkerMessageHandler::GetListenerCollection(const nsAString& aType) const
|
||||
{
|
||||
PRUint32 count = mCollections.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
const ListenerCollection& collection = mCollections[index];
|
||||
if (collection.type.Equals(aType)) {
|
||||
return &collection;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::GetListenersForType(const nsAString& aType,
|
||||
ListenerArray& _retval) const
|
||||
{
|
||||
_retval.Clear();
|
||||
|
||||
const ListenerCollection* collection = GetListenerCollection(aType);
|
||||
if (collection) {
|
||||
PRUint32 count = collection->listeners.Length();
|
||||
|
||||
if (!_retval.SetLength(count)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener =
|
||||
collection->listeners[index]->GetListener();
|
||||
_retval[index].swap(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
nsRefPtr<nsDOMWorkerWrappedWeakEventListener> wrappedListener;
|
||||
|
||||
ListenerCollection* collection =
|
||||
const_cast<ListenerCollection*>(GetListenerCollection(aType));
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool removed;
|
||||
#endif
|
||||
|
||||
if (collection) {
|
||||
wrappedListener.swap(collection->onXListener);
|
||||
if (wrappedListener) {
|
||||
#ifdef DEBUG
|
||||
removed =
|
||||
#endif
|
||||
collection->listeners.RemoveElement(wrappedListener);
|
||||
NS_ASSERTION(removed, "Element wasn't in the list!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!aListener) {
|
||||
if (collection && !collection->listeners.Length()) {
|
||||
#ifdef DEBUG
|
||||
removed =
|
||||
#endif
|
||||
mCollections.RemoveElement(*collection);
|
||||
NS_ASSERTION(removed, "Element wasn't in the list!");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerWeakEventListener> weakListener =
|
||||
new nsDOMWorkerWeakEventListener();
|
||||
NS_ENSURE_TRUE(weakListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = weakListener->Init(aListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
wrappedListener = new nsDOMWorkerWrappedWeakEventListener(weakListener);
|
||||
NS_ENSURE_TRUE(wrappedListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!collection) {
|
||||
collection = mCollections.AppendElement(aType);
|
||||
NS_ENSURE_TRUE(collection, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
WeakListener* newListener =
|
||||
collection->listeners.AppendElement(wrappedListener);
|
||||
NS_ENSURE_TRUE(newListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
wrappedListener.swap(collection->onXListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
nsDOMWorkerMessageHandler::GetOnXListener(const nsAString& aType) const
|
||||
{
|
||||
const ListenerCollection* collection = GetListenerCollection(aType);
|
||||
if (collection && collection->onXListener) {
|
||||
return collection->onXListener->GetListener();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::ClearListeners(const nsAString& aType)
|
||||
{
|
||||
PRUint32 count = mCollections.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
if (mCollections[index].type.Equals(aType)) {
|
||||
mCollections.RemoveElementAt(index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorkerMessageHandler::HasListeners(const nsAString& aType)
|
||||
{
|
||||
const ListenerCollection* collection = GetListenerCollection(aType);
|
||||
return collection && collection->listeners.Length();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::ClearAllListeners()
|
||||
{
|
||||
mCollections.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerMessageHandler::Trace(JSTracer* aTracer)
|
||||
{
|
||||
PRUint32 cCount = mCollections.Length();
|
||||
for (PRUint32 cIndex = 0; cIndex < cCount; cIndex++) {
|
||||
const ListenerCollection& collection = mCollections[cIndex];
|
||||
PRUint32 lCount = collection.listeners.Length();
|
||||
for (PRUint32 lIndex = 0; lIndex < lCount; lIndex++) {
|
||||
JSObject* obj = collection.listeners[lIndex]->GetJSObject();
|
||||
NS_ASSERTION(obj, "Null object!");
|
||||
JS_SET_TRACING_DETAILS(aTracer, nsnull, this, 0);
|
||||
JS_CallTracer(aTracer, obj, JSTRACE_OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageHandler::RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture)
|
||||
{
|
||||
ListenerCollection* collection =
|
||||
const_cast<ListenerCollection*>(GetListenerCollection(aType));
|
||||
|
||||
if (collection) {
|
||||
PRUint32 count = collection->listeners.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
WeakListener& weakListener = collection->listeners[index];
|
||||
if (weakListener == collection->onXListener) {
|
||||
continue;
|
||||
}
|
||||
nsCOMPtr<nsIDOMEventListener> listener = weakListener->GetListener();
|
||||
if (listener == aListener) {
|
||||
collection->listeners.RemoveElementAt(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!collection->listeners.Length()) {
|
||||
#ifdef DEBUG
|
||||
PRBool removed =
|
||||
#endif
|
||||
mCollections.RemoveElement(*collection);
|
||||
NS_ASSERTION(removed, "Somehow this wasn't in the list!");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageHandler::DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
nsCOMPtr<nsIDOMWorkerPrivateEvent> event;
|
||||
|
||||
if (_retval) {
|
||||
event = do_QueryInterface(aEvent);
|
||||
if (!event) {
|
||||
event = new nsDOMWorkerPrivateEvent(aEvent);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
aEvent = event;
|
||||
}
|
||||
|
||||
nsAutoString type;
|
||||
nsresult rv = aEvent->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoTArray<Listener, 10> listeners;
|
||||
GetListenersForType(type, listeners);
|
||||
|
||||
PRUint32 count = listeners.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
const Listener& listener = listeners[index];
|
||||
NS_ASSERTION(listener, "Null listener in array!");
|
||||
|
||||
listener->HandleEvent(aEvent);
|
||||
}
|
||||
|
||||
if (_retval) {
|
||||
*_retval = event->PreventDefaultCalled();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerMessageHandler::AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 aOptionalArgc)
|
||||
{
|
||||
// We don't support aWantsUntrusted yet.
|
||||
NS_ENSURE_TRUE(aOptionalArgc < 2, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
ListenerCollection* collection =
|
||||
const_cast<ListenerCollection*>(GetListenerCollection(aType));
|
||||
|
||||
if (!collection) {
|
||||
collection = mCollections.AppendElement(aType);
|
||||
NS_ENSURE_TRUE(collection, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerWeakEventListener> weakListener =
|
||||
new nsDOMWorkerWeakEventListener();
|
||||
NS_ENSURE_TRUE(weakListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = weakListener->Init(aListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
WeakListener* newListener = collection->listeners.AppendElement(weakListener);
|
||||
NS_ENSURE_TRUE(newListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDOMEventTarget *
|
||||
nsDOMWorkerMessageHandler::GetTargetForDOMEvent()
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIDOMEventTarget *
|
||||
nsDOMWorkerMessageHandler::GetTargetForEventTargetChain()
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::PreHandleEvent(nsEventChainPreVisitor & aVisitor)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::WillHandleEvent(nsEventChainPostVisitor & aVisitor)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::PostHandleEvent(nsEventChainPostVisitor & aVisitor)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::DispatchDOMEvent(nsEvent *aEvent, nsIDOMEvent *aDOMEvent,
|
||||
nsPresContext *aPresContext,
|
||||
nsEventStatus *aEventStatus)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsEventListenerManager*
|
||||
nsDOMWorkerMessageHandler::GetListenerManager(PRBool aMayCreate)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::AddEventListenerByIID(nsIDOMEventListener *aListener,
|
||||
const nsIID & aIID)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageHandler::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
|
||||
const nsIID & aIID)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsIScriptContext*
|
||||
nsDOMWorkerMessageHandler::GetContextForEventHandlers(nsresult *aRv)
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
*aRv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSContext*
|
||||
nsDOMWorkerMessageHandler::GetJSContextForEventHandlers()
|
||||
{
|
||||
NS_ERROR("Should not be called");
|
||||
return nsnull;
|
||||
}
|
|
@ -1,175 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERMESSAGEHANDLER_H__
|
||||
#define __NSDOMWORKERMESSAGEHANDLER_H__
|
||||
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMWorkers.h"
|
||||
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIWeakReference.h"
|
||||
|
||||
class nsDOMWorkerEventListenerBase
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
virtual already_AddRefed<nsIDOMEventListener> GetListener() = 0;
|
||||
virtual JSObject* GetJSObject() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerEventListenerBase() { }
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
class nsDOMWorkerWeakEventListener : public nsDOMWorkerEventListenerBase
|
||||
{
|
||||
public:
|
||||
nsDOMWorkerWeakEventListener()
|
||||
: mObj(NULL) { }
|
||||
|
||||
nsresult Init(nsIDOMEventListener* aListener);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener> GetListener();
|
||||
|
||||
virtual JSObject* GetJSObject() {
|
||||
return mObj;
|
||||
}
|
||||
|
||||
private:
|
||||
JSObject* mObj;
|
||||
};
|
||||
|
||||
class nsDOMWorkerWrappedWeakEventListener : public nsDOMWorkerEventListenerBase
|
||||
{
|
||||
public:
|
||||
nsDOMWorkerWrappedWeakEventListener(nsDOMWorkerWeakEventListener* aInner);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener> GetListener() {
|
||||
return mInner->GetListener();
|
||||
}
|
||||
|
||||
virtual JSObject* GetJSObject() {
|
||||
return mInner->GetJSObject();
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsDOMWorkerWeakEventListener> mInner;
|
||||
};
|
||||
|
||||
class nsDOMWorkerMessageHandler : public nsIDOMEventTarget,
|
||||
public nsIClassInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
virtual nsresult SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
GetOnXListener(const nsAString& aType) const;
|
||||
|
||||
void ClearListeners(const nsAString& aType);
|
||||
|
||||
PRBool HasListeners(const nsAString& aType);
|
||||
|
||||
void ClearAllListeners();
|
||||
|
||||
void Trace(JSTracer* aTracer);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerMessageHandler() { }
|
||||
|
||||
private:
|
||||
|
||||
typedef nsCOMPtr<nsIDOMEventListener> Listener;
|
||||
typedef nsTArray<Listener> ListenerArray;
|
||||
|
||||
typedef nsRefPtr<nsDOMWorkerEventListenerBase> WeakListener;
|
||||
typedef nsTArray<WeakListener> WeakListenerArray;
|
||||
|
||||
struct ListenerCollection {
|
||||
PRBool operator==(const ListenerCollection& aOther) const {
|
||||
return this == &aOther;
|
||||
}
|
||||
|
||||
ListenerCollection(const nsAString& aType)
|
||||
: type(aType) { }
|
||||
|
||||
nsString type;
|
||||
WeakListenerArray listeners;
|
||||
nsRefPtr<nsDOMWorkerWrappedWeakEventListener> onXListener;
|
||||
};
|
||||
|
||||
const ListenerCollection* GetListenerCollection(const nsAString& aType) const;
|
||||
|
||||
void GetListenersForType(const nsAString& aType,
|
||||
ListenerArray& _retval) const;
|
||||
|
||||
nsTArray<ListenerCollection> mCollections;
|
||||
};
|
||||
|
||||
#define NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(_to) \
|
||||
virtual nsIDOMEventTarget * GetTargetForDOMEvent(void) { return _to GetTargetForDOMEvent(); } \
|
||||
virtual nsIDOMEventTarget * GetTargetForEventTargetChain(void) { return _to GetTargetForEventTargetChain(); } \
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor & aVisitor) { return _to PreHandleEvent(aVisitor); } \
|
||||
virtual nsresult WillHandleEvent(nsEventChainPostVisitor & aVisitor) { return _to WillHandleEvent(aVisitor); } \
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor & aVisitor) { return _to PostHandleEvent(aVisitor); } \
|
||||
virtual nsresult DispatchDOMEvent(nsEvent *aEvent, nsIDOMEvent *aDOMEvent, nsPresContext *aPresContext, nsEventStatus *aEventStatus) { return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); } \
|
||||
virtual nsEventListenerManager * GetListenerManager(PRBool aMayCreate) { return _to GetListenerManager(aMayCreate); } \
|
||||
virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID & aIID) { return _to AddEventListenerByIID(aListener, aIID); } \
|
||||
virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID & aIID) { return _to RemoveEventListenerByIID(aListener, aIID); } \
|
||||
virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv NS_OUTPARAM) { return _to GetContextForEventHandlers(aRv); } \
|
||||
virtual JSContext * GetJSContextForEventHandlers(void) { return _to GetJSContextForEventHandlers(); }
|
||||
|
||||
|
||||
#endif /* __NSDOMWORKERMESSAGEHANDLER_H__ */
|
|
@ -1,108 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerNavigator.h"
|
||||
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerMacros.h"
|
||||
|
||||
#define XPC_MAP_CLASSNAME nsDOMWorkerNavigator
|
||||
#define XPC_MAP_QUOTED_CLASSNAME "Navigator"
|
||||
|
||||
#define XPC_MAP_FLAGS \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY | \
|
||||
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
|
||||
|
||||
#include "xpc_map_end.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsDOMWorkerNavigator, nsIWorkerNavigator,
|
||||
nsIClassInfo,
|
||||
nsIXPCScriptable)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerNavigator, nsIWorkerNavigator)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerNavigator)
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerNavigator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerNavigator::GetHelperForLanguage(PRUint32 aLanguage,
|
||||
nsISupports** _retval)
|
||||
{
|
||||
if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
NS_ADDREF(*_retval = NS_ISUPPORTS_CAST(nsIWorkerNavigator*, this));
|
||||
}
|
||||
else {
|
||||
*_retval = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerNavigator::GetAppName(nsAString& aAppName)
|
||||
{
|
||||
nsDOMThreadService::get()->GetAppName(aAppName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerNavigator::GetAppVersion(nsAString& aAppVersion)
|
||||
{
|
||||
nsDOMThreadService::get()->GetAppVersion(aAppVersion);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerNavigator::GetPlatform(nsAString& aPlatform)
|
||||
{
|
||||
nsDOMThreadService::get()->GetPlatform(aPlatform);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerNavigator::GetUserAgent(nsAString& aUserAgent)
|
||||
{
|
||||
nsDOMThreadService::get()->GetUserAgent(aUserAgent);
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerPool.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
nsDOMWorkerPool::nsDOMWorkerPool(nsIScriptGlobalObject* aGlobalObject,
|
||||
nsIDocument* aDocument)
|
||||
: mParentGlobal(aGlobalObject),
|
||||
mParentDocument(aDocument),
|
||||
mReentrantMonitor("nsDOMWorkerPool.mReentrantMonitor"),
|
||||
mCanceled(PR_FALSE),
|
||||
mSuspended(PR_FALSE),
|
||||
mWindowID(aDocument ? aDocument->OuterWindowID() : 0)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMWorkerPool::~nsDOMWorkerPool()
|
||||
{
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
|
||||
nsIScriptGlobalObject* global;
|
||||
mParentGlobal.forget(&global);
|
||||
if (global) {
|
||||
NS_ProxyRelease(mainThread, global, PR_FALSE);
|
||||
}
|
||||
|
||||
nsIDocument* document;
|
||||
mParentDocument.forget(&document);
|
||||
if (document) {
|
||||
NS_ProxyRelease(mainThread, document, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerPool)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerPool)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerPool::Init()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerPool::NoteWorker(nsDOMWorker* aWorker)
|
||||
{
|
||||
NS_ASSERTION(aWorker, "Null pointer!");
|
||||
|
||||
PRBool suspendWorker;
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsDOMWorker** newWorker = mWorkers.AppendElement(aWorker);
|
||||
NS_ENSURE_TRUE(newWorker, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
suspendWorker = mSuspended;
|
||||
}
|
||||
|
||||
if (suspendWorker) {
|
||||
aWorker->Suspend();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::NoteDyingWorker(nsDOMWorker* aWorker)
|
||||
{
|
||||
NS_ASSERTION(aWorker, "Null pointer!");
|
||||
|
||||
PRBool removeFromThreadService = PR_FALSE;
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
NS_ASSERTION(mWorkers.Contains(aWorker), "Worker from a different pool?!");
|
||||
mWorkers.RemoveElement(aWorker);
|
||||
|
||||
if (!mCanceled && !mWorkers.Length()) {
|
||||
removeFromThreadService = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeFromThreadService) {
|
||||
nsRefPtr<nsDOMWorkerPool> kungFuDeathGrip(this);
|
||||
nsDOMThreadService::get()->NoteEmptyPool(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::GetWorkers(nsTArray<nsDOMWorker*>& aArray)
|
||||
{
|
||||
mReentrantMonitor.AssertCurrentThreadIn();
|
||||
NS_ASSERTION(!aArray.Length(), "Should be empty!");
|
||||
|
||||
#ifdef DEBUG
|
||||
nsDOMWorker** newWorkers =
|
||||
#endif
|
||||
aArray.AppendElements(mWorkers);
|
||||
NS_WARN_IF_FALSE(newWorkers, "Out of memory!");
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!mCanceled, "Canceled more than once!");
|
||||
|
||||
nsAutoTArray<nsDOMWorker*, 10> workers;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
mCanceled = PR_TRUE;
|
||||
|
||||
GetWorkers(workers);
|
||||
}
|
||||
|
||||
PRUint32 count = workers.Length();
|
||||
if (count) {
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
workers[index]->Cancel();
|
||||
}
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mon.NotifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::Suspend()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoTArray<nsDOMWorker*, 10> workers;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
NS_ASSERTION(!mSuspended, "Suspended more than once!");
|
||||
mSuspended = PR_TRUE;
|
||||
|
||||
GetWorkers(workers);
|
||||
}
|
||||
|
||||
PRUint32 count = workers.Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
workers[index]->Suspend();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerPool::Resume()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoTArray<nsDOMWorker*, 10> workers;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
NS_ASSERTION(mSuspended, "Not suspended!");
|
||||
mSuspended = PR_FALSE;
|
||||
|
||||
GetWorkers(workers);
|
||||
}
|
||||
|
||||
PRUint32 count = workers.Length();
|
||||
if (count) {
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
workers[index]->Resume();
|
||||
}
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mon.NotifyAll();
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERPOOL_H__
|
||||
#define __NSDOMWORKERPOOL_H__
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsDOMWorker;
|
||||
class nsIDocument;
|
||||
class nsIScriptContext;
|
||||
class nsIScriptError;
|
||||
class nsIScriptGlobalObject;
|
||||
|
||||
class nsDOMWorkerPool
|
||||
{
|
||||
typedef mozilla::ReentrantMonitor ReentrantMonitor;
|
||||
|
||||
public:
|
||||
nsDOMWorkerPool(nsIScriptGlobalObject* aGlobalObject,
|
||||
nsIDocument* aDocument);
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||
NS_IMETHOD_(nsrefcnt) Release();
|
||||
|
||||
nsIScriptGlobalObject* ScriptGlobalObject() {
|
||||
return mParentGlobal;
|
||||
}
|
||||
|
||||
nsIDocument* ParentDocument() {
|
||||
return mParentDocument;
|
||||
}
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void Cancel();
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
||||
nsresult NoteWorker(nsDOMWorker* aWorker);
|
||||
void NoteDyingWorker(nsDOMWorker* aWorker);
|
||||
|
||||
ReentrantMonitor& GetReentrantMonitor() {
|
||||
return mReentrantMonitor;
|
||||
}
|
||||
|
||||
const PRUint64 WindowID() const {
|
||||
return mWindowID;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~nsDOMWorkerPool();
|
||||
|
||||
void GetWorkers(nsTArray<nsDOMWorker*>& aArray);
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
// Reference to the window that created and owns this pool.
|
||||
nsCOMPtr<nsIScriptGlobalObject> mParentGlobal;
|
||||
|
||||
// Reference to the document that created this pool.
|
||||
nsCOMPtr<nsIDocument> mParentDocument;
|
||||
|
||||
// Weak array of workers. The idea is that workers can be garbage collected
|
||||
// independently of the owning pool and other workers.
|
||||
nsTArray<nsDOMWorker*> mWorkers;
|
||||
|
||||
// ReentrantMonitor for suspending and resuming workers.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
PRPackedBool mCanceled;
|
||||
PRPackedBool mSuspended;
|
||||
|
||||
const PRUint64 mWindowID;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERPOOL_H__ */
|
|
@ -1,881 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerScriptLoader.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIStreamLoader.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsNetError.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "pratom.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsIChannelPolicy.h"
|
||||
#include "nsChannelPolicy.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorkerPool.h"
|
||||
#include "nsDOMWorkerSecurityManager.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerTimeout.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
nsDOMWorkerScriptLoader::nsDOMWorkerScriptLoader(nsDOMWorker* aWorker)
|
||||
: nsDOMWorkerFeature(aWorker),
|
||||
mTarget(nsnull),
|
||||
mScriptCount(0),
|
||||
mCanceled(PR_FALSE),
|
||||
mForWorker(PR_FALSE)
|
||||
{
|
||||
// Created on worker thread.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorker, "Null worker!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerScriptLoader, nsDOMWorkerFeature,
|
||||
nsIRunnable,
|
||||
nsIStreamLoaderObserver)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
|
||||
const nsTArray<nsString>& aURLs,
|
||||
PRBool aExecute)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
|
||||
mTarget = NS_GetCurrentThread();
|
||||
NS_ASSERTION(mTarget, "This should never be null!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mScriptCount = aURLs.Length();
|
||||
if (!mScriptCount) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Do all the memory work for these arrays now rather than checking for
|
||||
// failures all along the way.
|
||||
PRBool success = mLoadInfos.SetCapacity(mScriptCount);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Need one runnable per script and then an extra for the finished
|
||||
// notification.
|
||||
success = mPendingRunnables.SetCapacity(mScriptCount + 1);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo* newInfo = mLoadInfos.AppendElement();
|
||||
NS_ASSERTION(newInfo, "Shouldn't fail if SetCapacity succeeded above!");
|
||||
|
||||
newInfo->url.Assign(aURLs[index]);
|
||||
if (newInfo->url.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
success = newInfo->scriptObj.Hold(aCx);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Don't want timeouts, etc., from queuing up while we're waiting on the
|
||||
// network or compiling.
|
||||
AutoSuspendWorkerEvents aswe(this);
|
||||
|
||||
nsresult rv = DoRunLoop(aCx);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Verify that all scripts downloaded and compiled.
|
||||
rv = VerifyScripts(aCx);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aExecute) {
|
||||
rv = ExecuteScripts(aCx);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::LoadWorkerScript(JSContext* aCx,
|
||||
const nsString& aURL)
|
||||
{
|
||||
mForWorker = PR_TRUE;
|
||||
|
||||
nsAutoTArray<nsString, 1> url;
|
||||
url.AppendElement(aURL);
|
||||
|
||||
return LoadScripts(aCx, url, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::DoRunLoop(JSContext* aCx)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
volatile PRBool done = PR_FALSE;
|
||||
mDoneRunnable = new ScriptLoaderDone(this, &done);
|
||||
NS_ENSURE_TRUE(mDoneRunnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
while (!(done || mCanceled)) {
|
||||
JSAutoSuspendRequest asr(aCx);
|
||||
NS_ProcessNextEvent(mTarget);
|
||||
}
|
||||
|
||||
return mCanceled ? NS_ERROR_ABORT : NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::VerifyScripts(JSContext* aCx)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Shouldn't be null!");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
NS_ASSERTION(loadInfo.done, "Inconsistent state!");
|
||||
|
||||
if (NS_SUCCEEDED(loadInfo.result) && loadInfo.scriptObj.ToJSObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!loadInfo.scriptObj.ToJSObject(), "Inconsistent state!");
|
||||
|
||||
// Flag failure before worrying about whether or not to report an error.
|
||||
rv = NS_FAILED(loadInfo.result) ? loadInfo.result : NS_ERROR_FAILURE;
|
||||
|
||||
// If loadInfo.result is a success code then the compiler probably reported
|
||||
// an error already. Also we don't really care about NS_BINDING_ABORTED
|
||||
// since that's the code we set when some other script had a problem and the
|
||||
// rest were canceled.
|
||||
if (NS_SUCCEEDED(loadInfo.result) || loadInfo.result == NS_BINDING_ABORTED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, this is the script that caused us to fail.
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
// Only throw an error if there is no other pending exception.
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
const char* message;
|
||||
switch (loadInfo.result) {
|
||||
case NS_ERROR_MALFORMED_URI:
|
||||
message = "Malformed script URI: %s";
|
||||
break;
|
||||
case NS_ERROR_FILE_NOT_FOUND:
|
||||
case NS_ERROR_NOT_AVAILABLE:
|
||||
message = "Script file not found: %s";
|
||||
break;
|
||||
default:
|
||||
message = "Failed to load script: %s (nsresult = 0x%x)";
|
||||
break;
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 url(loadInfo.url);
|
||||
JS_ReportError(aCx, message, url.get(), loadInfo.result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::ExecuteScripts(JSContext* aCx)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Shouldn't be null!");
|
||||
|
||||
// Now execute all the scripts.
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
JSObject* scriptObj = loadInfo.scriptObj.ToJSObject();
|
||||
NS_ASSERTION(scriptObj, "This shouldn't ever be null!");
|
||||
|
||||
JSObject* global = mWorker->mGlobal ?
|
||||
mWorker->mGlobal :
|
||||
JS_GetGlobalObject(aCx);
|
||||
NS_ENSURE_STATE(global);
|
||||
|
||||
// Because we may have nested calls to this function we don't want the
|
||||
// execution to automatically report errors. We let them propagate instead.
|
||||
uint32 oldOpts =
|
||||
JS_SetOptions(aCx, JS_GetOptions(aCx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
|
||||
PRBool success = JS_ExecuteScript(aCx, global, scriptObj, NULL);
|
||||
|
||||
JS_SetOptions(aCx, oldOpts);
|
||||
|
||||
if (!success) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ASSERTION(!mCanceled, "Cancel called more than once!");
|
||||
mCanceled = PR_TRUE;
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
nsIRequest* request =
|
||||
static_cast<nsIRequest*>(loadInfo.channel.get());
|
||||
if (request) {
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
request->Cancel(NS_BINDING_ABORTED);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to cancel channel!");
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoTArray<ScriptLoaderRunnable*, 10> runnables;
|
||||
{
|
||||
MutexAutoLock lock(mWorker->GetLock());
|
||||
runnables.AppendElements(mPendingRunnables);
|
||||
mPendingRunnables.Clear();
|
||||
}
|
||||
|
||||
PRUint32 runnableCount = runnables.Length();
|
||||
for (PRUint32 index = 0; index < runnableCount; index++) {
|
||||
runnables[index]->Revoke();
|
||||
}
|
||||
|
||||
// We're about to post a revoked event to the worker thread, which seems
|
||||
// silly, but we have to do this because the worker thread may be sleeping
|
||||
// waiting on its event queue.
|
||||
NotifyDone();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// We may have been canceled already.
|
||||
if (mCanceled) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsresult rv = RunInternal();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Ok, something failed beyond a normal cancel.
|
||||
|
||||
// If necko is holding a ref to us then we'll end up notifying in the
|
||||
// OnStreamComplete method, not here.
|
||||
PRBool needsNotify = PR_TRUE;
|
||||
|
||||
// Cancel any async channels that were already opened.
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
nsIRequest* request = static_cast<nsIRequest*>(loadInfo.channel.get());
|
||||
if (request) {
|
||||
#ifdef DEBUG
|
||||
nsresult rvInner =
|
||||
#endif
|
||||
request->Cancel(NS_BINDING_ABORTED);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rvInner), "Failed to cancel channel!");
|
||||
|
||||
// Necko is holding a ref to us so make sure that the OnStreamComplete
|
||||
// code sends the done event.
|
||||
needsNotify = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
// Make sure to set this so that the OnStreamComplete code will dispatch
|
||||
// the done event.
|
||||
loadInfo.done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsNotify) {
|
||||
NotifyDone();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
PRUint32 aStringLen,
|
||||
const PRUint8* aString)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// We may have been canceled already.
|
||||
if (mCanceled) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsresult rv = OnStreamCompleteInternal(aLoader, aContext, aStatus, aStringLen,
|
||||
aString);
|
||||
|
||||
// Dispatch the done event if we've received all the data.
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
if (!mLoadInfos[index].done) {
|
||||
// Some async load is still outstanding, don't notify yet.
|
||||
break;
|
||||
}
|
||||
|
||||
if (index == mScriptCount - 1) {
|
||||
// All loads complete, signal the thread.
|
||||
NotifyDone();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::RunInternal()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mForWorker) {
|
||||
NS_ASSERTION(mScriptCount == 1, "Bad state!");
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorker> parentWorker = mWorker->GetParent();
|
||||
|
||||
// Figure out which principal to use.
|
||||
nsIPrincipal* principal = mWorker->GetPrincipal();
|
||||
if (!principal) {
|
||||
if (!parentWorker) {
|
||||
NS_ERROR("Must have a principal if this is not a subworker!");
|
||||
}
|
||||
principal = parentWorker->GetPrincipal();
|
||||
}
|
||||
NS_ASSERTION(principal, "This should never be null here!");
|
||||
|
||||
// Figure out our base URI.
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
if (mForWorker) {
|
||||
if (parentWorker) {
|
||||
baseURI = parentWorker->GetBaseURI();
|
||||
NS_ASSERTION(baseURI, "Should have been set already!");
|
||||
}
|
||||
else {
|
||||
// May be null.
|
||||
baseURI = mWorker->GetBaseURI();
|
||||
|
||||
// Don't leave a temporary URI hanging around.
|
||||
mWorker->ClearBaseURI();
|
||||
}
|
||||
NS_ASSERTION(!mWorker->GetBaseURI(), "Should not be set here!");
|
||||
}
|
||||
else {
|
||||
baseURI = mWorker->GetBaseURI();
|
||||
NS_ASSERTION(baseURI, "Should have been set already!");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> parentDoc = mWorker->Pool()->ParentDocument();
|
||||
|
||||
// All of these can potentially be null, but that should be ok. We'll either
|
||||
// succeed without them or fail below.
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
if (parentDoc) {
|
||||
loadGroup = parentDoc->GetDocumentLoadGroup();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIIOService> ios(do_GetIOService());
|
||||
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ASSERTION(secMan, "This should never be null!");
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
nsresult& rv = loadInfo.result;
|
||||
|
||||
nsCOMPtr<nsIURI>& uri = loadInfo.finalURI;
|
||||
rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
||||
loadInfo.url, parentDoc,
|
||||
baseURI);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If we're part of a document then check the content load policy.
|
||||
if (parentDoc) {
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, uri,
|
||||
principal, parentDoc,
|
||||
NS_LITERAL_CSTRING("text/javascript"),
|
||||
nsnull, &shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
secMan);
|
||||
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
||||
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
|
||||
return (rv = NS_ERROR_CONTENT_BLOCKED);
|
||||
}
|
||||
return (rv = NS_ERROR_CONTENT_BLOCKED_SHOW_ALT);
|
||||
}
|
||||
}
|
||||
|
||||
// If this script loader is being used to make a new worker then we need to
|
||||
// do a same-origin check. Otherwise we need to clear the load with the
|
||||
// security manager.
|
||||
rv = mForWorker ?
|
||||
principal->CheckMayLoad(uri, PR_FALSE):
|
||||
secMan->CheckLoadURIWithPrincipal(principal, uri, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We need to know which index we're on in OnStreamComplete so we know where
|
||||
// to put the result.
|
||||
nsCOMPtr<nsISupportsPRUint32> indexSupports =
|
||||
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = indexSupports->SetData(index);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We don't care about progress so just use the simple stream loader for
|
||||
// OnStreamComplete notification only.
|
||||
nsCOMPtr<nsIStreamLoader> loader;
|
||||
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get Content Security Policy from parent document to pass into channel
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = principal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannelPolicy> channelPolicy;
|
||||
if (csp) {
|
||||
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channelPolicy->SetContentSecurityPolicy(csp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(loadInfo.channel),
|
||||
uri, ios, loadGroup, nsnull,
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
|
||||
channelPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = loadInfo.channel->AsyncOpen(loader, indexSupports);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Null this out so we don't try to cancel it later.
|
||||
loadInfo.channel = nsnull;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
PRUint32 aStringLen,
|
||||
const PRUint8* aString)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint32> indexSupports(do_QueryInterface(aContext));
|
||||
NS_ENSURE_TRUE(indexSupports, NS_ERROR_NO_INTERFACE);
|
||||
|
||||
PRUint32 index = PR_UINT32_MAX;
|
||||
indexSupports->GetData(&index);
|
||||
|
||||
if (index >= mScriptCount) {
|
||||
NS_NOTREACHED("This really can't fail or we'll hang!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
|
||||
NS_ASSERTION(!loadInfo.done, "Got complete on the same load twice!");
|
||||
loadInfo.done = PR_TRUE;
|
||||
|
||||
// Use an alias to keep rv and loadInfo.result in sync.
|
||||
nsresult& rv = loadInfo.result;
|
||||
|
||||
if (NS_FAILED(aStatus)) {
|
||||
return rv = aStatus;
|
||||
}
|
||||
|
||||
if (!(aStringLen && aString)) {
|
||||
return rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Make sure we're not seeing the result of a 404 or something by checking the
|
||||
// 'requestSucceeded' attribute on the http channel.
|
||||
nsCOMPtr<nsIRequest> request;
|
||||
rv = aLoader->GetRequest(getter_AddRefs(request));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
||||
if (httpChannel) {
|
||||
PRBool requestSucceeded;
|
||||
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!requestSucceeded) {
|
||||
return rv = NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// May be null.
|
||||
nsIDocument* parentDoc = mWorker->Pool()->ParentDocument();
|
||||
|
||||
// Use the regular nsScriptLoader for this grunt work! Should be just fine
|
||||
// because we're running on the main thread.
|
||||
rv = nsScriptLoader::ConvertToUTF16(loadInfo.channel, aString, aStringLen,
|
||||
EmptyString(), parentDoc,
|
||||
loadInfo.scriptText);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (loadInfo.scriptText.IsEmpty()) {
|
||||
return rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCString filename;
|
||||
rv = loadInfo.finalURI->GetSpec(filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (filename.IsEmpty()) {
|
||||
filename.Assign(NS_LossyConvertUTF16toASCII(loadInfo.url));
|
||||
}
|
||||
else {
|
||||
// This will help callers figure out what their script url resolved to in
|
||||
// case of errors.
|
||||
loadInfo.url.Assign(NS_ConvertUTF8toUTF16(filename));
|
||||
}
|
||||
|
||||
// Update the principal of the worker and its base URI if we just loaded the
|
||||
// worker's primary script.
|
||||
if (mForWorker) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
NS_ASSERTION(channel, "This should never fail!");
|
||||
|
||||
// Take care of the base URI first.
|
||||
nsCOMPtr<nsIURI> finalURI;
|
||||
rv = NS_GetFinalChannelURI(channel, getter_AddRefs(finalURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mWorker->SetBaseURI(finalURI);
|
||||
|
||||
// Now to figure out which principal to give this worker.
|
||||
nsRefPtr<nsDOMWorker> parent = mWorker->GetParent();
|
||||
NS_ASSERTION(mWorker->GetPrincipal() || parent, "Must have one of these!");
|
||||
|
||||
nsCOMPtr<nsIPrincipal> loadPrincipal = mWorker->GetPrincipal() ?
|
||||
mWorker->GetPrincipal() :
|
||||
parent->GetPrincipal();
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
NS_ASSERTION(ssm, "Should never be null!");
|
||||
|
||||
nsCOMPtr<nsIPrincipal> channelPrincipal;
|
||||
rv = ssm->GetChannelPrincipal(channel, getter_AddRefs(channelPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// See if this is a resource URI. Since JSMs usually come from resource://
|
||||
// URIs we're currently considering all URIs with the URI_IS_UI_RESOURCE
|
||||
// flag as valid for creating privileged workers.
|
||||
if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
|
||||
PRBool isResource;
|
||||
rv = NS_URIChainHasFlags(finalURI,
|
||||
nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
||||
&isResource);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isResource) {
|
||||
rv = ssm->GetSystemPrincipal(getter_AddRefs(channelPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
// If the load principal is the system principal then the channel principal
|
||||
// must also be the system principal (we do not allow chrome code to create
|
||||
// workers with non-chrome scripts). Otherwise this channel principal must
|
||||
// be same origin with the load principal (we check again here in case
|
||||
// redirects changed the location of the script).
|
||||
if (nsContentUtils::IsSystemPrincipal(loadPrincipal)) {
|
||||
if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
|
||||
return rv = NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
else if (NS_FAILED(loadPrincipal->CheckMayLoad(finalURI, PR_FALSE))) {
|
||||
return rv = NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
mWorker->SetPrincipal(channelPrincipal);
|
||||
}
|
||||
|
||||
nsRefPtr<ScriptCompiler> compiler =
|
||||
new ScriptCompiler(this, loadInfo.scriptText, filename, loadInfo.scriptObj);
|
||||
NS_ASSERTION(compiler, "Out of memory!");
|
||||
if (!compiler) {
|
||||
return rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
rv = mTarget->Dispatch(compiler, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::NotifyDone()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mDoneRunnable) {
|
||||
// We've already completed, no need to cancel anything.
|
||||
return;
|
||||
}
|
||||
|
||||
for (PRUint32 index = 0; index < mScriptCount; index++) {
|
||||
ScriptLoadInfo& loadInfo = mLoadInfos[index];
|
||||
// Null both of these out because they aren't threadsafe and must be
|
||||
// destroyed on this thread.
|
||||
loadInfo.channel = nsnull;
|
||||
loadInfo.finalURI = nsnull;
|
||||
|
||||
if (mCanceled) {
|
||||
// Simulate a complete, yet failed, load.
|
||||
loadInfo.done = PR_TRUE;
|
||||
loadInfo.result = NS_BINDING_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
mTarget->Dispatch(mDoneRunnable, NS_DISPATCH_NORMAL);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Couldn't dispatch done event!");
|
||||
|
||||
mDoneRunnable = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::SuspendWorkerEvents()
|
||||
{
|
||||
NS_ASSERTION(mWorker, "No worker yet!");
|
||||
mWorker->SuspendFeatures();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::ResumeWorkerEvents()
|
||||
{
|
||||
NS_ASSERTION(mWorker, "No worker yet!");
|
||||
mWorker->ResumeFeatures();
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptLoaderRunnable::ScriptLoaderRunnable(nsDOMWorkerScriptLoader* aLoader)
|
||||
: mRevoked(PR_FALSE),
|
||||
mLoader(aLoader)
|
||||
{
|
||||
MutexAutoLock lock(aLoader->GetLock());
|
||||
#ifdef DEBUG
|
||||
nsDOMWorkerScriptLoader::ScriptLoaderRunnable** added =
|
||||
#endif
|
||||
aLoader->mPendingRunnables.AppendElement(this);
|
||||
NS_ASSERTION(added, "This shouldn't fail because we SetCapacity earlier!");
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptLoaderRunnable::~ScriptLoaderRunnable()
|
||||
{
|
||||
if (!mRevoked) {
|
||||
MutexAutoLock lock(mLoader->GetLock());
|
||||
#ifdef DEBUG
|
||||
PRBool removed =
|
||||
#endif
|
||||
mLoader->mPendingRunnables.RemoveElement(this);
|
||||
NS_ASSERTION(removed, "Someone has changed the array!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerScriptLoader::ScriptLoaderRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
void
|
||||
nsDOMWorkerScriptLoader::ScriptLoaderRunnable::Revoke()
|
||||
{
|
||||
mRevoked = PR_TRUE;
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptCompiler::ScriptCompiler(nsDOMWorkerScriptLoader* aLoader,
|
||||
const nsString& aScriptText,
|
||||
const nsCString& aFilename,
|
||||
nsAutoJSValHolder& aScriptObj)
|
||||
: ScriptLoaderRunnable(aLoader),
|
||||
mScriptText(aScriptText),
|
||||
mFilename(aFilename),
|
||||
mScriptObj(aScriptObj)
|
||||
{
|
||||
NS_ASSERTION(!aScriptText.IsEmpty(), "No script to compile!");
|
||||
NS_ASSERTION(aScriptObj.IsHeld(), "Should be held!");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::ScriptCompiler::Run()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mRevoked) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mScriptObj.ToJSObject(), "Already have a script object?!");
|
||||
NS_ASSERTION(mScriptObj.IsHeld(), "Not held?!");
|
||||
NS_ASSERTION(!mScriptText.IsEmpty(), "Shouldn't have empty source here!");
|
||||
|
||||
JSContext* cx = nsDOMThreadService::GetCurrentContext();
|
||||
NS_ENSURE_STATE(cx);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSObject* global = JS_GetGlobalObject(cx);
|
||||
NS_ENSURE_STATE(global);
|
||||
|
||||
// Because we may have nested calls to this function we don't want the
|
||||
// execution to automatically report errors. We let them propagate instead.
|
||||
uint32 oldOpts =
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT |
|
||||
JSOPTION_NO_SCRIPT_RVAL);
|
||||
|
||||
JSPrincipals* principal = nsDOMWorkerSecurityManager::WorkerPrincipal();
|
||||
|
||||
JSObject* scriptObj =
|
||||
JS_CompileUCScriptForPrincipals(cx, global, principal,
|
||||
reinterpret_cast<const jschar*>
|
||||
(mScriptText.BeginReading()),
|
||||
mScriptText.Length(), mFilename.get(), 1);
|
||||
|
||||
JS_SetOptions(cx, oldOpts);
|
||||
|
||||
if (!scriptObj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mScriptObj = scriptObj;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
ScriptLoaderDone::ScriptLoaderDone(nsDOMWorkerScriptLoader* aLoader,
|
||||
volatile PRBool* aDoneFlag)
|
||||
: ScriptLoaderRunnable(aLoader),
|
||||
mDoneFlag(aDoneFlag)
|
||||
{
|
||||
NS_ASSERTION(aDoneFlag && !*aDoneFlag, "Bad setup!");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerScriptLoader::ScriptLoaderDone::Run()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mRevoked) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*mDoneFlag = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
AutoSuspendWorkerEvents::AutoSuspendWorkerEvents(nsDOMWorkerScriptLoader* aLoader)
|
||||
: mLoader(aLoader)
|
||||
{
|
||||
NS_ASSERTION(aLoader, "Don't hand me null!");
|
||||
aLoader->SuspendWorkerEvents();
|
||||
}
|
||||
|
||||
nsDOMWorkerScriptLoader::
|
||||
AutoSuspendWorkerEvents::~AutoSuspendWorkerEvents()
|
||||
{
|
||||
mLoader->ResumeWorkerEvents();
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERSCRIPTLOADER_H__
|
||||
#define __NSDOMWORKERSCRIPTLOADER_H__
|
||||
|
||||
// Bases
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIStreamLoader.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
/**
|
||||
* This class takes a list of script URLs, downloads the scripts, compiles the
|
||||
* scripts, and then finally executes them. Due to platform limitations all
|
||||
* network operations must happen on the main thread so this object sends events
|
||||
* back and forth from the worker thread to the main thread. The flow goes like
|
||||
* this:
|
||||
*
|
||||
* 1. (Worker thread) nsDOMWorkerScriptLoader created.
|
||||
* 2. (Worker thread) LoadScript(s) called. Some simple argument validation is
|
||||
* performed (currently limited to ensuring that all
|
||||
* arguments are strings). nsDOMWorkerScriptLoader is then
|
||||
* dispatched to the main thread.
|
||||
* 3. (Main thread) Arguments validated as URIs, security checks performed,
|
||||
* content policy consulted. Network loads begin.
|
||||
* 4. (Necko thread) Necko stuff!
|
||||
* 5. (Main thread) Completed downloads are packaged in a ScriptCompiler
|
||||
* runnable and sent to the worker thread.
|
||||
* 6. (Worker thread) ScriptCompiler runnables are processed (i.e. their
|
||||
* scripts are compiled) in the order in which the necko
|
||||
* downloads completed.
|
||||
* 7. (Worker thread) After all loads complete and all compilation succeeds
|
||||
* the scripts are executed in the order that the URLs were
|
||||
* given to LoadScript(s).
|
||||
*
|
||||
* Currently if *anything* after 2 fails then we cancel any pending loads and
|
||||
* bail out entirely.
|
||||
*/
|
||||
class nsDOMWorkerScriptLoader : public nsDOMWorkerFeature,
|
||||
public nsIRunnable,
|
||||
public nsIStreamLoaderObserver
|
||||
{
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
friend class AutoSuspendWorkerEvents;
|
||||
friend class ScriptLoaderRunnable;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSISTREAMLOADEROBSERVER
|
||||
|
||||
nsDOMWorkerScriptLoader(nsDOMWorker* aWorker);
|
||||
|
||||
nsresult LoadScripts(JSContext* aCx,
|
||||
const nsTArray<nsString>& aURLs,
|
||||
PRBool aExecute);
|
||||
|
||||
nsresult LoadWorkerScript(JSContext* aCx,
|
||||
const nsString& aURL);
|
||||
|
||||
nsresult ExecuteScripts(JSContext* aCx);
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
private:
|
||||
~nsDOMWorkerScriptLoader() { }
|
||||
|
||||
|
||||
nsresult DoRunLoop(JSContext* aCx);
|
||||
nsresult VerifyScripts(JSContext* aCx);
|
||||
|
||||
nsresult RunInternal();
|
||||
|
||||
nsresult OnStreamCompleteInternal(nsIStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
PRUint32 aStringLen,
|
||||
const PRUint8* aString);
|
||||
|
||||
void NotifyDone();
|
||||
|
||||
void SuspendWorkerEvents();
|
||||
void ResumeWorkerEvents();
|
||||
|
||||
Mutex& GetLock() {
|
||||
return mWorker->GetLock();
|
||||
}
|
||||
|
||||
class ScriptLoaderRunnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
protected:
|
||||
// Meant to be inherited.
|
||||
ScriptLoaderRunnable(nsDOMWorkerScriptLoader* aLoader);
|
||||
virtual ~ScriptLoaderRunnable();
|
||||
|
||||
public:
|
||||
void Revoke();
|
||||
|
||||
protected:
|
||||
PRBool mRevoked;
|
||||
|
||||
private:
|
||||
nsDOMWorkerScriptLoader* mLoader;
|
||||
};
|
||||
|
||||
class ScriptCompiler : public ScriptLoaderRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
ScriptCompiler(nsDOMWorkerScriptLoader* aLoader,
|
||||
const nsString& aScriptText,
|
||||
const nsCString& aFilename,
|
||||
nsAutoJSValHolder& aScriptObj);
|
||||
|
||||
private:
|
||||
nsString mScriptText;
|
||||
nsCString mFilename;
|
||||
nsAutoJSValHolder& mScriptObj;
|
||||
};
|
||||
|
||||
class ScriptLoaderDone : public ScriptLoaderRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
ScriptLoaderDone(nsDOMWorkerScriptLoader* aLoader,
|
||||
volatile PRBool* aDoneFlag);
|
||||
|
||||
private:
|
||||
volatile PRBool* mDoneFlag;
|
||||
};
|
||||
|
||||
class AutoSuspendWorkerEvents
|
||||
{
|
||||
public:
|
||||
AutoSuspendWorkerEvents(nsDOMWorkerScriptLoader* aLoader);
|
||||
~AutoSuspendWorkerEvents();
|
||||
|
||||
private:
|
||||
nsDOMWorkerScriptLoader* mLoader;
|
||||
};
|
||||
|
||||
struct ScriptLoadInfo
|
||||
{
|
||||
ScriptLoadInfo() : done(PR_FALSE), result(NS_ERROR_NOT_INITIALIZED) { }
|
||||
|
||||
nsString url;
|
||||
nsString scriptText;
|
||||
PRBool done;
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIURI> finalURI;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsAutoJSValHolder scriptObj;
|
||||
};
|
||||
|
||||
nsIThread* mTarget;
|
||||
|
||||
nsRefPtr<ScriptLoaderDone> mDoneRunnable;
|
||||
|
||||
PRUint32 mScriptCount;
|
||||
nsTArray<ScriptLoadInfo> mLoadInfos;
|
||||
|
||||
// Protected by mWorker's lock!
|
||||
nsTArray<ScriptLoaderRunnable*> mPendingRunnables;
|
||||
|
||||
PRPackedBool mCanceled;
|
||||
PRPackedBool mForWorker;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERSCRIPTLOADER_H__ */
|
|
@ -1,148 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerSecurityManager.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIClassInfo.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
class nsDOMWorkerPrincipal
|
||||
{
|
||||
public:
|
||||
static void Destroy(JSContext*, JSPrincipals*) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
static JSBool Subsume(JSPrincipals*, JSPrincipals*) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
static JSPrincipals gWorkerPrincipal =
|
||||
{ "domworkerthread" /* codebase */,
|
||||
NULL /* getPrincipalArray */,
|
||||
NULL /* globalPrivilegesEnabled */,
|
||||
1 /* refcount */,
|
||||
nsDOMWorkerPrincipal::Destroy /* destroy */,
|
||||
nsDOMWorkerPrincipal::Subsume /* subsume */ };
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerSecurityManager,
|
||||
nsIXPCSecurityManager)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanCreateWrapper(JSContext* aCx,
|
||||
const nsIID& aIID,
|
||||
nsISupports* aObj,
|
||||
nsIClassInfo* aClassInfo,
|
||||
void** aPolicy)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanCreateInstance(JSContext* aCx,
|
||||
const nsCID& aCID)
|
||||
{
|
||||
return CanGetService(aCx, aCID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanGetService(JSContext* aCx,
|
||||
const nsCID& aCID)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
|
||||
NS_ASSERTION(worker, "This should be set by the DOM thread service!");
|
||||
|
||||
return worker->IsPrivileged() ? NS_OK : NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerSecurityManager::CanAccess(PRUint32 aAction,
|
||||
nsAXPCNativeCallContext* aCallContext,
|
||||
JSContext* aJSContext,
|
||||
JSObject* aJSObject,
|
||||
nsISupports* aObj,
|
||||
nsIClassInfo* aClassInfo,
|
||||
jsid aName,
|
||||
void** aPolicy)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSPrincipals*
|
||||
nsDOMWorkerSecurityManager::WorkerPrincipal()
|
||||
{
|
||||
return &gWorkerPrincipal;
|
||||
}
|
||||
|
||||
JSBool
|
||||
nsDOMWorkerSecurityManager::JSCheckAccess(JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
jsid aId,
|
||||
JSAccessMode aMode,
|
||||
jsval* aVp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSPrincipals*
|
||||
nsDOMWorkerSecurityManager::JSFindPrincipal(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return WorkerPrincipal();
|
||||
}
|
||||
|
||||
JSBool
|
||||
nsDOMWorkerSecurityManager::JSTranscodePrincipals(JSXDRState* aXdr,
|
||||
JSPrincipals** aJsprinp)
|
||||
{
|
||||
NS_NOTREACHED("Shouldn't ever call this!");
|
||||
return JS_FALSE;
|
||||
}
|
|
@ -1,485 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerTimeout.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "pratom.h"
|
||||
#include "prtime.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerSecurityManager.h"
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
#define CONSTRUCTOR_ENSURE_TRUE(_cond, _rv) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (NS_UNLIKELY(!(_cond))) { \
|
||||
NS_WARNING("CONSTRUCTOR_ENSURE_TRUE(" #_cond ") failed"); \
|
||||
(_rv) = NS_ERROR_FAILURE; \
|
||||
return; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
#define SUSPEND_SPINLOCK_COUNT 5000
|
||||
|
||||
static const char* kSetIntervalStr = "setInterval";
|
||||
static const char* kSetTimeoutStr = "setTimeout";
|
||||
|
||||
nsDOMWorkerTimeout::FunctionCallback::FunctionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
nsresult* aRv)
|
||||
: mCallbackArgsLength(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDOMWorkerTimeout::FunctionCallback);
|
||||
|
||||
JSRuntime* rt;
|
||||
*aRv = nsDOMThreadService::JSRuntimeService()->GetRuntime(&rt);
|
||||
if (NS_FAILED(*aRv))
|
||||
return;
|
||||
|
||||
JSBool ok = mCallback.Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
mCallback = aArgv[0];
|
||||
|
||||
// We want enough space for an extra lateness arg.
|
||||
mCallbackArgsLength = aArgc > 2 ? aArgc - 1 : 1;
|
||||
|
||||
PRBool success = mCallbackArgs.SetLength(mCallbackArgsLength);
|
||||
CONSTRUCTOR_ENSURE_TRUE(success, *aRv);
|
||||
|
||||
PRUint32 index = 0;
|
||||
for (; index < mCallbackArgsLength - 1; index++) {
|
||||
ok = mCallbackArgs[index].Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
mCallbackArgs[index] = aArgv[index + 2];
|
||||
}
|
||||
|
||||
// Take care of the last arg.
|
||||
index = mCallbackArgsLength - 1;
|
||||
|
||||
ok = mCallbackArgs[index].Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
*aRv = NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::FunctionCallback::~FunctionCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDOMWorkerTimeout::FunctionCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::FunctionCallback::Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx)
|
||||
{
|
||||
PRInt32 lateness = NS_MAX(0, PRInt32(PR_Now() - aTimeout->mTargetTime)) /
|
||||
(PRTime)PR_USEC_PER_MSEC;
|
||||
mCallbackArgs[mCallbackArgsLength - 1] = INT_TO_JSVAL(lateness);
|
||||
|
||||
JSObject* global = JS_GetGlobalObject(aCx);
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
|
||||
nsTArray<jsval> argv;
|
||||
PRBool success = argv.SetCapacity(mCallbackArgsLength);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (PRUint32 index = 0; index < mCallbackArgsLength; index++) {
|
||||
argv.AppendElement(mCallbackArgs[index]);
|
||||
}
|
||||
|
||||
jsval rval;
|
||||
JSBool ok =
|
||||
JS_CallFunctionValue(aCx, global, mCallback, mCallbackArgsLength,
|
||||
argv.Elements(), &rval);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::ExpressionCallback::ExpressionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
JSContext* aCx,
|
||||
nsresult* aRv)
|
||||
: mLineNumber(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDOMWorkerTimeout::ExpressionCallback);
|
||||
|
||||
JSString* expr = JS_ValueToString(aCx, aArgv[0]);
|
||||
*aRv = expr ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(*aRv))
|
||||
return;
|
||||
|
||||
JSRuntime* rt;
|
||||
*aRv = nsDOMThreadService::JSRuntimeService()->GetRuntime(&rt);
|
||||
if (NS_FAILED(*aRv))
|
||||
return;
|
||||
|
||||
JSBool ok = mExpression.Hold(rt);
|
||||
CONSTRUCTOR_ENSURE_TRUE(ok, *aRv);
|
||||
|
||||
mExpression = aArgv[0];
|
||||
|
||||
// Get the calling location.
|
||||
const char* fileName;
|
||||
PRUint32 lineNumber;
|
||||
if (nsJSUtils::GetCallingLocation(aCx, &fileName, &lineNumber)) {
|
||||
mFileName.Assign(fileName);
|
||||
mLineNumber = lineNumber;
|
||||
}
|
||||
|
||||
*aRv = NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::ExpressionCallback::~ExpressionCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDOMWorkerTimeout::ExpressionCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::ExpressionCallback::Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx)
|
||||
{
|
||||
JSObject* global = JS_GetGlobalObject(aCx);
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
|
||||
JSPrincipals* principal = nsDOMWorkerSecurityManager::WorkerPrincipal();
|
||||
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
|
||||
|
||||
JSString* expression = JS_ValueToString(aCx, mExpression);
|
||||
NS_ENSURE_TRUE(expression, NS_ERROR_FAILURE);
|
||||
|
||||
size_t stringLength;
|
||||
const jschar* string = JS_GetStringCharsAndLength(aCx, expression, &stringLength);
|
||||
NS_ENSURE_TRUE(string, NS_ERROR_FAILURE);
|
||||
|
||||
PRBool success = JS_EvaluateUCScriptForPrincipals(aCx, global, principal,
|
||||
string, stringLength,
|
||||
mFileName.get(),
|
||||
mLineNumber, nsnull);
|
||||
if (!success) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerTimeout::nsDOMWorkerTimeout(nsDOMWorker* aWorker,
|
||||
PRUint32 aId)
|
||||
: nsDOMWorkerFeature(aWorker, aId),
|
||||
mInterval(0),
|
||||
mSuspendSpinlock(0),
|
||||
mSuspendInterval(0),
|
||||
mIsInterval(PR_FALSE),
|
||||
mIsSuspended(PR_FALSE),
|
||||
mSuspendedBeforeStart(PR_FALSE),
|
||||
mStarted(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(mWorker, "Need a worker here!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerTimeout, nsDOMWorkerFeature,
|
||||
nsITimerCallback)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::Init(JSContext* aCx, PRUint32 aArgc, jsval* aArgv,
|
||||
PRBool aIsInterval)
|
||||
{
|
||||
NS_ASSERTION(aCx, "Null pointer!");
|
||||
NS_ASSERTION(aArgv, "Null pointer!");
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
if (!aArgc) {
|
||||
JS_ReportError(aCx, "Function %s requires at least 1 parameter",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
PRUint32 interval;
|
||||
if (aArgc > 1) {
|
||||
if (!JS_ValueToECMAUint32(aCx, aArgv[1], (uint32*)&interval)) {
|
||||
JS_ReportError(aCx, "Second argument to %s must be a millisecond value",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If no interval was specified, treat this like a timeout, to avoid
|
||||
// setting an interval of 0 milliseconds.
|
||||
interval = 0;
|
||||
aIsInterval = PR_FALSE;
|
||||
}
|
||||
|
||||
mInterval = interval;
|
||||
|
||||
mIsInterval = aIsInterval;
|
||||
|
||||
mTargetTime = PR_Now() + interval * (PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
nsresult rv;
|
||||
switch (JS_TypeOfValue(aCx, aArgv[0])) {
|
||||
case JSTYPE_FUNCTION:
|
||||
mCallback = new FunctionCallback(aArgc, aArgv, &rv);
|
||||
NS_ENSURE_TRUE(mCallback, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
break;
|
||||
|
||||
case JSTYPE_STRING:
|
||||
case JSTYPE_OBJECT:
|
||||
mCallback = new ExpressionCallback(aArgc, aArgv, aCx, &rv);
|
||||
NS_ENSURE_TRUE(mCallback, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
|
||||
default:
|
||||
JS_ReportError(aCx, "useless %s call (missing quotes around argument?)",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
|
||||
// Return an error that nsGlobalWindow can recognize and turn into NS_OK.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIEventTarget* target =
|
||||
static_cast<nsIEventTarget*>(nsDOMThreadService::get());
|
||||
|
||||
rv = timer->SetTarget(target);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mTimer.swap(timer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::Start()
|
||||
{
|
||||
if (IsSuspended()) {
|
||||
NS_ASSERTION(mSuspendedBeforeStart, "Bad state!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mTimer->InitWithCallback(this, mInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mStarted = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerTimeout::Run()
|
||||
{
|
||||
NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED);
|
||||
LOG(("Worker [0x%p] running timeout [0x%p] with id %u",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId));
|
||||
|
||||
JSContext* cx;
|
||||
nsresult rv =
|
||||
nsDOMThreadService::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
rv = mCallback->Run(this, cx);
|
||||
|
||||
// Make sure any pending exceptions are converted to errors for the pool.
|
||||
JS_ReportPendingException(cx);
|
||||
|
||||
if (mIsInterval) {
|
||||
mTargetTime = PR_Now() + mInterval * (PRTime)PR_USEC_PER_MSEC;
|
||||
nsresult rv2 = mTimer->InitWithCallback(this, mInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv2, rv2);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::Cancel()
|
||||
{
|
||||
NS_ASSERTION(mTimer, "Impossible to get here without a timer!");
|
||||
|
||||
LOG(("Worker [0x%p] canceling timeout [0x%p] with id %u",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId));
|
||||
|
||||
{
|
||||
AutoSpinlock lock(this);
|
||||
|
||||
if (IsSuspendedNoLock()) {
|
||||
mIsSuspended = PR_FALSE;
|
||||
// This should kill us when all is said and done.
|
||||
mSuspendedRef = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// This call to Cancel should kill us.
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::Suspend()
|
||||
{
|
||||
AutoSpinlock lock(this);
|
||||
|
||||
NS_ASSERTION(!IsSuspendedNoLock(), "Bad state!");
|
||||
|
||||
mIsSuspended = PR_TRUE;
|
||||
mSuspendedRef = this;
|
||||
|
||||
if (!mStarted) {
|
||||
mSuspendedBeforeStart = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
mTimer->Cancel();
|
||||
|
||||
mSuspendInterval = NS_MAX(0, PRInt32(mTargetTime - PR_Now())) /
|
||||
(PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
LOG(("Worker [0x%p] suspending timeout [0x%p] with id %u (interval = %u)",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId,
|
||||
mSuspendInterval));
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::Resume()
|
||||
{
|
||||
NS_ASSERTION(mTimer, "Impossible to get here without a timer!");
|
||||
|
||||
LOG(("Worker [0x%p] resuming timeout [0x%p] with id %u",
|
||||
static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId));
|
||||
|
||||
AutoSpinlock lock(this);
|
||||
|
||||
NS_ASSERTION(IsSuspendedNoLock(), "Should be suspended!");
|
||||
|
||||
if (mSuspendedBeforeStart) {
|
||||
NS_ASSERTION(!mSuspendInterval, "Bad state!");
|
||||
mSuspendedBeforeStart = PR_FALSE;
|
||||
mSuspendInterval = mInterval;
|
||||
mStarted = PR_TRUE;
|
||||
}
|
||||
|
||||
mTargetTime = PR_Now() + mSuspendInterval * (PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
mTimer->InitWithCallback(this, mSuspendInterval, nsITimer::TYPE_ONE_SHOT);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to init timer!");
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::AcquireSpinlock()
|
||||
{
|
||||
PRUint32 loopCount = 0;
|
||||
while (PR_ATOMIC_SET(&mSuspendSpinlock, 1) == 1) {
|
||||
if (++loopCount > SUSPEND_SPINLOCK_COUNT) {
|
||||
LOG(("AcquireSpinlock taking too long (looped %u times), yielding.",
|
||||
loopCount));
|
||||
loopCount = 0;
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
}
|
||||
}
|
||||
#ifdef PR_LOGGING
|
||||
if (loopCount) {
|
||||
LOG(("AcquireSpinlock needed %u loops", loopCount));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerTimeout::ReleaseSpinlock()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRInt32 suspended =
|
||||
#endif
|
||||
PR_ATOMIC_SET(&mSuspendSpinlock, 0);
|
||||
NS_ASSERTION(suspended == 1, "Huh?!");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerTimeout::Notify(nsITimer* aTimer)
|
||||
{
|
||||
// Should be on the timer thread.
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aTimer == mTimer, "Wrong timer?!");
|
||||
|
||||
PRUint32 type;
|
||||
nsresult rv = aTimer->GetType(&type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We only care about one-shot timers here because that may be the one that
|
||||
// we set from Resume().
|
||||
if (type == nsITimer::TYPE_ONE_SHOT) {
|
||||
AutoSpinlock lock(this);
|
||||
if (mIsSuspended) {
|
||||
mIsSuspended = PR_FALSE;
|
||||
mSuspendedRef = nsnull;
|
||||
if (mIsInterval) {
|
||||
// This is the first fire since we resumed. Set our interval back to the
|
||||
// real interval.
|
||||
mTargetTime = PR_Now() + mInterval * (PRTime)PR_USEC_PER_MSEC;
|
||||
|
||||
rv = aTimer->InitWithCallback(this, mInterval,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsDOMThreadService::get()->TimeoutReady(this);
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERTIMEOUT_H__
|
||||
#define __NSDOMWORKERTIMEOUT_H__
|
||||
|
||||
// Interfaces
|
||||
#include "nsITimer.h"
|
||||
|
||||
// Other includes
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorker.h"
|
||||
|
||||
/**
|
||||
* The nsDOMWorkerTimeout has a slightly complicated life cycle. It's created
|
||||
* by an nsDOMWorker (or one of its JS context functions) and immediately takes
|
||||
* a strong reference to the worker that created it. It does this so that the
|
||||
* worker can't be collected while a timeout is outstanding. However, the worker
|
||||
* needs a weak reference to the timeout so that it can be canceled if the
|
||||
* worker is canceled (in the event that the page falls out of the fastback
|
||||
* cache or the application is exiting, for instance). The only thing that holds
|
||||
* the timeout alive is its mTimer via the nsITimerCallback interface. If the
|
||||
* timer is single-shot and has run already or if the timer is canceled then
|
||||
* this object should die.
|
||||
*/
|
||||
class nsDOMWorkerTimeout : public nsDOMWorkerFeature,
|
||||
public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
nsDOMWorkerTimeout(nsDOMWorker* aWorker,
|
||||
PRUint32 aId);
|
||||
|
||||
nsresult Init(JSContext* aCx,
|
||||
PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
PRBool aIsInterval);
|
||||
|
||||
nsresult Start();
|
||||
|
||||
nsresult Run();
|
||||
|
||||
virtual void Cancel();
|
||||
virtual void Suspend();
|
||||
virtual void Resume();
|
||||
|
||||
PRIntervalTime GetInterval() {
|
||||
return mInterval;
|
||||
}
|
||||
|
||||
nsDOMWorker* GetWorker() {
|
||||
return mWorker;
|
||||
}
|
||||
|
||||
PRBool IsSuspended() {
|
||||
AutoSpinlock lock(this);
|
||||
return IsSuspendedNoLock();
|
||||
}
|
||||
|
||||
private:
|
||||
~nsDOMWorkerTimeout() { }
|
||||
|
||||
void AcquireSpinlock();
|
||||
void ReleaseSpinlock();
|
||||
|
||||
PRBool IsSuspendedNoLock() {
|
||||
return mIsSuspended;
|
||||
}
|
||||
|
||||
class AutoSpinlock
|
||||
{
|
||||
public:
|
||||
AutoSpinlock(nsDOMWorkerTimeout* aTimeout)
|
||||
: mTimeout(aTimeout) {
|
||||
aTimeout->AcquireSpinlock();
|
||||
}
|
||||
|
||||
~AutoSpinlock() {
|
||||
mTimeout->ReleaseSpinlock();
|
||||
}
|
||||
private:
|
||||
nsDOMWorkerTimeout* mTimeout;
|
||||
};
|
||||
|
||||
// We support two types of callbacks (functions and expressions) just like the
|
||||
// normal window timeouts. Each type has its own member and rooting needs so
|
||||
// we split them into two classes with a common base.
|
||||
class CallbackBase
|
||||
{
|
||||
public:
|
||||
virtual ~CallbackBase() { }
|
||||
virtual nsresult Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx) = 0;
|
||||
};
|
||||
|
||||
class FunctionCallback : public CallbackBase
|
||||
{
|
||||
public:
|
||||
FunctionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
nsresult* aRv);
|
||||
virtual ~FunctionCallback();
|
||||
virtual nsresult Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx);
|
||||
protected:
|
||||
nsAutoJSValHolder mCallback;
|
||||
nsTArray<nsAutoJSValHolder> mCallbackArgs;
|
||||
PRUint32 mCallbackArgsLength;
|
||||
};
|
||||
|
||||
class ExpressionCallback : public CallbackBase
|
||||
{
|
||||
public:
|
||||
ExpressionCallback(PRUint32 aArgc,
|
||||
jsval* aArgv,
|
||||
JSContext* aCx,
|
||||
nsresult* aRv);
|
||||
virtual ~ExpressionCallback();
|
||||
virtual nsresult Run(nsDOMWorkerTimeout* aTimeout,
|
||||
JSContext* aCx);
|
||||
protected:
|
||||
nsAutoJSValHolder mExpression;
|
||||
nsCString mFileName;
|
||||
PRUint32 mLineNumber;
|
||||
};
|
||||
|
||||
// Hold this object alive!
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
PRUint32 mInterval;
|
||||
|
||||
PRTime mTargetTime;
|
||||
|
||||
nsAutoPtr<CallbackBase> mCallback;
|
||||
|
||||
PRInt32 mSuspendSpinlock;
|
||||
PRUint32 mSuspendInterval;
|
||||
nsRefPtr<nsDOMWorkerTimeout> mSuspendedRef;
|
||||
|
||||
PRPackedBool mIsInterval;
|
||||
PRPackedBool mIsSuspended;
|
||||
PRPackedBool mSuspendedBeforeStart;
|
||||
PRPackedBool mStarted;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERTIMEOUT_H__ */
|
|
@ -1,910 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerEvents.h"
|
||||
#include "nsDOMWorkerPool.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// The list of event types that we support. This list and the defines based on
|
||||
// it determine the sizes of the listener arrays in nsDOMWorkerXHRProxy. Make
|
||||
// sure that any event types shared by both the XHR and Upload objects are
|
||||
// together at the beginning of the list. Any changes made to this list may
|
||||
// affect sMaxUploadEventTypes, so make sure that it is adjusted accordingly or
|
||||
// things will break!
|
||||
const char* const nsDOMWorkerXHREventTarget::sListenerTypes[] = {
|
||||
// nsIXMLHttpRequestEventTarget listeners.
|
||||
"abort", /* LISTENER_TYPE_ABORT */
|
||||
"error", /* LISTENER_TYPE_ERROR */
|
||||
"load", /* LISTENER_TYPE_LOAD */
|
||||
"loadstart", /* LISTENER_TYPE_LOADSTART */
|
||||
"progress", /* LISTENER_TYPE_PROGRESS */
|
||||
|
||||
// nsIXMLHttpRequest listeners.
|
||||
"readystatechange", /* LISTENER_TYPE_READYSTATECHANGE */
|
||||
"loadend"
|
||||
};
|
||||
|
||||
// This should always be set to the length of sListenerTypes.
|
||||
const PRUint32 nsDOMWorkerXHREventTarget::sMaxXHREventTypes =
|
||||
NS_ARRAY_LENGTH(nsDOMWorkerXHREventTarget::sListenerTypes);
|
||||
|
||||
// This should be set to the index of the first event type that is *not*
|
||||
// supported by the Upload object.
|
||||
const PRUint32 nsDOMWorkerXHREventTarget::sMaxUploadEventTypes =
|
||||
LISTENER_TYPE_READYSTATECHANGE;
|
||||
|
||||
// Enforce the invariant that the upload object supports no more event types
|
||||
// than the xhr object.
|
||||
PR_STATIC_ASSERT(nsDOMWorkerXHREventTarget::sMaxXHREventTypes >=
|
||||
nsDOMWorkerXHREventTarget::sMaxUploadEventTypes);
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerXHREventTarget,
|
||||
nsDOMWorkerMessageHandler,
|
||||
nsIXMLHttpRequestEventTarget)
|
||||
|
||||
PRUint32
|
||||
nsDOMWorkerXHREventTarget::GetListenerTypeFromString(const nsAString& aString)
|
||||
{
|
||||
for (PRUint32 index = 0; index < sMaxXHREventTypes; index++) {
|
||||
if (aString.EqualsASCII(sListenerTypes[index])) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return PR_UINT32_MAX;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnabort(nsIDOMEventListener** aOnabort)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnabort);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ABORT]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnabort);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnabort(nsIDOMEventListener* aOnabort)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ABORT]);
|
||||
|
||||
return SetOnXListener(type, aOnabort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnerror(nsIDOMEventListener** aOnerror)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnerror);
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ERROR]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnerror);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnerror(nsIDOMEventListener* aOnerror)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_ERROR]);
|
||||
|
||||
return SetOnXListener(type, aOnerror);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnload(nsIDOMEventListener** aOnload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnload);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOAD]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnload);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnload(nsIDOMEventListener* aOnload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOAD]);
|
||||
|
||||
return SetOnXListener(type, aOnload);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnloadstart(nsIDOMEventListener** aOnloadstart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnloadstart);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADSTART]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnloadstart);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnloadstart(nsIDOMEventListener* aOnloadstart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADSTART]);
|
||||
|
||||
return SetOnXListener(type, aOnloadstart);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnprogress(nsIDOMEventListener** aOnprogress)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnprogress);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_PROGRESS]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnprogress);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnprogress(nsIDOMEventListener* aOnprogress)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_PROGRESS]);
|
||||
|
||||
return SetOnXListener(type, aOnprogress);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnloadend(nsIDOMEventListener** aOnloadend)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aOnloadend);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADEND]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnloadend);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnloadend(nsIDOMEventListener* aOnloadend)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_LOADEND]);
|
||||
|
||||
return SetOnXListener(type, aOnloadend);
|
||||
}
|
||||
|
||||
nsDOMWorkerXHRUpload::nsDOMWorkerXHRUpload(nsDOMWorkerXHR* aWorkerXHR)
|
||||
: mWorkerXHR(aWorkerXHR)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorkerXHR, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorkerXHRUpload, nsDOMWorkerXHREventTarget,
|
||||
nsIXMLHttpRequestUpload)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER3(nsDOMWorkerXHRUpload, nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget,
|
||||
nsIXMLHttpRequestUpload)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerXHRUpload)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRUpload::RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
if (mWorkerXHR->mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::RemoveEventListener(aType, aListener,
|
||||
aUseCapture);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRUpload::DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
if (mWorkerXHR->mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::DispatchEvent(aEvent, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRUpload::AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
if (mWorkerXHR->mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = nsDOMWorkerXHREventTarget::AddEventListener(aType, aListener,
|
||||
aUseCapture,
|
||||
aWantsUntrusted,
|
||||
optional_argc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mWorkerXHR->mXHRProxy->UploadEventListenerAdded();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("UploadEventListenerAdded failed!");
|
||||
RemoveEventListener(aType, aListener, aUseCapture);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRUpload::SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mWorkerXHR->mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
PRUint32 type = GetListenerTypeFromString(aType);
|
||||
if (type > sMaxUploadEventTypes) {
|
||||
// Silently ignore junk events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::SetOnXListener(aType, aListener);
|
||||
}
|
||||
|
||||
nsDOMWorkerXHR::nsDOMWorkerXHR(nsDOMWorker* aWorker)
|
||||
: nsDOMWorkerFeature(aWorker),
|
||||
mWrappedNative(nsnull),
|
||||
mCanceled(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorker, "Must have a worker!");
|
||||
}
|
||||
|
||||
nsDOMWorkerXHR::~nsDOMWorkerXHR()
|
||||
{
|
||||
if (mXHRProxy) {
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(mXHRProxy, &nsDOMWorkerXHRProxy::Destroy);
|
||||
|
||||
if (runnable) {
|
||||
mXHRProxy = nsnull;
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mXHRProxy->Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tricky! We use the AddRef/Release method of nsDOMWorkerFeature (to make sure
|
||||
// we properly remove ourselves from the worker array) but inherit the QI of
|
||||
// nsDOMWorkerXHREventTarget.
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMWorkerXHR, nsDOMWorkerFeature)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMWorkerXHR, nsDOMWorkerFeature)
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE_INHERITED2(nsDOMWorkerXHR, nsDOMWorkerXHREventTarget,
|
||||
nsIXMLHttpRequest,
|
||||
nsIXPCScriptable)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER3(nsDOMWorkerXHR, nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget,
|
||||
nsIXMLHttpRequest)
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerXHR)
|
||||
|
||||
#define XPC_MAP_CLASSNAME nsDOMWorkerXHR
|
||||
#define XPC_MAP_QUOTED_CLASSNAME "XMLHttpRequest"
|
||||
#define XPC_MAP_WANT_POSTCREATE
|
||||
#define XPC_MAP_WANT_TRACE
|
||||
#define XPC_MAP_WANT_FINALIZE
|
||||
|
||||
#define XPC_MAP_FLAGS \
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY | \
|
||||
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES
|
||||
|
||||
#include "xpc_map_end.h"
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Trace(nsIXPConnectWrappedNative* /* aWrapper */,
|
||||
JSTracer* aTracer,
|
||||
JSObject* /*aObj */)
|
||||
{
|
||||
if (!mCanceled) {
|
||||
nsDOMWorkerMessageHandler::Trace(aTracer);
|
||||
if (mUpload) {
|
||||
mUpload->Trace(aTracer);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Finalize(nsIXPConnectWrappedNative* /* aWrapper */,
|
||||
JSContext* /* aCx */,
|
||||
JSObject* /* aObj */)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsDOMWorkerMessageHandler::ClearAllListeners();
|
||||
|
||||
if (mUpload) {
|
||||
mUpload->ClearAllListeners();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::PostCreate(nsIXPConnectWrappedNative* aWrapper,
|
||||
JSContext* /* aCx */,
|
||||
JSObject* /* aObj */)
|
||||
{
|
||||
mWrappedNative = aWrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::Init()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> proxy = new nsDOMWorkerXHRProxy(this);
|
||||
NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = proxy->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
proxy.swap(mXHRProxy);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerXHR::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Just in case mUpload holds the only ref to this object we make sure to stay
|
||||
// alive through this call.
|
||||
nsRefPtr<nsDOMWorkerXHR> kungFuDeathGrip(this);
|
||||
|
||||
{
|
||||
// This lock is here to prevent a race between Cancel and GetUpload, not to
|
||||
// protect mCanceled.
|
||||
MutexAutoLock lock(mWorker->GetLock());
|
||||
|
||||
mCanceled = PR_TRUE;
|
||||
mUpload = nsnull;
|
||||
}
|
||||
|
||||
if (mXHRProxy) {
|
||||
mXHRProxy->Destroy();
|
||||
mXHRProxy = nsnull;
|
||||
}
|
||||
|
||||
mWorker = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
PRUint32 type = GetListenerTypeFromString(aType);
|
||||
if (type > sMaxXHREventTypes) {
|
||||
// Silently ignore junk events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsDOMWorkerXHREventTarget::SetOnXListener(aType, aListener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetChannel(nsIChannel** aChannel)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
*aChannel = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseXML(nsIDOMDocument** aResponseXML)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aResponseXML);
|
||||
*aResponseXML = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseText(nsAString& aResponseText)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetResponseText(aResponseText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetStatus(PRUint32* aStatus)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetStatus(aStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetStatusText(nsACString& aStatusText)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetStatusText(aStatusText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Abort()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Abort();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetAllResponseHeaders(char** _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetAllResponseHeaders(_retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetResponseHeader(aHeader, _retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Open(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword, PRUint8 optional_argc)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (!optional_argc) {
|
||||
aAsync = PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Open(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Send(nsIVariant* aBody)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (mWorker->IsClosing() && !mXHRProxy->mSyncRequest) {
|
||||
// Cheat and don't start this request since we know we'll never be able to
|
||||
// use the data.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Send(aBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SendAsBinary(const nsAString& aBody)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (mWorker->IsClosing() && !mXHRProxy->mSyncRequest) {
|
||||
// Cheat and don't start this request since we know we'll never be able to
|
||||
// use the data.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SendAsBinary(aBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetRequestHeader(aHeader, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetReadyState(PRUint16* aReadyState)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aReadyState);
|
||||
|
||||
nsresult rv = mXHRProxy->GetReadyState(aReadyState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::OverrideMimeType(const nsACString& aMimetype)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->OverrideMimeType(aMimetype);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetMultipart(PRBool* aMultipart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMultipart);
|
||||
|
||||
nsresult rv = mXHRProxy->GetMultipart(aMultipart);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetMultipart(PRBool aMultipart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetMultipart(aMultipart);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetMozBackgroundRequest(PRBool* aMozBackgroundRequest)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMozBackgroundRequest);
|
||||
|
||||
*aMozBackgroundRequest = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetMozBackgroundRequest(PRBool aMozBackgroundRequest)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (aMozBackgroundRequest) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Init(nsIPrincipal* aPrincipal,
|
||||
nsIScriptContext* aScriptContext,
|
||||
nsPIDOMWindow* aOwnerWindow,
|
||||
nsIURI* aBaseURI)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_NOTREACHED("No one should be calling this!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetUpload(nsIXMLHttpRequestUpload** aUpload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<nsDOMWorker> worker = mWorker;
|
||||
if (!worker) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(worker->GetLock());
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aUpload);
|
||||
|
||||
if (!mUpload) {
|
||||
mUpload = new nsDOMWorkerXHRUpload(this);
|
||||
NS_ENSURE_TRUE(mUpload, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
NS_ADDREF(*aUpload = mUpload);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetOnreadystatechange(nsIDOMEventListener** aOnreadystatechange)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnreadystatechange);
|
||||
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_READYSTATECHANGE]);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(type);
|
||||
listener.forget(aOnreadystatechange);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetOnreadystatechange(nsIDOMEventListener* aOnreadystatechange)
|
||||
{
|
||||
nsAutoString type;
|
||||
type.AssignASCII(sListenerTypes[LISTENER_TYPE_READYSTATECHANGE]);
|
||||
|
||||
return SetOnXListener(type, aOnreadystatechange);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetWithCredentials(PRBool* aWithCredentials)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aWithCredentials);
|
||||
|
||||
nsresult rv = mXHRProxy->GetWithCredentials(aWithCredentials);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetWithCredentials(PRBool aWithCredentials)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetWithCredentials(aWithCredentials);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseType(nsAString& aResponseText)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetResponseType(const nsAString& aResponseText)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* readonly attribute jsval response; */
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponse(JSContext *aCx, jsval *aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHR_H__
|
||||
#define __NSDOMWORKERXHR_H__
|
||||
|
||||
// Bases
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorker.h"
|
||||
#include "nsDOMWorkerMacros.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
// Convenience defines for event *indexes* in the sListenerTypes array.
|
||||
#define LISTENER_TYPE_ABORT 0
|
||||
#define LISTENER_TYPE_ERROR 1
|
||||
#define LISTENER_TYPE_LOAD 2
|
||||
#define LISTENER_TYPE_LOADSTART 3
|
||||
#define LISTENER_TYPE_PROGRESS 4
|
||||
#define LISTENER_TYPE_READYSTATECHANGE 5
|
||||
#define LISTENER_TYPE_LOADEND 6
|
||||
|
||||
class nsIXPConnectWrappedNative;
|
||||
|
||||
class nsDOMWorkerXHREventTarget : public nsDOMWorkerMessageHandler,
|
||||
public nsIXMLHttpRequestEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
|
||||
|
||||
static const char* const sListenerTypes[];
|
||||
static const PRUint32 sMaxXHREventTypes;
|
||||
static const PRUint32 sMaxUploadEventTypes;
|
||||
|
||||
static PRUint32 GetListenerTypeFromString(const nsAString& aString);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHREventTarget() { }
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHRUpload;
|
||||
|
||||
class nsDOMWorkerXHR : public nsDOMWorkerFeature,
|
||||
public nsDOMWorkerXHREventTarget,
|
||||
public nsIXMLHttpRequest,
|
||||
public nsIXPCScriptable
|
||||
{
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHRLastProgressOrLoadEvent;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIXMLHTTPREQUEST
|
||||
NS_FORWARD_NSICLASSINFO_NOGETINTERFACES(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
NS_DECL_NSIXPCSCRIPTABLE
|
||||
|
||||
nsDOMWorkerXHR(nsDOMWorker* aWorker);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
virtual nsresult SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~nsDOMWorkerXHR();
|
||||
|
||||
Mutex& GetLock() {
|
||||
return mWorker->GetLock();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIXPConnectWrappedNative> GetWrappedNative() {
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative(mWrappedNative);
|
||||
return wrappedNative.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHRProxy;
|
||||
nsRefPtr<nsDOMWorkerXHRUpload> mUpload;
|
||||
|
||||
nsIXPConnectWrappedNative* mWrappedNative;
|
||||
|
||||
volatile PRBool mCanceled;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHRUpload : public nsDOMWorkerXHREventTarget,
|
||||
public nsIXMLHttpRequestUpload
|
||||
{
|
||||
friend class nsDOMWorkerXHR;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMEventHandler
|
||||
NS_FORWARD_INTERNAL_NSIDOMEVENTTARGET(nsDOMWorkerMessageHandler::)
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
NS_IMETHOD RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval);
|
||||
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSIXMLHTTPREQUESTUPLOAD
|
||||
NS_FORWARD_NSICLASSINFO_NOGETINTERFACES(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerXHRUpload(nsDOMWorkerXHR* aWorkerXHR);
|
||||
|
||||
virtual nsresult SetOnXListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHRUpload() { }
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHR> mWorkerXHR;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHR_H__ */
|
|
@ -1,182 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__
|
||||
#define __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION0(_name) \
|
||||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION1(_name, _arg1) \
|
||||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (_arg1 aArg1) : mArg1(aArg1) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
_arg1 mArg1; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION2(_name, _arg1, _arg2) \
|
||||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (_arg1 aArg1, _arg2 aArg2) : mArg1(aArg1), mArg2(aArg2) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1, mArg2); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
_arg1 mArg1; \
|
||||
_arg2 mArg2; \
|
||||
}
|
||||
|
||||
namespace nsDOMWorkerProxiedXHRFunctions
|
||||
{
|
||||
typedef nsDOMWorkerXHRProxy::SyncEventQueue SyncEventQueue;
|
||||
|
||||
class SyncEventCapturingRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SyncEventCapturingRunnable()
|
||||
: mXHR(nsnull), mQueue(nsnull) { }
|
||||
|
||||
void Init(nsDOMWorkerXHRProxy* aXHR,
|
||||
SyncEventQueue* aQueue) {
|
||||
NS_ASSERTION(aXHR, "Null pointer!");
|
||||
NS_ASSERTION(aQueue, "Null pointer!");
|
||||
|
||||
mXHR = aXHR;
|
||||
mQueue = aQueue;
|
||||
}
|
||||
|
||||
virtual nsresult RunInternal() = 0;
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
NS_ASSERTION(mXHR && mQueue, "Forgot to call Init!");
|
||||
|
||||
SyncEventQueue* oldQueue = mXHR->SetSyncEventQueue(mQueue);
|
||||
|
||||
nsresult rv = RunInternal();
|
||||
|
||||
mXHR->SetSyncEventQueue(oldQueue);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR;
|
||||
SyncEventQueue* mQueue;
|
||||
};
|
||||
|
||||
class Abort : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->Abort();
|
||||
}
|
||||
};
|
||||
|
||||
class Open : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
Open(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
: mMethod(aMethod), mUrl(aUrl), mAsync(aAsync), mUser(aUser),
|
||||
mPassword(aPassword) { }
|
||||
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->Open(mMethod, mUrl, mAsync, mUser, mPassword);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCString mMethod;
|
||||
nsCString mUrl;
|
||||
PRBool mAsync;
|
||||
nsString mUser;
|
||||
nsString mPassword;
|
||||
};
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetAllResponseHeaders, char**);
|
||||
|
||||
MAKE_PROXIED_FUNCTION2(GetResponseHeader, const nsACString&, nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(Send, nsIVariant*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SendAsBinary, const nsAString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION2(SetRequestHeader, const nsACString&,
|
||||
const nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(OverrideMimeType, const nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SetMultipart, PRBool);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetMultipart, PRBool*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetWithCredentials, PRBool*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SetWithCredentials, PRBool);
|
||||
}
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,198 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHRPROXY_H__
|
||||
#define __NSDOMWORKERXHRPROXY_H__
|
||||
|
||||
// Bases
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIJSXMLHttpRequest;
|
||||
class nsIThread;
|
||||
class nsIVariant;
|
||||
class nsIXMLHttpRequest;
|
||||
class nsIXMLHttpRequestUpload;
|
||||
class nsIXPConnectWrappedNative;
|
||||
class nsDOMWorkerXHR;
|
||||
class nsDOMWorkerXHREvent;
|
||||
class nsDOMWorkerXHRFinishSyncXHRRunnable;
|
||||
class nsDOMWorkerXHRState;
|
||||
class nsDOMWorkerXHRWrappedListener;
|
||||
class nsXMLHttpRequest;
|
||||
|
||||
class nsDOMWorkerXHRProxy : public nsIRunnable,
|
||||
public nsIDOMEventListener,
|
||||
public nsIRequestObserver
|
||||
{
|
||||
friend class nsDOMWorkerXHRAttachUploadListenersRunnable;
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHRFinishSyncXHRRunnable;
|
||||
friend class nsDOMWorkerXHRLastProgressOrLoadEvent;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
public:
|
||||
typedef nsAutoTArray<nsCOMPtr<nsIRunnable>, 5> SyncEventQueue;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
nsDOMWorkerXHRProxy(nsDOMWorkerXHR* aWorkerXHR);
|
||||
virtual ~nsDOMWorkerXHRProxy();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsIXMLHttpRequest* GetXMLHttpRequest();
|
||||
|
||||
nsresult Open(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword);
|
||||
|
||||
nsresult Abort();
|
||||
|
||||
SyncEventQueue* SetSyncEventQueue(SyncEventQueue* aQueue);
|
||||
|
||||
PRInt32 ChannelID() {
|
||||
return mChannelID;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct ProgressInfo {
|
||||
ProgressInfo() : computable(PR_FALSE), loaded(0), total(0) { }
|
||||
|
||||
PRBool computable;
|
||||
PRUint64 loaded;
|
||||
PRUint64 total;
|
||||
};
|
||||
|
||||
nsresult InitInternal();
|
||||
void DestroyInternal();
|
||||
|
||||
nsresult Destroy();
|
||||
|
||||
void AddRemoveXHRListeners(PRBool aAdd);
|
||||
void FlipOwnership();
|
||||
|
||||
nsresult UploadEventListenerAdded();
|
||||
|
||||
nsresult HandleWorkerEvent(nsDOMWorkerXHREvent* aEvent,
|
||||
PRBool aUploadEvent);
|
||||
|
||||
nsresult HandleEventRunnable(nsIRunnable* aRunnable);
|
||||
|
||||
// Methods of nsIXMLHttpRequest that we implement
|
||||
nsresult GetAllResponseHeaders(char** _retval);
|
||||
nsresult GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval);
|
||||
nsresult Send(nsIVariant* aBody);
|
||||
nsresult SendAsBinary(const nsAString& aBody);
|
||||
nsresult GetResponseText(nsAString& _retval);
|
||||
nsresult GetStatusText(nsACString& _retval);
|
||||
nsresult GetStatus(nsresult* _retval);
|
||||
nsresult GetReadyState(PRUint16* _retval);
|
||||
nsresult SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue);
|
||||
nsresult OverrideMimeType(const nsACString& aMimetype);
|
||||
nsresult GetMultipart(PRBool* aMultipart);
|
||||
nsresult SetMultipart(PRBool aMultipart);
|
||||
nsresult GetWithCredentials(PRBool* aWithCredentials);
|
||||
nsresult SetWithCredentials(PRBool aWithCredentials);
|
||||
|
||||
nsresult RunSyncEventLoop();
|
||||
|
||||
PRBool IsUploadEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
nsresult DispatchPrematureAbortEvents(PRUint32 aType,
|
||||
nsIDOMEventTarget* aTarget,
|
||||
ProgressInfo* aProgressInfo);
|
||||
|
||||
nsresult MaybeDispatchPrematureAbortEvents(PRBool aFromOpenRequest);
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsDOMWorkerXHR* mWorkerXHR;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> mWorkerXHRWN;
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsIXMLHttpRequest* mXHR;
|
||||
|
||||
// Always weak!
|
||||
nsXMLHttpRequest* mConcreteXHR;
|
||||
nsIXMLHttpRequestUpload* mUpload;
|
||||
|
||||
nsCOMPtr<nsIThread> mMainThread;
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRState> mLastXHRState;
|
||||
nsRefPtr<nsDOMWorkerXHREvent> mLastProgressOrLoadEvent;
|
||||
|
||||
SyncEventQueue* mSyncEventQueue;
|
||||
|
||||
PRInt32 mChannelID;
|
||||
|
||||
// Only touched on the worker thread!
|
||||
nsCOMPtr<nsIThread> mSyncXHRThread;
|
||||
|
||||
// Touched on more than one thread, protected by the worker's lock.
|
||||
nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> mSyncFinishedRunnable;
|
||||
|
||||
nsAutoPtr<ProgressInfo> mDownloadProgressInfo;
|
||||
nsAutoPtr<ProgressInfo> mUploadProgressInfo;
|
||||
|
||||
// Whether or not this object is owned by the real XHR object.
|
||||
PRPackedBool mOwnedByXHR;
|
||||
|
||||
PRPackedBool mWantUploadListeners;
|
||||
PRPackedBool mCanceled;
|
||||
|
||||
PRPackedBool mSyncRequest;
|
||||
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXY_H__ */
|
|
@ -1,76 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DOM Worker Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
onmessage = function(event) {
|
||||
let chromeURL = event.data.replace("test_chromeWorkerJSM.xul",
|
||||
"WorkerTest_badworker.js");
|
||||
|
||||
let mochitestURL = event.data.replace("test_chromeWorkerJSM.xul",
|
||||
"WorkerTest_badworker.js")
|
||||
.replace("chrome://mochitests/content/chrome",
|
||||
"http://mochi.test:8888/tests");
|
||||
|
||||
// We should be able to XHR to anything we want, including a chrome URL.
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", mochitestURL, false);
|
||||
xhr.send();
|
||||
|
||||
if (!xhr.responseText) {
|
||||
throw "Can't load script file via XHR!";
|
||||
}
|
||||
|
||||
// We shouldn't be able to make a ChromeWorker to a non-chrome URL.
|
||||
let worker = new ChromeWorker(mochitestURL);
|
||||
worker.onmessage = function(event) {
|
||||
throw event.data;
|
||||
};
|
||||
worker.onerror = function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// And we shouldn't be able to make a regular Worker to a non-chrome URL.
|
||||
worker = new Worker(mochitestURL);
|
||||
worker.onmessage = function(event) {
|
||||
throw event.data;
|
||||
};
|
||||
worker.onerror = function(event) {
|
||||
event.preventDefault();
|
||||
postMessage("Done");
|
||||
};
|
||||
worker.postMessage("Hi");
|
||||
};
|
||||
worker.postMessage("Hi");
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
onclose = function() {
|
||||
postMessage("closed");
|
||||
};
|
||||
|
||||
setTimeout(function() { close(); }, 1000);
|
|
@ -1,26 +0,0 @@
|
|||
var worker = new Worker("errorPropagation_worker2.js");
|
||||
|
||||
var errorCount = 0;
|
||||
worker.onerror = function(event) {
|
||||
switch (errorCount++) {
|
||||
case 0:
|
||||
case 1:
|
||||
// Let it propagate.
|
||||
break;
|
||||
case 2:
|
||||
// Stop and rethrow.
|
||||
event.preventDefault();
|
||||
throw event.message;
|
||||
break;
|
||||
case 3:
|
||||
event.preventDefault();
|
||||
postMessage(event.message);
|
||||
worker.onerror = null;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
onmessage = function(event) {
|
||||
worker.postMessage(event.data);
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
onmessage = function(event) {
|
||||
throw event.data;
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
var results = [];
|
||||
|
||||
function messageHandler(event) {
|
||||
results.push(parseInt(event.data));
|
||||
if (results.length == 2) {
|
||||
postMessage(results[0] + results[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function errorHandler(event) {
|
||||
throw event.data;
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
var n = parseInt(event.data);
|
||||
|
||||
if (n == 0 || n == 1) {
|
||||
postMessage(n);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 1; i <= 2; i++) {
|
||||
var worker = new Worker("fibonacci_worker.js");
|
||||
worker.onmessage = messageHandler;
|
||||
worker.onerror = errorHandler;
|
||||
worker.postMessage(n - i);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
function onmessage(event) {
|
||||
throw event.data;
|
||||
}
|
||||
|
||||
function onerror(event) {
|
||||
postMessage(event.message);
|
||||
event.preventDefault();
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
// Deliberate syntax error, should generate a worker exception!
|
||||
for (var index = 0; index < 100) {}
|
|
@ -1,2 +0,0 @@
|
|||
// Deliberate throw, should generate a worker exception!
|
||||
throw new Error("Bah!");
|
|
@ -1,4 +0,0 @@
|
|||
for (var string in self.location) {
|
||||
postMessage({ "string": string, "value": self.location[string] });
|
||||
}
|
||||
postMessage({"string": "testfinished", "value": self.location.toString()});
|
|
@ -1 +0,0 @@
|
|||
throw new Error("foo!");
|
|
@ -1,34 +0,0 @@
|
|||
onerror = function(event) {
|
||||
// Do nothing.
|
||||
};
|
||||
|
||||
// Pure JS recursion
|
||||
function recurse() {
|
||||
recurse();
|
||||
}
|
||||
|
||||
// JS -> C++ -> JS -> C++ recursion
|
||||
function recurse2() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
xhr.open("GET", "nonexistent.file");
|
||||
}
|
||||
xhr.open("GET", "nonexistent.file");
|
||||
postMessage("Done");
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
onmessage = function(event) {
|
||||
switch (++count) {
|
||||
case 1:
|
||||
recurse();
|
||||
break;
|
||||
case 2:
|
||||
recurse2();
|
||||
// Have to return here because we don't propagate exceptions from event
|
||||
// handlers!
|
||||
return;
|
||||
default:
|
||||
}
|
||||
throw "Never should have gotten here!";
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
var runCount = 0;
|
||||
var timeout;
|
||||
|
||||
onmessage = function() {
|
||||
run();
|
||||
timeout = setTimeout(run, 0);
|
||||
timeout = setTimeout(run, 5000);
|
||||
};
|
||||
|
||||
function run() {
|
||||
if (RegExp.$1) {
|
||||
throw "RegExp.$1 already set!";
|
||||
cancelTimeout(timeout);
|
||||
}
|
||||
|
||||
var match = /a(sd)f/.exec("asdf");
|
||||
if (!RegExp.$1) {
|
||||
throw "RegExp.$1 didn't get set!";
|
||||
cancelTimeout(timeout);
|
||||
}
|
||||
|
||||
if (++runCount == 3) {
|
||||
postMessage("done");
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
const workerURL = "relativeLoad_worker.js";
|
|
@ -1 +0,0 @@
|
|||
const workerSubURL = "subdir/relativeLoad_sub_worker.js";
|
|
@ -1,5 +0,0 @@
|
|||
const importSubURL = "relativeLoad_sub_import.js";
|
||||
|
||||
importScripts(importSubURL);
|
||||
|
||||
postMessage(workerSubURL);
|
|
@ -1,5 +0,0 @@
|
|||
const importURL = "relativeLoad_import.js";
|
||||
|
||||
importScripts(importURL);
|
||||
|
||||
postMessage(workerURL);
|
|
@ -1,26 +0,0 @@
|
|||
if (onerror !== undefined || typeof(onerror) != "undefined") {
|
||||
throw "Undefined onerror has bad type!";
|
||||
}
|
||||
|
||||
onerror = function(event) {
|
||||
if (!event.cancelable) {
|
||||
throw "Error event is not cancelable!";
|
||||
}
|
||||
|
||||
if (event.target != this) {
|
||||
throw "Error event is targeted at the wrong object!";
|
||||
}
|
||||
|
||||
if (event.message == "uncaught exception: This error should not make it back out") {
|
||||
event.preventDefault();
|
||||
postMessage("Done");
|
||||
}
|
||||
}
|
||||
|
||||
if (onerror === undefined || typeof(onerror) == "undefined") {
|
||||
throw "onerror has a bad type!";
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
throw event.data;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
var counter = 0;
|
||||
|
||||
setInterval(function() {
|
||||
postMessage(++counter);
|
||||
}, 100);
|
|
@ -1,97 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is DOM Worker tests.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- The Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2010
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Ben Turner <bent.mozilla@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<window title="DOM Worker Threads Test"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function test()
|
||||
{
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var worker = new ChromeWorker("chromeWorker_worker.js");
|
||||
worker.onmessage = function(event) {
|
||||
is(event.data, "Done!", "Wrong message!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
worker.onerror = function(event) {
|
||||
ok(false, "Worker had an error: " + event.message);
|
||||
worker.terminate();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Test passing a non-threadsafe wrapped native to the worker.
|
||||
var isupports =
|
||||
Components.classes["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsPRBool);
|
||||
|
||||
try {
|
||||
worker.postMessage(isupports);
|
||||
ok(false, "Passing non-threadsafe thing should throw!");
|
||||
}
|
||||
catch (e) {
|
||||
ok(true, "Passing non-threadsafe thing threw");
|
||||
}
|
||||
|
||||
// Test passing a wrapped native to the worker.
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService().newThread(0);
|
||||
|
||||
worker.postMessage(thread);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
<label id="test-result"/>
|
||||
</window>
|
|
@ -1,88 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is DOM Worker tests.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- The Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2010
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Ben Turner <bent.mozilla@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<window title="DOM Worker Threads Test"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function test()
|
||||
{
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
var wf = Cc["@mozilla.org/threads/workerfactory;1"]
|
||||
.createInstance(Ci.nsIWorkerFactory);
|
||||
|
||||
var worker = wf.newChromeWorker("chromeWorker_worker.js");
|
||||
worker.onmessage = function(event) {
|
||||
is(event.data, "Done!", "Wrong message!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
worker.onerror = function(event) {
|
||||
ok(false, "Worker had an error: " + event.message);
|
||||
worker.terminate();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Test passing a wrapped native to the worker.
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService().newThread(0);
|
||||
|
||||
worker.postMessage(thread);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
<label id="test-result"/>
|
||||
</window>
|
|
@ -1,90 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is DOM Worker tests.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- The Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2010
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Ben Turner <bent.mozilla@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<window title="DOM Worker Threads Test"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function test()
|
||||
{
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var worker;
|
||||
|
||||
function done()
|
||||
{
|
||||
worker = null;
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function messageCallback(event) {
|
||||
is(event.data, "Done", "Correct message");
|
||||
done();
|
||||
}
|
||||
|
||||
function errorCallback(event) {
|
||||
ok(false, "Worker had an error: " + event.message);
|
||||
done();
|
||||
}
|
||||
|
||||
Components.utils.import("chrome://mochitests/content/chrome/dom/src/threads/test/WorkerTest.jsm");
|
||||
|
||||
worker = WorkerTest.go(window.location.href, messageCallback,
|
||||
errorCallback);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
<label id="test-result"/>
|
||||
</window>
|
|
@ -1,107 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var errors = [
|
||||
"This exception should show up in the JS console",
|
||||
"This exception should make it to onerror",
|
||||
"This exception should too",
|
||||
"This exception should should show up in onmessage"
|
||||
];
|
||||
|
||||
var errorIndex = -1;
|
||||
|
||||
var worker = new Worker("errorPropagation_worker1.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
is(event.target, worker);
|
||||
isnot(-1, event.data.indexOf(errors[errorIndex]));
|
||||
ok(errorIndex == errors.length - 1, "Wrong number of errors seen!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function nextError() {
|
||||
worker.postMessage(errors[++errorIndex]);
|
||||
}
|
||||
|
||||
function errorHandler(event) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
is(event.target, worker);
|
||||
isnot(-1, event.message.indexOf(errors[errorIndex]));
|
||||
|
||||
switch (errorIndex) {
|
||||
case 1:
|
||||
consoleService.unregisterListener(consoleListener);
|
||||
consoleService.reset();
|
||||
consoleListener = null;
|
||||
nextError();
|
||||
break;
|
||||
case 2:
|
||||
nextError();
|
||||
break;
|
||||
default:
|
||||
ok(false, "Too many errors!");
|
||||
}
|
||||
}
|
||||
|
||||
var consoleListener = {
|
||||
count: 0,
|
||||
|
||||
observe: function(message) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
if (this.count++) {
|
||||
ok(false, "Seen too many errors!");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
is(message.message,
|
||||
'[JavaScript Error: "uncaught exception: This exception should show ' +
|
||||
'up in the JS console"]');
|
||||
worker.onerror = errorHandler;
|
||||
nextError();
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
if (iid.equals(Ci.nsIConsoleListener) ||
|
||||
iid.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Cr.NS_NOINTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
var consoleService =
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
|
||||
|
||||
consoleService.reset();
|
||||
consoleService.registerListener(consoleListener);
|
||||
|
||||
nextError();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads RegExp statics
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads RegExp statics</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
const WORKER_COUNT = 25;
|
||||
|
||||
var doneWorkers = 0;
|
||||
function onmessage(event) {
|
||||
if (++doneWorkers == WORKER_COUNT) {
|
||||
ok(true, "All messages received from workers");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function onerror(event) {
|
||||
ok(false, "Worker had an error: " + event.data);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
for (var i = 0; i < WORKER_COUNT; i++) {
|
||||
var worker = new Worker("regExpStatics_worker.js");
|
||||
worker.onmessage = onmessage;
|
||||
worker.onerror = onerror;
|
||||
worker.postMessage("start");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,44 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var errors = [
|
||||
"This exception should make it to onerror",
|
||||
"This error should not make it back out"
|
||||
];
|
||||
|
||||
var worker = new Worker("scopeOnerror_worker.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
ok(event.data == "Done");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
worker.onerror = function(event) {
|
||||
is(event.target, worker);
|
||||
is(event.message, "uncaught exception: " + errors[0]);
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
for (var index in errors) {
|
||||
worker.postMessage(errors[index]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var worker = new Worker("xpcom_worker.js");
|
||||
worker.onmessage = function(event) {
|
||||
is(event.data, "Done", "Correct message");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
worker.onerror = function(event) {
|
||||
ok(false, "Worker had an error: " + event.message);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
// Test passing a wrapped native to the worker.
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService().newThread(0);
|
||||
|
||||
try {
|
||||
worker.postMessage(thread);
|
||||
ok(false, "postMessage with a wrapped native should fail!");
|
||||
}
|
||||
catch(e) {
|
||||
ok(true, "postMessage with a wrapped native failed");
|
||||
}
|
||||
|
||||
worker.postMessage("Hi");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// Syntax error
|
||||
onmessage = function(event) {
|
||||
for (var i = 0; i < 10) { }
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
// Bad function error
|
||||
onmessage = function(event) {
|
||||
foopy();
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
// Unhandled exception in body
|
||||
onmessage = function(event) {
|
||||
};
|
||||
|
||||
throw new Error("Bah!");
|
|
@ -1,4 +0,0 @@
|
|||
// Throwing message listener
|
||||
onmessage = function(event) {
|
||||
throw new Error("Bah!");
|
||||
};
|
|
@ -1,52 +0,0 @@
|
|||
var events = [];
|
||||
|
||||
function runTest() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
function pushEvent(event) {
|
||||
var str = event.type + "(" + xhr.readyState + ", '" + xhr.responseText +
|
||||
"'";
|
||||
if (typeof event.loaded != "undefined") {
|
||||
str += ", progressEvent";
|
||||
}
|
||||
str += ")";
|
||||
events.push(str);
|
||||
}
|
||||
|
||||
xhr.onerror = function(event) {
|
||||
dump("Error: " + xhr.statusText + "\n");
|
||||
}
|
||||
|
||||
xhr.onload = function(event) {
|
||||
pushEvent(event);
|
||||
postMessage(events);
|
||||
};
|
||||
|
||||
xhr.onabort = function(event) {
|
||||
pushEvent(event);
|
||||
postMessage(events);
|
||||
};
|
||||
|
||||
var count = 0;
|
||||
xhr.onreadystatechange = function(event) {
|
||||
pushEvent(event);
|
||||
if (++count == 3) {
|
||||
xhr.abort();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.open("GET", "testXHR.txt");
|
||||
xhr.overrideMimeType("text/plain");
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function messageListener(event) {
|
||||
switch (event.data) {
|
||||
case "start":
|
||||
runTest();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("message", messageListener, false);
|
|
@ -1,18 +0,0 @@
|
|||
var exception;
|
||||
try {
|
||||
var xpcom = XPCOM;
|
||||
}
|
||||
catch(e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
if (!exception) {
|
||||
throw "Worker shouldn't be able to access the XPCOM object!";
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
if (event.data != "Hi") {
|
||||
throw "Bad message!";
|
||||
}
|
||||
postMessage("Done");
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ChromeWorkerScope.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef BUILD_CTYPES
|
||||
char*
|
||||
UnicodeToNative(JSContext* aCx, const jschar* aSource, size_t aSourceLen)
|
||||
{
|
||||
nsDependentString unicode(aSource, aSourceLen);
|
||||
|
||||
nsCAutoString native;
|
||||
if (NS_FAILED(NS_CopyUnicodeToNative(unicode, native))) {
|
||||
JS_ReportError(aCx, "Could not convert string to native charset!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
char* result = static_cast<char*>(JS_malloc(aCx, native.Length() + 1));
|
||||
if (!result) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
memcpy(result, native.get(), native.Length());
|
||||
result[native.Length()] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
JSCTypesCallbacks gCTypesCallbacks = {
|
||||
UnicodeToNative
|
||||
};
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace chromeworker {
|
||||
|
||||
bool
|
||||
DefineChromeWorkerFunctions(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
#ifdef BUILD_CTYPES
|
||||
jsval ctypes;
|
||||
if (!JS_InitCTypesClass(aCx, aGlobal) ||
|
||||
!JS_GetProperty(aCx, aGlobal, "ctypes", &ctypes) ||
|
||||
!JS_SetCTypesCallbacks(aCx, JSVAL_TO_OBJECT(ctypes), &gCTypesCallbacks)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace chromeworker
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_workers_chromeworkerscope_h__
|
||||
#define mozilla_dom_workers_chromeworkerscope_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace chromeworker {
|
||||
|
||||
bool
|
||||
DefineChromeWorkerFunctions(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
} // namespace chromeworker
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_chromeworkerscope_h__
|
|
@ -0,0 +1,248 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "EventTarget.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#include "WorkerInlines.h"
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
using mozilla::dom::workers::events::EventTarget;
|
||||
|
||||
namespace {
|
||||
|
||||
#define DECL_EVENTTARGET_CLASS(_varname, _name) \
|
||||
JSClass _varname = { \
|
||||
_name, 0, \
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, \
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS \
|
||||
};
|
||||
|
||||
DECL_EVENTTARGET_CLASS(gClass, "EventTarget")
|
||||
DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget")
|
||||
|
||||
#undef DECL_EVENTTARGET_CLASS
|
||||
|
||||
inline
|
||||
EventTarget*
|
||||
GetPrivate(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return GetJSPrivateSafeish<EventTarget>(aCx, aObj);
|
||||
}
|
||||
|
||||
JSBool
|
||||
Construct(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
|
||||
gClass.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSFunctionSpec gFunctions[] = {
|
||||
JS_FN("addEventListener", EventTarget::AddEventListener, 3, JSPROP_ENUMERATE),
|
||||
JS_FN("removeEventListener", EventTarget::RemoveEventListener, 3,
|
||||
JSPROP_ENUMERATE),
|
||||
JS_FN("dispatchEvent", EventTarget::DispatchEvent, 1, JSPROP_ENUMERATE),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
EventTarget::EventTarget()
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::events::EventTarget);
|
||||
}
|
||||
|
||||
EventTarget::~EventTarget()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::dom::workers::events::EventTarget);
|
||||
}
|
||||
|
||||
bool
|
||||
EventTarget::GetEventListenerOnEventTarget(JSContext* aCx, const char* aType,
|
||||
jsval* aVp)
|
||||
{
|
||||
JSString* type = JS_InternString(aCx, aType);
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mListenerManager.GetEventListener(aCx, type, aVp);
|
||||
}
|
||||
|
||||
bool
|
||||
EventTarget::SetEventListenerOnEventTarget(JSContext* aCx, const char* aType,
|
||||
jsval* aVp)
|
||||
{
|
||||
JSString* type = JS_InternString(aCx, aType);
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject* listenerObj;
|
||||
if (!JS_ValueToObject(aCx, *aVp, &listenerObj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mListenerManager.SetEventListener(aCx, type, *aVp);
|
||||
}
|
||||
|
||||
// static
|
||||
EventTarget*
|
||||
EventTarget::FromJSObject(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return GetPrivate(aCx, aObj);
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
EventTarget::AddEventListener(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
|
||||
|
||||
EventTarget* self = GetPrivate(aCx, obj);
|
||||
JS_ASSERT(self);
|
||||
|
||||
JSString* type;
|
||||
JSObject* listener;
|
||||
JSBool capturing = false, wantsUntrusted = false;
|
||||
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "So/bb", &type,
|
||||
&listener, &capturing, &wantsUntrusted)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!listener) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self->mListenerManager.AddEventListener(aCx, type,
|
||||
JS_ARGV(aCx, aVp)[1],
|
||||
capturing, wantsUntrusted);
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
EventTarget::RemoveEventListener(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
|
||||
|
||||
EventTarget* self = GetPrivate(aCx, obj);
|
||||
JS_ASSERT(self);
|
||||
|
||||
JSString* type;
|
||||
JSObject* listener;
|
||||
JSBool capturing = false;
|
||||
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "So/b", &type,
|
||||
&listener, &capturing)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!listener) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self->mListenerManager.RemoveEventListener(aCx, type,
|
||||
JS_ARGV(aCx, aVp)[1],
|
||||
capturing);
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
EventTarget::DispatchEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
|
||||
|
||||
EventTarget* self = GetPrivate(aCx, obj);
|
||||
JS_ASSERT(self);
|
||||
|
||||
JSObject* event;
|
||||
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "o", &event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool preventDefaultCalled;
|
||||
if (!self->mListenerManager.DispatchEvent(aCx, obj, event,
|
||||
&preventDefaultCalled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_SET_RVAL(aCx, aVp, BOOLEAN_TO_JSVAL(preventDefaultCalled));
|
||||
return true;
|
||||
}
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace events {
|
||||
|
||||
JSObject*
|
||||
InitEventTargetClass(JSContext* aCx, JSObject* aObj, bool aMainRuntime)
|
||||
{
|
||||
if (aMainRuntime) {
|
||||
// XXX Hack to prevent instanceof checks failing on the main thread.
|
||||
jsval windowEventTarget;
|
||||
if (!JS_GetProperty(aCx, aObj, gClass.name, &windowEventTarget)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(windowEventTarget)) {
|
||||
jsval protoVal;
|
||||
if (!JS_GetProperty(aCx, JSVAL_TO_OBJECT(windowEventTarget), "prototype",
|
||||
&protoVal)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(protoVal)) {
|
||||
return JS_InitClass(aCx, aObj, JSVAL_TO_OBJECT(protoVal),
|
||||
&gMainThreadClass, Construct, 0, NULL, gFunctions,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JS_InitClass(aCx, aObj, NULL, &gClass, Construct, 0, NULL,
|
||||
gFunctions, NULL, NULL);
|
||||
}
|
||||
|
||||
} // namespace events
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_workers_eventtarget_h__
|
||||
#define mozilla_dom_workers_eventtarget_h__
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "ListenerManager.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace events {
|
||||
|
||||
class EventTarget : public PrivatizableBase
|
||||
{
|
||||
ListenerManager mListenerManager;
|
||||
|
||||
protected:
|
||||
EventTarget();
|
||||
~EventTarget();
|
||||
|
||||
void
|
||||
TraceInstance(JSTracer* aTrc)
|
||||
{
|
||||
mListenerManager.Trace(aTrc);
|
||||
}
|
||||
|
||||
void
|
||||
FinalizeInstance(JSContext* aCx)
|
||||
{
|
||||
mListenerManager.Finalize(aCx);
|
||||
}
|
||||
|
||||
bool
|
||||
GetEventListenerOnEventTarget(JSContext* aCx, const char* aType, jsval* aVp);
|
||||
|
||||
bool
|
||||
SetEventListenerOnEventTarget(JSContext* aCx, const char* aType, jsval* aVp);
|
||||
|
||||
public:
|
||||
static EventTarget*
|
||||
FromJSObject(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
static JSBool
|
||||
AddEventListener(JSContext* aCx, uintN aArgc, jsval* aVp);
|
||||
|
||||
static JSBool
|
||||
RemoveEventListener(JSContext* aCx, uintN aArgc, jsval* aVp);
|
||||
|
||||
static JSBool
|
||||
DispatchEvent(JSContext* aCx, uintN aArgc, jsval* aVp);
|
||||
|
||||
bool
|
||||
HasListeners()
|
||||
{
|
||||
return mListenerManager.HasListeners();
|
||||
}
|
||||
|
||||
bool
|
||||
HasListenersForType(JSContext* aCx, JSString* aType)
|
||||
{
|
||||
return mListenerManager.HasListenersForType(aCx, aType);
|
||||
}
|
||||
};
|
||||
|
||||
JSObject*
|
||||
InitEventTargetClass(JSContext* aCx, JSObject* aGlobal, bool aMainRuntime);
|
||||
|
||||
} // namespace events
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_eventtarget_h__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,88 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_workers_events_h__
|
||||
#define mozilla_dom_workers_events_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
class JSAutoStructuredCloneBuffer;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace events {
|
||||
|
||||
bool
|
||||
InitClasses(JSContext* aCx, JSObject* aGlobal, bool aMainRuntime);
|
||||
|
||||
JSObject*
|
||||
CreateGenericEvent(JSContext* aCx, JSString* aType, bool aBubbles,
|
||||
bool aCancelable, bool aMainRuntime);
|
||||
|
||||
JSObject*
|
||||
CreateMessageEvent(JSContext* aCx, JSAutoStructuredCloneBuffer& aData,
|
||||
bool aMainRuntime);
|
||||
|
||||
JSObject*
|
||||
CreateErrorEvent(JSContext* aCx, JSString* aMessage, JSString* aFilename,
|
||||
uint32 aLineNumber, bool aMainRuntime);
|
||||
|
||||
JSObject*
|
||||
CreateProgressEvent(JSContext* aCx, JSString* aType, bool aLengthComputable,
|
||||
jsdouble aLoaded, jsdouble aTotal);
|
||||
|
||||
bool
|
||||
IsSupportedEventClass(JSContext* aCx, JSObject* aEvent);
|
||||
|
||||
bool
|
||||
SetEventTarget(JSContext* aCx, JSObject* aEvent, JSObject* aTarget);
|
||||
|
||||
bool
|
||||
EventWasCanceled(JSContext* aCx, JSObject* aEvent);
|
||||
|
||||
bool
|
||||
DispatchEventToTarget(JSContext* aCx, JSObject* aTarget, JSObject* aEvent,
|
||||
bool* aPreventDefaultCalled);
|
||||
|
||||
} // namespace events
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_events_h__ */
|
|
@ -0,0 +1,303 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "Exceptions.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsprf.h"
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#include "WorkerInlines.h"
|
||||
|
||||
#define PROPERTY_FLAGS \
|
||||
JSPROP_ENUMERATE | JSPROP_SHARED
|
||||
|
||||
#define CONSTANT_FLAGS \
|
||||
JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_PERMANENT | JSPROP_READONLY
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
class DOMException : public PrivatizableBase
|
||||
{
|
||||
static JSClass sClass;
|
||||
static JSPropertySpec sProperties[];
|
||||
static JSFunctionSpec sFunctions[];
|
||||
static JSPropertySpec sStaticProperties[];
|
||||
|
||||
enum SLOT {
|
||||
SLOT_code = 0,
|
||||
SLOT_name,
|
||||
|
||||
SLOT_COUNT
|
||||
};
|
||||
|
||||
public:
|
||||
static JSObject*
|
||||
InitClass(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
JSObject* proto = JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0,
|
||||
sProperties, sFunctions, sStaticProperties,
|
||||
NULL);
|
||||
if (proto && !JS_DefineProperties(aCx, proto, sStaticProperties)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
Create(JSContext* aCx, intN aCode);
|
||||
|
||||
private:
|
||||
DOMException()
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::exceptions::DOMException);
|
||||
}
|
||||
|
||||
~DOMException()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::dom::workers::exceptions::DOMException);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Construct(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
|
||||
sClass.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
Finalize(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
JS_ASSERT(JS_GET_CLASS(aCx, aObj) == &sClass);
|
||||
delete GetJSPrivateSafeish<DOMException>(aCx, aObj);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ToString(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
|
||||
|
||||
JSClass* classPtr;
|
||||
if (!obj || ((classPtr = JS_GET_CLASS(aCx, obj)) != &sClass)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO, sClass.name, "toString",
|
||||
classPtr ? classPtr->name : "object");
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[100];
|
||||
JS_snprintf(buf, sizeof(buf), "%s: ", sClass.name);
|
||||
|
||||
JSString* classString = JS_NewStringCopyZ(aCx, buf);
|
||||
if (!classString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval name;
|
||||
if (!JS_GetReservedSlot(aCx, obj, SLOT_name, &name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(JSVAL_IS_STRING(name));
|
||||
|
||||
JSString* out = JS_ConcatStrings(aCx, classString, JSVAL_TO_STRING(name));
|
||||
if (!out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(out));
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_INT(aIdval));
|
||||
|
||||
int32 slot = JSID_TO_INT(aIdval);
|
||||
|
||||
JSClass* classPtr = JS_GET_CLASS(aCx, aObj);
|
||||
|
||||
if (classPtr != &sClass ||
|
||||
!GetJSPrivateSafeish<DOMException>(aCx, aObj)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO, sClass.name,
|
||||
sProperties[slot].name,
|
||||
classPtr ? classPtr->name : "object");
|
||||
return false;
|
||||
}
|
||||
|
||||
return JS_GetReservedSlot(aCx, aObj, slot, aVp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetConstant(JSContext* aCx, JSObject* aObj, jsid idval, jsval* aVp)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_INT(idval));
|
||||
*aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JSClass DOMException::sClass = {
|
||||
"DOMException",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
|
||||
JSPropertySpec DOMException::sProperties[] = {
|
||||
{ "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
JSFunctionSpec DOMException::sFunctions[] = {
|
||||
JS_FN("toString", ToString, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
JSPropertySpec DOMException::sStaticProperties[] = {
|
||||
|
||||
#define EXCEPTION_ENTRY(_name) \
|
||||
{ #_name, _name, CONSTANT_FLAGS, GetConstant, NULL },
|
||||
|
||||
EXCEPTION_ENTRY(INDEX_SIZE_ERR)
|
||||
EXCEPTION_ENTRY(DOMSTRING_SIZE_ERR)
|
||||
EXCEPTION_ENTRY(HIERARCHY_REQUEST_ERR)
|
||||
EXCEPTION_ENTRY(WRONG_DOCUMENT_ERR)
|
||||
EXCEPTION_ENTRY(INVALID_CHARACTER_ERR)
|
||||
EXCEPTION_ENTRY(NO_DATA_ALLOWED_ERR)
|
||||
EXCEPTION_ENTRY(NO_MODIFICATION_ALLOWED_ERR)
|
||||
EXCEPTION_ENTRY(NOT_FOUND_ERR)
|
||||
EXCEPTION_ENTRY(NOT_SUPPORTED_ERR)
|
||||
EXCEPTION_ENTRY(INUSE_ATTRIBUTE_ERR)
|
||||
EXCEPTION_ENTRY(INVALID_STATE_ERR)
|
||||
EXCEPTION_ENTRY(SYNTAX_ERR)
|
||||
EXCEPTION_ENTRY(INVALID_MODIFICATION_ERR)
|
||||
EXCEPTION_ENTRY(NAMESPACE_ERR)
|
||||
EXCEPTION_ENTRY(INVALID_ACCESS_ERR)
|
||||
EXCEPTION_ENTRY(VALIDATION_ERR)
|
||||
EXCEPTION_ENTRY(TYPE_MISMATCH_ERR)
|
||||
EXCEPTION_ENTRY(SECURITY_ERR)
|
||||
EXCEPTION_ENTRY(NETWORK_ERR)
|
||||
EXCEPTION_ENTRY(ABORT_ERR)
|
||||
EXCEPTION_ENTRY(URL_MISMATCH_ERR)
|
||||
EXCEPTION_ENTRY(QUOTA_EXCEEDED_ERR)
|
||||
EXCEPTION_ENTRY(TIMEOUT_ERR)
|
||||
EXCEPTION_ENTRY(INVALID_NODE_TYPE_ERR)
|
||||
EXCEPTION_ENTRY(DATA_CLONE_ERR)
|
||||
|
||||
#undef EXCEPTION_ENTRY
|
||||
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
// static
|
||||
JSObject*
|
||||
DOMException::Create(JSContext* aCx, intN aCode)
|
||||
{
|
||||
JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
|
||||
if (!obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t foundIndex = size_t(-1);
|
||||
for (size_t index = 0;
|
||||
index < JS_ARRAY_LENGTH(sStaticProperties) - 1;
|
||||
index++) {
|
||||
if (sStaticProperties[index].tinyid == aCode) {
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(foundIndex != size_t(-1));
|
||||
|
||||
JSString* name = JS_NewStringCopyZ(aCx, sStaticProperties[foundIndex].name);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(aCx, obj, SLOT_code, INT_TO_JSVAL(aCode)) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_name, STRING_TO_JSVAL(name))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DOMException* priv = new DOMException();
|
||||
if (!SetJSPrivateSafeish(aCx, obj, priv)) {
|
||||
delete priv;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace exceptions {
|
||||
|
||||
bool
|
||||
InitClasses(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return !!DOMException::InitClass(aCx, aGlobal);
|
||||
}
|
||||
|
||||
void
|
||||
ThrowDOMExceptionForCode(JSContext* aCx, intN aCode)
|
||||
{
|
||||
JSObject* exception = DOMException::Create(aCx, aCode);
|
||||
JS_ASSERT(exception);
|
||||
|
||||
JS_SetPendingException(aCx, OBJECT_TO_JSVAL(exception));
|
||||
}
|
||||
|
||||
} // namespace exceptions
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -11,15 +12,15 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DOM Worker Tests.
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -35,34 +36,51 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Test XPCOM.getService()
|
||||
let threadMan = XPCOM.getService("@mozilla.org/thread-manager;1");
|
||||
let mainThread = threadMan.mainThread;
|
||||
if (mainThread.isOnCurrentThread()) {
|
||||
throw "Thread manager is lying to us!";
|
||||
}
|
||||
#ifndef mozilla_dom_workers_exceptions_h__
|
||||
#define mozilla_dom_workers_exceptions_h__
|
||||
|
||||
// Test XPCOM.createInstance
|
||||
let threadPool = XPCOM.createInstance("@mozilla.org/thread-pool;1");
|
||||
threadPool.shutdown();
|
||||
#include "Workers.h"
|
||||
|
||||
let notThreadsafe;
|
||||
try {
|
||||
notThreadsafe = XPCOM.createInstance("@mozilla.org/supports-PRBool;1");
|
||||
}
|
||||
catch(e) { }
|
||||
#include "jspubtd.h"
|
||||
|
||||
if (notThreadsafe) {
|
||||
throw "Shouldn't be able to create non-threadsafe component!";
|
||||
}
|
||||
#define INDEX_SIZE_ERR 1
|
||||
#define DOMSTRING_SIZE_ERR 2
|
||||
#define HIERARCHY_REQUEST_ERR 3
|
||||
#define WRONG_DOCUMENT_ERR 4
|
||||
#define INVALID_CHARACTER_ERR 5
|
||||
#define NO_DATA_ALLOWED_ERR 6
|
||||
#define NO_MODIFICATION_ALLOWED_ERR 7
|
||||
#define NOT_FOUND_ERR 8
|
||||
#define NOT_SUPPORTED_ERR 9
|
||||
#define INUSE_ATTRIBUTE_ERR 10
|
||||
#define INVALID_STATE_ERR 11
|
||||
#define SYNTAX_ERR 12
|
||||
#define INVALID_MODIFICATION_ERR 13
|
||||
#define NAMESPACE_ERR 14
|
||||
#define INVALID_ACCESS_ERR 15
|
||||
#define VALIDATION_ERR 16
|
||||
#define TYPE_MISMATCH_ERR 17
|
||||
#define SECURITY_ERR 18
|
||||
#define NETWORK_ERR 19
|
||||
#define ABORT_ERR 20
|
||||
#define URL_MISMATCH_ERR 21
|
||||
#define QUOTA_EXCEEDED_ERR 22
|
||||
#define TIMEOUT_ERR 23
|
||||
#define INVALID_NODE_TYPE_ERR 24
|
||||
#define DATA_CLONE_ERR 25
|
||||
|
||||
function onmessage(event) {
|
||||
// Test passing wrapped natives from the main thread.
|
||||
event.data.shutdown();
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
let worker = new ChromeWorker("chromeWorker_subworker.js");
|
||||
worker.onmessage = function(event) {
|
||||
postMessage(event.data);
|
||||
}
|
||||
worker.postMessage("Go");
|
||||
}
|
||||
namespace exceptions {
|
||||
|
||||
bool
|
||||
InitClasses(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
void
|
||||
ThrowDOMExceptionForCode(JSContext* aCx, intN aCode);
|
||||
|
||||
} // namespace exceptions
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_exceptions_h__
|
|
@ -0,0 +1,458 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ListenerManager.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsvector.h"
|
||||
|
||||
#include "Events.h"
|
||||
|
||||
using mozilla::dom::workers::events::ListenerManager;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Listener;
|
||||
|
||||
struct ListenerCollection : PRCList
|
||||
{
|
||||
static ListenerCollection*
|
||||
Add(JSContext* aCx, ListenerCollection* aCollectionHead, jsid aTypeId)
|
||||
{
|
||||
ListenerCollection* collection =
|
||||
static_cast<ListenerCollection*>(JS_malloc(aCx,
|
||||
sizeof(ListenerCollection)));
|
||||
if (!collection) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PR_APPEND_LINK(collection, aCollectionHead);
|
||||
|
||||
collection->mTypeId = aTypeId;
|
||||
PR_INIT_CLIST(&collection->mListenerHead);
|
||||
return collection;
|
||||
}
|
||||
|
||||
static void
|
||||
Remove(JSContext* aCx, ListenerCollection* aCollection)
|
||||
{
|
||||
PR_REMOVE_LINK(aCollection);
|
||||
JS_free(aCx, aCollection);
|
||||
}
|
||||
|
||||
jsid mTypeId;
|
||||
PRCList mListenerHead;
|
||||
};
|
||||
|
||||
struct Listener : PRCList
|
||||
{
|
||||
static Listener*
|
||||
Add(JSContext* aCx, Listener* aListenerHead, jsval aListenerVal,
|
||||
ListenerManager::Phase aPhase, bool aWantsUntrusted)
|
||||
{
|
||||
Listener* listener =
|
||||
static_cast<Listener*>(JS_malloc(aCx, sizeof(Listener)));
|
||||
if (!listener) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PR_APPEND_LINK(listener, aListenerHead);
|
||||
|
||||
listener->mListenerVal = aListenerVal;
|
||||
listener->mPhase = aPhase;
|
||||
listener->mWantsUntrusted = aWantsUntrusted;
|
||||
return listener;
|
||||
}
|
||||
|
||||
static void
|
||||
Remove(JSContext* aCx, Listener* aListener)
|
||||
{
|
||||
PR_REMOVE_LINK(aListener);
|
||||
JS_free(aCx, aListener);
|
||||
}
|
||||
|
||||
jsval mListenerVal;
|
||||
ListenerManager::Phase mPhase;
|
||||
bool mWantsUntrusted;
|
||||
};
|
||||
|
||||
void
|
||||
DestroyList(JSContext* aCx, PRCList* aListHead)
|
||||
{
|
||||
for (PRCList* elem = PR_NEXT_LINK(aListHead); elem != aListHead; ) {
|
||||
PRCList* nextElem = PR_NEXT_LINK(elem);
|
||||
JS_free(aCx, elem);
|
||||
elem = nextElem;
|
||||
}
|
||||
}
|
||||
|
||||
ListenerCollection*
|
||||
GetCollectionForType(PRCList* aHead, jsid aTypeId)
|
||||
{
|
||||
for (PRCList* elem = PR_NEXT_LINK(aHead);
|
||||
elem != aHead;
|
||||
elem = PR_NEXT_LINK(elem)) {
|
||||
ListenerCollection* collection = static_cast<ListenerCollection*>(elem);
|
||||
if (collection->mTypeId == aTypeId) {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#ifdef DEBUG
|
||||
ListenerManager::~ListenerManager()
|
||||
{
|
||||
JS_ASSERT(PR_CLIST_IS_EMPTY(&mCollectionHead));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ListenerManager::TraceInternal(JSTracer* aTrc)
|
||||
{
|
||||
JS_ASSERT(!PR_CLIST_IS_EMPTY(&mCollectionHead));
|
||||
|
||||
for (PRCList* collectionElem = PR_NEXT_LINK(&mCollectionHead);
|
||||
collectionElem != &mCollectionHead;
|
||||
collectionElem = PR_NEXT_LINK(collectionElem)) {
|
||||
ListenerCollection* collection =
|
||||
static_cast<ListenerCollection*>(collectionElem);
|
||||
|
||||
for (PRCList* listenerElem = PR_NEXT_LINK(&collection->mListenerHead);
|
||||
listenerElem != &collection->mListenerHead;
|
||||
listenerElem = PR_NEXT_LINK(listenerElem)) {
|
||||
JS_CALL_VALUE_TRACER(aTrc,
|
||||
static_cast<Listener*>(listenerElem)->mListenerVal,
|
||||
"EventListenerManager listener value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ListenerManager::FinalizeInternal(JSContext* aCx)
|
||||
{
|
||||
JS_ASSERT(!PR_CLIST_IS_EMPTY(&mCollectionHead));
|
||||
|
||||
for (PRCList* elem = PR_NEXT_LINK(&mCollectionHead);
|
||||
elem != &mCollectionHead;
|
||||
elem = PR_NEXT_LINK(elem)) {
|
||||
DestroyList(aCx, &static_cast<ListenerCollection*>(elem)->mListenerHead);
|
||||
}
|
||||
|
||||
DestroyList(aCx, &mCollectionHead);
|
||||
|
||||
#ifdef DEBUG
|
||||
PR_INIT_CLIST(&mCollectionHead);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ListenerManager::Add(JSContext* aCx, JSString* aType, jsval aListenerVal,
|
||||
Phase aPhase, bool aWantsUntrusted)
|
||||
{
|
||||
aType = JS_InternJSString(aCx, aType);
|
||||
if (!aType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(aListenerVal)) {
|
||||
JS_ReportError(aCx, "Bad listener!");
|
||||
return false;
|
||||
}
|
||||
|
||||
jsid typeId = INTERNED_STRING_TO_JSID(aCx, aType);
|
||||
|
||||
ListenerCollection* collection =
|
||||
GetCollectionForType(&mCollectionHead, typeId);
|
||||
if (!collection) {
|
||||
ListenerCollection* head =
|
||||
static_cast<ListenerCollection*>(&mCollectionHead);
|
||||
collection = ListenerCollection::Add(aCx, head, typeId);
|
||||
if (!collection) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (PRCList* elem = PR_NEXT_LINK(&collection->mListenerHead);
|
||||
elem != &collection->mListenerHead;
|
||||
elem = PR_NEXT_LINK(elem)) {
|
||||
Listener* listener = static_cast<Listener*>(elem);
|
||||
if (listener->mListenerVal == aListenerVal && listener->mPhase == aPhase) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Listener* listener =
|
||||
Listener::Add(aCx, static_cast<Listener*>(&collection->mListenerHead),
|
||||
aListenerVal, aPhase, aWantsUntrusted);
|
||||
if (!listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ListenerManager::Remove(JSContext* aCx, JSString* aType, jsval aListenerVal,
|
||||
Phase aPhase, bool aClearEmpty)
|
||||
{
|
||||
aType = JS_InternJSString(aCx, aType);
|
||||
if (!aType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ListenerCollection* collection =
|
||||
GetCollectionForType(&mCollectionHead, INTERNED_STRING_TO_JSID(aCx, aType));
|
||||
if (!collection) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (PRCList* elem = PR_NEXT_LINK(&collection->mListenerHead);
|
||||
elem != &collection->mListenerHead;
|
||||
elem = PR_NEXT_LINK(elem)) {
|
||||
Listener* listener = static_cast<Listener*>(elem);
|
||||
if (listener->mListenerVal == aListenerVal && listener->mPhase == aPhase) {
|
||||
Listener::Remove(aCx, listener);
|
||||
if (aClearEmpty && PR_CLIST_IS_EMPTY(&collection->mListenerHead)) {
|
||||
ListenerCollection::Remove(aCx, collection);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ListenerManager::SetEventListener(JSContext* aCx, JSString* aType,
|
||||
jsval aListener)
|
||||
{
|
||||
jsval existing;
|
||||
if (!GetEventListener(aCx, aType, &existing)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_VOID(existing) &&
|
||||
!Remove(aCx, aType, existing, Onfoo, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return JSVAL_IS_VOID(aListener) || JSVAL_IS_NULL(aListener) ?
|
||||
true :
|
||||
Add(aCx, aType, aListener, Onfoo, false);
|
||||
}
|
||||
|
||||
bool
|
||||
ListenerManager::GetEventListener(JSContext* aCx, JSString* aType,
|
||||
jsval* aListenerVal)
|
||||
{
|
||||
if (PR_CLIST_IS_EMPTY(&mCollectionHead)) {
|
||||
*aListenerVal = JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
|
||||
aType = JS_InternJSString(aCx, aType);
|
||||
if (!aType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jsid typeId = INTERNED_STRING_TO_JSID(aCx, aType);
|
||||
|
||||
ListenerCollection* collection =
|
||||
GetCollectionForType(&mCollectionHead, typeId);
|
||||
if (collection) {
|
||||
for (PRCList* elem = PR_PREV_LINK(&collection->mListenerHead);
|
||||
elem != &collection->mListenerHead;
|
||||
elem = PR_NEXT_LINK(elem)) {
|
||||
Listener* listener = static_cast<Listener*>(elem);
|
||||
if (listener->mPhase == Onfoo) {
|
||||
*aListenerVal = listener->mListenerVal;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*aListenerVal = JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ListenerManager::DispatchEvent(JSContext* aCx, JSObject* aTarget,
|
||||
JSObject* aEvent, bool* aPreventDefaultCalled)
|
||||
{
|
||||
if (!events::IsSupportedEventClass(aCx, aEvent)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_METHOD,
|
||||
"EventTarget", "dispatchEvent", "Event object");
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval val;
|
||||
if (!JS_GetProperty(aCx, aEvent, "target", &val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_NULL(val)) {
|
||||
// Already has a target, must be recursively dispatched. Throw.
|
||||
JS_ReportError(aCx, "Cannot recursively dispatch the same event!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PR_CLIST_IS_EMPTY(&mCollectionHead)) {
|
||||
*aPreventDefaultCalled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSString* eventType;
|
||||
JSBool eventIsTrusted;
|
||||
|
||||
if (!JS_GetProperty(aCx, aEvent, "type", &val) ||
|
||||
!(eventType = JS_ValueToString(aCx, val)) ||
|
||||
!(eventType = JS_InternJSString(aCx, eventType))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have already ensure that the event is one of our types of events so
|
||||
// there is no need to worry about this property being faked.
|
||||
if (!JS_GetProperty(aCx, aEvent, "isTrusted", &val) ||
|
||||
!JS_ValueToBoolean(aCx, val, &eventIsTrusted)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ListenerCollection* collection =
|
||||
GetCollectionForType(&mCollectionHead,
|
||||
INTERNED_STRING_TO_JSID(aCx, eventType));
|
||||
if (!collection) {
|
||||
*aPreventDefaultCalled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
js::ContextAllocPolicy ap(aCx);
|
||||
js::Vector<jsval, 10, js::ContextAllocPolicy> listeners(ap);
|
||||
|
||||
for (PRCList* elem = PR_NEXT_LINK(&collection->mListenerHead);
|
||||
elem != &collection->mListenerHead;
|
||||
elem = PR_NEXT_LINK(elem)) {
|
||||
Listener* listener = static_cast<Listener*>(elem);
|
||||
|
||||
// Listeners that don't want untrusted events will be skipped if this is an
|
||||
// untrusted event.
|
||||
if ((eventIsTrusted || listener->mWantsUntrusted) &&
|
||||
!listeners.append(listener->mListenerVal)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (listeners.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!events::SetEventTarget(aCx, aEvent, aTarget)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < listeners.length(); index++) {
|
||||
// If anything fails in here we want to report the exception and continue on
|
||||
// to the next listener rather than bailing out. If something fails and
|
||||
// does not set an exception then we bail out entirely as we've either run
|
||||
// out of memory or the operation callback has indicated that we should
|
||||
// stop running.
|
||||
|
||||
jsval listenerVal = listeners[index];
|
||||
|
||||
JSObject* listenerObj;
|
||||
if (!JS_ValueToObject(aCx, listenerVal, &listenerObj)) {
|
||||
if (!JS_ReportPendingException(aCx)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
static const char sHandleEventChars[] = "handleEvent";
|
||||
|
||||
JSBool hasHandleEvent;
|
||||
if (!JS_HasProperty(aCx, listenerObj, sHandleEventChars, &hasHandleEvent)) {
|
||||
if (!JS_ReportPendingException(aCx)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasHandleEvent) {
|
||||
if (!JS_GetProperty(aCx, listenerObj, sHandleEventChars, &listenerVal)) {
|
||||
if (!JS_ReportPendingException(aCx)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
jsval argv[] = { OBJECT_TO_JSVAL(aEvent) };
|
||||
jsval rval = JSVAL_VOID;
|
||||
if (!JS_CallFunctionValue(aCx, aTarget, listenerVal, JS_ARRAY_LENGTH(argv),
|
||||
argv, &rval)) {
|
||||
if (!JS_ReportPendingException(aCx)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!events::SetEventTarget(aCx, aEvent, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*aPreventDefaultCalled = events::EventWasCanceled(aCx, aEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ListenerManager::HasListenersForTypeInternal(JSContext* aCx, JSString* aType)
|
||||
{
|
||||
JS_ASSERT(!PR_CLIST_IS_EMPTY(&mCollectionHead));
|
||||
|
||||
aType = JS_InternJSString(aCx, aType);
|
||||
if (!aType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jsid typeId = INTERNED_STRING_TO_JSID(aCx, aType);
|
||||
return !!GetCollectionForType(&mCollectionHead, typeId);
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_workers_listenermanager_h__
|
||||
#define mozilla_dom_workers_listenermanager_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "prclist.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace events {
|
||||
|
||||
// XXX Current impl doesn't divide into phases.
|
||||
// XXX Current impl doesn't handle event target chains.
|
||||
class ListenerManager
|
||||
{
|
||||
public:
|
||||
enum Phase
|
||||
{
|
||||
All = 0,
|
||||
Capturing,
|
||||
Onfoo,
|
||||
Bubbling
|
||||
};
|
||||
|
||||
private:
|
||||
PRCList mCollectionHead;
|
||||
|
||||
public:
|
||||
ListenerManager()
|
||||
{
|
||||
PR_INIT_CLIST(&mCollectionHead);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
~ListenerManager();
|
||||
#endif
|
||||
|
||||
void
|
||||
Trace(JSTracer* aTrc)
|
||||
{
|
||||
if (!PR_CLIST_IS_EMPTY(&mCollectionHead)) {
|
||||
TraceInternal(aTrc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Finalize(JSContext* aCx)
|
||||
{
|
||||
if (!PR_CLIST_IS_EMPTY(&mCollectionHead)) {
|
||||
FinalizeInternal(aCx);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AddEventListener(JSContext* aCx, JSString* aType, jsval aListener,
|
||||
bool aCapturing, bool aWantsUntrusted)
|
||||
{
|
||||
return Add(aCx, aType, aListener, aCapturing ? Capturing : Bubbling,
|
||||
aWantsUntrusted);
|
||||
}
|
||||
|
||||
bool
|
||||
SetEventListener(JSContext* aCx, JSString* aType, jsval aListener);
|
||||
|
||||
bool
|
||||
RemoveEventListener(JSContext* aCx, JSString* aType, jsval aListener,
|
||||
bool aCapturing)
|
||||
{
|
||||
if (PR_CLIST_IS_EMPTY(&mCollectionHead)) {
|
||||
return true;
|
||||
}
|
||||
return Remove(aCx, aType, aListener, aCapturing ? Capturing : Bubbling,
|
||||
true);
|
||||
}
|
||||
|
||||
bool
|
||||
GetEventListener(JSContext* aCx, JSString* aType, jsval* aListener);
|
||||
|
||||
bool
|
||||
DispatchEvent(JSContext* aCx, JSObject* aTarget, JSObject* aEvent,
|
||||
bool* aPreventDefaultCalled);
|
||||
|
||||
bool
|
||||
HasListeners()
|
||||
{
|
||||
return !PR_CLIST_IS_EMPTY(&mCollectionHead);
|
||||
}
|
||||
|
||||
bool
|
||||
HasListenersForType(JSContext* aCx, JSString* aType)
|
||||
{
|
||||
return HasListeners() && HasListenersForTypeInternal(aCx, aType);
|
||||
}
|
||||
|
||||
bool
|
||||
HasListenersForTypeInternal(JSContext* aCx, JSString* aType);
|
||||
|
||||
private:
|
||||
void
|
||||
TraceInternal(JSTracer* aTrc);
|
||||
|
||||
void
|
||||
FinalizeInternal(JSContext* aCx);
|
||||
|
||||
bool
|
||||
Add(JSContext* aCx, JSString* aType, jsval aListener, Phase aPhase,
|
||||
bool aWantsUntrusted);
|
||||
|
||||
bool
|
||||
Remove(JSContext* aCx, JSString* aType, jsval aListener, Phase aPhase,
|
||||
bool aClearEmpty);
|
||||
};
|
||||
|
||||
} // namespace events
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_listenermanager_h__ */
|
|
@ -0,0 +1,241 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "Location.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#define PROPERTY_FLAGS \
|
||||
JSPROP_ENUMERATE | JSPROP_SHARED
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
class Location
|
||||
{
|
||||
static JSClass sClass;
|
||||
static JSPropertySpec sProperties[];
|
||||
static JSFunctionSpec sFunctions[];
|
||||
|
||||
enum SLOT {
|
||||
SLOT_href = 0,
|
||||
SLOT_protocol,
|
||||
SLOT_host,
|
||||
SLOT_hostname,
|
||||
SLOT_port,
|
||||
SLOT_pathname,
|
||||
SLOT_search,
|
||||
SLOT_hash,
|
||||
|
||||
SLOT_COUNT
|
||||
};
|
||||
|
||||
public:
|
||||
static JSObject*
|
||||
InitClass(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
|
||||
sFunctions, NULL, NULL);
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
Create(JSContext* aCx, JSString* aHref, JSString* aProtocol, JSString* aHost,
|
||||
JSString* aHostname, JSString* aPort, JSString* aPathname,
|
||||
JSString* aSearch, JSString* aHash)
|
||||
{
|
||||
JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
|
||||
if (!obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsval empty = JS_GetEmptyStringValue(aCx);
|
||||
|
||||
if (!JS_SetReservedSlot(aCx, obj, SLOT_href,
|
||||
aHref ? STRING_TO_JSVAL(aHref) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_protocol,
|
||||
aProtocol ? STRING_TO_JSVAL(aProtocol) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_host,
|
||||
aHost ? STRING_TO_JSVAL(aHost) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_hostname,
|
||||
aHostname ? STRING_TO_JSVAL(aHostname) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_port,
|
||||
aPort ? STRING_TO_JSVAL(aPort) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_pathname,
|
||||
aPathname ? STRING_TO_JSVAL(aPathname) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_search,
|
||||
aSearch ? STRING_TO_JSVAL(aSearch) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_hash,
|
||||
aHash ? STRING_TO_JSVAL(aHash) : empty)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Location* priv = new Location();
|
||||
|
||||
if (!JS_SetPrivate(aCx, obj, priv)) {
|
||||
delete priv;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
Location()
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::Location);
|
||||
}
|
||||
|
||||
~Location()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::dom::workers::Location);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Construct(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
|
||||
sClass.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
Finalize(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
JS_ASSERT(JS_GET_CLASS(aCx, aObj) == &sClass);
|
||||
delete static_cast<Location*>(JS_GetPrivate(aCx, aObj));
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ToString(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
|
||||
|
||||
JSClass* classPtr;
|
||||
if (!obj || ((classPtr = JS_GET_CLASS(aCx, obj)) != &sClass)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO, sClass.name, "toString",
|
||||
classPtr ? classPtr->name : "object");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
jsval href;
|
||||
if (!JS_GetReservedSlot(aCx, obj, SLOT_href, &href)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_SET_RVAL(aCx, aVp, href);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
|
||||
{
|
||||
JSClass* classPtr;
|
||||
if (!aObj || ((classPtr = JS_GET_CLASS(aCx, aObj)) != &sClass)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
|
||||
classPtr ? classPtr->name : "object");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(JSID_IS_INT(aIdval));
|
||||
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
|
||||
|
||||
return JS_GetReservedSlot(aCx, aObj, JSID_TO_INT(aIdval), aVp);
|
||||
}
|
||||
};
|
||||
|
||||
JSClass Location::sClass = {
|
||||
"WorkerLocation",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
JSPropertySpec Location::sProperties[] = {
|
||||
{ "href", SLOT_href, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "protocol", SLOT_protocol, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "host", SLOT_host, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "hostname", SLOT_hostname, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "port", SLOT_port, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "pathname", SLOT_pathname, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "search", SLOT_search, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "hash", SLOT_hash, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
JSFunctionSpec Location::sFunctions[] = {
|
||||
JS_FN("toString", ToString, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace location {
|
||||
|
||||
bool
|
||||
InitClass(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return !!Location::InitClass(aCx, aGlobal);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Create(JSContext* aCx, JSString* aHref, JSString* aProtocol, JSString* aHost,
|
||||
JSString* aHostname, JSString* aPort, JSString* aPathname,
|
||||
JSString* aSearch, JSString* aHash)
|
||||
{
|
||||
return Location::Create(aCx, aHref, aProtocol, aHost, aHostname, aPort,
|
||||
aPathname, aSearch, aHash);
|
||||
}
|
||||
|
||||
} // namespace location
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -11,15 +12,15 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DOM Worker Tests.
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -35,23 +36,27 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let EXPORTED_SYMBOLS = [
|
||||
"WorkerTest"
|
||||
];
|
||||
#ifndef mozilla_dom_workers_location_h__
|
||||
#define mozilla_dom_workers_location_h__
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
#include "Workers.h"
|
||||
|
||||
// Define our lazy getters.
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "workerFactory",
|
||||
"@mozilla.org/threads/workerfactory;1",
|
||||
"nsIWorkerFactory");
|
||||
#include "jspubtd.h"
|
||||
|
||||
const WorkerTest = {
|
||||
go: function(message, messageCallback, errorCallback) {
|
||||
let worker = workerFactory.newChromeWorker("WorkerTest_worker.js");
|
||||
worker.onmessage = messageCallback;
|
||||
worker.onerror = errorCallback;
|
||||
worker.postMessage(message);
|
||||
return worker;
|
||||
}
|
||||
};
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace location {
|
||||
|
||||
bool
|
||||
InitClass(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
JSObject*
|
||||
Create(JSContext* aCx, JSString* aHref, JSString* aProtocol, JSString* aHost,
|
||||
JSString* aHostname, JSString* aPort, JSString* aPathname,
|
||||
JSString* aSearch, JSString* aHash);
|
||||
|
||||
} // namespace location
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_location_h__
|
|
@ -36,7 +36,7 @@
|
|||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
@ -44,31 +44,38 @@ VPATH = @srcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dom
|
||||
LIBRARY_NAME = domthreads_s
|
||||
LIBRARY_NAME = domworkers_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/dom/workers
|
||||
|
||||
EXPORTS_mozilla/dom/workers = Workers.h
|
||||
|
||||
CPPSRCS = \
|
||||
nsDOMThreadService.cpp \
|
||||
nsDOMWorker.cpp \
|
||||
nsDOMWorkerEvents.cpp \
|
||||
nsDOMWorkerLocation.cpp \
|
||||
nsDOMWorkerMessageHandler.cpp \
|
||||
nsDOMWorkerNavigator.cpp \
|
||||
nsDOMWorkerPool.cpp \
|
||||
nsDOMWorkerScriptLoader.cpp \
|
||||
nsDOMWorkerSecurityManager.cpp \
|
||||
nsDOMWorkerTimeout.cpp \
|
||||
nsDOMWorkerXHR.cpp \
|
||||
nsDOMWorkerXHRProxy.cpp \
|
||||
ChromeWorkerScope.cpp \
|
||||
Events.cpp \
|
||||
EventTarget.cpp \
|
||||
Exceptions.cpp \
|
||||
ListenerManager.cpp \
|
||||
Location.cpp \
|
||||
Navigator.cpp \
|
||||
Principal.cpp \
|
||||
RuntimeService.cpp \
|
||||
ScriptLoader.cpp \
|
||||
Worker.cpp \
|
||||
WorkerPrivate.cpp \
|
||||
WorkerScope.cpp \
|
||||
XMLHttpRequest.cpp \
|
||||
XMLHttpRequestPrivate.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/json \
|
||||
-I$(topsrcdir)/js/src/xpconnect/src \
|
||||
-I$(topsrcdir)/xpcom/build \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
|
@ -0,0 +1,217 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "Navigator.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#include "RuntimeService.h"
|
||||
|
||||
#define PROPERTY_FLAGS \
|
||||
JSPROP_ENUMERATE | JSPROP_SHARED
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
class Navigator
|
||||
{
|
||||
static JSClass sClass;
|
||||
static JSPropertySpec sProperties[];
|
||||
|
||||
enum SLOT {
|
||||
SLOT_appName = 0,
|
||||
SLOT_appVersion,
|
||||
SLOT_platform,
|
||||
SLOT_userAgent,
|
||||
|
||||
SLOT_COUNT
|
||||
};
|
||||
|
||||
public:
|
||||
static JSObject*
|
||||
InitClass(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
Create(JSContext* aCx)
|
||||
{
|
||||
RuntimeService* rts = RuntimeService::GetService();
|
||||
JS_ASSERT(rts);
|
||||
|
||||
const RuntimeService::NavigatorStrings& strings =
|
||||
rts->GetNavigatorStrings();
|
||||
|
||||
JSString* appName, *version, *platform, *userAgent;
|
||||
|
||||
#define COPY_STRING(_jsstr, _str) \
|
||||
if (strings. _str .IsEmpty()) { \
|
||||
_jsstr = NULL; \
|
||||
} \
|
||||
else if (!(_jsstr = JS_NewUCStringCopyN(aCx, strings. _str .get(), \
|
||||
strings. _str .Length()))) { \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
COPY_STRING(appName, mAppName);
|
||||
COPY_STRING(version, mAppVersion);
|
||||
COPY_STRING(platform, mPlatform);
|
||||
COPY_STRING(userAgent, mUserAgent);
|
||||
|
||||
#undef COPY_STRING
|
||||
|
||||
JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
|
||||
if (!obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsval empty = JS_GetEmptyStringValue(aCx);
|
||||
|
||||
if (!JS_SetReservedSlot(aCx, obj, SLOT_appName,
|
||||
appName ? STRING_TO_JSVAL(appName) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_appVersion,
|
||||
version ? STRING_TO_JSVAL(version) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_platform,
|
||||
platform ? STRING_TO_JSVAL(platform) : empty) ||
|
||||
!JS_SetReservedSlot(aCx, obj, SLOT_userAgent,
|
||||
userAgent ? STRING_TO_JSVAL(userAgent) : empty)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Navigator* priv = new Navigator();
|
||||
|
||||
if (!JS_SetPrivate(aCx, obj, priv)) {
|
||||
delete priv;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
Navigator()
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::Navigator);
|
||||
}
|
||||
|
||||
~Navigator()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::dom::workers::Navigator);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Construct(JSContext* aCx, uintN aArgc, jsval* aVp)
|
||||
{
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
|
||||
sClass.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
Finalize(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
JS_ASSERT(JS_GET_CLASS(aCx, aObj) == &sClass);
|
||||
delete static_cast<Navigator*>(JS_GetPrivate(aCx, aObj));
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
|
||||
{
|
||||
JSClass* classPtr;
|
||||
if (!aObj || ((classPtr = JS_GET_CLASS(aCx, aObj)) != &sClass)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
|
||||
classPtr ? classPtr->name : "object");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(JSID_IS_INT(aIdval));
|
||||
JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
|
||||
|
||||
return JS_GetReservedSlot(aCx, aObj, JSID_TO_INT(aIdval), aVp);
|
||||
}
|
||||
};
|
||||
|
||||
JSClass Navigator::sClass = {
|
||||
"WorkerNavigator",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
JSPropertySpec Navigator::sProperties[] = {
|
||||
{ "appName", SLOT_appName, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "appVersion", SLOT_appVersion, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "platform", SLOT_platform, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ "userAgent", SLOT_userAgent, PROPERTY_FLAGS, GetProperty,
|
||||
js_GetterOnlyPropertyStub },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace navigator {
|
||||
|
||||
bool
|
||||
InitClass(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return !!Navigator::InitClass(aCx, aGlobal);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Create(JSContext* aCx)
|
||||
{
|
||||
return Navigator::Create(aCx);
|
||||
}
|
||||
|
||||
} // namespace navigator
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -11,15 +12,15 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DOM Worker Tests.
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -35,10 +36,25 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
onmessage = function(event) {
|
||||
let worker = new ChromeWorker("WorkerTest_subworker.js");
|
||||
worker.onmessage = function(event) {
|
||||
postMessage(event.data);
|
||||
}
|
||||
worker.postMessage(event.data);
|
||||
}
|
||||
#ifndef mozilla_dom_workers_navigator_h__
|
||||
#define mozilla_dom_workers_navigator_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace navigator {
|
||||
|
||||
bool
|
||||
InitClass(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
JSObject*
|
||||
Create(JSContext* aCx);
|
||||
|
||||
} // namespace navigator
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_navigator_h__
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "Principal.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
PrincipalDestroy(JSContext*, JSPrincipals*)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
JSBool
|
||||
PrincipalSubsume(JSPrincipals*, JSPrincipals*)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
const char gPrincipalCodebase[] = "Web Worker";
|
||||
|
||||
JSPrincipals gPrincipal = {
|
||||
const_cast<char*>(gPrincipalCodebase),
|
||||
NULL, NULL, 1, PrincipalDestroy, PrincipalSubsume
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
JSPrincipals*
|
||||
GetWorkerPrincipal()
|
||||
{
|
||||
return &gPrincipal;
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -11,15 +12,15 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DOM Worker Tests.
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -35,6 +36,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
onmessage = function(event) {
|
||||
throw "Shouldn't be able to read this!";
|
||||
}
|
||||
#ifndef mozilla_dom_workers_principal_h__
|
||||
#define mozilla_dom_workers_principal_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
JSPrincipals*
|
||||
GetWorkerPrincipal();
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_principal_h__ */
|
|
@ -0,0 +1,235 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_workers_queue_h__
|
||||
#define mozilla_dom_workers_queue_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
template <typename T, int TCount>
|
||||
struct StorageWithTArray
|
||||
{
|
||||
typedef nsAutoTArray<T, TCount> StorageType;
|
||||
|
||||
static void Reverse(StorageType& aStorage)
|
||||
{
|
||||
PRUint32 length = aStorage.Length();
|
||||
for (PRUint32 index = 0; index < length / 2; index++) {
|
||||
PRUint32 reverseIndex = length - 1 - index;
|
||||
|
||||
T t1 = aStorage.ElementAt(index);
|
||||
T t2 = aStorage.ElementAt(reverseIndex);
|
||||
|
||||
aStorage.ReplaceElementsAt(index, 1, t2);
|
||||
aStorage.ReplaceElementsAt(reverseIndex, 1, t1);
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsEmpty(const StorageType& aStorage)
|
||||
{
|
||||
return !!aStorage.IsEmpty();
|
||||
}
|
||||
|
||||
static bool Push(StorageType& aStorage, const T& aEntry)
|
||||
{
|
||||
return !!aStorage.AppendElement(aEntry);
|
||||
}
|
||||
|
||||
static bool Pop(StorageType& aStorage, T& aEntry)
|
||||
{
|
||||
if (IsEmpty(aStorage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PRUint32 index = aStorage.Length() - 1;
|
||||
aEntry = aStorage.ElementAt(index);
|
||||
aStorage.RemoveElementAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Clear(StorageType& aStorage)
|
||||
{
|
||||
aStorage.Clear();
|
||||
}
|
||||
|
||||
static void Compact(StorageType& aStorage)
|
||||
{
|
||||
aStorage.Compact();
|
||||
}
|
||||
};
|
||||
|
||||
class LockingWithMutex
|
||||
{
|
||||
mozilla::Mutex mMutex;
|
||||
|
||||
protected:
|
||||
LockingWithMutex()
|
||||
: mMutex("LockingWithMutex::mMutex")
|
||||
{ }
|
||||
|
||||
void Lock()
|
||||
{
|
||||
mMutex.Lock();
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
class AutoLock
|
||||
{
|
||||
LockingWithMutex& mHost;
|
||||
|
||||
public:
|
||||
AutoLock(LockingWithMutex& aHost)
|
||||
: mHost(aHost)
|
||||
{
|
||||
mHost.Lock();
|
||||
}
|
||||
|
||||
~AutoLock()
|
||||
{
|
||||
mHost.Unlock();
|
||||
}
|
||||
};
|
||||
|
||||
friend class AutoLock;
|
||||
};
|
||||
|
||||
class NoLocking
|
||||
{
|
||||
protected:
|
||||
void Lock()
|
||||
{ }
|
||||
|
||||
void Unlock()
|
||||
{ }
|
||||
|
||||
class AutoLock
|
||||
{
|
||||
public:
|
||||
AutoLock(NoLocking& aHost)
|
||||
{ }
|
||||
|
||||
~AutoLock()
|
||||
{ }
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T,
|
||||
int TCount = 256,
|
||||
class LockingPolicy = NoLocking,
|
||||
class StoragePolicy = StorageWithTArray<T, TCount % 2 ?
|
||||
TCount / 2 + 1 :
|
||||
TCount / 2> >
|
||||
class Queue : public LockingPolicy
|
||||
{
|
||||
typedef typename StoragePolicy::StorageType StorageType;
|
||||
typedef typename LockingPolicy::AutoLock AutoLock;
|
||||
|
||||
StorageType mStorage1;
|
||||
StorageType mStorage2;
|
||||
|
||||
StorageType* mFront;
|
||||
StorageType* mBack;
|
||||
|
||||
public:
|
||||
Queue()
|
||||
: mFront(&mStorage1), mBack(&mStorage2)
|
||||
{ }
|
||||
|
||||
bool IsEmpty()
|
||||
{
|
||||
AutoLock lock(*this);
|
||||
return StoragePolicy::IsEmpty(*mFront) &&
|
||||
StoragePolicy::IsEmpty(*mBack);
|
||||
}
|
||||
|
||||
bool Push(const T& aEntry)
|
||||
{
|
||||
AutoLock lock(*this);
|
||||
return StoragePolicy::Push(*mBack, aEntry);
|
||||
}
|
||||
|
||||
bool Pop(T& aEntry)
|
||||
{
|
||||
AutoLock lock(*this);
|
||||
if (StoragePolicy::IsEmpty(*mFront)) {
|
||||
StoragePolicy::Compact(*mFront);
|
||||
StoragePolicy::Reverse(*mBack);
|
||||
StorageType* tmp = mFront;
|
||||
mFront = mBack;
|
||||
mBack = tmp;
|
||||
}
|
||||
return StoragePolicy::Pop(*mFront, aEntry);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
AutoLock lock(*this);
|
||||
StoragePolicy::Clear(*mFront);
|
||||
StoragePolicy::Clear(*mBack);
|
||||
}
|
||||
|
||||
// XXX Do we need this?
|
||||
void Lock()
|
||||
{
|
||||
LockingPolicy::Lock();
|
||||
}
|
||||
|
||||
// XXX Do we need this?
|
||||
void Unlock()
|
||||
{
|
||||
LockingPolicy::Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
// Queue is not copyable.
|
||||
Queue(const Queue&);
|
||||
Queue & operator=(const Queue&);
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_queue_h__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,247 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Web Workers.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_workers_runtimeservice_h__
|
||||
#define mozilla_dom_workers_runtimeservice_h__
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIThread;
|
||||
class nsITimer;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class WorkerPrivate;
|
||||
|
||||
class RuntimeService : public nsIObserver
|
||||
{
|
||||
struct WorkerDomainInfo
|
||||
{
|
||||
nsCString mDomain;
|
||||
nsTArray<WorkerPrivate*> mActiveWorkers;
|
||||
nsTArray<WorkerPrivate*> mQueuedWorkers;
|
||||
PRUint32 mChildWorkerCount;
|
||||
|
||||
WorkerDomainInfo() : mActiveWorkers(1), mChildWorkerCount(0) { }
|
||||
|
||||
PRUint32
|
||||
ActiveWorkerCount() const
|
||||
{
|
||||
return mActiveWorkers.Length() + mChildWorkerCount;
|
||||
}
|
||||
};
|
||||
|
||||
struct IdleThreadInfo
|
||||
{
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
mozilla::TimeStamp mExpirationTime;
|
||||
};
|
||||
|
||||
mozilla::Mutex mMutex;
|
||||
|
||||
// Protected by mMutex.
|
||||
nsClassHashtable<nsCStringHashKey, WorkerDomainInfo> mDomainMap;
|
||||
|
||||
// Protected by mMutex.
|
||||
nsTArray<IdleThreadInfo> mIdleThreadArray;
|
||||
|
||||
// *Not* protected by mMutex.
|
||||
nsClassHashtable<nsVoidPtrHashKey, nsTArray<WorkerPrivate*> > mWindowMap;
|
||||
|
||||
// Only used on the main thread.
|
||||
nsCOMPtr<nsITimer> mIdleThreadTimer;
|
||||
|
||||
static PRUint32 sDefaultJSContextOptions;
|
||||
static PRInt32 sCloseHandlerTimeoutSeconds;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static PRUint8 sDefaultGCZeal;
|
||||
#endif
|
||||
|
||||
public:
|
||||
struct NavigatorStrings
|
||||
{
|
||||
nsString mAppName;
|
||||
nsString mAppVersion;
|
||||
nsString mPlatform;
|
||||
nsString mUserAgent;
|
||||
};
|
||||
|
||||
private:
|
||||
NavigatorStrings mNavigatorStrings;
|
||||
|
||||
// True when the observer service holds a reference to this object.
|
||||
bool mObserved;
|
||||
bool mShuttingDown;
|
||||
bool mNavigatorStringsLoaded;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static RuntimeService*
|
||||
GetOrCreateService();
|
||||
|
||||
static RuntimeService*
|
||||
GetService();
|
||||
|
||||
bool
|
||||
RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
void
|
||||
UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
void
|
||||
CancelWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
|
||||
|
||||
void
|
||||
SuspendWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
|
||||
|
||||
void
|
||||
ResumeWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
|
||||
|
||||
const NavigatorStrings&
|
||||
GetNavigatorStrings() const
|
||||
{
|
||||
return mNavigatorStrings;
|
||||
}
|
||||
|
||||
void
|
||||
NoteIdleThread(nsIThread* aThread);
|
||||
|
||||
static PRUint32
|
||||
GetDefaultJSContextOptions()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
return sDefaultJSContextOptions;
|
||||
}
|
||||
|
||||
static void
|
||||
SetDefaultJSContextOptions(PRUint32 aOptions)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
sDefaultJSContextOptions = aOptions;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateAllWorkerJSContextOptions();
|
||||
|
||||
static PRUint32
|
||||
GetCloseHandlerTimeoutSeconds()
|
||||
{
|
||||
return sCloseHandlerTimeoutSeconds > 0 ? sCloseHandlerTimeoutSeconds : 0;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static PRUint8
|
||||
GetDefaultGCZeal()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
return sDefaultGCZeal;
|
||||
}
|
||||
|
||||
static void
|
||||
SetDefaultGCZeal(PRUint8 aGCZeal)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
sDefaultGCZeal = aGCZeal;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateAllWorkerGCZeal();
|
||||
#endif
|
||||
|
||||
class AutoSafeJSContext
|
||||
{
|
||||
JSContext* mContext;
|
||||
|
||||
public:
|
||||
AutoSafeJSContext(JSContext* aCx = nsnull);
|
||||
~AutoSafeJSContext();
|
||||
|
||||
operator JSContext*() const
|
||||
{
|
||||
return mContext;
|
||||
}
|
||||
|
||||
static JSContext*
|
||||
GetSafeContext();
|
||||
};
|
||||
|
||||
private:
|
||||
RuntimeService();
|
||||
~RuntimeService();
|
||||
|
||||
nsresult
|
||||
Init();
|
||||
|
||||
void
|
||||
Cleanup();
|
||||
|
||||
static PLDHashOperator
|
||||
AddAllTopLevelWorkersToArray(const nsACString& aKey,
|
||||
WorkerDomainInfo* aData,
|
||||
void* aUserArg);
|
||||
|
||||
void
|
||||
GetWorkersForWindow(nsPIDOMWindow* aWindow,
|
||||
nsTArray<WorkerPrivate*>& aWorkers);
|
||||
|
||||
bool
|
||||
ScheduleWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
static void
|
||||
ShutdownIdleThreads(nsITimer* aTimer, void* aClosure);
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_runtimeservice_h__ */
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче