import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1268976 - Assert that the micro-task queues are empty upon destruction of CycleCollectedJSRuntime; r=mccr8 (a459a4af91)
- Bug 1191354 part 1 - Clean up nsHTMLEditRules::GetHighestInlineParent; r=ehsan (a2f401887c)
- Bug 1191354 part 2 - Clean up nsHTMLEditRules::CheckInterlinePosition; r=ehsan (75d3829eec)
- Bug 1191354 part 3 - Clean up nsHTMLEditRules::InsertMozBRIfNeeded; r=ehsan (bedbba7c14)
- Bug 772796 - Handle newlines correctly when joining <div> and <pre>. r=roc (323eaf4fe9)
- Bug 1258085 - Avoid empty whitespace nodes when editing (b77825fb31)
- Bug 1156062 part 4 - Clean up ns*EditRules::WillInsert; r=ehsan (f351557776)
- Bug 1156062 part 5 - Make CreateBR return regular pointer; r=ehsan (8720917dee)
- Bug 1156062 part 6 - Clean up nsHTMLEditRules::WillInsertBreak; r=ehsan (d71bca568f)
- Bug 1156062 part 7 - Clean up nsHTMLEditRules::StandardBreakImpl; r=ehsan (625db32c02)
- Bug 1156062 part 8 - Clean up nsHTMLEditRules::JoinBlocks; r=ehsan (266b6c5150)
- Bug 1156062 part 9 - Clean up nsHTMLEditRules::WillAlign; r=masayuki (a6e3227001)
- Bug 1156062 part 10 - Clean up MarginPropertyAtomForIndent; r=masayuki (28612e062c)
- Bug 1184665 - Remove a spammy editor warning (a2db555918)
- Bug 1156062 part 11 - Clean up nsHTMLEditRules::Before/AfterEdit; r=masayuki (6be722082e)
- Bug 1156062 part 12 - Clean up nsHTMLEditRules::GetAlignment; r=masayuki (350be10ee8)
- Bug 1190172 part 1 - Clean up nsHTMLEditor::SplitStyleAbovePoint; r=ehsan (ce5e360af6)
- Bug 1145395 - Introduce an overload of nsHTMLEditor::SelElementPosition that takes an Element; r=ehsan (7ca9dfd2f8)
- Bug 1190172 part 2 - Clean up nsHTMLEditor::ClearStyle; r=ehsan (84334514ad)
- Bug 1190172 part 3 - Remove old method variants; r=ehsan (e042bd64d5)
- Bug 1190172 part 4 - Remove unused nsHTMLEditor::HasAttr; r=ehsan (a4f1563465)
- Bug 1190172 part 5 - Clean up nsHTMLEditor::NodeIsProperty; r=ehsan (98afb84bd4)
- Bug 1190172 part 6 - Clean up nsHTMLEditor::RelativeFontChangeOnTextNode; r=ehsan (0bf036d206)
- Bug 1190172 part 7 - Clean up nsHTMLEditor::PromoteInlineRange; r=ehsan (0a21347500)
- Bug 1190172 part 8 - Clean up nsHTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor; r=ehsan (78cf619036)
- Bug 1190172 part 9 - Clean up nsHTMLEditor::ReturnInHeader; r=ehsan (1d8d151ff1)
- Bug 1190172 part 10 - Clean up nsHTMLEditor::ReturnInListItem; r=ehsan (0ce94d3cb1)
- Bug 1190172 part 11 - Clean up nsHTMLEditRules::IsEmptyBlock; r=ehsan (a8dc5092f8)
- Bug 1190172 part 12 - Clean up nsHTMLEditRules::ExpandSelectionForDeletion; r=ehsan (3d4a87a56d)
- Bug 1191354 part 4 - Clean up nsHTMLEditRules::AlignBlock; r=ehsan (b39372d726)
- Bug 1191354 part 5 - Clean up nsHTMLEditRules::IsEmptyInline; r=ehsan (0b8ab19fd1)
- Bug 1191354 part 6 - Clean up IsBlockNode/IsInlineNode in nsHTMLEditRules.cpp; r=ehsan (8ba8047e12)
- Bug 1191354 part 7 - Clean up nsHTMLEditRules::CheckForInvisibleBR; r=ehsan (0bc61269bd)
- Bug 1191354 part 8 - Typedefs in headers for readability; r=ehsan (50b43dc3e9)
- Bug 1191354 part 9 - Remove old nsHTMLEditRules::ConvertListType variant; r=ehsan (871f1b30a5)
- Bug 1191354 part 10 - More features for OwningNonNull; r=froydnj (8e365d079a)
- Bug 1191354 part 11 - Clean up nsHTMLEditRules::WillOutdent; r=ehsan (0c59a81c10)
- Bug 1191354 part 12 - Clean up nsHTMLEditRules::OutdentPartOfBlock; r=ehsan (243d7ab42f)
- Bug 1191354 part 13 - Clean up nsHTMLEditRules::SplitBlock; r=ehsan (c1141ab04d)
- Bug 1191356 part 1 - Clean up nsHTMLEditRules::RemoveListStructure; r=ehsan (1d2ad5faa6)
- Bug 1191356 part 2 - Clean up nsHTMLEditor::RemoveBlockContainer; r=ehsan (a9d140f511)
- Bug 1191356 part 3 - Clean up nsHTMLEditRules::MoveBlock; r=ehsan (6bc14cd40c)
- Bug 1191356 part 4 - Clean up nsHTMLEditRules::MoveNodeSmart, MoveContents; r=ehsan (00e6536e47)
- Bug 1191356 part 5 - Clean up nsHTMLEditRules::RelativeChangeIndentationOfElementNode; r=ehsan (c3139c7d90)
- Bug 1191356 part 6 - Clean up nsHTMLEditRules::WillMakeBasicBlock; r=ehsan (b3f73c2e12)
- Bug 1191356 part 7 - Clean up nsHTMLEditor::GetSelectionContainer; r=ehsan (091e999587)
- Bug 1191356 part 8 - Clean up nsHTMLEditRules::WillAbsolutePosition; r=ehsan (9982c65a99)
- Bug 1208884 - Fix a few null check ordering bugs in nsHTMLEditRules::SplitParagraph; r=roc (d04eece297)
- Bug 1209037 - Eliminate some unneeded null checks; r=jdm (b35d5308c5)
- Bug 1191356 part 9 - Convert nsHTMLEditRules::mNewBlock to Element; r=ehsan (f374780e22)
- Bug 1253734 - Add some more editor things to CC traversal. r=mccr8. (94a0c77bb1)
- Bug 1193762 part 1 - Remove nsEditor::IsBlockNode(nsIDOMNode*); r=ehsan (5e107cbdbb)
- Bug 1193762 part 2 - Remove nsHTMLEditor::IsVisBreak(nsIDOMNode*); r=ehsan (5e61c27d21)
- Bug 1193762 part 3 - Remove nsEditor::IsDescendantOfEditorRoot(nsIDOMNode*); r=ehsan (022a37d442)
- Bug 1193762 part 4 - Avoid nsCOMPtr in ternary operator; r=froydnj (e4bc35cbe0)
- Bug 1193762 part 5 - Convert DecodePool::threads to nsTArray; r=froydnj (c61f063f4d)
- Bug 1193762 part 6 - Return raw pointer, not nsCOMPtr; r=froydnj (a43c30f92e)
- Bug 1193762 part 7 - Use .get() when assigning to variables; r=froydnj (a61ad819f0)
- Bug 1193762 part 8 - Fix things that will break; r=froydnj (40a76db662)
- Bug 1193762 part 9 - Delete nsCOMPtr<T>::operator T*()&&; r=froydnj (022c1f0dba)
- Bug 1168223 - Fix a crash caused by unexpected flushes under nsIEditor::SetFlags. r=ehsan (cc49d468b8)
- Bug 1158837 - Ensure the start and end nodes are non-null before using them. r=roc (7c28121aa7)
- Bug 1269047 - Remove chained ENSURE calls from GetStartNodeAndOffset. r=ehsan (f36c1c67aa)
- Bug 1248078 - Remove the dedicated scroll acknowledgement message. r=botond (500b8d7574)
- Bug 1260806: Remove some more dead MessageLoop code. r=jld (1c223cafe8)
- Bug 1266595: Replace Chromium Task with Runnable. r=froydnj (5c1c056c83)
- Bug 1242343 - p1. ConstructSystem32Path from LoadLibrarySystem32 - r=jimm (b28fcbc0c4)
- Bug 1242343 - p2. Blacklist msmpeg2vdec.dll 12.0.9200.16426 & .17037 - r=cpearce (9a71795ab0)
- Bug 1253395 - Disable msmpeg2vdec.dll blackslisting - r=cpearce (e1d4dc47be)
- Bug 1242456 - Create RAIIs to manage HGLOBAL and printer HANDLE in ShowNativePrintDialog and CreateGlobalDevModeAndInit. r=jimm, r=bobowen (a22cecaebd)
- Bug 1262399 - remove Impl suffixes from nsSupports* implementations; r=mccr8 (6733db9394)
- Bug 1268772 (part 1) - Remove nsCheapSet::Put()'s return value. r=erahm. (5f3f553e84)
- Bug 1268772 (part 2) - Make infallible nsVariant methods return |void| instead of |nsresult|. r=erahm. (22ae74fdaf)
- Bug 1268772 (part 3) - Remove NS_NewWindowsRegKey()'s return value. r=erahm. (dc32bd698e)
- Bug 1268772 (part 4) - Use MOZ_MUST_USE with NS_NewISupportsArray(). r=erahm. (e51ecfdf9f)
- Bug 1268772 (part 5) - Use MOZ_MUST_USE in other parts of xpcom/ds/. r=erahm. (4d8a5183eb)
- Bug 1266027 part 1 - make the MediaDecoderReaderWrapper as a proxy of requesting media data; r=jwwang (fbaa79019d)
- Bug 1195601 - Remove MediaDecoderStateMachine::mLogicallySeeking. r=kinetik. (5ab1ff1ca0)
- Bug 1266027 part 2 - make MDSM and SeekTask to adopt new MediaDecoderReaderWrapper API; r=jwwang (1961e26e80)
- add mac specific dupes (4e4ff4b123)
- Bug 1269262 - Unbreak build without NO_EXPAND_LIBS in js/src/moz.build after bug 1239083. r=ted (46d2dec64a)
- Bug 1253215 - Initialize RequestSyncService only if its pref is enabled, r=ehsan (aec1b2f889)
- Bug 1269303 - Remove RequestSync API, r=fabrice (f774336e34)
This commit is contained in:
2024-08-26 15:51:12 +08:00
parent 5851545f5e
commit 8aa2e840a6
241 changed files with 4756 additions and 8828 deletions
-3
View File
@@ -1088,9 +1088,6 @@ pref("dom.mozSettings.SettingsService.verbose.enabled", false);
// readwrite.
pref("dom.mozSettings.allowForceReadOnly", false);
// RequestSync API is enabled by default on B2G.
pref("dom.requestSync.enabled", true);
// Comma separated list of activity names that can only be provided by
// the system app in dev mode.
pref("dom.activities.developer_mode_only", "import-app");
-1
View File
@@ -17,7 +17,6 @@ Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
Cu.import('resource://gre/modules/Keyboard.jsm');
Cu.import('resource://gre/modules/ErrorPage.jsm');
Cu.import('resource://gre/modules/AlertsHelper.jsm');
Cu.import('resource://gre/modules/RequestSyncService.jsm');
Cu.import('resource://gre/modules/SystemUpdateService.jsm');
if (isGonk) {
-3
View File
@@ -373,9 +373,6 @@
@RESPATH@/components/zipwriter.xpt
; JavaScript components
@RESPATH@/components/RequestSync.manifest
@RESPATH@/components/RequestSyncManager.js
@RESPATH@/components/RequestSyncScheduler.js
@RESPATH@/components/ChromeNotifications.js
@RESPATH@/components/ChromeNotifications.manifest
@RESPATH@/components/ConsoleAPI.manifest
+3
View File
@@ -623,6 +623,9 @@ browser/chrome/devtools/skin/images/security-state-weak.svg
browser/chrome/browser/skin/classic/browser/identity-secure.svg
browser/chrome/browser/skin/classic/browser/identity-not-secure.svg
browser/chrome/browser/defaults/permissions
browser/defaults/permissions
#Windows ArcticFox exceptions
chrome/toolkit/skin/classic/mozapps/extensions/category-plugins.png
-4
View File
@@ -554,10 +554,6 @@
@RESPATH@/components/htmlMenuBuilder.js
@RESPATH@/components/htmlMenuBuilder.manifest
@RESPATH@/components/RequestSync.manifest
@RESPATH@/components/RequestSyncManager.js
@RESPATH@/components/RequestSyncScheduler.js
@RESPATH@/components/PermissionSettings.js
@RESPATH@/components/PermissionSettings.manifest
@RESPATH@/components/ContactManager.js
-5
View File
@@ -472,11 +472,6 @@ this.PermissionsTable = { geolocation: {
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"requestsync-manager": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"secureelement-manage": {
app: DENY_ACTION,
privileged: DENY_ACTION,
+1 -1
View File
@@ -29,7 +29,7 @@ AnonymousContent::~AnonymousContent()
{
}
nsCOMPtr<Element>
Element*
AnonymousContent::GetContentNode()
{
return mContentNode;
+1 -1
View File
@@ -25,7 +25,7 @@ public:
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnonymousContent)
explicit AnonymousContent(Element* aContentNode);
nsCOMPtr<Element> GetContentNode();
Element* GetContentNode();
void SetContentNode(Element* aContentNode);
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
+8 -2
View File
@@ -159,7 +159,10 @@ public:
// nullptr if the import is not yet ready.
nsIDocument* GetImport()
{
return mReady ? mDocument : nullptr;
if (!mReady) {
return nullptr;
}
return mDocument;
}
// There is only one referring link that is marked as primary link per
@@ -170,7 +173,10 @@ public:
// a new import link is added to the manager.
nsINode* GetMainReferrer()
{
return mLinks.IsEmpty() ? nullptr : mLinks[mMainReferrer];
if (mLinks.IsEmpty()) {
return nullptr;
}
return mLinks[mMainReferrer];
}
// An import is not only blocked by its import children, but also
+8 -2
View File
@@ -52,7 +52,10 @@ public:
static nsIGlobalObject* IncumbentGlobal() {
ScriptSettingsStackEntry *entry = Top();
return entry ? entry->mGlobalObject : nullptr;
if (!entry) {
return nullptr;
}
return entry->mGlobalObject;
}
static ScriptSettingsStackEntry* EntryPoint() {
@@ -70,7 +73,10 @@ public:
static nsIGlobalObject* EntryGlobal() {
ScriptSettingsStackEntry *entry = EntryPoint();
return entry ? entry->mGlobalObject : nullptr;
if (!entry) {
return nullptr;
}
return entry->mGlobalObject;
}
};
+2 -2
View File
@@ -1314,9 +1314,9 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
// Restore the correct treeowners
// (and also chrome event handlers for content frames only).
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourDocshell, otherOwner,
ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler : nullptr);
ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler.get() : nullptr);
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherDocshell, ourOwner,
ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler : nullptr);
ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler.get() : nullptr);
// Switch the owner content before we start calling AddTreeItemToTreeOwner.
// Note that we rely on this to deal with setting mObservingOwnerContent to
+5 -2
View File
@@ -2092,7 +2092,10 @@ nsIScriptContext *
nsGlobalWindow::GetScriptContext()
{
nsGlobalWindow* outer = GetOuterWindowInternal();
return outer ? outer->mContext : nullptr;
if (!outer) {
return nullptr;
}
return outer->mContext;
}
JSObject *
@@ -7248,7 +7251,7 @@ nsGlobalWindow::PrintOuter(ErrorResult& aError)
if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
getter_AddRefs(webBrowserPrint)))) {
nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ?
GetCurrentInnerWindowInternal()->mDoc :
GetCurrentInnerWindowInternal()->mDoc.get() :
nullptr);
nsCOMPtr<nsIPrintSettingsService> printSettingsService =
+4 -1
View File
@@ -550,7 +550,10 @@ nsXMLHttpRequest::GetResponseXML(ErrorResult& aRv)
mWarnAboutSyncHtml = false;
LogMessage("HTMLSyncXHRWarning", GetOwner());
}
return (XML_HTTP_REQUEST_DONE & mState) ? mResponseXML : nullptr;
if (!(XML_HTTP_REQUEST_DONE & mState)) {
return nullptr;
}
return mResponseXML;
}
/*
+2 -1
View File
@@ -222,7 +222,8 @@ already_AddRefed<ImageBitmap>
OffscreenCanvas::TransferToImageBitmap()
{
ErrorResult rv;
RefPtr<ImageBitmap> result = ImageBitmap::CreateFromOffscreenCanvas(GetGlobalObject(), *this, rv);
nsCOMPtr<nsIGlobalObject> globalObject = GetGlobalObject();
RefPtr<ImageBitmap> result = ImageBitmap::CreateFromOffscreenCanvas(globalObject, *this, rv);
// Clear the content.
if ((mCurrentContextType == CanvasContextType::WebGL1 ||
+1 -7
View File
@@ -1,11 +1,5 @@
/**
* Support logic to run a test file as an installed app. This file is derived
* from dom/requestsync/tests/test_basic_app.html but uses
* DOMApplicationRegistry in a chrome script (shim_app_as_test_chrome.js) to
* directly install the apps instead of mozApps.install because mozApps.install
* can't install privileged/certified apps. (This is the same mechanism used by
* the Firefox OS Gaia email app's backend test runner.)
*
* Support logic to run a test file as an installed app.
* You really only want to do this if your test cares about the app's origin
* or you REALLY want to double-check AvailableIn and other WebIDL-provided
* security mechanisms.
+1 -1
View File
@@ -1899,7 +1899,7 @@ public:
MediaStreamTrackSource)
explicit CaptureStreamTrackSource(HTMLMediaElement* aElement)
: MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()),
: MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()).get(),
true,
nsString())
, mElement(aElement)
+2 -2
View File
@@ -27,14 +27,14 @@ ContentBridgeChild::ContentBridgeChild(Transport* aTransport)
ContentBridgeChild::~ContentBridgeChild()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport);
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
void
ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
{
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentBridgeChild::DeferredDestroy));
}
+2 -3
View File
@@ -26,7 +26,8 @@ ContentBridgeParent::ContentBridgeParent(Transport* aTransport)
ContentBridgeParent::~ContentBridgeParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport);
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
void
@@ -37,7 +38,6 @@ ContentBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
os->RemoveObserver(this, "content-child-shutdown");
}
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentBridgeParent::DeferredDestroy));
}
@@ -169,7 +169,6 @@ ContentBridgeParent::NotifyTabDestroyed()
int32_t numLiveTabs = ManagedPBrowserParent().Count();
if (numLiveTabs == 1) {
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentBridgeParent::Close));
}
}
+5 -5
View File
@@ -1513,7 +1513,7 @@ ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL)
return true;
}
static CancelableTask* sFirstIdleTask;
static CancelableRunnable* sFirstIdleTask;
static void FirstIdle(void)
{
@@ -1594,8 +1594,9 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
hasRunOnce = true;
MOZ_ASSERT(!sFirstIdleTask);
sFirstIdleTask = NewRunnableFunction(FirstIdle);
MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask);
RefPtr<CancelableRunnable> firstIdleTask = NewRunnableFunction(FirstIdle);
sFirstIdleTask = firstIdleTask;
MessageLoop::current()->PostIdleTask(firstIdleTask.forget());
// Redo InitProcessAttributes() when the app or browser is really
// launching so the attributes will be correct.
@@ -2617,8 +2618,7 @@ ContentChild::RecvAppInit()
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
ContentChild::GetSingleton()->RecvGarbageCollect();
MessageLoop::current()->PostTask(
FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation));
MessageLoop::current()->PostTask(NewRunnableFunction(OnFinishNuwaPreparation));
}
#endif
+1 -5
View File
@@ -793,8 +793,7 @@ ContentParent::JoinAllSubprocesses()
bool done = false;
Monitor monitor("mozilla.dom.ContentParent.JoinAllSubprocesses");
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
NewRunnableFunction(
XRE_GetIOMessageLoop()->PostTask(NewRunnableFunction(
&ContentParent::JoinProcessesIOThread,
&processes, &monitor, &done));
{
@@ -2173,7 +2172,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
for(uint32_t i = 0; i < childIDArray.Length(); i++) {
ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(cp, &ContentParent::ShutDownProcess,
SEND_SHUTDOWN_MESSAGE));
}
@@ -2257,7 +2255,6 @@ ContentParent::NotifyTabDestroyed(const TabId& aTabId,
// In the case of normal shutdown, send a shutdown message to child to
// allow it to perform shutdown tasks.
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentParent::ShutDownProcess,
SEND_SHUTDOWN_MESSAGE));
}
@@ -3622,7 +3619,6 @@ ContentParent::KillHard(const char* aReason)
// EnsureProcessTerminated has responsibilty for closing otherProcessHandle.
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated,
otherProcessHandle, /*force=*/true));
}
+3 -5
View File
@@ -205,7 +205,6 @@ PreallocatedProcessManagerImpl::AllocateAfterDelay()
}
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle),
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
DEFAULT_ALLOCATE_DELAY));
@@ -219,7 +218,6 @@ PreallocatedProcessManagerImpl::AllocateOnIdle()
}
MessageLoop::current()->PostIdleTask(
FROM_HERE,
NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateNow));
}
@@ -245,10 +243,10 @@ PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork()
return;
}
mPreallocateAppProcessTask = NewRunnableMethod(
RefPtr<CancelableTask> task = NewRunnableMethod(
this, &PreallocatedProcessManagerImpl::DelayedNuwaFork);
MessageLoop::current()->PostDelayedTask(
FROM_HERE, mPreallocateAppProcessTask,
mPreallocateAppProcessTask = task;
MessageLoop::current()->PostDelayedTask(task.forget(),
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
DEFAULT_ALLOCATE_DELAY));
}
+4 -12
View File
@@ -265,7 +265,8 @@ HangMonitorChild::~HangMonitorChild()
{
// For some reason IPDL doesn't automatically delete the channel for a
// bridged protocol (bug 1090570). So we have to do it ourselves.
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sInstance == this);
@@ -303,7 +304,6 @@ HangMonitorChild::ActorDestroy(ActorDestroyReason aWhy)
// We use a task here to ensure that IPDL is finished with this
// HangMonitorChild before it gets deleted on the main thread.
MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &HangMonitorChild::ShutdownOnThread));
}
@@ -391,7 +391,6 @@ HangMonitorChild::NotifySlowScript(nsITabChild* aTabChild,
nsAutoCString filename(aFileName);
MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &HangMonitorChild::NotifySlowScriptAsync,
id, filename, aLineNo));
return SlowScriptAction::Continue;
@@ -422,7 +421,6 @@ HangMonitorChild::NotifyPluginHang(uint32_t aPluginId)
// bounce to background thread
MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(this,
&HangMonitorChild::NotifyPluginHangAsync,
aPluginId));
@@ -448,7 +446,6 @@ HangMonitorChild::ClearHang()
if (mSentReport) {
// bounce to background thread
MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &HangMonitorChild::ClearHangAsync));
MonitorAutoLock lock(mMonitor);
@@ -487,7 +484,8 @@ HangMonitorParent::~HangMonitorParent()
{
// For some reason IPDL doesn't automatically delete the channel for a
// bridged protocol (bug 1090570). So we have to do it ourselves.
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
#ifdef MOZ_CRASHREPORTER
MutexAutoLock lock(mBrowserCrashDumpHashLock);
@@ -514,7 +512,6 @@ HangMonitorParent::Shutdown()
}
MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &HangMonitorParent::ShutdownOnThread));
while (!mShutdownDone) {
@@ -836,7 +833,6 @@ HangMonitoredProcess::TerminateScript()
}
ProcessHangMonitor::Get()->MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(mActor, &HangMonitorParent::TerminateScript));
return NS_OK;
}
@@ -854,7 +850,6 @@ HangMonitoredProcess::BeginStartingDebugger()
}
ProcessHangMonitor::Get()->MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(mActor, &HangMonitorParent::BeginStartingDebugger));
return NS_OK;
}
@@ -872,7 +867,6 @@ HangMonitoredProcess::EndStartingDebugger()
}
ProcessHangMonitor::Get()->MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(mActor, &HangMonitorParent::EndStartingDebugger));
return NS_OK;
}
@@ -1052,7 +1046,6 @@ mozilla::CreateHangMonitorParent(ContentParent* aContentParent,
parent->SetProcess(process);
monitor->MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(parent, &HangMonitorParent::Open,
aTransport, aOtherPid, XRE_GetIOMessageLoop()));
@@ -1069,7 +1062,6 @@ mozilla::CreateHangMonitorChild(mozilla::ipc::Transport* aTransport,
HangMonitorChild* child = new HangMonitorChild(monitor);
monitor->MonitorLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(child, &HangMonitorChild::Open,
aTransport, aOtherPid, XRE_GetIOMessageLoop()));
+50
View File
@@ -0,0 +1,50 @@
#include "MediaCallbackID.h"
namespace mozilla {
char const* CallbackID::INVALID_TAG = "INVALID_TAG";
int32_t const CallbackID::INVALID_ID = -1;
CallbackID::CallbackID()
: mTag(INVALID_TAG), mID(INVALID_ID)
{
}
CallbackID::CallbackID(char const* aTag, int32_t aID /* = 0*/)
: mTag(aTag), mID(aID)
{
}
CallbackID&
CallbackID::operator++()
{
++mID;
return *this;
}
CallbackID
CallbackID::operator++(int)
{
CallbackID ret = *this;
++(*this); // call prefix++
return ret;
}
bool
CallbackID::operator==(const CallbackID& rhs) const
{
return (strcmp(mTag, rhs.mTag) == 0) && (mID == rhs.mID);
}
bool
CallbackID::operator!=(const CallbackID& rhs) const
{
return !(*this == rhs);
}
CallbackID::operator int() const
{
return mID;
}
} // namespace mozilla
+38
View File
@@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MediaCallbackID_h_
#define MediaCallbackID_h_
namespace mozilla {
struct CallbackID
{
static char const* INVALID_TAG;
static int32_t const INVALID_ID;
CallbackID();
explicit CallbackID(char const* aTag, int32_t aID = 0);
CallbackID& operator++(); // prefix++
CallbackID operator++(int); // postfix++
bool operator==(const CallbackID& rhs) const;
bool operator!=(const CallbackID& rhs) const;
operator int() const;
private:
char const* mTag;
int32_t mID;
};
} // namespace mozilla
#endif // MediaCallbackID_h_
+92 -14
View File
@@ -144,6 +144,8 @@ MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(bool aIsRealTime,
: mForceZeroStartTime(aIsRealTime || aReader->ForceZeroStartTime())
, mOwnerThread(aOwnerThread)
, mReader(aReader)
, mAudioCallbackID("AudioCallbackID")
, mVideoCallbackID("VideoCallbackID")
{}
MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
@@ -178,11 +180,30 @@ MediaDecoderReaderWrapper::AwaitStartTime()
return mStartTimeRendezvous->AwaitStartTime();
}
RefPtr<MediaDecoderReaderWrapper::MediaDataPromise>
void
MediaDecoderReaderWrapper::CancelAudioCallback(CallbackID aID)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(aID == mAudioCallbackID);
++mAudioCallbackID;
mRequestAudioDataCB = nullptr;
}
void
MediaDecoderReaderWrapper::CancelVideoCallback(CallbackID aID)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(aID == mVideoCallbackID);
++mVideoCallbackID;
mRequestVideoDataCB = nullptr;
}
void
MediaDecoderReaderWrapper::RequestAudioData()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
MOZ_ASSERT(mRequestAudioDataCB, "Request audio data without callback!");
auto p = InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
&MediaDecoderReader::RequestAudioData);
@@ -194,18 +215,31 @@ MediaDecoderReaderWrapper::RequestAudioData()
->CompletionPromise();
}
return p->Then(mOwnerThread, __func__, this,
&MediaDecoderReaderWrapper::OnSampleDecoded,
&MediaDecoderReaderWrapper::OnNotDecoded)
->CompletionPromise();
RefPtr<MediaDecoderReaderWrapper> self = this;
mAudioDataRequest.Begin(p->Then(mOwnerThread, __func__,
[self] (MediaData* aAudioSample) {
MOZ_ASSERT(self->mRequestAudioDataCB);
self->mAudioDataRequest.Complete();
self->OnSampleDecoded(self->mRequestAudioDataCB.get(), aAudioSample, TimeStamp());
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
MOZ_ASSERT(self->mRequestAudioDataCB);
self->mAudioDataRequest.Complete();
self->OnNotDecoded(self->mRequestAudioDataCB.get(), aReason);
}));
}
RefPtr<MediaDecoderReaderWrapper::MediaDataPromise>
void
MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
media::TimeUnit aTimeThreshold)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
MOZ_ASSERT(mRequestVideoDataCB, "Request video data without callback!");
// Time the video decode and send this value back to callbacks who accept
// a TimeStamp as its second parameter.
TimeStamp videoDecodeStartTime = TimeStamp::Now();
if (aTimeThreshold.ToMicroseconds() > 0 &&
mStartTimeRendezvous->HaveStartTime()) {
@@ -223,10 +257,32 @@ MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
->CompletionPromise();
}
return p->Then(mOwnerThread, __func__, this,
&MediaDecoderReaderWrapper::OnSampleDecoded,
&MediaDecoderReaderWrapper::OnNotDecoded)
->CompletionPromise();
RefPtr<MediaDecoderReaderWrapper> self = this;
mVideoDataRequest.Begin(p->Then(mOwnerThread, __func__,
[self, videoDecodeStartTime] (MediaData* aVideoSample) {
MOZ_ASSERT(self->mRequestVideoDataCB);
self->mVideoDataRequest.Complete();
self->OnSampleDecoded(self->mRequestVideoDataCB.get(), aVideoSample, videoDecodeStartTime);
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
MOZ_ASSERT(self->mRequestVideoDataCB);
self->mVideoDataRequest.Complete();
self->OnNotDecoded(self->mRequestVideoDataCB.get(), aReason);
}));
}
bool
MediaDecoderReaderWrapper::IsRequestingAudioData() const
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
return mAudioDataRequest.Exists();
}
bool
MediaDecoderReaderWrapper::IsRequestingVidoeData() const
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
return mVideoDataRequest.Exists();
}
RefPtr<MediaDecoderReader::SeekPromise>
@@ -277,6 +333,10 @@ void
MediaDecoderReaderWrapper::ResetDecode()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
mAudioDataRequest.DisconnectIfExists();
mVideoDataRequest.DisconnectIfExists();
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode);
mReader->OwnerThread()->Dispatch(r.forget());
@@ -286,6 +346,11 @@ RefPtr<ShutdownPromise>
MediaDecoderReaderWrapper::Shutdown()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mRequestAudioDataCB);
MOZ_ASSERT(!mRequestVideoDataCB);
MOZ_ASSERT(!mAudioDataRequest.Exists());
MOZ_ASSERT(!mVideoDataRequest.Exists());
mShutdown = true;
if (mStartTimeRendezvous) {
mStartTimeRendezvous->Destroy();
@@ -323,12 +388,25 @@ MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder* aMetadata)
}
void
MediaDecoderReaderWrapper::OnSampleDecoded(MediaData* aSample)
MediaDecoderReaderWrapper::OnSampleDecoded(CallbackBase* aCallback,
MediaData* aSample,
TimeStamp aDecodeStartTime)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
if (!mShutdown) {
aSample->AdjustForStartTime(StartTime().ToMicroseconds());
}
MOZ_ASSERT(!mShutdown);
aSample->AdjustForStartTime(StartTime().ToMicroseconds());
aCallback->OnResolved(aSample, aDecodeStartTime);
}
void
MediaDecoderReaderWrapper::OnNotDecoded(CallbackBase* aCallback,
MediaDecoderReader::NotDecodedReason aReason)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
aCallback->OnRejected(aReason);
}
} // namespace mozilla
+222 -5
View File
@@ -12,6 +12,7 @@
#include "nsISupportsImpl.h"
#include "MediaDecoderReader.h"
#include "MediaCallbackID.h"
namespace mozilla {
@@ -33,6 +34,135 @@ class MediaDecoderReaderWrapper {
typedef MediaDecoderReader::BufferedUpdatePromise BufferedUpdatePromise;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReaderWrapper);
/*
* Type 1: void(MediaData*)
* void(RefPtr<MediaData>)
*/
template <typename T>
class ArgType1CheckHelper {
template<typename C, typename... Ts>
static TrueType
test(void(C::*aMethod)(Ts...),
decltype((DeclVal<C>().*aMethod)(DeclVal<MediaData*>()), 0));
template <typename F>
static TrueType
test(F&&, decltype(DeclVal<F>()(DeclVal<MediaData*>()), 0));
static FalseType test(...);
public:
typedef decltype(test(DeclVal<T>(), 0)) Type;
};
template <typename T>
struct ArgType1Check : public ArgType1CheckHelper<T>::Type {};
/*
* Type 2: void(MediaData*, TimeStamp)
* void(RefPtr<MediaData>, TimeStamp)
* void(MediaData*, TimeStamp&)
* void(RefPtr<MediaData>, const TimeStamp&&)
*/
template <typename T>
class ArgType2CheckHelper {
template<typename C, typename... Ts>
static TrueType
test(void(C::*aMethod)(Ts...),
decltype((DeclVal<C>().*aMethod)(DeclVal<MediaData*>(), DeclVal<TimeStamp>()), 0));
template <typename F>
static TrueType
test(F&&, decltype(DeclVal<F>()(DeclVal<MediaData*>(), DeclVal<TimeStamp>()), 0));
static FalseType test(...);
public:
typedef decltype(test(DeclVal<T>(), 0)) Type;
};
template <typename T>
struct ArgType2Check : public ArgType2CheckHelper<T>::Type {};
struct CallbackBase
{
virtual ~CallbackBase() {}
virtual void OnResolved(MediaData*, TimeStamp) = 0;
virtual void OnRejected(MediaDecoderReader::NotDecodedReason) = 0;
};
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
struct MethodCallback : public CallbackBase
{
MethodCallback(ThisType* aThis, ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
: mThis(aThis), mResolveMethod(aResolveMethod), mRejectMethod(aRejectMethod)
{
}
template<typename F>
typename EnableIf<ArgType1Check<F>::value, void>::Type
CallHelper(MediaData* aSample, TimeStamp)
{
(mThis->*mResolveMethod)(aSample);
}
template<typename F>
typename EnableIf<ArgType2Check<F>::value, void>::Type
CallHelper(MediaData* aSample, TimeStamp aDecodeStartTime)
{
(mThis->*mResolveMethod)(aSample, aDecodeStartTime);
}
void OnResolved(MediaData* aSample, TimeStamp aDecodeStartTime) override
{
CallHelper<ResolveMethodType>(aSample, aDecodeStartTime);
}
void OnRejected(MediaDecoderReader::NotDecodedReason aReason) override
{
(mThis->*mRejectMethod)(aReason);
}
RefPtr<ThisType> mThis;
ResolveMethodType mResolveMethod;
RejectMethodType mRejectMethod;
};
template<typename ResolveFunctionType, typename RejectFunctionType>
struct FunctionCallback : public CallbackBase
{
FunctionCallback(ResolveFunctionType&& aResolveFuntion, RejectFunctionType&& aRejectFunction)
: mResolveFuntion(Move(aResolveFuntion)), mRejectFunction(Move(aRejectFunction))
{
}
template<typename F>
typename EnableIf<ArgType1Check<F>::value, void>::Type
CallHelper(MediaData* aSample, TimeStamp)
{
mResolveFuntion(aSample);
}
template<typename F>
typename EnableIf<ArgType2Check<F>::value, void>::Type
CallHelper(MediaData* aSample, TimeStamp aDecodeStartTime)
{
mResolveFuntion(aSample, aDecodeStartTime);
}
void OnResolved(MediaData* aSample, TimeStamp aDecodeStartTime) override
{
CallHelper<ResolveFunctionType>(aSample, aDecodeStartTime);
}
void OnRejected(MediaDecoderReader::NotDecodedReason aReason) override
{
mRejectFunction(aReason);
}
ResolveFunctionType mResolveFuntion;
RejectFunctionType mRejectFunction;
};
public:
MediaDecoderReaderWrapper(bool aIsRealTime,
AbstractThread* aOwnerThread,
@@ -41,9 +171,83 @@ public:
media::TimeUnit StartTime() const;
RefPtr<MetadataPromise> ReadMetadata();
RefPtr<HaveStartTimePromise> AwaitStartTime();
RefPtr<MediaDataPromise> RequestAudioData();
RefPtr<MediaDataPromise> RequestVideoData(bool aSkipToNextKeyframe,
media::TimeUnit aTimeThreshold);
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
CallbackID
SetAudioCallback(ThisType* aThisVal,
ResolveMethodType aResolveMethod,
RejectMethodType aRejectMethod)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mRequestAudioDataCB,
"Please cancel the original callback before setting a new one.");
mRequestAudioDataCB.reset(
new MethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
aThisVal, aResolveMethod, aRejectMethod));
return mAudioCallbackID;
}
template<typename ResolveFunction, typename RejectFunction>
CallbackID
SetAudioCallback(ResolveFunction&& aResolveFunction,
RejectFunction&& aRejectFunction)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mRequestAudioDataCB,
"Please cancel the original callback before setting a new one.");
mRequestAudioDataCB.reset(
new FunctionCallback<ResolveFunction, RejectFunction>(
Move(aResolveFunction), Move(aRejectFunction)));
return mAudioCallbackID;
}
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
CallbackID
SetVideoCallback(ThisType* aThisVal,
ResolveMethodType aResolveMethod,
RejectMethodType aRejectMethod)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mRequestVideoDataCB,
"Please cancel the original callback before setting a new one.");
mRequestVideoDataCB.reset(
new MethodCallback<ThisType, ResolveMethodType, RejectMethodType>(
aThisVal, aResolveMethod, aRejectMethod));
return mVideoCallbackID;
}
template<typename ResolveFunction, typename RejectFunction>
CallbackID
SetVideoCallback(ResolveFunction&& aResolveFunction,
RejectFunction&& aRejectFunction)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mRequestVideoDataCB,
"Please cancel the original callback before setting a new one.");
mRequestVideoDataCB.reset(
new FunctionCallback<ResolveFunction, RejectFunction>(
Move(aResolveFunction), Move(aRejectFunction)));
return mVideoCallbackID;
}
void CancelAudioCallback(CallbackID aID);
void CancelVideoCallback(CallbackID aID);
// NOTE: please set callbacks before requesting audio/video data!
void RequestAudioData();
void RequestVideoData(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
bool IsRequestingAudioData() const;
bool IsRequestingVidoeData() const;
RefPtr<SeekPromise> Seek(SeekTarget aTarget, media::TimeUnit aEndTime);
RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType);
RefPtr<BufferedUpdatePromise> UpdateBufferedWithPromise();
@@ -96,8 +300,10 @@ private:
void OnMetadataRead(MetadataHolder* aMetadata);
void OnMetadataNotRead() {}
void OnSampleDecoded(MediaData* aSample);
void OnNotDecoded() {}
void OnSampleDecoded(CallbackBase* aCallback, MediaData* aSample,
TimeStamp aVideoDecodeStartTime);
void OnNotDecoded(CallbackBase* aCallback,
MediaDecoderReader::NotDecodedReason aReason);
const bool mForceZeroStartTime;
const RefPtr<AbstractThread> mOwnerThread;
@@ -105,6 +311,17 @@ private:
bool mShutdown = false;
RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
UniquePtr<CallbackBase> mRequestAudioDataCB;
UniquePtr<CallbackBase> mRequestVideoDataCB;
MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
/*
* These callback ids are used to prevent mis-canceling callback.
*/
CallbackID mAudioCallbackID;
CallbackID mVideoCallbackID;
};
} // namespace mozilla
+99 -63
View File
@@ -258,8 +258,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
"MediaDecoderStateMachine::mPlayState (Mirror)"),
mNextPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_PAUSED,
"MediaDecoderStateMachine::mNextPlayState (Mirror)"),
mLogicallySeeking(mTaskQueue, false,
"MediaDecoderStateMachine::mLogicallySeeking (Mirror)"),
mVolume(mTaskQueue, 1.0, "MediaDecoderStateMachine::mVolume (Mirror)"),
mLogicalPlaybackRate(mTaskQueue, 1.0,
"MediaDecoderStateMachine::mLogicalPlaybackRate (Mirror)"),
@@ -331,7 +329,6 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
mExplicitDuration.Connect(aDecoder->CanonicalExplicitDuration());
mPlayState.Connect(aDecoder->CanonicalPlayState());
mNextPlayState.Connect(aDecoder->CanonicalNextPlayState());
mLogicallySeeking.Connect(aDecoder->CanonicalLogicallySeeking());
mVolume.Connect(aDecoder->CanonicalVolume());
mLogicalPlaybackRate.Connect(aDecoder->CanonicalPlaybackRate());
mPreservesPitch.Connect(aDecoder->CanonicalPreservesPitch());
@@ -355,7 +352,9 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
mWatchManager.Watch(mExplicitDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mObservedDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged);
// Configure MediaDecoderReaderWrapper.
SetMediaDecoderReaderWrapperCallback();
}
media::MediaSink*
@@ -564,7 +563,6 @@ MediaDecoderStateMachine::OnAudioDecoded(MediaData* aAudioSample)
RefPtr<MediaData> audio(aAudioSample);
MOZ_ASSERT(audio);
mAudioDataRequest.Complete();
// audio->GetEndTime() is not always mono-increasing in chained ogg.
mDecodedAudioEndTime = std::max(audio->GetEndTime(), mDecodedAudioEndTime);
@@ -678,11 +676,6 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
bool isAudio = aType == MediaData::AUDIO_DATA;
MOZ_ASSERT_IF(!isAudio, aType == MediaData::VIDEO_DATA);
if (isAudio) {
mAudioDataRequest.Complete();
} else {
mVideoDataRequest.Complete();
}
if (IsShutdown()) {
// Already shutdown;
return;
@@ -797,7 +790,6 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample,
RefPtr<MediaData> video(aVideoSample);
MOZ_ASSERT(video);
mVideoDataRequest.Complete();
// Handle abnormal or negative timestamps.
mDecodedVideoEndTime = std::max(mDecodedVideoEndTime, video->GetEndTime());
@@ -931,6 +923,33 @@ nsresult MediaDecoderStateMachine::Init(MediaDecoder* aDecoder)
return NS_OK;
}
void
MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
{
mAudioCallbackID =
mReader->SetAudioCallback(this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded);
mVideoCallbackID =
mReader->SetVideoCallback(this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded);
DECODER_LOG("MDSM set audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
DECODER_LOG("MDSM set video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
}
void
MediaDecoderStateMachine::CancelMediaDecoderReaderWrapperCallback()
{
DECODER_LOG("MDSM cancel audio callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
mReader->CancelAudioCallback(mAudioCallbackID);
DECODER_LOG("MDSM cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
mReader->CancelVideoCallback(mVideoCallbackID);
}
void MediaDecoderStateMachine::StopPlayback()
{
MOZ_ASSERT(OnTaskQueue());
@@ -1153,10 +1172,7 @@ MediaDecoderStateMachine::SetDormant(bool aDormant)
}
// Discard the current seek task.
if (mSeekTask) {
mSeekTask->Discard();
mSeekTask = nullptr;
}
DiscardSeekTaskIfExist();
SetState(DECODER_STATE_DORMANT);
if (IsPlaying()) {
@@ -1193,10 +1209,8 @@ MediaDecoderStateMachine::Shutdown()
mBufferedUpdateRequest.DisconnectIfExists();
mQueuedSeek.RejectIfExists(__func__);
if (mSeekTask) {
mSeekTask->Discard();
mSeekTask = nullptr;
}
DiscardSeekTaskIfExist();
#ifdef MOZ_EME
mCDMProxyPromise.DisconnectIfExists();
@@ -1206,6 +1220,9 @@ MediaDecoderStateMachine::Shutdown()
StopPlayback();
}
// To break the cycle-reference between MediaDecoderReaderWrapper and MDSM.
CancelMediaDecoderReaderWrapperCallback();
Reset();
mMediaSink->Shutdown();
@@ -1309,12 +1326,6 @@ void MediaDecoderStateMachine::PlayStateChanged()
ScheduleStateMachine();
}
void MediaDecoderStateMachine::LogicallySeekingChanged()
{
MOZ_ASSERT(OnTaskQueue());
ScheduleStateMachine();
}
void MediaDecoderStateMachine::BufferedRangeUpdated()
{
MOZ_ASSERT(OnTaskQueue());
@@ -1467,12 +1478,13 @@ MediaDecoderStateMachine::InitiateSeek(SeekJob aSeekJob)
MOZ_ASSERT(OnTaskQueue());
// Discard the existing seek task.
if (mSeekTask) {
mSeekTask->Discard();
}
DiscardSeekTaskIfExist();
mSeekTaskRequest.DisconnectIfExists();
// SeekTask will register its callbacks to MediaDecoderReaderWrapper.
CancelMediaDecoderReaderWrapperCallback();
// Create a new SeekTask instance for the incoming seek task.
mSeekTask = SeekTask::CreateSeekTask(mDecoderID, OwnerThread(),
mReader.get(), Move(aSeekJob),
@@ -1535,9 +1547,6 @@ MediaDecoderStateMachine::OnSeekTaskResolved(SeekTaskResolveValue aValue)
}
SeekCompleted();
mSeekTask->Discard();
mSeekTask = nullptr;
}
void
@@ -1568,8 +1577,19 @@ MediaDecoderStateMachine::OnSeekTaskRejected(SeekTaskRejectValue aValue)
DecodeError();
mSeekTask->Discard();
mSeekTask = nullptr;
DiscardSeekTaskIfExist();
}
void
MediaDecoderStateMachine::DiscardSeekTaskIfExist()
{
if (mSeekTask) {
mSeekTask->Discard();
mSeekTask = nullptr;
// Reset the MediaDecoderReaderWrapper's callbask.
SetMediaDecoderReaderWrapperCallback();
}
}
nsresult
@@ -1602,7 +1622,7 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
return NS_OK;
}
if (!IsAudioDecoding() || mAudioDataRequest.Exists() ||
if (!IsAudioDecoding() || mReader->IsRequestingAudioData() ||
mAudioWaitRequest.Exists()) {
return NS_OK;
}
@@ -1620,11 +1640,7 @@ MediaDecoderStateMachine::RequestAudioData()
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
mAudioDataRequest.Begin(
mReader->RequestAudioData()
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded));
mReader->RequestAudioData();
}
nsresult
@@ -1657,7 +1673,7 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
return NS_OK;
}
if (!IsVideoDecoding() || mVideoDataRequest.Exists() ||
if (!IsVideoDecoding() || mReader->IsRequestingVidoeData() ||
mVideoWaitRequest.Exists()) {
return NS_OK;
}
@@ -1672,11 +1688,6 @@ MediaDecoderStateMachine::RequestVideoData()
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState != DECODER_STATE_SEEKING);
// Time the video decode, so that if it's slow, we can increase our low
// audio threshold to reduce the chance of an audio underrun while we're
// waiting for a video decode to complete.
TimeStamp videoDecodeStartTime = TimeStamp::Now();
bool skipToNextKeyFrame = mSentFirstFrameLoadedEvent &&
NeedToSkipToNextKeyframe();
@@ -1686,16 +1697,11 @@ MediaDecoderStateMachine::RequestVideoData()
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
currentTime.ToMicroseconds());
RefPtr<MediaDecoderStateMachine> self = this;
mVideoDataRequest.Begin(
mReader->RequestVideoData(skipToNextKeyFrame, currentTime)
->Then(OwnerThread(), __func__,
[self, videoDecodeStartTime] (MediaData* aVideoSample) {
self->OnVideoDecoded(aVideoSample, videoDecodeStartTime);
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
self->OnVideoNotDecoded(aReason);
}));
// MediaDecoderReaderWrapper::RequestVideoData() records the decoding start
// time and sent it back to MDSM::OnVideoDecoded() so that if the decoding is
// slow, we can increase our low audio threshold to reduce the chance of an
// audio underrun while we're waiting for a video decode to complete.
mReader->RequestVideoData(skipToNextKeyFrame, currentTime);
}
void
@@ -2016,6 +2022,15 @@ MediaDecoderStateMachine::SeekCompleted()
// to ensure that the seeked event is fired prior loadeded.
mSeekTask->GetSeekJob().Resolve(nextState == DECODER_STATE_COMPLETED, __func__);
// Discard and nullify the seek task.
// Reset the MediaDecoderReaderWrapper's callbask.
DiscardSeekTaskIfExist();
// NOTE: Discarding the mSeekTask must be done before here. The following code
// might ask the MediaDecoderReaderWrapper to request media data, however, the
// SeekTask::Discard() will ask MediaDecoderReaderWrapper to discard media
// data requests.
if (mDecodingFirstFrame) {
// We were resuming from dormant, or initiated a seek early.
// We can fire loadeddata now.
@@ -2074,7 +2089,6 @@ MediaDecoderStateMachine::FinishShutdown()
mExplicitDuration.DisconnectIfConnected();
mPlayState.DisconnectIfConnected();
mNextPlayState.DisconnectIfConnected();
mLogicallySeeking.DisconnectIfConnected();
mVolume.DisconnectIfConnected();
mLogicalPlaybackRate.DisconnectIfConnected();
mPreservesPitch.DisconnectIfConnected();
@@ -2138,7 +2152,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
UpdatePlaybackPositionPeriodically();
NS_ASSERTION(!IsPlaying() ||
mLogicallySeeking ||
IsStateMachineScheduled(),
"Must have timer scheduled");
return NS_OK;
@@ -2170,8 +2183,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Don't yet have a strategy for non-heuristic + non-WaitForData");
DispatchDecodeTasksIfNeeded();
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mAudioDataRequest.Exists() || mAudioWaitRequest.Exists());
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mVideoDataRequest.Exists() || mVideoWaitRequest.Exists());
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mAudioWaitRequest.Exists());
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mReader->IsRequestingVidoeData() || mVideoWaitRequest.Exists());
DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
"mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
OutOfDecodedAudio(), AudioRequestStatus(),
@@ -2204,7 +2217,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
MaybeStartPlayback();
UpdatePlaybackPositionPeriodically();
NS_ASSERTION(!IsPlaying() ||
mLogicallySeeking ||
IsStateMachineScheduled(),
"Must have timer scheduled");
return NS_OK;
@@ -2266,9 +2278,7 @@ MediaDecoderStateMachine::Reset()
VideoQueue().Reset();
mMetadataRequest.DisconnectIfExists();
mAudioDataRequest.DisconnectIfExists();
mAudioWaitRequest.DisconnectIfExists();
mVideoDataRequest.DisconnectIfExists();
mVideoWaitRequest.DisconnectIfExists();
mSeekTaskRequest.DisconnectIfExists();
@@ -2291,7 +2301,7 @@ MediaDecoderStateMachine::UpdatePlaybackPositionPeriodically()
{
MOZ_ASSERT(OnTaskQueue());
if (!IsPlaying() || mLogicallySeeking) {
if (!IsPlaying()) {
return;
}
@@ -2737,6 +2747,32 @@ MediaDecoderStateMachine::OnMediaNotSeekable() const
return mReader->OnMediaNotSeekable();
}
const char*
MediaDecoderStateMachine::AudioRequestStatus() const
{
MOZ_ASSERT(OnTaskQueue());
if (mReader->IsRequestingAudioData()) {
MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
return "pending";
} else if (mAudioWaitRequest.Exists()) {
return "waiting";
}
return "idle";
}
const char*
MediaDecoderStateMachine::VideoRequestStatus() const
{
MOZ_ASSERT(OnTaskQueue());
if (mReader->IsRequestingVidoeData()) {
MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
return "pending";
} else if (mVideoWaitRequest.Exists()) {
return "waiting";
}
return "idle";
}
} // namespace mozilla
// avoid redefined macro in unified build
+12 -28
View File
@@ -87,6 +87,7 @@ hardware (via AudioStream).
#include "mozilla/StateMirroring.h"
#include "nsThreadUtils.h"
#include "MediaCallbackID.h"
#include "MediaDecoder.h"
#include "MediaDecoderReader.h"
#include "MediaDecoderOwner.h"
@@ -143,6 +144,9 @@ public:
nsresult Init(MediaDecoder* aDecoder);
void SetMediaDecoderReaderWrapperCallback();
void CancelMediaDecoderReaderWrapperCallback();
// Enumeration for the valid decoding states
enum State {
DECODER_STATE_DECODING_METADATA,
@@ -467,9 +471,6 @@ protected:
// Notification method invoked when mPlayState changes.
void PlayStateChanged();
// Notification method invoked when mLogicallySeeking changes.
void LogicallySeekingChanged();
// Sets internal state which causes playback of media to pause.
// The decoder monitor must be held.
void StopPlayback();
@@ -682,6 +683,10 @@ private:
void OnSeekTaskResolved(SeekTaskResolveValue aValue);
void OnSeekTaskRejected(SeekTaskRejectValue aValue);
// This method discards the seek task and then get the ownership of
// MedaiDecoderReaderWarpper back via registering MDSM's callback into it.
void DiscardSeekTaskIfExist();
// Media Fragment end time in microseconds. Access controlled by decoder monitor.
int64_t mFragmentEndTime;
@@ -810,33 +815,13 @@ private:
// Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
// should exist at any given moment.
MozPromiseRequestHolder<MediaDecoderReader::MediaDataPromise> mAudioDataRequest;
CallbackID mAudioCallbackID;
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
const char* AudioRequestStatus()
{
MOZ_ASSERT(OnTaskQueue());
if (mAudioDataRequest.Exists()) {
MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
return "pending";
} else if (mAudioWaitRequest.Exists()) {
return "waiting";
}
return "idle";
}
const char* AudioRequestStatus() const;
CallbackID mVideoCallbackID;
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
MozPromiseRequestHolder<MediaDecoderReader::MediaDataPromise> mVideoDataRequest;
const char* VideoRequestStatus()
{
MOZ_ASSERT(OnTaskQueue());
if (mVideoDataRequest.Exists()) {
MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
return "pending";
} else if (mVideoWaitRequest.Exists()) {
return "waiting";
}
return "idle";
}
const char* VideoRequestStatus() const;
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
{
@@ -980,7 +965,6 @@ private:
// The current play state and next play state, mirrored from the main thread.
Mirror<MediaDecoder::PlayState> mPlayState;
Mirror<MediaDecoder::PlayState> mNextPlayState;
Mirror<bool> mLogicallySeeking;
// Volume of playback. 0.0 = muted. 1.0 = full volume.
Mirror<double> mVolume;
+67 -55
View File
@@ -246,7 +246,7 @@ HostHasPermission(nsIURI &docURI)
// Generic class for running long media operations like Start off the main
// thread, and then (because nsDOMMediaStreams aren't threadsafe),
// ProxyReleases mStream since it's cycle collected.
class MediaOperationTask : public Task
class MediaOperationTask : public Runnable
{
public:
// so we can send Stop without AddRef()ing from the MSG thread
@@ -280,14 +280,14 @@ public:
void
ReturnCallbackError(nsresult rv, const char* errorLog);
void
Run()
NS_IMETHOD
Run() override
{
SourceMediaStream *source = mListener->GetSourceStream();
// No locking between these is required as all the callbacks for the
// same MediaStream will occur on the same thread.
if (!source) // means the stream was never Activated()
return;
return NS_OK;
switch (mType) {
case MEDIA_START:
@@ -300,7 +300,7 @@ public:
mListener->GetPrincipalHandle());
if (NS_FAILED(rv)) {
ReturnCallbackError(rv, "Starting audio failed");
return;
return NS_OK;
}
}
if (mVideoDevice) {
@@ -308,7 +308,7 @@ public:
mListener->GetPrincipalHandle());
if (NS_FAILED(rv)) {
ReturnCallbackError(rv, "Starting video failed");
return;
return NS_OK;
}
}
// Start() queued the tracks to be added synchronously to avoid races
@@ -377,6 +377,8 @@ public:
MOZ_ASSERT(false,"invalid MediaManager operation");
break;
}
return NS_OK;
}
private:
@@ -974,11 +976,12 @@ public:
// because that can take a while.
// Pass ownership of domStream to the MediaOperationTask
// to ensure it's kept alive until the MediaOperationTask runs (at least).
MediaManager::PostTask(FROM_HERE,
RefPtr<Runnable> mediaOperation =
new MediaOperationTask(MEDIA_START, mListener, domStream,
tracksAvailableCallback,
mAudioDevice, mVideoDevice,
false, mWindowID, mOnFailure.forget()));
false, mWindowID, mOnFailure.forget());
MediaManager::PostTask(mediaOperation.forget());
// We won't need mOnFailure now.
mOnFailure = nullptr;
@@ -1068,8 +1071,7 @@ MediaManager::SelectSettings(
// Algorithm accesses device capabilities code and must run on media thread.
// Modifies passed-in aSources.
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aConstraints,
aSources]() mutable {
MediaManager::PostTask(NewTaskFrom([id, aConstraints, aSources]() mutable {
auto& sources = **aSources;
// Since the advanced part of the constraints algorithm needs to know when
@@ -1105,14 +1107,14 @@ MediaManager::SelectSettings(
sources.AppendElement(audio);
}
}
NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, badConstraint]() mutable {
NS_DispatchToMainThread(NewRunnableFrom([id, badConstraint]() mutable {
RefPtr<MediaManager> mgr = MediaManager_GetInstance();
RefPtr<PledgeChar> p = mgr->mOutstandingCharPledges.Remove(id);
if (p) {
p->Resolve(badConstraint);
}
return NS_OK;
})));
}));
}));
return p.forget();
}
@@ -1125,7 +1127,7 @@ MediaManager::SelectSettings(
* Do not run this on the main thread. The success and error callbacks *MUST*
* be dispatched on the main thread!
*/
class GetUserMediaTask : public Task
class GetUserMediaTask : public Runnable
{
public:
GetUserMediaTask(
@@ -1168,8 +1170,8 @@ public:
NS_DispatchToMainThread(do_AddRef(new GetUserMediaListenerRemove(mWindowID, mListener)));
}
void
Run()
NS_IMETHOD
Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mOnSuccess);
@@ -1188,7 +1190,7 @@ public:
LOG(("Failed to allocate audiosource %d",rv));
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
NS_LITERAL_STRING("Failed to allocate audiosource"));
return;
return NS_OK;
}
}
if (mVideoDevice) {
@@ -1201,7 +1203,7 @@ public:
}
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
NS_LITERAL_STRING("Failed to allocate videosource"));
return;
return NS_OK;
}
}
PeerIdentity* peerIdentity = nullptr;
@@ -1215,6 +1217,7 @@ public:
mVideoDevice, peerIdentity)));
MOZ_ASSERT(!mOnSuccess);
MOZ_ASSERT(!mOnFailure);
return NS_OK;
}
nsresult
@@ -1306,7 +1309,7 @@ public:
~GetUserMediaRunnableWrapper() {
}
NS_IMETHOD Run() {
NS_IMETHOD Run() override {
mTask->Run();
return NS_OK;
}
@@ -1351,10 +1354,10 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
aFakeTracks = false;
}
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aWindowId, audioLoopDev,
videoLoopDev, aVideoType,
aAudioType, aFake,
aFakeTracks]() mutable {
MediaManager::PostTask(NewTaskFrom([id, aWindowId, audioLoopDev,
videoLoopDev, aVideoType,
aAudioType, aFake,
aFakeTracks]() mutable {
// Only enumerate what's asked for, and only fake cams and mics.
bool hasVideo = aVideoType != MediaSourceEnum::Other;
bool hasAudio = aAudioType != MediaSourceEnum::Other;
@@ -1389,7 +1392,7 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
}
}
SourceSet* handoff = result.release();
NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, handoff]() mutable {
NS_DispatchToMainThread(NewRunnableFrom([id, handoff]() mutable {
UniquePtr<SourceSet> result(handoff); // grab result
RefPtr<MediaManager> mgr = MediaManager_GetInstance();
if (!mgr) {
@@ -1400,7 +1403,7 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
p->Resolve(result.release());
}
return NS_OK;
})));
}));
}));
return p.forget();
}
@@ -1599,16 +1602,19 @@ MediaManager::StartupInit()
/* static */
void
MediaManager::PostTask(const tracked_objects::Location& from_here, Task* task)
MediaManager::PostTask(already_AddRefed<Runnable> task)
{
if (sInShutdown) {
// Can't safely delete task here since it may have items with specific
// thread-release requirements.
// XXXkhuey well then who is supposed to delete it?! We don't signal
// that we failed ...
MOZ_CRASH();
return;
}
NS_ASSERTION(Get(), "MediaManager singleton?");
NS_ASSERTION(Get()->mMediaThread, "No thread yet");
Get()->mMediaThread->message_loop()->PostTask(from_here, task);
Get()->mMediaThread->message_loop()->PostTask(Move(task));
}
/* static */ nsresult
@@ -2124,11 +2130,11 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
}
// Pass callbacks and MediaStreamListener along to GetUserMediaTask.
nsAutoPtr<GetUserMediaTask> task (new GetUserMediaTask(c, onSuccess.forget(),
onFailure.forget(),
windowID, listener,
prefs, origin,
devices->release()));
RefPtr<GetUserMediaTask> task (new GetUserMediaTask(c, onSuccess.forget(),
onFailure.forget(),
windowID, listener,
prefs, origin,
devices->release()));
// Store the task w/callbacks.
mActiveCallbacks.Put(callID, task.forget());
@@ -2376,9 +2382,9 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindowInner* aWindow,
}
for (auto& callID : *callIDs) {
GetUserMediaTask* task;
RefPtr<GetUserMediaTask> task;
if (!aCallID.Length() || aCallID == callID) {
if (mActiveCallbacks.Get(callID, &task)) {
if (mActiveCallbacks.Get(callID, getter_AddRefs(task))) {
nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*task->mSourceSet);
onSuccess->OnSuccess(array);
return NS_OK;
@@ -2618,15 +2624,15 @@ MediaManager::Shutdown()
// Because mMediaThread is not an nsThread, we must dispatch to it so it can
// clean up BackgroundChild. Continue stopping thread once this is done.
class ShutdownTask : public Task
class ShutdownTask : public Runnable
{
public:
ShutdownTask(MediaManager* aManager,
Runnable* aReply)
already_AddRefed<Runnable> aReply)
: mManager(aManager)
, mReply(aReply) {}
private:
void
NS_IMETHOD
Run() override
{
LOG(("MediaManager Thread Shutdown"));
@@ -2644,6 +2650,8 @@ MediaManager::Shutdown()
if (NS_FAILED(NS_DispatchToMainThread(mReply.forget()))) {
LOG(("Will leak thread: DispatchToMainthread of reply runnable failed in MediaManager shutdown"));
}
return NS_OK;
}
RefPtr<MediaManager> mManager;
RefPtr<Runnable> mReply;
@@ -2660,7 +2668,7 @@ MediaManager::Shutdown()
RefPtr<MediaManager> that(sSingleton);
// Release the backend (and call Shutdown()) from within the MediaManager thread
// Don't use MediaManager::PostTask() because we're sInShutdown=true here!
mMediaThread->message_loop()->PostTask(FROM_HERE, new ShutdownTask(this,
RefPtr<ShutdownTask> shutdown = new ShutdownTask(this,
media::NewRunnableFrom([this, that]() mutable {
LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread"));
if (mMediaThread) {
@@ -2676,7 +2684,8 @@ MediaManager::Shutdown()
sSingleton = nullptr;
return NS_OK;
})));
}));
mMediaThread->message_loop()->PostTask(shutdown.forget());
}
nsresult
@@ -2702,8 +2711,8 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
} else if (!strcmp(aTopic, "getUserMedia:privileged:allow") ||
!strcmp(aTopic, "getUserMedia:response:allow")) {
nsString key(aData);
nsAutoPtr<GetUserMediaTask> task;
mActiveCallbacks.RemoveAndForget(key, task);
RefPtr<GetUserMediaTask> task;
mActiveCallbacks.Remove(key, getter_AddRefs(task));
if (!task) {
return NS_OK;
}
@@ -2750,7 +2759,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
return task->Denied(NS_LITERAL_STRING("In shutdown"));
}
// Reuse the same thread to save memory.
MediaManager::PostTask(FROM_HERE, task.forget());
MediaManager::PostTask(task.forget());
return NS_OK;
} else if (!strcmp(aTopic, "getUserMedia:response:deny")) {
@@ -2765,8 +2774,8 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
}
nsString key(aData);
nsAutoPtr<GetUserMediaTask> task;
mActiveCallbacks.RemoveAndForget(key, task);
RefPtr<GetUserMediaTask> task;
mActiveCallbacks.Remove(key, getter_AddRefs(task));
if (task) {
task->Denied(errorMessage);
}
@@ -3086,12 +3095,13 @@ GetUserMediaCallbackMediaStreamListener::Stop()
// thread.
// Pass a ref to us (which is threadsafe) so it can query us for the
// source stream info.
MediaManager::PostTask(FROM_HERE,
RefPtr<MediaOperationTask> mediaOperation =
new MediaOperationTask(MEDIA_STOP,
this, nullptr, nullptr,
!mAudioStopped ? mAudioDevice.get() : nullptr,
!mVideoStopped ? mVideoDevice.get() : nullptr,
false, mWindowID, nullptr));
false, mWindowID, nullptr);
MediaManager::PostTask(mediaOperation.forget());
mStopped = mAudioStopped = mVideoStopped = true;
}
@@ -3151,9 +3161,9 @@ GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
uint32_t id = mgr->mOutstandingVoidPledges.Append(*p);
uint64_t windowId = aWindow->WindowID();
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, windowId,
audioDevice, videoDevice,
aConstraints]() mutable {
MediaManager::PostTask(NewTaskFrom([id, windowId,
audioDevice, videoDevice,
aConstraints]() mutable {
MOZ_ASSERT(MediaManager::IsInMediaThread());
RefPtr<MediaManager> mgr = MediaManager::GetInstance();
const char* badConstraint = nullptr;
@@ -3176,8 +3186,8 @@ GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
videos);
}
}
NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, windowId, rv,
badConstraint]() mutable {
NS_DispatchToMainThread(NewRunnableFrom([id, windowId, rv,
badConstraint]() mutable {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<MediaManager> mgr = MediaManager_GetInstance();
if (!mgr) {
@@ -3209,7 +3219,7 @@ GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
}
}
return NS_OK;
})));
}));
}));
return p.forget();
}
@@ -3246,12 +3256,13 @@ GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aTrackID)
return;
}
MediaManager::PostTask(FROM_HERE,
RefPtr<MediaOperationTask> mediaOperation =
new MediaOperationTask(MEDIA_STOP_TRACK,
this, nullptr, nullptr,
stopAudio ? mAudioDevice.get() : nullptr,
stopVideo ? mVideoDevice.get() : nullptr,
false , mWindowID, nullptr));
false , mWindowID, nullptr);
MediaManager::PostTask(mediaOperation.forget());
mAudioStopped |= stopAudio;
mVideoStopped |= stopVideo;
}
@@ -3276,11 +3287,12 @@ void
GetUserMediaCallbackMediaStreamListener::NotifyDirectListeners(MediaStreamGraph* aGraph,
bool aHasListeners)
{
MediaManager::PostTask(FROM_HERE,
RefPtr<MediaOperationTask> mediaOperation =
new MediaOperationTask(MEDIA_DIRECT_LISTENERS,
this, nullptr, nullptr,
mAudioDevice, mVideoDevice,
aHasListeners, mWindowID, nullptr));
aHasListeners, mWindowID, nullptr);
MediaManager::PostTask(mediaOperation.forget());
}
// this can be in response to our own RemoveListener() (via ::Remove()), or
+2 -2
View File
@@ -424,7 +424,7 @@ public:
static MediaManager* Get();
static MediaManager* GetIfExists();
static void StartupInit();
static void PostTask(const tracked_objects::Location& from_here, Task* task);
static void PostTask(already_AddRefed<Runnable> task);
#ifdef DEBUG
static bool IsInMediaThread();
#endif
@@ -536,7 +536,7 @@ private:
// ONLY access from MainThread so we don't need to lock
WindowTable mActiveWindows;
nsClassHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks;
nsRefPtrHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks;
nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds;
// Always exists
+35 -18
View File
@@ -86,6 +86,9 @@ SeekTask::SeekTask(const void* aDecoderID,
mDropAudioUntilNextDiscontinuity = HasAudio();
mDropVideoUntilNextDiscontinuity = HasVideo();
// Configure MediaDecoderReaderWrapper.
SetMediaDecoderReaderWrapperCallback();
}
SeekTask::~SeekTask()
@@ -152,12 +155,11 @@ SeekTask::Discard()
// Disconnect MDSM.
RejectIfExist(__func__);
// Disconnect MediaDecoderReader.
// Disconnect MediaDecoderReaderWrapper.
mSeekRequest.DisconnectIfExists();
mAudioDataRequest.DisconnectIfExists();
mVideoDataRequest.DisconnectIfExists();
mAudioWaitRequest.DisconnectIfExists();
mVideoWaitRequest.DisconnectIfExists();
CancelMediaDecoderReaderWrapperCallback();
mIsDiscarded = true;
}
@@ -216,7 +218,7 @@ SeekTask::EnsureAudioDecodeTaskQueued()
IsAudioDecoding(), AudioRequestStatus());
if (!IsAudioDecoding() ||
mAudioDataRequest.Exists() ||
mReader->IsRequestingAudioData() ||
mAudioWaitRequest.Exists() ||
mSeekRequest.Exists()) {
return NS_OK;
@@ -235,7 +237,7 @@ SeekTask::EnsureVideoDecodeTaskQueued()
IsVideoDecoding(), VideoRequestStatus());
if (!IsVideoDecoding() ||
mVideoDataRequest.Exists() ||
mReader->IsRequestingVidoeData() ||
mVideoWaitRequest.Exists() ||
mSeekRequest.Exists()) {
return NS_OK;
@@ -249,7 +251,7 @@ const char*
SeekTask::AudioRequestStatus()
{
AssertOwnerThread();
if (mAudioDataRequest.Exists()) {
if (mReader->IsRequestingAudioData()) {
MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
return "pending";
} else if (mAudioWaitRequest.Exists()) {
@@ -262,7 +264,7 @@ const char*
SeekTask::VideoRequestStatus()
{
AssertOwnerThread();
if (mVideoDataRequest.Exists()) {
if (mReader->IsRequestingVidoeData()) {
MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
return "pending";
} else if (mVideoWaitRequest.Exists()) {
@@ -279,9 +281,7 @@ SeekTask::RequestAudioData()
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
!!mSeekedAudioData, mReader->SizeOfAudioQueueInFrames());
mAudioDataRequest.Begin(mReader->RequestAudioData()
->Then(OwnerThread(), __func__, this,
&SeekTask::OnAudioDecoded, &SeekTask::OnAudioNotDecoded));
mReader->RequestAudioData();
}
void
@@ -296,10 +296,7 @@ SeekTask::RequestVideoData()
!!mSeekedVideoData, mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
currentTime.ToMicroseconds());
mVideoDataRequest.Begin(
mReader->RequestVideoData(skipToNextKeyFrame, currentTime)
->Then(OwnerThread(), __func__, this,
&SeekTask::OnVideoDecoded, &SeekTask::OnVideoNotDecoded));
mReader->RequestVideoData(skipToNextKeyFrame, currentTime);
}
nsresult
@@ -500,7 +497,6 @@ SeekTask::OnAudioDecoded(MediaData* aAudioSample)
AssertOwnerThread();
RefPtr<MediaData> audio(aAudioSample);
MOZ_ASSERT(audio);
mAudioDataRequest.Complete();
// The MDSM::mDecodedAudioEndTime will be updated once the whole SeekTask is
// resolved.
@@ -553,7 +549,6 @@ SeekTask::OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
AssertOwnerThread();
SAMPLE_LOG("OnAduioNotDecoded (aReason=%u)", aReason);
mAudioDataRequest.Complete();
if (aReason == MediaDecoderReader::DECODE_ERROR) {
// If this is a decode error, delegate to the generic error path.
@@ -602,7 +597,6 @@ SeekTask::OnVideoDecoded(MediaData* aVideoSample)
AssertOwnerThread();
RefPtr<MediaData> video(aVideoSample);
MOZ_ASSERT(video);
mVideoDataRequest.Complete();
// The MDSM::mDecodedVideoEndTime will be updated once the whole SeekTask is
// resolved.
@@ -657,7 +651,6 @@ SeekTask::OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
AssertOwnerThread();
SAMPLE_LOG("OnVideoNotDecoded (aReason=%u)", aReason);
mVideoDataRequest.Complete();
if (aReason == MediaDecoderReader::DECODE_ERROR) {
// If this is a decode error, delegate to the generic error path.
@@ -710,4 +703,28 @@ SeekTask::OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
}
}
void
SeekTask::SetMediaDecoderReaderWrapperCallback()
{
mAudioCallbackID =
mReader->SetAudioCallback(this, &SeekTask::OnAudioDecoded,
&SeekTask::OnAudioNotDecoded);
mVideoCallbackID =
mReader->SetVideoCallback(this, &SeekTask::OnVideoDecoded,
&SeekTask::OnVideoNotDecoded);
DECODER_LOG("SeekTask set audio callbacks: mAudioCallbackID = %d\n", (int)mAudioCallbackID);
DECODER_LOG("SeekTask set video callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
}
void
SeekTask::CancelMediaDecoderReaderWrapperCallback()
{
DECODER_LOG("SeekTask cancel audio callbacks: mVideoCallbackID = %d\n", (int)mAudioCallbackID);
mReader->CancelAudioCallback(mAudioCallbackID);
DECODER_LOG("SeekTask cancel video callbacks: mVideoCallbackID = %d\n", (int)mVideoCallbackID);
mReader->CancelVideoCallback(mVideoCallbackID);
}
} // namespace mozilla
+7 -2
View File
@@ -8,6 +8,7 @@
#define SEEK_TASK_H
#include "mozilla/MozPromise.h"
#include "MediaCallbackID.h"
#include "MediaDecoderReader.h"
#include "SeekJob.h"
@@ -127,6 +128,10 @@ protected:
virtual void OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason);
void SetMediaDecoderReaderWrapperCallback();
void CancelMediaDecoderReaderWrapperCallback();
/*
* Data shared with MDSM.
*/
@@ -157,8 +162,8 @@ protected:
* Track the current seek promise made by the reader.
*/
MozPromiseRequestHolder<MediaDecoderReader::SeekPromise> mSeekRequest;
MozPromiseRequestHolder<MediaDecoderReader::MediaDataPromise> mAudioDataRequest;
MozPromiseRequestHolder<MediaDecoderReader::MediaDataPromise> mVideoDataRequest;
CallbackID mAudioCallbackID;
CallbackID mVideoCallbackID;
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
+3 -2
View File
@@ -617,8 +617,9 @@ GMPChild::GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild)
UniquePtr<GMPContentChild>& toDestroy = mGMPContentChildren[i - 1];
if (toDestroy.get() == aGMPContentChild) {
SendPGMPContentChildDestroyed();
MessageLoop::current()->PostTask(FROM_HERE,
new DeleteTask<GMPContentChild>(toDestroy.release()));
RefPtr<DeleteTask<GMPContentChild>> task =
new DeleteTask<GMPContentChild>(toDestroy.release());
MessageLoop::current()->PostTask(task.forget());
mGMPContentChildren.RemoveElementAt(i - 1);
break;
}
+2 -2
View File
@@ -22,8 +22,8 @@ GMPContentChild::GMPContentChild(GMPChild* aChild)
GMPContentChild::~GMPContentChild()
{
MOZ_COUNT_DTOR(GMPContentChild);
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
MessageLoop*
+2 -2
View File
@@ -43,8 +43,8 @@ GMPContentParent::GMPContentParent(GMPParent* aParent)
GMPContentParent::~GMPContentParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
class ReleaseGMPContentParent : public Runnable
+4 -4
View File
@@ -61,8 +61,8 @@ GMPDecryptorChild::CallOnGMPThread(MethodType aMethod, ParamType&&... aParams)
// Use const reference when we have to.
auto m = &GMPDecryptorChild::CallMethod<
decltype(aMethod), typename AddConstReference<ParamType>::Type...>;
auto t = NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...);
mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
RefPtr<mozilla::Runnable> t = NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...);
mPlugin->GMPMessageLoop()->PostTask(t.forget());
}
}
@@ -170,8 +170,8 @@ GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
if (!ON_GMP_THREAD()) {
// We should run this whole method on the GMP thread since the buffer needs
// to be deleted after the SendDecrypted call.
auto t = NewRunnableMethod(this, &GMPDecryptorChild::Decrypted, aBuffer, aResult);
mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
RefPtr<Runnable> t = NewRunnableMethod(this, &GMPDecryptorChild::Decrypted, aBuffer, aResult);
mPlugin->GMPMessageLoop()->PostTask(t.forget());
return;
}
+3 -3
View File
@@ -73,7 +73,7 @@ public:
// main thread tries to do a sync call back to the calling thread.
MOZ_ASSERT(!IsOnChildMainThread());
mMessageLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &SyncRunnable::Run));
mMessageLoop->PostTask(NewRunnableMethod(this, &SyncRunnable::Run));
MonitorAutoLock lock(mMonitor);
while (!mDone) {
lock.Wait();
@@ -121,7 +121,7 @@ RunOnMainThread(GMPTask* aTask)
}
RefPtr<Runnable> r = new Runnable(aTask);
sMainLoop->PostTask(FROM_HERE, NewRunnableMethod(r.get(), &Runnable::Run));
sMainLoop->PostTask(NewRunnableMethod(r.get(), &Runnable::Run));
return GMPNoErr;
}
@@ -254,7 +254,7 @@ GMPThreadImpl::Post(GMPTask* aTask)
RefPtr<Runnable> r = new Runnable(aTask);
mThread.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(r.get(), &Runnable::Run));
mThread.message_loop()->PostTask(NewRunnableMethod(r.get(), &Runnable::Run));
}
void
+1 -1
View File
@@ -85,7 +85,7 @@ void
GMPProcessParent::Delete(nsCOMPtr<nsIRunnable> aCallback)
{
mDeletedCallback = aCallback;
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod(this, &GMPProcessParent::DoDelete));
XRE_GetIOMessageLoop()->PostTask(NewRunnableMethod(this, &GMPProcessParent::DoDelete));
}
void
+2 -2
View File
@@ -251,8 +251,8 @@ GMPServiceChild::GMPServiceChild()
GMPServiceChild::~GMPServiceChild()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
PGMPContentParent*
+2 -2
View File
@@ -1774,8 +1774,8 @@ GeckoMediaPluginServiceParent::ClearStorage()
GMPServiceParent::~GMPServiceParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
bool
+1 -1
View File
@@ -15,7 +15,7 @@
_func(__VA_ARGS__); \
} else { \
mPlugin->GMPMessageLoop()->PostTask( \
FROM_HERE, NewRunnableMethod(this, &GMPStorageChild::_func, ##__VA_ARGS__) \
NewRunnableMethod(this, &GMPStorageChild::_func, ##__VA_ARGS__) \
); \
} \
} while(false)
+1 -2
View File
@@ -226,8 +226,7 @@ GMPVideoDecoderChild::Alloc(size_t aSize,
rv = CallNeedShmem(aSize, aMem);
--mNeedShmemIntrCount;
if (mPendingDecodeComplete) {
auto t = NewRunnableMethod(this, &GMPVideoDecoderChild::RecvDecodingComplete);
mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
mPlugin->GMPMessageLoop()->PostTask(NewRunnableMethod(this, &GMPVideoDecoderChild::RecvDecodingComplete));
}
#else
#ifdef GMP_SAFE_SHMEM
+1 -2
View File
@@ -207,8 +207,7 @@ GMPVideoEncoderChild::Alloc(size_t aSize,
rv = CallNeedShmem(aSize, aMem);
--mNeedShmemIntrCount;
if (mPendingEncodeComplete) {
auto t = NewRunnableMethod(this, &GMPVideoEncoderChild::RecvEncodingComplete);
mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
mPlugin->GMPMessageLoop()->PostTask(NewRunnableMethod(this, &GMPVideoEncoderChild::RecvEncodingComplete));
}
#else
#ifdef GMP_SAFE_SHMEM
+2
View File
@@ -105,6 +105,7 @@ EXPORTS += [
'Intervals.h',
'Latency.h',
'MediaCache.h',
'MediaCallbackID.h',
'MediaData.h',
'MediaDataDemuxer.h',
'MediaDecoder.h',
@@ -215,6 +216,7 @@ UNIFIED_SOURCES += [
'GraphDriver.cpp',
'Latency.cpp',
'MediaCache.cpp',
'MediaCallbackID.cpp',
'MediaData.cpp',
'MediaDecoder.cpp',
'MediaDecoderReader.cpp',
+5 -4
View File
@@ -31,7 +31,7 @@ namespace mozilla {
extern LazyLogModule gMediaDecoderLog;
#define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg)
class MediaOmxReader::ProcessCachedDataTask : public Task
class MediaOmxReader::ProcessCachedDataTask : public Runnable
{
public:
ProcessCachedDataTask(MediaOmxReader* aOmxReader, int64_t aOffset)
@@ -39,11 +39,12 @@ public:
mOffset(aOffset)
{ }
void Run()
NS_IMETHOD Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mOmxReader.get());
mOmxReader->ProcessCachedData(mOffset);
return NS_OK;
}
private:
@@ -105,8 +106,8 @@ private:
// We cannot read data in the main thread because it
// might block for too long. Instead we post an IO task
// to the IO thread if there is more data available.
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new ProcessCachedDataTask(mOmxReader.get(), mOffset));
RefPtr<Runnable> task = new ProcessCachedDataTask(mOmxReader.get(), mOffset);
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
}
@@ -17,6 +17,7 @@
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIGfxInfo.h"
#include "nsWindowsHelpers.h"
#include "GfxDriverInfo.h"
#include "gfxWindowsPlatform.h"
#include "MediaInfo.h"
@@ -165,9 +166,45 @@ CanCreateWMFDecoder()
return result.value();
}
static bool
IsH264DecoderBlacklisted()
{
#ifdef BLACKLIST_CRASHY_H264_DECODERS
WCHAR systemPath[MAX_PATH + 1];
if (!ConstructSystem32Path(L"msmpeg2vdec.dll", systemPath, MAX_PATH + 1)) {
// Cannot build path -> Assume it's not the blacklisted DLL.
return false;
}
DWORD zero;
DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero);
if (infoSize == 0) {
// Can't get file info -> Assume we don't have the blacklisted DLL.
return false;
}
auto infoData = MakeUnique<unsigned char[]>(infoSize);
VS_FIXEDFILEINFO *vInfo;
UINT vInfoLen;
if (GetFileVersionInfoW(systemPath, 0, infoSize, infoData.get()) &&
VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen))
{
if ((vInfo->dwFileVersionMS == ((12u << 16) | 0u))
&& ((vInfo->dwFileVersionLS == ((9200u << 16) | 16426u))
|| (vInfo->dwFileVersionLS == ((9200u << 16) | 17037u)))) {
// 12.0.9200.16426 & .17037 are blacklisted on Win64, see bug 1242343.
return true;
}
}
#endif // BLACKLIST_CRASHY_H264_DECODERS
return false;
}
/* static */ bool
WMFDecoderModule::HasH264()
{
if (IsH264DecoderBlacklisted()) {
return false;
}
return CanCreateWMFDecoder<CLSID_CMSH264DecoderMFT>();
}
+3 -3
View File
@@ -165,7 +165,7 @@ CamerasParent::Observe(nsISupports *aSubject,
}
nsresult
CamerasParent::DispatchToVideoCaptureThread(Runnable *event)
CamerasParent::DispatchToVideoCaptureThread(Runnable* event)
{
// Don't try to dispatch if we're already on the right thread.
// There's a potential deadlock because the mThreadMonitor is likely
@@ -182,8 +182,8 @@ CamerasParent::DispatchToVideoCaptureThread(Runnable *event)
if (!mVideoCaptureThread || !mVideoCaptureThread->IsRunning()) {
return NS_ERROR_FAILURE;
}
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE,
new RunnableTask(event));
RefPtr<Runnable> addrefedEvent = event;
mVideoCaptureThread->message_loop()->PostTask(addrefedEvent.forget());
return NS_OK;
}
+2 -1
View File
@@ -129,7 +129,8 @@ protected:
void CloseEngines();
void StopIPC();
void StopVideoCapture();
nsresult DispatchToVideoCaptureThread(Runnable *event);
// Can't take already_AddRefed because it can fail in stupid ways.
nsresult DispatchToVideoCaptureThread(Runnable* event);
EngineHelper mEngines[CaptureEngine::MaxEngine];
nsTArray<CallbackHelper*> mCallbacks;
-15
View File
@@ -39,21 +39,6 @@ private:
nsCOMPtr<nsIThread> mThread;
};
class RunnableTask : public Task
{
public:
explicit RunnableTask(Runnable* aRunnable)
: mRunnable(aRunnable) {}
void Run() override {
mRunnable->Run();
}
private:
~RunnableTask() {}
RefPtr<Runnable> mRunnable;
};
}
}
@@ -39,20 +39,6 @@ MediaSystemResourceManager::Shutdown()
}
}
class RunnableCallTask : public Task
{
public:
explicit RunnableCallTask(nsIRunnable* aRunnable)
: mRunnable(aRunnable) {}
void Run() override
{
mRunnable->Run();
}
protected:
nsCOMPtr<nsIRunnable> mRunnable;
};
/* static */ void
MediaSystemResourceManager::Init()
{
@@ -77,7 +63,7 @@ MediaSystemResourceManager::Init()
ReentrantMonitorAutoEnter autoMon(barrier);
bool done = false;
nsCOMPtr<nsIRunnable> runnable =
RefPtr<Runnable> runnable =
NS_NewRunnableFunction([&]() {
if (!sSingleton) {
sSingleton = new MediaSystemResourceManager();
@@ -87,8 +73,7 @@ MediaSystemResourceManager::Init()
barrier.NotifyAll();
});
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
FROM_HERE, new RunnableCallTask(runnable));
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(runnable.forget());
// should stop the thread until done.
while (!done) {
@@ -214,7 +199,6 @@ MediaSystemResourceManager::Acquire(MediaSystemResourceClient* aClient)
}
aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(
this,
&MediaSystemResourceManager::DoAcquire,
@@ -260,7 +244,6 @@ MediaSystemResourceManager::AcquireSyncNoWait(MediaSystemResourceClient* aClient
}
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(
this,
&MediaSystemResourceManager::DoAcquire,
@@ -328,7 +311,6 @@ MediaSystemResourceManager::ReleaseResource(MediaSystemResourceClient* aClient)
aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(
this,
&MediaSystemResourceManager::DoRelease,
@@ -357,7 +339,6 @@ MediaSystemResourceManager::HandleAcquireResult(uint32_t aId, bool aSuccess)
{
if (!InImageBridgeChildThread()) {
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(
this,
&MediaSystemResourceManager::HandleAcquireResult,
+13 -8
View File
@@ -200,31 +200,36 @@ private:
};
template<typename OnRunType>
LambdaRunnable<OnRunType>*
already_AddRefed<LambdaRunnable<OnRunType>>
NewRunnableFrom(OnRunType&& aOnRun)
{
return new LambdaRunnable<OnRunType>(Forward<OnRunType>(aOnRun));
typedef LambdaRunnable<OnRunType> LambdaType;
RefPtr<LambdaType> lambda = new LambdaType(Forward<OnRunType>(aOnRun));
return lambda.forget();
}
template<typename OnRunType>
class LambdaTask : public Task
class LambdaTask : public Runnable
{
public:
explicit LambdaTask(OnRunType&& aOnRun) : mOnRun(Move(aOnRun)) {}
private:
void
Run()
NS_IMETHOD
Run() override
{
return mOnRun();
mOnRun();
return NS_OK;
}
OnRunType mOnRun;
};
template<typename OnRunType>
LambdaTask<OnRunType>*
already_AddRefed<LambdaTask<OnRunType>>
NewTaskFrom(OnRunType&& aOnRun)
{
return new LambdaTask<OnRunType>(Forward<OnRunType>(aOnRun));
typedef LambdaTask<OnRunType> LambdaType;
RefPtr<LambdaType> lambda = new LambdaType(Forward<OnRunType>(aOnRun));
return lambda.forget();
}
/* media::CoatCheck - There and back again. Park an object in exchange for an id.
+2 -2
View File
@@ -158,8 +158,8 @@ ReverbConvolver::ReverbConvolver(const float* impulseResponseData,
NS_WARNING("Cannot start convolver thread.");
return;
}
CancelableTask* task = NewRunnableMethod(this, &ReverbConvolver::backgroundThreadEntry);
m_backgroundThread.message_loop()->PostTask(FROM_HERE, task);
m_backgroundThread.message_loop()->PostTask(
NewRunnableMethod(this, &ReverbConvolver::backgroundThreadEntry));
}
}
-1
View File
@@ -46,7 +46,6 @@ DIRS += [
'bluetooth',
'activities',
'archivereader',
'requestsync',
'bindings',
'battery',
'browser-element',
+2 -1
View File
@@ -3378,7 +3378,8 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
// in case aURL is relative
RefPtr<nsPluginInstanceOwner> owner = aInstance->GetOwner();
if (owner) {
rv = NS_MakeAbsoluteURI(absUrl, aURL, nsCOMPtr<nsIURI>(owner->GetBaseURI()));
nsCOMPtr<nsIURI> baseURI = owner->GetBaseURI();
rv = NS_MakeAbsoluteURI(absUrl, aURL, baseURI);
}
if (absUrl.IsEmpty())
@@ -103,7 +103,10 @@ nsPluginByteRangeStreamListener::OnStartRequest(nsIRequest *request, nsISupports
nsPluginStreamListenerPeer *pslp =
static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get());
NS_ASSERTION(pslp->mRequests.IndexOfObject(GetBaseRequest(request)) != -1,
#ifdef DEBUG
nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
#endif
NS_ASSERTION(pslp->mRequests.IndexOfObject(baseRequest) != -1,
"Untracked byte-range request?");
nsCOMPtr<nsIStreamConverterService> serv = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
@@ -430,7 +433,8 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest",
js::ProfileEntry::Category::OTHER);
if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
if (mRequests.IndexOfObject(baseRequest) == -1) {
NS_ASSERTION(mRequests.Count() == 0,
"Only our initial stream should be unknown!");
TrackRequest(request);
@@ -833,7 +837,8 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
uint64_t sourceOffset,
uint32_t aLength)
{
if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
if (mRequests.IndexOfObject(baseRequest) == -1) {
MOZ_ASSERT(false, "Received OnDataAvailable for untracked request.");
return NS_ERROR_UNEXPECTED;
}
+1 -1
View File
@@ -190,7 +190,7 @@ BrowserStreamChild::NPN_DestroyStream(NPReason reason)
void
BrowserStreamChild::EnsureDeliveryPending()
{
MessageLoop::current()->PostTask(FROM_HERE,
MessageLoop::current()->PostTask(
mDeliveryTracker.NewRunnableMethod(&BrowserStreamChild::Deliver));
}
+5 -2
View File
@@ -19,12 +19,13 @@ ChildAsyncCall::ChildAsyncCall(PluginInstanceChild* instance,
{
}
void
nsresult
ChildAsyncCall::Cancel()
{
mInstance = nullptr;
mFunc = nullptr;
mData = nullptr;
return NS_OK;
}
void
@@ -36,13 +37,15 @@ ChildAsyncCall::RemoveFromAsyncList()
}
}
void
NS_IMETHODIMP
ChildAsyncCall::Run()
{
RemoveFromAsyncList();
if (mFunc)
mFunc(mData);
return NS_OK;
}
} // namespace plugins
+4 -4
View File
@@ -9,7 +9,7 @@
#define mozilla_plugins_ChildAsyncCall_h
#include "PluginMessageUtils.h"
#include "base/task.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace plugins {
@@ -18,14 +18,14 @@ typedef void (*PluginThreadCallback)(void*);
class PluginInstanceChild;
class ChildAsyncCall : public CancelableTask
class ChildAsyncCall : public CancelableRunnable
{
public:
ChildAsyncCall(PluginInstanceChild* instance,
PluginThreadCallback aFunc, void* aUserData);
void Run() override;
void Cancel() override;
NS_IMETHOD Run() override;
nsresult Cancel() override;
protected:
PluginInstanceChild* mInstance;
+24 -19
View File
@@ -195,8 +195,6 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
, mAccumulatedInvalidRect(0,0,0,0)
, mIsTransparent(false)
, mSurfaceType(gfxSurfaceType::Max)
, mCurrentInvalidateTask(nullptr)
, mCurrentAsyncSetWindowTask(nullptr)
, mPendingPluginCall(false)
, mDoAlphaExtraction(false)
, mHasPainted(false)
@@ -2624,7 +2622,7 @@ PluginInstanceChild::FlashThrottleAsyncMsg::GetProc()
return nullptr;
}
void
NS_IMETHODIMP
PluginInstanceChild::FlashThrottleAsyncMsg::Run()
{
RemoveFromAsyncList();
@@ -2633,10 +2631,11 @@ PluginInstanceChild::FlashThrottleAsyncMsg::Run()
// PluginInstanceChild. We don't transport sub-class procedure
// ptrs around in FlashThrottleAsyncMsg msgs.
if (!GetProc())
return;
return NS_OK;
// deliver the event to flash
CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam());
return NS_OK;
}
void
@@ -2648,14 +2647,15 @@ PluginInstanceChild::FlashThrottleMessage(HWND aWnd,
{
// We reuse ChildAsyncCall so we get the cancelation work
// that's done in Destroy.
FlashThrottleAsyncMsg* task = new FlashThrottleAsyncMsg(this,
aWnd, aMsg, aWParam, aLParam, isWindowed);
RefPtr<FlashThrottleAsyncMsg> task =
new FlashThrottleAsyncMsg(this, aWnd, aMsg, aWParam,
aLParam, isWindowed);
{
MutexAutoLock lock(mAsyncCallMutex);
mPendingAsyncCalls.AppendElement(task);
}
MessageLoop::current()->PostDelayedTask(FROM_HERE,
task, kFlashWMUSERMessageThrottleDelayMs);
MessageLoop::current()->PostDelayedTask(task.forget(),
kFlashWMUSERMessageThrottleDelayMs);
}
#endif // OS_WIN
@@ -2797,7 +2797,7 @@ public:
{
}
void Run() override
NS_IMETHOD Run() override
{
RemoveFromAsyncList();
@@ -2807,6 +2807,7 @@ public:
DebugOnly<bool> sendOk =
mBrowserStreamChild->SendAsyncNPP_NewStreamResult(rv, stype);
MOZ_ASSERT(sendOk);
return NS_OK;
}
private:
@@ -2822,9 +2823,9 @@ PluginInstanceChild::RecvAsyncNPP_NewStream(PBrowserStreamChild* actor,
{
// Reusing ChildAsyncCall so that the task is cancelled properly on Destroy
BrowserStreamChild* child = static_cast<BrowserStreamChild*>(actor);
NewStreamAsyncCall* task = new NewStreamAsyncCall(this, child, mimeType,
seekable);
PostChildAsyncCall(task);
RefPtr<NewStreamAsyncCall> task =
new NewStreamAsyncCall(this, child, mimeType, seekable);
PostChildAsyncCall(task.forget());
return true;
}
@@ -3303,7 +3304,8 @@ PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
const gfxSurfaceType&, const NPRemoteWindow&, bool>
(this, &PluginInstanceChild::DoAsyncSetWindow,
aSurfaceType, aWindow, true);
MessageLoop::current()->PostTask(FROM_HERE, mCurrentAsyncSetWindowTask);
RefPtr<Runnable> addrefedTask = mCurrentAsyncSetWindowTask;
MessageLoop::current()->PostTask(addrefedTask.forget());
return true;
}
@@ -4222,7 +4224,8 @@ PluginInstanceChild::AsyncShowPluginFrame(void)
mCurrentInvalidateTask =
NewRunnableMethod(this, &PluginInstanceChild::InvalidateRectDelayed);
MessageLoop::current()->PostTask(FROM_HERE, mCurrentInvalidateTask);
RefPtr<Runnable> addrefedTask = mCurrentInvalidateTask;
MessageLoop::current()->PostTask(addrefedTask.forget());
}
void
@@ -4378,18 +4381,20 @@ PluginInstanceChild::UnscheduleTimer(uint32_t id)
void
PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc, void* aUserData)
{
ChildAsyncCall* task = new ChildAsyncCall(this, aFunc, aUserData);
PostChildAsyncCall(task);
RefPtr<ChildAsyncCall> task = new ChildAsyncCall(this, aFunc, aUserData);
PostChildAsyncCall(task.forget());
}
void
PluginInstanceChild::PostChildAsyncCall(ChildAsyncCall* aTask)
PluginInstanceChild::PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask)
{
RefPtr<ChildAsyncCall> task = aTask;
{
MutexAutoLock lock(mAsyncCallMutex);
mPendingAsyncCalls.AppendElement(aTask);
mPendingAsyncCalls.AppendElement(task);
}
ProcessChild::message_loop()->PostTask(FROM_HERE, aTask);
ProcessChild::message_loop()->PostTask(task.forget());
}
void
+5 -5
View File
@@ -259,7 +259,7 @@ public:
void AsyncCall(PluginThreadCallback aFunc, void* aUserData);
// This function is a more general version of AsyncCall
void PostChildAsyncCall(ChildAsyncCall* aTask);
void PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask);
int GetQuirks();
@@ -384,7 +384,7 @@ private:
mWindowed(isWindowed)
{}
void Run() override;
NS_IMETHOD Run() override;
WNDPROC GetProc();
HWND GetWnd() { return mWnd; }
@@ -446,7 +446,7 @@ private:
#endif
mozilla::Mutex mAsyncInvalidateMutex;
CancelableTask *mAsyncInvalidateTask;
CancelableRunnable *mAsyncInvalidateTask;
// Cached scriptable actors to avoid IPC churn
PluginScriptableObjectChild* mCachedWindowActor;
@@ -637,10 +637,10 @@ private:
gfxSurfaceType mSurfaceType;
// Keep InvalidateRect task pointer to be able Cancel it on Destroy
CancelableTask *mCurrentInvalidateTask;
RefPtr<CancelableRunnable> mCurrentInvalidateTask;
// Keep AsyncSetWindow task pointer to be able to Cancel it on Destroy
CancelableTask *mCurrentAsyncSetWindowTask;
RefPtr<CancelableRunnable> mCurrentAsyncSetWindowTask;
// True while plugin-child in plugin call
// Use to prevent plugin paint re-enter
+2 -2
View File
@@ -151,7 +151,6 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mShColorSpace(nullptr)
#endif
#if defined(XP_WIN)
, mCaptureRefreshTask(nullptr)
, mValidFirstCapture(false)
, mIsScrolling(false)
#endif
@@ -1225,7 +1224,8 @@ PluginInstanceParent::ScheduleScrollCapture(int aTimeout)
CAPTURE_LOG("delayed scroll capture requested.");
mCaptureRefreshTask =
NewRunnableMethod(this, &PluginInstanceParent::ScheduledUpdateScrollCaptureCallback);
MessageLoop::current()->PostDelayedTask(FROM_HERE, mCaptureRefreshTask,
RefPtr<Runnable> addrefedTask = mCaptureRefreshTask;
MessageLoop::current()->PostDelayedTask(addrefedTask.forget(),
kScrollCaptureDelayMs);
}
+1 -1
View File
@@ -474,7 +474,7 @@ private:
void CancelScheduledScrollCapture();
RefPtr<gfxASurface> mScrollCapture;
CancelableTask* mCaptureRefreshTask;
RefPtr<CancelableRunnable> mCaptureRefreshTask;
bool mValidFirstCapture;
bool mIsScrolling;
#endif
+10 -5
View File
@@ -166,7 +166,8 @@ PluginModuleChild::~PluginModuleChild()
// bridged protocol (bug 1090570). So we have to do it ourselves. This
// code is only invoked for PluginModuleChild instances created via
// bridging; otherwise mTransport is null.
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport);
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
if (mIsChrome) {
@@ -831,7 +832,9 @@ PluginModuleChild::ActorDestroy(ActorDestroyReason why)
}
// Destroy ourselves once we finish other teardown activities.
MessageLoop::current()->PostTask(FROM_HERE, new DeleteTask<PluginModuleChild>(this));
RefPtr<DeleteTask<PluginModuleChild>> task =
new DeleteTask<PluginModuleChild>(this);
MessageLoop::current()->PostTask(task.forget());
return;
}
@@ -2207,11 +2210,12 @@ public:
{
}
void Run() override
NS_IMETHOD Run() override
{
RemoveFromAsyncList();
DebugOnly<bool> sendOk = mInstance->SendAsyncNPP_NewResult(mResult);
MOZ_ASSERT(sendOk);
return NS_OK;
}
private:
@@ -2225,8 +2229,9 @@ RunAsyncNPP_New(void* aChildInstance)
PluginInstanceChild* childInstance =
static_cast<PluginInstanceChild*>(aChildInstance);
NPError rv = childInstance->DoNPP_New();
AsyncNewResultSender* task = new AsyncNewResultSender(childInstance, rv);
childInstance->PostChildAsyncCall(task);
RefPtr<AsyncNewResultSender> task =
new AsyncNewResultSender(childInstance, rv);
childInstance->PostChildAsyncCall(task.forget());
}
bool
+10 -18
View File
@@ -150,7 +150,7 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId,
/**
* Use for executing CreateToolhelp32Snapshot off main thread
*/
class mozilla::plugins::FinishInjectorInitTask : public CancelableTask
class mozilla::plugins::FinishInjectorInitTask : public mozilla::CancelableRunnable
{
public:
FinishInjectorInitTask()
@@ -169,34 +169,31 @@ public:
void PostToMainThread()
{
RefPtr<Runnable> self = this;
mSnapshot.own(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
bool deleteThis = false;
{ // Scope for lock
mozilla::MutexAutoLock lock(mMutex);
if (mMainThreadMsgLoop) {
mMainThreadMsgLoop->PostTask(FROM_HERE, this);
} else {
deleteThis = true;
mMainThreadMsgLoop->PostTask(self.forget());
}
}
if (deleteThis) {
delete this;
}
}
void Run() override
NS_IMETHOD Run() override
{
mParent->DoInjection(mSnapshot);
// We don't need to hold this lock during DoInjection, but we do need
// to obtain it before returning from Run() to ensure that
// PostToMainThread has completed before we return.
mozilla::MutexAutoLock lock(mMutex);
return NS_OK;
}
void Cancel() override
nsresult Cancel() override
{
mozilla::MutexAutoLock lock(mMutex);
mMainThreadMsgLoop = nullptr;
return NS_OK;
}
private:
@@ -710,8 +707,9 @@ PluginModuleContentParent::PluginModuleContentParent(bool aAllowAsyncInit)
PluginModuleContentParent::~PluginModuleContentParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
XRE_GetIOMessageLoop()->PostTask(task.forget());
Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this);
}
@@ -906,7 +904,6 @@ PluginModuleChromeParent::CleanupFromTimeout(const bool aFromHangUI)
if (!OkToCleanup()) {
// there's still plugin code on the C++ stack, try again
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
mChromeTaskFactory.NewRunnableMethod(
&PluginModuleChromeParent::CleanupFromTimeout, aFromHangUI), 10);
return;
@@ -1171,7 +1168,6 @@ PluginModuleChromeParent::ShouldContinueFromReplyTimeout()
{
if (mIsFlashPlugin) {
MessageLoop::current()->PostTask(
FROM_HERE,
mTaskFactory.NewRunnableMethod(
&PluginModuleChromeParent::NotifyFlashHang));
}
@@ -1349,7 +1345,6 @@ PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
// or not at all
bool isFromHangUI = aMsgLoop != MessageLoop::current();
aMsgLoop->PostTask(
FROM_HERE,
mChromeTaskFactory.NewRunnableMethod(
&PluginModuleChromeParent::CleanupFromTimeout, isFromHangUI));
@@ -1599,7 +1594,6 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
// and potentially modify the actor child list while enumerating it.
if (mPlugin)
MessageLoop::current()->PostTask(
FROM_HERE,
mTaskFactory.NewRunnableMethod(
&PluginModuleParent::NotifyPluginCrashed));
break;
@@ -1655,7 +1649,6 @@ PluginModuleParent::NotifyPluginCrashed()
if (!OkToCleanup()) {
// there's still plugin code on the C++ stack. try again
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
mTaskFactory.NewRunnableMethod(
&PluginModuleParent::NotifyPluginCrashed), 10);
return;
@@ -3156,7 +3149,6 @@ PluginModuleChromeParent::InitializeInjector()
mFinishInitTask->Init(this);
if (!::QueueUserWorkItem(&PluginModuleChromeParent::GetToolhelpSnapshot,
mFinishInitTask, WT_EXECUTEDEFAULT)) {
delete mFinishInitTask;
mFinishInitTask = nullptr;
return;
}
+3 -2
View File
@@ -610,7 +610,7 @@ private:
DWORD mFlashProcess1;
DWORD mFlashProcess2;
mozilla::plugins::FinishInjectorInitTask* mFinishInitTask;
RefPtr<mozilla::plugins::FinishInjectorInitTask> mFinishInitTask;
#endif
void OnProcessLaunched(const bool aSucceeded);
@@ -624,9 +624,10 @@ private:
MOZ_ASSERT(aModule);
}
void Run() override
NS_IMETHOD Run() override
{
mModule->OnProcessLaunched(mLaunchSucceeded);
return NS_OK;
}
private:
+3 -4
View File
@@ -194,8 +194,7 @@ PluginProcessParent::Delete()
return;
}
ioLoop->PostTask(FROM_HERE,
NewRunnableMethod(this, &PluginProcessParent::Delete));
ioLoop->PostTask(NewRunnableMethod(this, &PluginProcessParent::Delete));
}
void
@@ -239,7 +238,7 @@ PluginProcessParent::OnChannelConnected(int32_t peer_pid)
GeckoChildProcessHost::OnChannelConnected(peer_pid);
if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
mLaunchCompleteTask->SetLaunchSucceeded();
mMainMsgLoop->PostTask(FROM_HERE, mTaskFactory.NewRunnableMethod(
mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod(
&PluginProcessParent::RunLaunchCompleteTask));
}
}
@@ -249,7 +248,7 @@ PluginProcessParent::OnChannelError()
{
GeckoChildProcessHost::OnChannelError();
if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
mMainMsgLoop->PostTask(FROM_HERE, mTaskFactory.NewRunnableMethod(
mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod(
&PluginProcessParent::RunLaunchCompleteTask));
}
}
+1 -1
View File
@@ -25,7 +25,7 @@
namespace mozilla {
namespace plugins {
class LaunchCompleteTask : public Task
class LaunchCompleteTask : public Runnable
{
public:
LaunchCompleteTask()
+17 -12
View File
@@ -36,9 +36,10 @@ private:
{
}
virtual void Run() {
NS_IMETHOD Run() override {
if (!revocable_.revoked())
TaskType::Run();
return NS_OK;
}
private:
@@ -49,34 +50,35 @@ public:
explicit TaskFactory(T* object) : object_(object) { }
template <typename TaskParamType, typename... Args>
inline TaskParamType* NewTask(Args&&... args)
inline already_AddRefed<TaskParamType> NewTask(Args&&... args)
{
typedef TaskWrapper<TaskParamType> TaskWrapper;
TaskWrapper* task = new TaskWrapper(this, mozilla::Forward<Args>(args)...);
return task;
RefPtr<TaskWrapper> task =
new TaskWrapper(this, mozilla::Forward<Args>(args)...);
return task.forget();
}
template <class Method>
inline Task* NewRunnableMethod(Method method) {
inline already_AddRefed<Runnable> NewRunnableMethod(Method method) {
typedef TaskWrapper<RunnableMethod<Method, Tuple0> > TaskWrapper;
TaskWrapper* task = new TaskWrapper(this);
RefPtr<TaskWrapper> task = new TaskWrapper(this);
task->Init(object_, method, base::MakeTuple());
return task;
return task.forget();
}
template <class Method, class A>
inline Task* NewRunnableMethod(Method method, const A& a) {
inline already_AddRefed<Runnable> NewRunnableMethod(Method method, const A& a) {
typedef TaskWrapper<RunnableMethod<Method, Tuple1<A> > > TaskWrapper;
TaskWrapper* task = new TaskWrapper(this);
RefPtr<TaskWrapper> task = new TaskWrapper(this);
task->Init(object_, method, base::MakeTuple(a));
return task;
return task.forget();
}
protected:
template <class Method, class Params>
class RunnableMethod : public Task {
class RunnableMethod : public Runnable {
public:
RunnableMethod() { }
@@ -86,7 +88,10 @@ protected:
params_ = params;
}
virtual void Run() { DispatchToMethod(obj_, meth_, params_); }
NS_IMETHOD Run() override {
DispatchToMethod(obj_, meth_, params_);
return NS_OK;
}
private:
T* obj_;
-5
View File
@@ -1,5 +0,0 @@
component {8ee5ab74-15c4-478f-9d32-67627b9f0f1a} RequestSyncScheduler.js
contract @mozilla.org/dom/request-sync-scheduler;1 {8ee5ab74-15c4-478f-9d32-67627b9f0f1a}
component {e6f55080-e549-4e30-9d00-15f240fb763c} RequestSyncManager.js
contract @mozilla.org/dom/request-sync-manager;1 {e6f55080-e549-4e30-9d00-15f240fb763c}
-48
View File
@@ -1,48 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
this.EXPORTED_SYMBOLS = ['RequestSyncApp'];
function debug(s) {
//dump('DEBUG RequestSyncApp: ' + s + '\n');
}
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
this.RequestSyncApp = function(aData) {
debug('created');
let keys = [ 'origin', 'manifestURL', 'isInBrowserElement' ];
for (let i = 0; i < keys.length; ++i) {
if (!(keys[i] in aData)) {
dump("ERROR - RequestSyncApp must receive a full app object: " + keys[i] + " missing.");
throw "ERROR!";
}
this["_" + keys[i]] = aData[keys[i]];
}
}
this.RequestSyncApp.prototype = {
classDescription: 'RequestSyncApp XPCOM Component',
classID: Components.ID('{5a0b64db-a2be-4f08-a6c5-8bf2e3ae0c57}'),
contractID: '@mozilla.org/dom/request-sync-manager;1',
QueryInterface: XPCOMUtils.generateQI([]),
get origin() {
return this._origin;
},
get manifestURL() {
return this._manifestURL;
},
get isInBrowserElement() {
return this._isInBrowserElement;
}
};
-134
View File
@@ -1,134 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
function debug(s) {
//dump('DEBUG RequestSyncManager: ' + s + '\n');
}
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/RequestSyncApp.jsm');
Cu.import('resource://gre/modules/RequestSyncTask.jsm');
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
function RequestSyncManager() {
debug('created');
}
RequestSyncManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
classDescription: 'RequestSyncManager XPCOM Component',
classID: Components.ID('{e6f55080-e549-4e30-9d00-15f240fb763c}'),
contractID: '@mozilla.org/dom/request-sync-manager;1',
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
Ci.nsIObserver,
Ci.nsIDOMGlobalPropertyInitializer]),
_messages: [ "RequestSyncManager:Registrations:Return",
"RequestSyncManager:SetPolicy:Return",
"RequestSyncManager:RunTask:Return" ],
init: function(aWindow) {
debug("init");
// DOMRequestIpcHelper.initHelper sets this._window
this.initDOMRequestHelper(aWindow, this._messages);
},
sendMessage: function(aMsg, aObj) {
let self = this;
return this.createPromiseWithId(function(aResolverId) {
aObj.requestID = aResolverId;
cpmm.sendAsyncMessage(aMsg, aObj, null,
self._window.document.nodePrincipal);
});
},
registrations: function() {
debug('registrations');
return this.sendMessage("RequestSyncManager:Registrations", {});
},
setPolicy: function(aTask, aOrigin, aManifestURL, aIsInIsolatedMozBrowserElement,
aState, aOverwrittenMinInterval) {
debug('setPolicy');
return this.sendMessage("RequestSyncManager:SetPolicy",
{ task: aTask,
origin: aOrigin,
manifestURL: aManifestURL,
isInBrowserElement: aIsInIsolatedMozBrowserElement,
state: aState,
overwrittenMinInterval: aOverwrittenMinInterval });
},
runTask: function(aTask, aOrigin, aManifestURL, aIsInIsolatedMozBrowserElement) {
debug('runTask');
return this.sendMessage("RequestSyncManager:RunTask",
{ task: aTask,
origin: aOrigin,
manifestURL: aManifestURL,
isInBrowserElement: aIsInIsolatedMozBrowserElement });
},
registrationsResult: function(aData) {
debug("registrationsResult");
let results = new this._window.Array();
for (let i = 0; i < aData.length; ++i) {
if (!("app" in aData[i])) {
dump("ERROR - Serialization error in RequestSyncManager.\n");
continue;
}
let app = new RequestSyncApp(aData[i].app);
let exposedApp =
this._window.RequestSyncApp._create(this._window, app);
let task = new RequestSyncTask(this, this._window, exposedApp, aData[i]);
let exposedTask =
this._window.RequestSyncTask._create(this._window, task);
results.push(exposedTask);
}
return results;
},
receiveMessage: function(aMessage) {
debug('receiveMessage');
let req = this.getPromiseResolver(aMessage.data.requestID);
if (!req) {
return;
}
if ('error' in aMessage.data) {
req.reject(Cu.cloneInto(aMessage.data.error, this._window));
return;
}
if (aMessage.name == 'RequestSyncManager:Registrations:Return') {
req.resolve(this.registrationsResult(aMessage.data.results));
return;
}
if ('results' in aMessage.data) {
req.resolve(Cu.cloneInto(aMessage.data.results, this._window));
return;
}
req.resolve();
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RequestSyncManager]);
-100
View File
@@ -1,100 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
function debug(s) {
//dump('DEBUG RequestSyncScheduler: ' + s + '\n');
}
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/DOMRequestHelper.jsm');
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyServiceGetter(this, 'cpmm',
'@mozilla.org/childprocessmessagemanager;1',
'nsIMessageSender');
function RequestSyncScheduler() {
debug('created');
}
RequestSyncScheduler.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
classDescription: 'RequestSyncScheduler XPCOM Component',
classID: Components.ID('{8ee5ab74-15c4-478f-9d32-67627b9f0f1a}'),
contractID: '@mozilla.org/dom/request-sync-scheduler;1',
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
Ci.nsIObserver,
Ci.nsIDOMGlobalPropertyInitializer]),
_messages: [ 'RequestSync:Register:Return',
'RequestSync:Unregister:Return',
'RequestSync:Registrations:Return',
'RequestSync:Registration:Return' ],
init: function(aWindow) {
debug('init');
// DOMRequestIpcHelper.initHelper sets this._window
this.initDOMRequestHelper(aWindow, this._messages);
},
register: function(aTask, aParams) {
debug('register');
return this.sendMessage('RequestSync:Register',
{ task: aTask, params: aParams });
},
unregister: function(aTask) {
debug('unregister');
return this.sendMessage('RequestSync:Unregister',
{ task: aTask });
},
registrations: function() {
debug('registrations');
return this.sendMessage('RequestSync:Registrations', {});
},
registration: function(aTask) {
debug('registration');
return this.sendMessage('RequestSync:Registration',
{ task: aTask });
},
sendMessage: function(aMsg, aObj) {
let self = this;
return this.createPromiseWithId(function(aResolverId) {
aObj.requestID = aResolverId;
cpmm.sendAsyncMessage(aMsg, aObj, null,
self._window.document.nodePrincipal);
});
},
receiveMessage: function(aMessage) {
debug('receiveMessage');
let req = this.getPromiseResolver(aMessage.data.requestID);
if (!req) {
return;
}
if ('error' in aMessage.data) {
req.reject(Cu.cloneInto(aMessage.data.error, this._window));
return;
}
if ('results' in aMessage.data) {
req.resolve(Cu.cloneInto(aMessage.data.results, this._window));
return;
}
req.resolve();
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RequestSyncScheduler]);
File diff suppressed because it is too large Load Diff
-108
View File
@@ -1,108 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
this.EXPORTED_SYMBOLS = ['RequestSyncTask'];
function debug(s) {
//dump('DEBUG RequestSyncTask: ' + s + '\n');
}
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
this.RequestSyncTask = function(aManager, aWindow, aApp, aData) {
debug('created');
this._manager = aManager;
this._window = aWindow;
this._app = aApp;
let keys = [ 'task', 'lastSync', 'oneShot', 'minInterval', 'wakeUpPage',
'wifiOnly', 'data', 'state', 'overwrittenMinInterval' ];
for (let i = 0; i < keys.length; ++i) {
if (!(keys[i] in aData)) {
dump("ERROR - RequestSyncTask must receive a fully app object: " + keys[i] + " missing.");
throw "ERROR!";
}
this["_" + keys[i]] = aData[keys[i]];
}
}
this.RequestSyncTask.prototype = {
classDescription: 'RequestSyncTask XPCOM Component',
classID: Components.ID('{a1e1c9c6-ce42-49d4-b8b4-fbd686d8fdd9}'),
contractID: '@mozilla.org/dom/request-sync-manager;1',
QueryInterface: XPCOMUtils.generateQI([]),
get app() {
return this._app;
},
get state() {
return this._state;
},
get overwrittenMinInterval() {
return this._overwrittenMinInterval;
},
get task() {
return this._task;
},
get lastSync() {
return this._lastSync;
},
get wakeUpPage() {
return this._wakeUpPage;
},
get oneShot() {
return this._oneShot;
},
get minInterval() {
return this._minInterval;
},
get wifiOnly() {
return this._wifiOnly;
},
get data() {
return this._data;
},
setPolicy: function(aState, aOverwrittenMinInterval) {
debug("setPolicy");
let self = this;
return new this._window.Promise(function(aResolve, aReject) {
let p = self._manager.setPolicy(self._task, self._app.origin,
self._app.manifestURL,
self._app.isInBrowserElement,
aState,
aOverwrittenMinInterval);
// Set the new value only when the promise is resolved.
p.then(function() {
self._state = aState;
self._overwrittenMinInterval = aOverwrittenMinInterval;
aResolve();
}, aReject);
});
},
runNow: function() {
debug("runNow");
return this._manager.runTask(this._task, this._app.origin,
this._app.manifestURL,
this._app.isInBrowserElement);
}
};
@@ -1,67 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RequestSyncWifiService.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "nsIObserverService.h"
namespace mozilla {
namespace dom {
using namespace hal;
NS_IMPL_ISUPPORTS0(RequestSyncWifiService)
namespace {
StaticRefPtr<RequestSyncWifiService> sService;
} // namespace
/* static */ void
RequestSyncWifiService::Init()
{
RefPtr<RequestSyncWifiService> service = GetInstance();
if (!service) {
NS_WARNING("Failed to initialize RequestSyncWifiService.");
}
}
/* static */ already_AddRefed<RequestSyncWifiService>
RequestSyncWifiService::GetInstance()
{
if (!sService) {
sService = new RequestSyncWifiService();
hal::RegisterNetworkObserver(sService);
ClearOnShutdown(&sService);
}
RefPtr<RequestSyncWifiService> service = sService.get();
return service.forget();
}
void
RequestSyncWifiService::Notify(const hal::NetworkInformation& aNetworkInfo)
{
bool isWifi = aNetworkInfo.isWifi();
if (isWifi == mIsWifi) {
return;
}
mIsWifi = isWifi;
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->NotifyObservers(nullptr, "wifi-state-changed",
mIsWifi ? MOZ_UTF16("enabled") :
MOZ_UTF16("disabled"));
}
}
} // namespace dom
} // namespace mozilla
-43
View File
@@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_RequestSyncWifiService_h
#define mozilla_dom_RequestSyncWifiService_h
#include "mozilla/dom/network/Types.h"
#include "mozilla/Hal.h"
#include "nsIObserver.h"
namespace mozilla {
namespace dom {
class RequestSyncWifiService final : public nsISupports
, public NetworkObserver
{
public:
NS_DECL_ISUPPORTS
static void Init();
static already_AddRefed<RequestSyncWifiService> GetInstance();
void Notify(const hal::NetworkInformation& aNetworkInfo) override;
private:
RequestSyncWifiService()
: mIsWifi(false)
{}
~RequestSyncWifiService()
{}
bool mIsWifi;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_RequestSyncWifiService_h
-34
View File
@@ -1,34 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
EXPORTS.mozilla.dom += [
'RequestSyncWifiService.h',
]
EXTRA_COMPONENTS += [
'RequestSync.manifest',
'RequestSyncManager.js',
'RequestSyncScheduler.js',
]
EXTRA_JS_MODULES += [
'RequestSyncApp.jsm',
'RequestSyncService.jsm',
'RequestSyncTask.jsm',
]
SOURCES += [
'RequestSyncWifiService.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
-15
View File
@@ -1,15 +0,0 @@
function is(a, b, msg) {
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
}
function ok(a, msg) {
alert((a ? 'OK' : 'KO')+ ' ' + msg)
}
function cbError() {
alert('KO error');
}
function finish() {
alert('DONE');
}
-188
View File
@@ -1,188 +0,0 @@
function test_registerFailure() {
ok("sync" in navigator, "navigator.sync exists");
navigator.sync.register().then(
function() {
ok(false, "navigator.sync.register() throws without a task name");
}, function() {
ok(true, "navigator.sync.register() throws without a task name");
})
.then(function() {
return navigator.sync.register(42);
}).then(function() {
ok(false, "navigator.sync.register() throws without a string task name");
}, function() {
ok(true, "navigator.sync.register() throws without a string task name");
})
.then(function() {
return navigator.sync.register('foobar');
}).then(function() {
ok(false, "navigator.sync.register() throws without a param dictionary");
}, function() {
ok(true, "navigator.sync.register() throws without a param dictionary");
})
.then(function() {
return navigator.sync.register('foobar', 42);
}).then(function() {
ok(false, "navigator.sync.register() throws without a real dictionary");
}, function() {
ok(true, "navigator.sync.register() throws without a real dictionary");
})
.then(function() {
return navigator.sync.register('foobar', {});
}).then(function() {
ok(false, "navigator.sync.register() throws without a minInterval and wakeUpPage");
}, function() {
ok(true, "navigator.sync.register() throws without a minInterval and wakeUpPage");
})
.then(function() {
return navigator.sync.register('foobar', { minInterval: 100 });
}).then(function() {
ok(false, "navigator.sync.register() throws without a wakeUpPage");
}, function() {
ok(true, "navigator.sync.register() throws without a wakeUpPage");
})
.then(function() {
return navigator.sync.register('foobar', { wakeUpPage: 100 });
}).then(function() {
ok(false, "navigator.sync.register() throws without a minInterval");
}, function() {
ok(true, "navigator.sync.register() throws without a minInterval");
})
.then(function() {
runTests();
});
}
function genericError(name, val) {
ok(false, "Promise from " + name + " rejected with value: " + val);
}
function test_register() {
navigator.sync.register('foobar', { minInterval: 5, wakeUpPage:'/' }).then(
function() {
ok(true, "navigator.sync.register() worked!");
runTests();
}, genericError.bind(null, 'register'));
}
function test_unregister() {
navigator.sync.unregister('foobar').then(
function() {
ok(true, "navigator.sync.unregister() worked!");
runTests();
}, genericError.bind(null, 'unregister'));
}
function test_unregisterDuplicate() {
navigator.sync.unregister('foobar').then(
genericError.bind(null, 'unregisterDuplicate'),
function(error) {
ok(true, "navigator.sync.unregister() should throw if the task doesn't exist.");
ok(error, "UnknownTaskError", "Duplicate unregistration error is correct");
runTests();
});
}
function test_registrationEmpty() {
navigator.sync.registration('bar').then(
function(results) {
is(results, null, "navigator.sync.registration() should return null.");
runTests();
},
genericError.bind(null, 'registrationEmpty'));
}
function test_registration() {
navigator.sync.registration('foobar').then(
function(results) {
is(results.task, 'foobar', "navigator.sync.registration().task is correct");
ok("lastSync" in results, "navigator.sync.registration().lastSync is correct");
is(results.oneShot, true, "navigator.sync.registration().oneShot is correct");
is(results.minInterval, 5, "navigator.sync.registration().minInterval is correct");
ok("wakeUpPage" in results, "navigator.sync.registration().wakeUpPage is correct");
ok("wifiOnly" in results, "navigator.sync.registration().wifiOnly is correct");
ok("data" in results, "navigator.sync.registration().data is correct");
ok(!("app" in results), "navigator.sync.registrations().app is correct");
runTests();
},
genericError.bind(null, 'registration'));
}
function test_registrationsEmpty() {
navigator.sync.registrations().then(
function(results) {
is(results.length, 0, "navigator.sync.registrations() should return an empty array.");
runTests();
},
genericError.bind(null, 'registrationEmpty'));
}
function test_registrations() {
navigator.sync.registrations().then(
function(results) {
is(results.length, 1, "navigator.sync.registrations() should not return an empty array.");
is(results[0].task, 'foobar', "navigator.sync.registrations()[0].task is correct");
ok("lastSync" in results[0], "navigator.sync.registrations()[0].lastSync is correct");
is(results[0].oneShot, true, "navigator.sync.registrations()[0].oneShot is correct");
is(results[0].minInterval, 5, "navigator.sync.registrations()[0].minInterval is correct");
ok("wakeUpPage" in results[0], "navigator.sync.registration()[0].wakeUpPage is correct");
ok("wifiOnly" in results[0], "navigator.sync.registrations()[0].wifiOnly is correct");
ok("data" in results[0], "navigator.sync.registrations()[0].data is correct");
ok(!("app" in results[0]), "navigator.sync.registrations()[0].app is correct");
runTests();
},
genericError.bind(null, 'registrations'));
}
function test_managerRegistrationsEmpty() {
navigator.syncManager.registrations().then(
function(results) {
is(results.length, 0, "navigator.syncManager.registrations() should return an empty array.");
runTests();
},
genericError.bind(null, 'managerRegistrationsEmpty'));
}
function test_managerRegistrations(state, overwrittenMinInterval) {
navigator.syncManager.registrations().then(
function(results) {
is(results.length, 1, "navigator.sync.registrations() should not return an empty array.");
is(results[0].task, 'foobar', "navigator.sync.registrations()[0].task is correct");
ok("lastSync" in results[0], "navigator.sync.registrations()[0].lastSync is correct");
is(results[0].oneShot, true, "navigator.sync.registrations()[0].oneShot is correct");
is(results[0].minInterval, 5, "navigator.sync.registrations()[0].minInterval is correct");
ok("wakeUpPage" in results[0], "navigator.sync.registration()[0].wakeUpPage is correct");
ok("wifiOnly" in results[0], "navigator.sync.registrations()[0].wifiOnly is correct");
ok("data" in results[0], "navigator.sync.registrations()[0].data is correct");
ok("app" in results[0], "navigator.sync.registrations()[0].app is correct");
ok("manifestURL" in results[0].app, "navigator.sync.registrations()[0].app.manifestURL is correct");
is(results[0].app.origin, 'http://mochi.test:8888', "navigator.sync.registrations()[0].app.origin is correct");
is(results[0].app.isInBrowserElement, false, "navigator.sync.registrations()[0].app.isInBrowserElement is correct");
is(results[0].state, state, "navigator.sync.registrations()[0].state is correct");
is(results[0].overwrittenMinInterval, overwrittenMinInterval, "navigator.sync.registrations()[0].overwrittenMinInterval is correct");
ok("setPolicy" in results[0], "navigator.sync.registrations()[0].setPolicy is correct");
ok("runNow" in results[0], "navigator.sync.registrations()[0].runNow is correct");
runTests();
},
genericError.bind(null, 'managerRegistrations'));
}
function test_managerSetPolicy(state, overwrittenMinInterval) {
navigator.syncManager.registrations().then(
function(results) {
results[0].setPolicy(state, overwrittenMinInterval).then(
function() {
ok(state, results[0].state, "State matches");
ok(overwrittenMinInterval, results[0].overwrittenMinInterval, "OverwrittenMinInterval matches");
runTests();
}, genericError.bind(null, 'managerSetPolicy'));
}).catch(genericError.bind(null, 'managerSetPolicy_catch'));
}
-52
View File
@@ -1,52 +0,0 @@
var gBasePath = "tests/dom/requestsync/tests/";
var gTemplate = "file_app.template.webapp";
function handleRequest(request, response) {
var query = getQuery(request);
var testToken = '';
if ('testToken' in query) {
testToken = query.testToken;
}
var template = gBasePath + gTemplate;
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken));
}
// Copy-pasted incantations. There ought to be a better way to synchronously read
// a file into a string, but I guess we're trying to discourage that.
function readTemplate(path) {
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("CurWorkD", Components.interfaces.nsILocalFile);
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
createInstance(Components.interfaces.nsIFileInputStream);
var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
createInstance(Components.interfaces.nsIConverterInputStream);
var split = path.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);
}
fis.init(file, -1, -1, false);
cis.init(fis, "UTF-8", 0, 0);
var data = "";
let str = {};
let read = 0;
do {
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
data += str.value;
} while (read != 0);
cis.close();
return data;
}
function getQuery(request) {
var query = {};
request.queryString.split('&').forEach(function (val) {
var [name, value] = val.split('=');
query[name] = unescape(value);
});
return query;
}
@@ -1,6 +0,0 @@
{
"name": "Really Rapid Release (hosted)",
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
"launch_path": "/tests/dom/requestsync/tests/TESTTOKEN",
"icons": { "128": "default_icon" }
}
-62
View File
@@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="common_app.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<meta charset="utf-8">
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
function test_sync_interface() {
ok("sync" in navigator, "navigator.sync should exist with permissions");
ok(!("syncManager" in navigator), "navigator.syncManager should not exist without permissions");
ok("register" in navigator.sync, "navigator.sync.register exists");
ok("unregister" in navigator.sync, "navigator.sync.unregister exists");
ok("registrations" in navigator.sync, "navigator.sync.registrations exists");
ok("registration" in navigator.sync, "navigator.sync.registration exists");
runTests();
}
var tests = [
test_sync_interface,
test_registrationsEmpty,
test_registerFailure,
test_register,
// overwrite the same registration.
test_register,
test_registrations,
test_registrationEmpty,
test_registration,
test_unregister,
test_unregisterDuplicate,
test_registrationsEmpty,
// Let's keep a registration active when the app is uninstall...
test_register,
test_registrations
];
function runTests() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
runTests();
</script>
</body>
</html>
-21
View File
@@ -1,21 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="common_app.js"></script>
<meta charset="utf-8">
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
ok("sync" in navigator, "navigator.sync should exist with permissions");
ok("register" in navigator.sync, "navigator.sync.register exists");
ok("unregister" in navigator.sync, "navigator.sync.unregister exists");
ok("registrations" in navigator.sync, "navigator.sync.registrations exists");
ok("registration" in navigator.sync, "navigator.sync.registration exists");
finish();
</script>
</body>
</html>
-25
View File
@@ -1,25 +0,0 @@
[DEFAULT]
support-files =
file_app.template.webapp
file_app.sjs
file_basic_app.html
common_app.js
common_basic.js
system_message_chrome_script.js
[test_webidl.html]
skip-if = os == "android" || toolkit == "gonk"
[test_minInterval.html]
skip-if = os == "android" || toolkit == "gonk"
[test_basic.html]
skip-if = os == "android" || toolkit == "gonk"
[test_basic_app.html]
skip-if = buildapp != 'mulet' || e10s # mozapps
[test_wakeUp.html]
run-if = buildapp == 'b2g' && toolkit == 'gonk'
[test_runNow.html]
run-if = buildapp == 'b2g' && toolkit == 'gonk'
[test_promise.html]
skip-if = os == "android" || toolkit == "gonk"
[test_bug1151082.html]
skip-if = os == "android" || toolkit == "gonk"
@@ -1,18 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
'use strict';
var { classes: Cc, interfaces: Ci } = Components;
const systemMessenger = Cc["@mozilla.org/system-message-internal;1"]
.getService(Ci.nsISystemMessagesInternal);
const ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
addMessageListener("trigger-register-page", function(aData) {
systemMessenger.registerPage(aData.type,
ioService.newURI(aData.pageURL, null, null),
ioService.newURI(aData.manifestURL, null, null));
sendAsyncMessage("page-registered");
});
-77
View File
@@ -1,77 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for RequestSync basic use</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1],
["dom.ignore_webidl_scope_checks", true]]}, runTests);
},
function() {
SpecialPowers.pushPermissions(
[{ "type": "requestsync-manager", "allow": 1, "context": document } ], runTests);
},
function() {
SpecialPowers.importInMainProcess("resource://gre/modules/RequestSyncService.jsm");
runTests();
},
test_managerRegistrationsEmpty,
test_registrationsEmpty,
test_registerFailure,
test_register,
// overwrite the same registration.
test_register,
function() { test_managerRegistrations('wifiOnly', 0); },
test_registrations,
test_registrationEmpty,
test_registration,
function() { test_managerSetPolicy('disabled', 123); },
function() { test_managerRegistrations('disabled', 123); },
function() { test_managerSetPolicy('enabled', 42); },
function() { test_managerRegistrations('enabled', 42); },
test_unregister,
test_unregisterDuplicate,
test_managerRegistrationsEmpty,
test_registrationsEmpty,
];
function runTests() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
-130
View File
@@ -1,130 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for requestSync - basic operations in app</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
var gHostedManifestURL = 'http://test/tests/dom/requestsync/tests/file_app.sjs?testToken=file_basic_app.html';
var gApp;
function cbError() {
ok(false, "Error callback invoked");
finish();
}
function installApp() {
var request = navigator.mozApps.install(gHostedManifestURL);
request.onerror = cbError;
request.onsuccess = function() {
gApp = request.result;
runTests();
}
}
function uninstallApp() {
// Uninstall the app.
var request = navigator.mozApps.mgmt.uninstall(gApp);
request.onerror = cbError;
request.onsuccess = function() {
// All done.
info("All done");
runTests();
}
}
function testApp() {
var ifr = document.createElement('iframe');
ifr.setAttribute('mozbrowser', 'true');
ifr.setAttribute('mozapp', gApp.manifestURL);
ifr.setAttribute('src', gApp.manifest.launch_path);
var domParent = document.getElementById('container');
// Set us up to listen for messages from the app.
var listener = function(e) {
var message = e.detail.message;
if (/^OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/DONE/.exec(message)) {
ok(true, "Messaging from app complete");
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
domParent.removeChild(ifr);
runTests();
}
}
// This event is triggered when the app calls "alert".
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
domParent.appendChild(ifr);
}
var tests = [
// Permissions
function() {
SpecialPowers.pushPermissions(
[{ "type": "browser", "allow": 1, "context": document },
{ "type": "embed-apps", "allow": 1, "context": document },
{ "type": "requestsync-manager", "allow": 1, "context": document },
{ "type": "webapps-manage", "allow": 1, "context": document }], runTests);
},
// Preferences
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1],
["dom.ignore_webidl_scope_checks", true],
["dom.testing.ignore_ipc_principal", true]]}, runTests);
},
function() {
SpecialPowers.importInMainProcess("resource://gre/modules/RequestSyncService.jsm");
SpecialPowers.pushPrefEnv({"set":[["dom.mozBrowserFramesEnabled", true]]}, runTests);
},
// No confirmation needed when an app is installed
function() {
SpecialPowers.autoConfirmAppInstall(() =>
SpecialPowers.autoConfirmAppUninstall(runTests));
},
test_managerRegistrationsEmpty,
// Installing the app
installApp,
// Run tests in app
testApp,
// Uninstall the app
uninstallApp,
test_managerRegistrationsEmpty
];
function runTests() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
@@ -1,77 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for RequestSync bug 1151082</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1],
["dom.ignore_webidl_scope_checks", true]]}, runTests);
},
function() {
SpecialPowers.pushPermissions(
[{ "type": "requestsync-manager", "allow": 1, "context": document } ], runTests);
},
function() {
SpecialPowers.importInMainProcess("resource://gre/modules/RequestSyncService.jsm");
runTests();
},
function() {
counter = 2;
function registerCb() {
if (!--counter) {
ok(true, "All the registrations are done.");
runTests();
}
}
navigator.sync.register('foobar', { minInterval: 5, wakeUpPage:'/' }).then(registerCb, genericError);
navigator.sync.register('barfoo', { minInterval: 5, wakeUpPage:'/' }).then(registerCb, genericError);
},
function() {
counter = 2;
function unregisterCb() {
if (!--counter) {
ok(true, "All the unregistrations are done.");
runTests();
}
}
navigator.sync.unregister('foobar').then(unregisterCb, genericError);
navigator.sync.unregister('barfoo').then(unregisterCb, genericError);
}
];
function runTests() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
@@ -1,69 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for RequestSync minInterval pref</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
function test_minInterval(expected) {
navigator.sync.register('foobar', { minInterval: 1, wakeUpPage: '/' }).then(
function() {
ok(expected, "MinInterval succeeded");
},
function(e) {
ok(!expected, "MinInterval failed");
is(e, "ParamsError", "Correct error received");
})
.then(function() {
if (expected) {
navigator.sync.unregister('foobar').then(runTests);
} else {
runTests();
}
});
}
var tests = [
function() {
SpecialPowers.importInMainProcess("resource://gre/modules/RequestSyncService.jsm");
runTests();
},
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.ignore_webidl_scope_checks", true],
["dom.requestSync.enabled", true]]}, runTests);
},
function() { test_minInterval(false); },
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.minInterval", 1]]}, runTests);
},
function() { test_minInterval(true); },
];
function runTests() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
-56
View File
@@ -1,56 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for requestSync - promise</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.sysmsg.enabled", true]]}, function() {
ok("mozSetMessageHandlerPromise" in navigator, "mozSetMessageHandlerPromise exists");
var status = false;
try {
navigator.mozSetMessageHandlerPromise();
} catch(e) {
status = true;
}
ok(status, "mozSetMessageHandlerPromise wants a promise 1");
status = false;
try {
navigator.mozSetMessageHandlerPromise(42);
} catch(e) {
status = true;
}
ok(status, "mozSetMessageHandlerPromise wants a promise 2");
status = false;
try {
navigator.mozSetMessageHandlerPromise("hello world");
} catch(e) {
status = true;
}
ok(status, "mozSetMessageHandlerPromise wants a promise 3");
status = false;
try {
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {}));
} catch(e) {
info(e);
status = true;
}
ok(status, "mozSetMessageHandlerPromise cannot be called outside a messageHandler");
SimpleTest.finish();
});
</script>
</body>
</html>
-125
View File
@@ -1,125 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for requestSync - runNow</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
var taskExecuted = false;
function registerPage() {
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('system_message_chrome_script.js'));
gScript.addMessageListener("page-registered", function pageRegisteredHandler() {
gScript.removeMessageListener("page-registered", pageRegisteredHandler);
gScript.destroy();
runTests();
});
gScript.sendAsyncMessage("trigger-register-page",
{ type: "request-sync",
manifestURL: window.location.origin + "/manifest.webapp",
pageURL: window.location.href });
}
function setMessageHandler() {
navigator.mozSetMessageHandler('request-sync', function(e) {
ok(true, "One event has been received!");
if (e.task == "oneShot") {
is(e.data, 42, "e.data is correct");
is(e.lastSync, 0, "e.lastSync is correct");
is(e.oneShot, true, "e.oneShot is correct");
is(e.minInterval, 1024, "e.minInterval is correct");
is(e.wifiOnly, false, "e.wifiOnly is correct");
taskExecuted = true;
} else {
ok(false, "Unknown event has been received!");
}
});
runTests();
}
function test_register_oneShot() {
navigator.sync.register('oneShot', { minInterval: 1024,
oneShot: true,
data: 42,
wifiOnly: false,
wakeUpPage: location.href }).then(
function() {
ok(true, "navigator.sync.register() oneShot done");
runTests();
}, genericError);
}
function test_unregister_oneShot() {
navigator.sync.unregister('oneShot').then(
function() {
ok(true, "navigator.sync.unregister() oneShot done");
runTests();
}, genericError);
}
function test_runNow() {
navigator.syncManager.registrations().then(
function(array) {
for (var i = 0; i < array.length; ++i) { info(array[i].task); }
is(array.length, 1, "One registration found.");
array[0].runNow().then(function() {
ok(taskExecuted, "Task has been executed");
runTests();
});
}, genericError);
}
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.sysmsg.enabled", true],
["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1],
["dom.requestSync.maxTaskTimeout", 10000 /* 10 seconds */],
["dom.ignore_webidl_scope_checks", true]]}, runTests);
},
function() {
SpecialPowers.pushPermissions(
[{ "type": "requestsync-manager", "allow": 1, "context": document } ], runTests);
},
function() {
SpecialPowers.importInMainProcess("resource://gre/modules/RequestSyncService.jsm");
runTests();
},
registerPage,
setMessageHandler,
test_register_oneShot,
test_runNow,
test_unregister_oneShot,
];
function runTests() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
-187
View File
@@ -1,187 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for requestSync - wakeUp</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
var oneShotCounter = 0;
var multiShotCounter = 0;
function maybeDone() {
if (oneShotCounter == 1 && multiShotCounter == 5) {
runTests();
}
}
function registerPage() {
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('system_message_chrome_script.js'));
gScript.addMessageListener("page-registered", function pageRegisteredHandler() {
gScript.removeMessageListener("page-registered", pageRegisteredHandler);
gScript.destroy();
runTests();
});
gScript.sendAsyncMessage("trigger-register-page",
{ type: "request-sync",
manifestURL: window.location.origin + "/manifest.webapp",
pageURL: window.location.href });
}
function setMessageHandler() {
navigator.mozSetMessageHandler('request-sync', function(e) {
ok(true, "One event has been received!");
if (e.task == "oneShot") {
is(e.data, 42, "e.data is correct");
is(e.lastSync, 0, "e.lastSync is correct");
is(e.oneShot, true, "e.oneShot is correct");
is(e.minInterval, 2, "e.minInterval is correct");
is(e.wifiOnly, false, "e.wifiOnly is correct");
is(++oneShotCounter, 1, "Only 1 shot should be received here");
maybeDone();
}
else if (e.task == "multiShots") {
is(e.data, 'hello world!', "e.data is correct");
if (multiShotCounter == 0) {
is(e.lastSync, 0, "e.lastSync is correct");
} else {
isnot(e.lastSync, 0, "e.lastSync is correct");
}
is(e.oneShot, false, "e.oneShot is correct");
is(e.minInterval, 3, "e.minInterval is correct");
is(e.wifiOnly, false, "e.wifiOnly is correct");
++multiShotCounter;
if (multiShotCounter == 1) {
info("Setting a promise object.");
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {
setTimeout(a, 0);
}));
} else if (multiShotCounter == 2) {
// The second time we don't reply at all.
info("Setting a promise object without resolving it.");
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {}));
} else if (multiShotCounter == 3) {
info("Throwing an exception.");
// Now we throw an exception
SimpleTest.expectUncaughtException();
throw "Booom!";
} else {
info("Setting a promise object and reject it.");
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {
setTimeout(b, 0);
}));
}
maybeDone();
}
else {
ok(false, "Unknown event has been received!");
}
});
runTests();
}
function test_register_oneShot() {
navigator.sync.register('oneShot', { minInterval: 2,
oneShot: true,
data: 42,
wifiOnly: false,
wakeUpPage: location.href }).then(
function() {
ok(true, "navigator.sync.register() oneShot done");
runTests();
}, genericError);
}
function test_register_multiShots() {
navigator.sync.register('multiShots', { minInterval: 3,
oneShot: false,
data: 'hello world!',
wifiOnly: false,
wakeUpPage: location.href }).then(
function() {
ok(true, "navigator.sync.register() multiShots done");
runTests();
}, genericError);
}
function test_unregister_oneShot() {
navigator.sync.unregister('oneShot').then(
function() {
ok(true, "navigator.sync.unregister() oneShot done");
runTests();
}, genericError);
}
function test_unregister_multiShots() {
navigator.sync.unregister('multiShots').then(
function() {
ok(true, "navigator.sync.unregister() multiShots done");
runTests();
}, genericError);
}
function test_wait() {
// nothing to do here.
}
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1],
["dom.requestSync.maxTaskTimeout", 10000 /* 10 seconds */],
["dom.ignore_webidl_scope_checks", true]]}, runTests);
},
function() {
SpecialPowers.pushPermissions(
[{ "type": "requestsync-manager", "allow": 1, "context": document } ], runTests);
},
function() {
SpecialPowers.importInMainProcess("resource://gre/modules/RequestSyncService.jsm");
runTests();
},
registerPage,
setMessageHandler,
test_register_oneShot,
test_register_multiShots,
test_wait,
test_unregister_oneShot,
test_unregister_multiShots,
];
function runTests() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
-104
View File
@@ -1,104 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for RequestSync interfaces</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
function makeIframe() {
var iframe = document.createElement('iframe');
return document.body.appendChild(iframe);
}
function destroyIframe(iframe) {
iframe.remove();
}
function test_no_interface() {
var iframe = makeIframe();
ok(!("sync" in iframe.contentWindow.navigator), "navigator.sync should not exist without permissions");
ok(!("syncManager" in iframe.contentWindow.navigator), "navigator.syncManager should not exist without permissions");
destroyIframe(iframe);
runTests();
}
function test_sync(win) {
ok("register" in win.navigator.sync, "navigator.sync.register exists");
ok("unregister" in win.navigator.sync, "navigator.sync.unregister exists");
ok("registrations" in win.navigator.sync, "navigator.sync.registrations exists");
ok("registration" in win.navigator.sync, "navigator.sync.registration exists");
}
function test_sync_interface() {
var iframe = makeIframe();
ok("sync" in iframe.contentWindow.navigator, "navigator.sync should exist with permissions");
ok(!("syncManager" in iframe.contentWindow.navigator), "navigator.syncManager should not exist without permissions");
test_sync(iframe.contentWindow);
destroyIframe(iframe);
runTests();
}
function test_sync_manager_interface() {
var iframe = makeIframe();
ok("sync" in iframe.contentWindow.navigator, "navigator.sync should exist with permissions");
ok("syncManager" in iframe.contentWindow.navigator, "navigator.syncManager should exist with permissions");
test_sync(iframe.contentWindow);
ok("registrations" in iframe.contentWindow.navigator.syncManager, "navigator.syncManager.registrations exists");
destroyIframe(iframe);
runTests();
}
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", false]]}, runTests);
},
test_no_interface,
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.ignore_webidl_scope_checks", true]]}, runTests);
},
test_no_interface,
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1]]}, runTests);
},
test_sync_interface,
// Permissions
function() {
SpecialPowers.pushPermissions(
[{ "type": "requestsync-manager", "allow": 1, "context": document } ], runTests);
},
test_sync_manager_interface,
];
function runTests() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>
+4 -2
View File
@@ -578,7 +578,8 @@ nsCSPParser::keywordSource()
}
if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_INLINE)) {
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
nsWeakPtr ctx = mCSPContext->GetLoadingContext();
nsCOMPtr<nsIDocument> doc = do_QueryReferent(ctx);
if (doc) {
doc->SetHasUnsafeInlineCSP(true);
}
@@ -597,7 +598,8 @@ nsCSPParser::keywordSource()
}
if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_EVAL)) {
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mCSPContext->GetLoadingContext());
nsWeakPtr ctx = mCSPContext->GetLoadingContext();
nsCOMPtr<nsIDocument> doc = do_QueryReferent(ctx);
if (doc) {
doc->SetHasUnsafeEvalCSP(true);
}
@@ -1300,12 +1300,6 @@ var interfaceNamesInGlobalScope =
"SVGZoomAndPan",
// IMPORTANT: Do not change this list without review from a DOM peer!
"SVGZoomEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "RequestSyncManager", b2g: true, permission: ["requestsync-manager"] },
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "RequestSyncApp", b2g: true, permission: ["requestsync-manager"] },
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "RequestSyncTask", b2g: true, permission: ["requestsync-manager"] },
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Telephony", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
-56
View File
@@ -1,56 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[AvailableIn=CertifiedApps,
Pref="dom.requestSync.enabled",
CheckAnyPermissions="requestsync-manager",
JSImplementation="@mozilla.org/dom/request-sync-task-app;1"]
interface RequestSyncApp {
readonly attribute USVString origin;
readonly attribute USVString manifestURL;
readonly attribute boolean isInBrowserElement;
};
enum RequestSyncTaskPolicyState { "enabled", "disabled", "wifiOnly" };
// Like a normal task, but with info about the app.
[AvailableIn=CertifiedApps,
Pref="dom.requestSync.enabled",
CheckAnyPermissions="requestsync-manager",
JSImplementation="@mozilla.org/dom/request-sync-task-manager;1"]
interface RequestSyncTask {
// This object describes the app that is owning the task.
readonly attribute RequestSyncApp app;
// Using setPolicy it's possible to owerwrite the state and the minInterval.
readonly attribute RequestSyncTaskPolicyState state;
readonly attribute long overwrittenMinInterval;
// These attributes are taken from the configuration of the task:
readonly attribute USVString task;
readonly attribute DOMTimeStamp lastSync;
readonly attribute USVString wakeUpPage;
readonly attribute boolean oneShot;
readonly attribute long minInterval;
readonly attribute boolean wifiOnly;
readonly attribute any data;
Promise<void> setPolicy(RequestSyncTaskPolicyState aState,
optional long ovewrittenMinInterval);
Promise<void> runNow();
};
[NavigatorProperty="syncManager",
AvailableIn=CertifiedApps,
Pref="dom.requestSync.enabled",
CheckAnyPermissions="requestsync-manager",
JSImplementation="@mozilla.org/dom/request-sync-manager;1"]
// This interface will be used only by the B2G SystemApp
interface RequestSyncManager {
Promise<sequence<RequestSyncTask>> registrations();
};
-38
View File
@@ -1,38 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// This is the dictionary for the creation of a new task.
dictionary RequestTaskParams {
required USVString wakeUpPage;
boolean oneShot = true;
required long minInterval; // in seconds >= dom.requestSync.minInterval or 100 secs
boolean wifiOnly = true;
any data = null;
};
// This is the dictionary you can have back from registration{s}().
dictionary RequestTaskFull : RequestTaskParams {
USVString task = "";
// Last synchonization date.. maybe it's useful to know.
DOMTimeStamp lastSync;
};
[NavigatorProperty="sync",
AvailableIn=CertifiedApps,
Pref="dom.requestSync.enabled",
JSImplementation="@mozilla.org/dom/request-sync-scheduler;1"]
interface RequestSyncScheduler {
Promise<void> register(USVString task,
optional RequestTaskParams params);
Promise<void> unregister(USVString task);
// Useful methods to get registrations
Promise<sequence<RequestTaskFull>> registrations();
Promise<RequestTaskFull> registration(USVString task);
};
-2
View File
@@ -396,8 +396,6 @@ WEBIDL_FILES = [
'Range.webidl',
'Rect.webidl',
'Request.webidl',
'RequestSyncManager.webidl',
'RequestSyncScheduler.webidl',
'ResourceStats.webidl',
'ResourceStatsManager.webidl',
'Response.webidl',
+4 -4
View File
@@ -32,14 +32,14 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTxn)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTxn,
EditAggregateTxn)
tmp->mStartSel->DoUnlink();
tmp->mEndSel.DoUnlink();
ImplCycleCollectionUnlink(*tmp->mStartSel);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndSel);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTxn,
EditAggregateTxn)
tmp->mStartSel->DoTraverse(cb);
tmp->mEndSel.DoTraverse(cb);
ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndSel);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTxn)
+17 -28
View File
@@ -176,14 +176,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEditor)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
if (tmp->mEventListener) {
nsEditorEventListener* listener =
reinterpret_cast<nsEditorEventListener*>(tmp->mEventListener.get());
listener->Disconnect();
tmp->mEventListener = nullptr;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
@@ -202,6 +197,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSavedSel);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeUpdater);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEditor)
@@ -3261,13 +3258,6 @@ nsEditor::GetLeftmostChild(nsINode *aCurrentNode,
return nullptr;
}
bool
nsEditor::IsBlockNode(nsIDOMNode* aNode)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
return IsBlockNode(node);
}
bool
nsEditor::IsBlockNode(nsINode* aNode)
{
@@ -3363,13 +3353,6 @@ nsEditor::IsDescendantOfRoot(nsINode* inNode)
return nsContentUtils::ContentIsDescendantOf(inNode, root);
}
bool
nsEditor::IsDescendantOfEditorRoot(nsIDOMNode* aNode)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
return IsDescendantOfEditorRoot(node);
}
bool
nsEditor::IsDescendantOfEditorRoot(nsINode* aNode)
{
@@ -3664,13 +3647,15 @@ nsEditor::GetChildAt(nsIDOMNode *aParent, int32_t aOffset)
// assuming that aParentOrNode is the node itself if it's a text node, or
// the node's parent otherwise.
//
nsCOMPtr<nsIDOMNode>
nsIContent*
nsEditor::GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset)
{
if (IsTextNode(aParentOrNode)) {
return aParentOrNode;
nsCOMPtr<nsINode> parentOrNode = do_QueryInterface(aParentOrNode);
NS_ENSURE_TRUE(parentOrNode || !aParentOrNode, nullptr);
if (parentOrNode->GetAsText()) {
return parentOrNode->AsContent();
}
return GetChildAt(aParentOrNode, aOffset);
return parentOrNode->GetChildAt(aOffset);
}
@@ -3687,7 +3672,9 @@ nsEditor::GetStartNodeAndOffset(Selection* aSelection,
nsCOMPtr<nsINode> startNode;
nsresult rv = GetStartNodeAndOffset(aSelection, getter_AddRefs(startNode),
outStartOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
return rv;
}
if (startNode) {
NS_ADDREF(*outStartNode = startNode->AsDOMNode());
@@ -3708,7 +3695,9 @@ nsEditor::GetStartNodeAndOffset(Selection* aSelection, nsINode** aStartNode,
*aStartNode = nullptr;
*aStartOffset = 0;
NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
if (!aSelection->RangeCount()) {
return NS_ERROR_FAILURE;
}
const nsRange* range = aSelection->GetRangeAt(0);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);

Some files were not shown because too many files have changed in this diff Show More