зеркало из https://github.com/mozilla/gecko-dev.git
Bug 925437 - Implement navigator.onLine on Workers. r=khuey sr=sicking
This commit is contained in:
Родитель
35ea1b2c2d
Коммит
c3934ac5d1
|
@ -19,6 +19,8 @@ interface WorkerGlobalScope : EventTarget {
|
|||
void close();
|
||||
attribute OnErrorEventHandler onerror;
|
||||
|
||||
attribute EventHandler onoffline;
|
||||
attribute EventHandler ononline;
|
||||
// also has additional members in a partial interface
|
||||
};
|
||||
|
||||
|
|
|
@ -6,3 +6,4 @@ interface WorkerNavigator {
|
|||
};
|
||||
|
||||
WorkerNavigator implements NavigatorID;
|
||||
WorkerNavigator implements NavigatorOnLine;
|
||||
|
|
|
@ -17,17 +17,18 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WorkerNavigator, AddRef)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WorkerNavigator, Release)
|
||||
|
||||
/* static */ already_AddRefed<WorkerNavigator>
|
||||
WorkerNavigator::Create()
|
||||
WorkerNavigator::Create(bool aOnLine)
|
||||
{
|
||||
RuntimeService* rts = RuntimeService::GetService();
|
||||
MOZ_ASSERT(rts);
|
||||
|
||||
const RuntimeService::NavigatorStrings& strings =
|
||||
rts->GetNavigatorStrings();
|
||||
const RuntimeService::NavigatorProperties& properties =
|
||||
rts->GetNavigatorProperties();
|
||||
|
||||
nsRefPtr<WorkerNavigator> navigator =
|
||||
new WorkerNavigator(strings.mAppName, strings.mAppVersion,
|
||||
strings.mPlatform, strings.mUserAgent);
|
||||
new WorkerNavigator(properties.mAppName, properties.mAppVersion,
|
||||
properties.mPlatform, properties.mUserAgent,
|
||||
aOnLine);
|
||||
|
||||
return navigator.forget();
|
||||
}
|
||||
|
|
|
@ -18,15 +18,18 @@ class WorkerNavigator MOZ_FINAL : public nsWrapperCache
|
|||
nsString mAppVersion;
|
||||
nsString mPlatform;
|
||||
nsString mUserAgent;
|
||||
bool mOnline;
|
||||
|
||||
WorkerNavigator(const nsAString& aAppName,
|
||||
const nsAString& aAppVersion,
|
||||
const nsAString& aPlatform,
|
||||
const nsAString& aUserAgent)
|
||||
const nsAString& aUserAgent,
|
||||
bool aOnline)
|
||||
: mAppName(aAppName)
|
||||
, mAppVersion(aAppVersion)
|
||||
, mPlatform(aPlatform)
|
||||
, mUserAgent(aUserAgent)
|
||||
, mOnline(aOnline)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WorkerNavigator);
|
||||
SetIsDOMBinding();
|
||||
|
@ -38,7 +41,7 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WorkerNavigator)
|
||||
|
||||
static already_AddRefed<WorkerNavigator>
|
||||
Create();
|
||||
Create(bool aOnLine);
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
@ -60,10 +63,12 @@ public:
|
|||
{
|
||||
aAppName = mAppName;
|
||||
}
|
||||
|
||||
void GetAppVersion(nsString& aAppVersion) const
|
||||
{
|
||||
aAppVersion = mAppVersion;
|
||||
}
|
||||
|
||||
void GetPlatform(nsString& aPlatform) const
|
||||
{
|
||||
aPlatform = mPlatform;
|
||||
|
@ -76,10 +81,22 @@ public:
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GetUserAgent(nsString& aUserAgent) const
|
||||
{
|
||||
aUserAgent = mUserAgent;
|
||||
}
|
||||
|
||||
bool OnLine() const
|
||||
{
|
||||
return mOnline;
|
||||
}
|
||||
|
||||
// Worker thread only!
|
||||
void SetOnLine(bool aOnline)
|
||||
{
|
||||
mOnline = aOnline;
|
||||
}
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
|
|
@ -1223,7 +1223,7 @@ bool RuntimeService::sDefaultPreferences[WORKERPREF_COUNT] = { false };
|
|||
|
||||
RuntimeService::RuntimeService()
|
||||
: mMutex("RuntimeService::mMutex"), mObserved(false),
|
||||
mShuttingDown(false), mNavigatorStringsLoaded(false)
|
||||
mShuttingDown(false), mNavigatorPropertiesLoaded(false)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
NS_ASSERTION(!gRuntimeService, "More than one service!");
|
||||
|
@ -1352,17 +1352,17 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!mNavigatorStringsLoaded) {
|
||||
NS_GetNavigatorAppName(mNavigatorStrings.mAppName);
|
||||
if (NS_FAILED(NS_GetNavigatorAppVersion(mNavigatorStrings.mAppVersion)) ||
|
||||
NS_FAILED(NS_GetNavigatorPlatform(mNavigatorStrings.mPlatform)) ||
|
||||
NS_FAILED(NS_GetNavigatorUserAgent(mNavigatorStrings.mUserAgent))) {
|
||||
if (!mNavigatorPropertiesLoaded) {
|
||||
NS_GetNavigatorAppName(mNavigatorProperties.mAppName);
|
||||
if (NS_FAILED(NS_GetNavigatorAppVersion(mNavigatorProperties.mAppVersion)) ||
|
||||
NS_FAILED(NS_GetNavigatorPlatform(mNavigatorProperties.mPlatform)) ||
|
||||
NS_FAILED(NS_GetNavigatorUserAgent(mNavigatorProperties.mUserAgent))) {
|
||||
JS_ReportError(aCx, "Failed to load navigator strings!");
|
||||
UnregisterWorker(aCx, aWorkerPrivate);
|
||||
return false;
|
||||
}
|
||||
|
||||
mNavigatorStringsLoaded = true;
|
||||
mNavigatorPropertiesLoaded = true;
|
||||
}
|
||||
|
||||
nsPIDOMWindow* window = aWorkerPrivate->GetWindow();
|
||||
|
@ -1660,6 +1660,10 @@ RuntimeService::Init()
|
|||
NS_WARNING("Failed to register for memory pressure notifications!");
|
||||
}
|
||||
|
||||
if (NS_FAILED(obs->AddObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC, false))) {
|
||||
NS_WARNING("Failed to register for offline notification event!");
|
||||
}
|
||||
|
||||
NS_ASSERTION(!gRuntimeServiceDuringInit, "This should be null!");
|
||||
gRuntimeServiceDuringInit = this;
|
||||
|
||||
|
@ -1911,6 +1915,10 @@ RuntimeService::Cleanup()
|
|||
NS_WARNING("Failed to unregister for memory pressure notifications!");
|
||||
}
|
||||
|
||||
if (NS_FAILED(obs->RemoveObserver(this,
|
||||
NS_IOSERVICE_OFFLINE_STATUS_TOPIC))) {
|
||||
NS_WARNING("Failed to unregister for offline notification event!");
|
||||
}
|
||||
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID);
|
||||
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
mObserved = false;
|
||||
|
@ -2288,6 +2296,12 @@ RuntimeService::CycleCollectAllWorkers()
|
|||
BROADCAST_ALL_WORKERS(CycleCollect, /* dummy = */ false);
|
||||
}
|
||||
|
||||
void
|
||||
RuntimeService::SendOfflineStatusChangeEventToAllWorkers(bool aIsOffline)
|
||||
{
|
||||
BROADCAST_ALL_WORKERS(OfflineStatusChangeEvent, aIsOffline);
|
||||
}
|
||||
|
||||
// nsISupports
|
||||
NS_IMPL_ISUPPORTS1(RuntimeService, nsIObserver)
|
||||
|
||||
|
@ -2319,6 +2333,10 @@ RuntimeService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
CycleCollectAllWorkers();
|
||||
return NS_OK;
|
||||
}
|
||||
if (!strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
|
||||
SendOfflineStatusChangeEventToAllWorkers(NS_IsOffline());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Unknown observer topic!");
|
||||
return NS_OK;
|
||||
|
|
|
@ -100,7 +100,7 @@ private:
|
|||
static bool sDefaultPreferences[WORKERPREF_COUNT];
|
||||
|
||||
public:
|
||||
struct NavigatorStrings
|
||||
struct NavigatorProperties
|
||||
{
|
||||
nsString mAppName;
|
||||
nsString mAppVersion;
|
||||
|
@ -109,12 +109,12 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
NavigatorStrings mNavigatorStrings;
|
||||
NavigatorProperties mNavigatorProperties;
|
||||
|
||||
// True when the observer service holds a reference to this object.
|
||||
bool mObserved;
|
||||
bool mShuttingDown;
|
||||
bool mNavigatorStringsLoaded;
|
||||
bool mNavigatorPropertiesLoaded;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -150,10 +150,10 @@ public:
|
|||
void
|
||||
ForgetSharedWorker(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
const NavigatorStrings&
|
||||
GetNavigatorStrings() const
|
||||
const NavigatorProperties&
|
||||
GetNavigatorProperties() const
|
||||
{
|
||||
return mNavigatorStrings;
|
||||
return mNavigatorProperties;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -239,6 +239,9 @@ public:
|
|||
void
|
||||
CycleCollectAllWorkers();
|
||||
|
||||
void
|
||||
SendOfflineStatusChangeEventToAllWorkers(bool aIsOffline);
|
||||
|
||||
private:
|
||||
RuntimeService();
|
||||
~RuntimeService();
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
|
||||
#include "File.h"
|
||||
#include "MessagePort.h"
|
||||
#include "Navigator.h"
|
||||
#include "Principal.h"
|
||||
#include "RuntimeService.h"
|
||||
#include "ScriptLoader.h"
|
||||
|
@ -1693,6 +1694,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class OfflineStatusChangeRunnable : public WorkerRunnable
|
||||
{
|
||||
public:
|
||||
OfflineStatusChangeRunnable(WorkerPrivate* aWorkerPrivate, bool aIsOffline)
|
||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
|
||||
mIsOffline(aIsOffline)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->OfflineStatusChangeEventInternal(aCx, mIsOffline);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mIsOffline;
|
||||
};
|
||||
|
||||
class WorkerJSRuntimeStats : public JS::RuntimeStats
|
||||
{
|
||||
const nsACString& mRtPath;
|
||||
|
@ -3035,6 +3056,56 @@ WorkerPrivateParent<Derived>::CycleCollect(JSContext* aCx, bool aDummy)
|
|||
}
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::OfflineStatusChangeEvent(JSContext* aCx, bool aIsOffline)
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
|
||||
nsRefPtr<OfflineStatusChangeRunnable> runnable =
|
||||
new OfflineStatusChangeRunnable(ParentAsWorkerPrivate(), aIsOffline);
|
||||
if (!runnable->Dispatch(aCx)) {
|
||||
NS_WARNING("Failed to dispatch offline status change event!");
|
||||
JS_ClearPendingException(aCx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::OfflineStatusChangeEventInternal(JSContext* aCx, bool aIsOffline)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
for (uint32_t index = 0; index < mChildWorkers.Length(); ++index) {
|
||||
mChildWorkers[index]->OfflineStatusChangeEvent(aCx, aIsOffline);
|
||||
}
|
||||
|
||||
mOnLine = !aIsOffline;
|
||||
WorkerGlobalScope* globalScope = GlobalScope();
|
||||
nsRefPtr<WorkerNavigator> nav = globalScope->GetExistingNavigator();
|
||||
if (nav) {
|
||||
nav->SetOnLine(mOnLine);
|
||||
}
|
||||
|
||||
nsString eventType;
|
||||
if (aIsOffline) {
|
||||
eventType.AssignLiteral("offline");
|
||||
} else {
|
||||
eventType.AssignLiteral("online");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsresult rv =
|
||||
NS_NewDOMEvent(getter_AddRefs(event), globalScope, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
rv = event->InitEvent(eventType, false, false);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
event->SetTrusted(true);
|
||||
|
||||
globalScope->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
bool
|
||||
WorkerPrivateParent<Derived>::RegisterSharedWorker(JSContext* aCx,
|
||||
|
@ -3554,10 +3625,12 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
|
|||
if (aParent) {
|
||||
aParent->AssertIsOnWorkerThread();
|
||||
aParent->GetAllPreferences(mPreferences);
|
||||
mOnLine = aParent->OnLine();
|
||||
}
|
||||
else {
|
||||
AssertIsOnMainThread();
|
||||
RuntimeService::GetDefaultPreferences(mPreferences);
|
||||
mOnLine = !NS_IsOffline();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -392,6 +392,9 @@ public:
|
|||
void
|
||||
CycleCollect(JSContext* aCx, bool aDummy);
|
||||
|
||||
void
|
||||
OfflineStatusChangeEvent(JSContext* aCx, bool aIsOffline);
|
||||
|
||||
bool
|
||||
RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
|
||||
|
||||
|
@ -743,6 +746,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|||
#endif
|
||||
|
||||
bool mPreferences[WORKERPREF_COUNT];
|
||||
bool mOnLine;
|
||||
|
||||
protected:
|
||||
~WorkerPrivate();
|
||||
|
@ -902,6 +906,9 @@ public:
|
|||
void
|
||||
CycleCollectInternal(JSContext* aCx, bool aCollectChildren);
|
||||
|
||||
void
|
||||
OfflineStatusChangeEventInternal(JSContext* aCx, bool aIsOffline);
|
||||
|
||||
JSContext*
|
||||
GetJSContext() const
|
||||
{
|
||||
|
@ -983,6 +990,13 @@ public:
|
|||
return mPreferences[WORKERPREF_PROMISE];
|
||||
}
|
||||
|
||||
bool
|
||||
OnLine() const
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
return mOnLine;
|
||||
}
|
||||
|
||||
void
|
||||
StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ WorkerGlobalScope::Navigator()
|
|||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
if (!mNavigator) {
|
||||
mNavigator = WorkerNavigator::Create();
|
||||
mNavigator = WorkerNavigator::Create(mWorkerPrivate->OnLine());
|
||||
MOZ_ASSERT(mNavigator);
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,15 @@ WorkerGlobalScope::Navigator()
|
|||
return navigator.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WorkerNavigator>
|
||||
WorkerGlobalScope::GetExistingNavigator() const
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<WorkerNavigator> navigator = mNavigator;
|
||||
return navigator.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerGlobalScope::Close(JSContext* aCx)
|
||||
{
|
||||
|
|
|
@ -60,8 +60,13 @@ public:
|
|||
|
||||
already_AddRefed<WorkerLocation>
|
||||
Location();
|
||||
|
||||
already_AddRefed<WorkerNavigator>
|
||||
Navigator();
|
||||
|
||||
already_AddRefed<WorkerNavigator>
|
||||
GetExistingNavigator() const;
|
||||
|
||||
void
|
||||
Close(JSContext* aCx);
|
||||
|
||||
|
@ -97,6 +102,8 @@ public:
|
|||
void
|
||||
Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const;
|
||||
|
||||
IMPL_EVENT_HANDLER(online)
|
||||
IMPL_EVENT_HANDLER(offline)
|
||||
IMPL_EVENT_HANDLER(close)
|
||||
|
||||
void
|
||||
|
|
|
@ -27,6 +27,9 @@ support-files =
|
|||
multi_sharedWorker_sharedWorker.js
|
||||
navigator_worker.js
|
||||
newError_worker.js
|
||||
onLine_worker.js
|
||||
onLine_worker_child.js
|
||||
onLine_worker_head.js
|
||||
promise_worker.js
|
||||
recursion_worker.js
|
||||
recursiveOnerror_worker.js
|
||||
|
@ -90,6 +93,7 @@ support-files =
|
|||
[test_multi_sharedWorker_lifetimes.html]
|
||||
[test_navigator.html]
|
||||
[test_newError.html]
|
||||
[test_onLine.html]
|
||||
[test_promise.html]
|
||||
[test_recursion.html]
|
||||
[test_recursiveOnerror.html]
|
||||
|
|
|
@ -9,7 +9,8 @@ var supportedProps = [
|
|||
"platform",
|
||||
"product",
|
||||
"taintEnabled",
|
||||
"userAgent"
|
||||
"userAgent",
|
||||
"onLine"
|
||||
];
|
||||
|
||||
for (var prop in navigator) {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
importScripts("onLine_worker_head.js");
|
||||
|
||||
var N_CHILDREN = 3;
|
||||
var children = [];
|
||||
var finishedChildrenCount = 0;
|
||||
var lastTest = false;
|
||||
|
||||
for (var event of ["online", "offline"]) {
|
||||
addEventListener(event,
|
||||
makeHandler(
|
||||
"addEventListener('%1', ..., false)",
|
||||
event, 1, "Parent Worker"),
|
||||
false);
|
||||
}
|
||||
|
||||
onmessage = function(e) {
|
||||
if (e.data === 'lastTest') {
|
||||
children.forEach(function(w) {
|
||||
w.postMessage({ type: 'lastTest' });
|
||||
});
|
||||
lastTest = true;
|
||||
}
|
||||
}
|
||||
|
||||
function setupChildren(cb) {
|
||||
var readyCount = 0;
|
||||
for (var i = 0; i < N_CHILDREN; ++i) {
|
||||
var w = new Worker("onLine_worker_child.js");
|
||||
children.push(w);
|
||||
|
||||
w.onerror = function(e) {
|
||||
info("Error creating child " + e.message);
|
||||
}
|
||||
|
||||
w.onmessage = function(e) {
|
||||
if (e.data.type === 'ready') {
|
||||
info("Got ready from child");
|
||||
readyCount++;
|
||||
if (readyCount === N_CHILDREN) {
|
||||
cb();
|
||||
}
|
||||
} else if (e.data.type === 'finished') {
|
||||
finishedChildrenCount++;
|
||||
|
||||
if (lastTest && finishedChildrenCount === N_CHILDREN) {
|
||||
postMessage({ type: 'finished' });
|
||||
children = [];
|
||||
close();
|
||||
}
|
||||
} else if (e.data.type === 'ok') {
|
||||
// Pass on test to page.
|
||||
postMessage(e.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupChildren(function() {
|
||||
postMessage({ type: 'ready' });
|
||||
});
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
function info(text) {
|
||||
dump("Test for Bug 925437: worker: " + text + "\n");
|
||||
}
|
||||
|
||||
function ok(test, message) {
|
||||
postMessage({ type: 'ok', test: test, message: message });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a handler function for an online/offline event. The returned handler
|
||||
* ensures the passed event object has expected properties and that the handler
|
||||
* is called at the right moment (according to the gState variable).
|
||||
* @param nameTemplate The string identifying the hanlder. '%1' in that
|
||||
* string will be replaced with the event name.
|
||||
* @param eventName 'online' or 'offline'
|
||||
* @param expectedState value of gState at the moment the handler is called.
|
||||
* The handler increases gState by one before checking
|
||||
* if it matches expectedState.
|
||||
*/
|
||||
function makeHandler(nameTemplate, eventName, expectedState, prefix, custom) {
|
||||
prefix += ": ";
|
||||
return function(e) {
|
||||
var name = nameTemplate.replace(/%1/, eventName);
|
||||
ok(e.constructor == Event, prefix + "event should be an Event");
|
||||
ok(e.type == eventName, prefix + "event type should be " + eventName);
|
||||
ok(!e.bubbles, prefix + "event should not bubble");
|
||||
ok(!e.cancelable, prefix + "event should not be cancelable");
|
||||
ok(e.target == self, prefix + "the event target should be the worker scope");
|
||||
ok(eventName == 'online' ? navigator.onLine : !navigator.onLine, prefix + "navigator.onLine " + navigator.onLine + " should reflect event " + eventName);
|
||||
|
||||
if (custom) {
|
||||
custom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var lastTest = false;
|
||||
|
||||
function lastTestTest() {
|
||||
if (lastTest) {
|
||||
postMessage({ type: 'finished' });
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
for (var event of ["online", "offline"]) {
|
||||
addEventListener(event,
|
||||
makeHandler(
|
||||
"addEventListener('%1', ..., false)",
|
||||
event, 1, "Child Worker", lastTestTest
|
||||
),
|
||||
false);
|
||||
}
|
||||
|
||||
onmessage = function(e) {
|
||||
if (e.data.type === 'lastTest') {
|
||||
lastTest = true;
|
||||
} else if (e.data.type === 'navigatorState') {
|
||||
ok(e.data.state === navigator.onLine, "Child and parent navigator state should match");
|
||||
}
|
||||
}
|
||||
|
||||
postMessage({ type: 'ready' });
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
function info(text) {
|
||||
dump("Test for Bug 925437: worker: " + text + "\n");
|
||||
}
|
||||
|
||||
function ok(test, message) {
|
||||
postMessage({ type: 'ok', test: test, message: message });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a handler function for an online/offline event. The returned handler
|
||||
* ensures the passed event object has expected properties and that the handler
|
||||
* is called at the right moment (according to the gState variable).
|
||||
* @param nameTemplate The string identifying the hanlder. '%1' in that
|
||||
* string will be replaced with the event name.
|
||||
* @param eventName 'online' or 'offline'
|
||||
* @param expectedState value of gState at the moment the handler is called.
|
||||
* The handler increases gState by one before checking
|
||||
* if it matches expectedState.
|
||||
*/
|
||||
function makeHandler(nameTemplate, eventName, expectedState, prefix, custom) {
|
||||
prefix += ": ";
|
||||
return function(e) {
|
||||
var name = nameTemplate.replace(/%1/, eventName);
|
||||
ok(e.constructor == Event, prefix + "event should be an Event");
|
||||
ok(e.type == eventName, prefix + "event type should be " + eventName);
|
||||
ok(!e.bubbles, prefix + "event should not bubble");
|
||||
ok(!e.cancelable, prefix + "event should not be cancelable");
|
||||
ok(e.target == self, prefix + "the event target should be the worker scope");
|
||||
ok(eventName == 'online' ? navigator.onLine : !navigator.onLine, prefix + "navigator.onLine " + navigator.onLine + " should reflect event " + eventName);
|
||||
|
||||
if (custom) {
|
||||
custom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 925437: online/offline events tests.
|
||||
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 925437 (worker online/offline events)</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=925437">Mozilla Bug 925437</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
addLoadEvent(function() {
|
||||
var w = new Worker("onLine_worker.js");
|
||||
|
||||
w.onmessage = function(e) {
|
||||
if (e.data.type === 'ready') {
|
||||
doTest();
|
||||
} else if (e.data.type === 'ok') {
|
||||
ok(e.data.test, e.data.message);
|
||||
} else if (e.data.type === 'finished') {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
var iosvc = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIIOService2);
|
||||
iosvc.manageOfflineStatus = false;
|
||||
|
||||
info("setting iosvc.offline = true");
|
||||
iosvc.offline = true;
|
||||
|
||||
info("setting iosvc.offline = false");
|
||||
iosvc.offline = false;
|
||||
|
||||
info("setting iosvc.offline = true");
|
||||
iosvc.offline = true;
|
||||
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
iosvc.offline = !iosvc.offline;
|
||||
}
|
||||
|
||||
info("setting iosvc.offline = false");
|
||||
w.postMessage('lastTest');
|
||||
iosvc.offline = false;
|
||||
}
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче