mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:37:11 +00:00
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:
@@ -1090,9 +1090,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");
|
||||
|
||||
@@ -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');
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
Cu.import('resource://gre/modules/MultiscreenHandler.jsm');
|
||||
|
||||
@@ -383,9 +383,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
|
||||
|
||||
@@ -549,10 +549,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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -29,7 +29,7 @@ AnonymousContent::~AnonymousContent()
|
||||
{
|
||||
}
|
||||
|
||||
nsCOMPtr<Element>
|
||||
Element*
|
||||
AnonymousContent::GetContentNode()
|
||||
{
|
||||
return mContentNode;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1321,9 +1321,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
|
||||
|
||||
@@ -2063,7 +2063,10 @@ nsIScriptContext *
|
||||
nsGlobalWindow::GetScriptContext()
|
||||
{
|
||||
nsGlobalWindow* outer = GetOuterWindowInternal();
|
||||
return outer ? outer->mContext : nullptr;
|
||||
if (!outer) {
|
||||
return nullptr;
|
||||
}
|
||||
return outer->mContext;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
@@ -7538,7 +7541,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 =
|
||||
|
||||
@@ -561,7 +561,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
@@ -1881,7 +1881,7 @@ public:
|
||||
MediaStreamTrackSource)
|
||||
|
||||
explicit CaptureStreamTrackSource(HTMLMediaElement* aElement)
|
||||
: MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()),
|
||||
: MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()).get(),
|
||||
true,
|
||||
nsString())
|
||||
, mElement(aElement)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1511,7 +1511,7 @@ ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL)
|
||||
return true;
|
||||
}
|
||||
|
||||
static CancelableTask* sFirstIdleTask;
|
||||
static CancelableRunnable* sFirstIdleTask;
|
||||
|
||||
static void FirstIdle(void)
|
||||
{
|
||||
@@ -1592,8 +1592,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.
|
||||
@@ -2612,8 +2613,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
|
||||
|
||||
|
||||
@@ -790,8 +790,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));
|
||||
{
|
||||
@@ -2165,7 +2164,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));
|
||||
}
|
||||
@@ -2249,7 +2247,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));
|
||||
}
|
||||
@@ -3616,7 +3613,6 @@ ContentParent::KillHard(const char* aReason)
|
||||
|
||||
// EnsureProcessTerminated has responsibilty for closing otherProcessHandle.
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated,
|
||||
otherProcessHandle, /*force=*/true));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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:
|
||||
@@ -975,11 +977,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;
|
||||
|
||||
@@ -1069,8 +1072,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
|
||||
@@ -1106,14 +1108,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();
|
||||
}
|
||||
@@ -1126,7 +1128,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(
|
||||
@@ -1169,8 +1171,8 @@ public:
|
||||
NS_DispatchToMainThread(do_AddRef(new GetUserMediaListenerRemove(mWindowID, mListener)));
|
||||
}
|
||||
|
||||
void
|
||||
Run()
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(mOnSuccess);
|
||||
@@ -1189,7 +1191,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) {
|
||||
@@ -1202,7 +1204,7 @@ public:
|
||||
}
|
||||
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
|
||||
NS_LITERAL_STRING("Failed to allocate videosource"));
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
PeerIdentity* peerIdentity = nullptr;
|
||||
@@ -1216,6 +1218,7 @@ public:
|
||||
mVideoDevice, peerIdentity)));
|
||||
MOZ_ASSERT(!mOnSuccess);
|
||||
MOZ_ASSERT(!mOnFailure);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@@ -1308,7 +1311,7 @@ public:
|
||||
~GetUserMediaRunnableWrapper() {
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
NS_IMETHOD Run() override {
|
||||
mTask->Run();
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1353,10 +1356,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;
|
||||
@@ -1391,7 +1394,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) {
|
||||
@@ -1402,7 +1405,7 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
|
||||
p->Resolve(result.release());
|
||||
}
|
||||
return NS_OK;
|
||||
})));
|
||||
}));
|
||||
}));
|
||||
return p.forget();
|
||||
}
|
||||
@@ -1601,16 +1604,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
|
||||
@@ -2093,11 +2099,11 @@ MediaManager::GetUserMedia(nsPIDOMWindow* 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());
|
||||
|
||||
@@ -2345,9 +2351,9 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* 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;
|
||||
@@ -2589,15 +2595,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"));
|
||||
@@ -2615,6 +2621,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;
|
||||
@@ -2631,7 +2639,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) {
|
||||
@@ -2647,7 +2655,8 @@ MediaManager::Shutdown()
|
||||
sSingleton = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
})));
|
||||
}));
|
||||
mMediaThread->message_loop()->PostTask(shutdown.forget());
|
||||
}
|
||||
|
||||
nsresult
|
||||
@@ -2673,8 +2682,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;
|
||||
}
|
||||
@@ -2721,7 +2730,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")) {
|
||||
@@ -2736,8 +2745,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);
|
||||
}
|
||||
@@ -3065,12 +3074,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;
|
||||
}
|
||||
|
||||
@@ -3130,9 +3140,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;
|
||||
@@ -3155,8 +3165,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) {
|
||||
@@ -3189,7 +3199,7 @@ GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
})));
|
||||
}));
|
||||
}));
|
||||
return p.forget();
|
||||
}
|
||||
@@ -3226,12 +3236,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;
|
||||
}
|
||||
@@ -3256,11 +3267,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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -621,8 +621,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;
|
||||
}
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -104,6 +104,7 @@ EXPORTS += [
|
||||
'Intervals.h',
|
||||
'Latency.h',
|
||||
'MediaCache.h',
|
||||
'MediaCallbackID.h',
|
||||
'MediaData.h',
|
||||
'MediaDataDemuxer.h',
|
||||
'MediaDecoder.h',
|
||||
@@ -212,6 +213,7 @@ UNIFIED_SOURCES += [
|
||||
'GraphDriver.cpp',
|
||||
'Latency.cpp',
|
||||
'MediaCache.cpp',
|
||||
'MediaCallbackID.cpp',
|
||||
'MediaData.cpp',
|
||||
'MediaDecoder.cpp',
|
||||
'MediaDecoderReader.cpp',
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ DIRS += [
|
||||
'bluetooth',
|
||||
'activities',
|
||||
'archivereader',
|
||||
'requestsync',
|
||||
'bindings',
|
||||
'battery',
|
||||
'browser-element',
|
||||
|
||||
@@ -3279,7 +3279,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;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ BrowserStreamChild::NPN_DestroyStream(NPReason reason)
|
||||
void
|
||||
BrowserStreamChild::EnsureDeliveryPending()
|
||||
{
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
MessageLoop::current()->PostTask(
|
||||
mDeliveryTracker.NewRunnableMethod(&BrowserStreamChild::Deliver));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -474,7 +474,7 @@ private:
|
||||
void CancelScheduledScrollCapture();
|
||||
|
||||
RefPtr<gfxASurface> mScrollCapture;
|
||||
CancelableTask* mCaptureRefreshTask;
|
||||
RefPtr<CancelableRunnable> mCaptureRefreshTask;
|
||||
bool mValidFirstCapture;
|
||||
bool mIsScrolling;
|
||||
#endif
|
||||
|
||||
@@ -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) {
|
||||
@@ -828,7 +829,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;
|
||||
}
|
||||
|
||||
@@ -2204,11 +2207,12 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
RemoveFromAsyncList();
|
||||
DebugOnly<bool> sendOk = mInstance->SendAsyncNPP_NewResult(mResult);
|
||||
MOZ_ASSERT(sendOk);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -2222,8 +2226,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
|
||||
|
||||
@@ -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;
|
||||
@@ -3114,7 +3107,6 @@ PluginModuleChromeParent::InitializeInjector()
|
||||
mFinishInitTask->Init(this);
|
||||
if (!::QueueUserWorkItem(&PluginModuleChromeParent::GetToolhelpSnapshot,
|
||||
mFinishInitTask, WT_EXECUTEDEFAULT)) {
|
||||
delete mFinishInitTask;
|
||||
mFinishInitTask = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ private:
|
||||
|
||||
DWORD mFlashProcess1;
|
||||
DWORD mFlashProcess2;
|
||||
mozilla::plugins::FinishInjectorInitTask* mFinishInitTask;
|
||||
RefPtr<mozilla::plugins::FinishInjectorInitTask> mFinishInitTask;
|
||||
#endif
|
||||
|
||||
void OnProcessLaunched(const bool aSucceeded);
|
||||
@@ -612,9 +612,10 @@ private:
|
||||
MOZ_ASSERT(aModule);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
mModule->OnProcessLaunched(mLaunchSucceeded);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class LaunchCompleteTask : public Task
|
||||
class LaunchCompleteTask : public Runnable
|
||||
{
|
||||
public:
|
||||
LaunchCompleteTask()
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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, aIsInBrowserElement,
|
||||
aState, aOverwrittenMinInterval) {
|
||||
debug('setPolicy');
|
||||
|
||||
return this.sendMessage("RequestSyncManager:SetPolicy",
|
||||
{ task: aTask,
|
||||
origin: aOrigin,
|
||||
manifestURL: aManifestURL,
|
||||
isInBrowserElement: aIsInBrowserElement,
|
||||
state: aState,
|
||||
overwrittenMinInterval: aOverwrittenMinInterval });
|
||||
},
|
||||
|
||||
runTask: function(aTask, aOrigin, aManifestURL, aIsInBrowserElement) {
|
||||
debug('runTask');
|
||||
|
||||
return this.sendMessage("RequestSyncManager:RunTask",
|
||||
{ task: aTask,
|
||||
origin: aOrigin,
|
||||
manifestURL: aManifestURL,
|
||||
isInBrowserElement: aIsInBrowserElement });
|
||||
},
|
||||
|
||||
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]);
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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']
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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'));
|
||||
}
|
||||
@@ -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" }
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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");
|
||||
});
|
||||
@@ -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>
|
||||
@@ -1,131 +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.setAllAppsLaunchable(true);
|
||||
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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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!
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
@@ -394,8 +394,6 @@ WEBIDL_FILES = [
|
||||
'Range.webidl',
|
||||
'Rect.webidl',
|
||||
'Request.webidl',
|
||||
'RequestSyncManager.webidl',
|
||||
'RequestSyncScheduler.webidl',
|
||||
'ResourceStats.webidl',
|
||||
'ResourceStatsManager.webidl',
|
||||
'Response.webidl',
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
+47
-49
@@ -143,6 +143,11 @@ class nsEditor : public nsIEditor,
|
||||
public nsIPhonetic
|
||||
{
|
||||
public:
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::dom::Selection Selection;
|
||||
typedef mozilla::dom::Text Text;
|
||||
template<typename T> using OwningNonNull = mozilla::OwningNonNull<T>;
|
||||
|
||||
enum IterDirection
|
||||
{
|
||||
@@ -199,36 +204,33 @@ public:
|
||||
int32_t* aInOutOffset,
|
||||
nsIDocument* aDoc);
|
||||
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
mozilla::dom::Text& aTextNode,
|
||||
int32_t aOffset,
|
||||
Text& aTextNode, int32_t aOffset,
|
||||
bool aSuppressIME = false);
|
||||
NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
|
||||
EStripWrappers aStripWrappers);
|
||||
|
||||
already_AddRefed<mozilla::dom::Element>
|
||||
DeleteSelectionAndCreateElement(nsIAtom& aTag);
|
||||
already_AddRefed<Element> DeleteSelectionAndCreateElement(nsIAtom& aTag);
|
||||
|
||||
/* helper routines for node/parent manipulations */
|
||||
nsresult DeleteNode(nsINode* aNode);
|
||||
nsresult InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition);
|
||||
enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
|
||||
already_AddRefed<mozilla::dom::Element> ReplaceContainer(
|
||||
mozilla::dom::Element* aOldContainer,
|
||||
nsIAtom* aNodeType,
|
||||
nsIAtom* aAttribute = nullptr,
|
||||
const nsAString* aValue = nullptr,
|
||||
ECloneAttributes aCloneAttributes = eDontCloneAttributes);
|
||||
void CloneAttributes(mozilla::dom::Element* aDest,
|
||||
mozilla::dom::Element* aSource);
|
||||
already_AddRefed<Element> ReplaceContainer(Element* aOldContainer,
|
||||
nsIAtom* aNodeType,
|
||||
nsIAtom* aAttribute = nullptr,
|
||||
const nsAString* aValue = nullptr,
|
||||
ECloneAttributes aCloneAttributes
|
||||
= eDontCloneAttributes);
|
||||
void CloneAttributes(Element* aDest, Element* aSource);
|
||||
|
||||
nsresult RemoveContainer(nsIContent* aNode);
|
||||
already_AddRefed<mozilla::dom::Element> InsertContainerAbove(
|
||||
nsIContent* aNode,
|
||||
nsIAtom* aNodeType,
|
||||
nsIAtom* aAttribute = nullptr,
|
||||
const nsAString* aValue = nullptr);
|
||||
already_AddRefed<Element> InsertContainerAbove(nsIContent* aNode,
|
||||
nsIAtom* aNodeType,
|
||||
nsIAtom* aAttribute = nullptr,
|
||||
const nsAString* aValue =
|
||||
nullptr);
|
||||
nsIContent* SplitNode(nsIContent& aNode, int32_t aOffset,
|
||||
mozilla::ErrorResult& aResult);
|
||||
ErrorResult& aResult);
|
||||
nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
|
||||
nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
|
||||
|
||||
@@ -236,7 +238,7 @@ public:
|
||||
Arguments:
|
||||
nsIAtom* aTag - tag you want
|
||||
*/
|
||||
already_AddRefed<mozilla::dom::Element> CreateHTMLContent(nsIAtom* aTag);
|
||||
already_AddRefed<Element> CreateHTMLContent(nsIAtom* aTag);
|
||||
|
||||
// IME event handlers
|
||||
virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
|
||||
@@ -253,15 +255,14 @@ protected:
|
||||
* returns null.
|
||||
*/
|
||||
already_AddRefed<mozilla::dom::ChangeAttributeTxn>
|
||||
CreateTxnForSetAttribute(mozilla::dom::Element& aElement,
|
||||
nsIAtom& aAttribute, const nsAString& aValue);
|
||||
CreateTxnForSetAttribute(Element& aElement, nsIAtom& aAttribute,
|
||||
const nsAString& aValue);
|
||||
|
||||
/** Create a transaction for removing aAttribute on aElement. Never returns
|
||||
* null.
|
||||
*/
|
||||
already_AddRefed<mozilla::dom::ChangeAttributeTxn>
|
||||
CreateTxnForRemoveAttribute(mozilla::dom::Element& aElement,
|
||||
nsIAtom& aAttribute);
|
||||
CreateTxnForRemoveAttribute(Element& aElement, nsIAtom& aAttribute);
|
||||
|
||||
/** create a transaction for creating a new child node of aParent of type aTag.
|
||||
*/
|
||||
@@ -270,9 +271,8 @@ protected:
|
||||
nsINode& aParent,
|
||||
int32_t aPosition);
|
||||
|
||||
already_AddRefed<mozilla::dom::Element> CreateNode(nsIAtom* aTag,
|
||||
nsINode* aParent,
|
||||
int32_t aPosition);
|
||||
already_AddRefed<Element> CreateNode(nsIAtom* aTag, nsINode* aParent,
|
||||
int32_t aPosition);
|
||||
|
||||
/** create a transaction for inserting aNode as a child of aParent.
|
||||
*/
|
||||
@@ -302,8 +302,8 @@ protected:
|
||||
* returns null.
|
||||
*/
|
||||
already_AddRefed<mozilla::dom::InsertTextTxn>
|
||||
CreateTxnForInsertText(const nsAString& aStringToInsert,
|
||||
mozilla::dom::Text& aTextNode, int32_t aOffset);
|
||||
CreateTxnForInsertText(const nsAString& aStringToInsert, Text& aTextNode,
|
||||
int32_t aOffset);
|
||||
|
||||
// Never returns null.
|
||||
already_AddRefed<mozilla::dom::IMETextTxn>
|
||||
@@ -365,7 +365,7 @@ protected:
|
||||
NS_IMETHOD NotifyDocumentListeners(TDocumentListenerNotification aNotificationType);
|
||||
|
||||
/** make the given selection span the entire document */
|
||||
virtual nsresult SelectEntireDocument(mozilla::dom::Selection* aSelection);
|
||||
virtual nsresult SelectEntireDocument(Selection* aSelection);
|
||||
|
||||
/** helper method for scrolling the selection into view after
|
||||
* an edit operation. aScrollToAnchor should be true if you
|
||||
@@ -379,8 +379,6 @@ protected:
|
||||
*/
|
||||
NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
|
||||
|
||||
// Convenience method; forwards to IsBlockNode(nsINode*).
|
||||
bool IsBlockNode(nsIDOMNode* aNode);
|
||||
// stub. see comment in source.
|
||||
virtual bool IsBlockNode(nsINode* aNode);
|
||||
|
||||
@@ -431,8 +429,8 @@ public:
|
||||
/** routines for managing the preservation of selection across
|
||||
* various editor actions */
|
||||
bool ArePreservingSelection();
|
||||
void PreserveSelectionAcrossActions(mozilla::dom::Selection* aSel);
|
||||
nsresult RestorePreservedSelection(mozilla::dom::Selection* aSel);
|
||||
void PreserveSelectionAcrossActions(Selection* aSel);
|
||||
nsresult RestorePreservedSelection(Selection* aSel);
|
||||
void StopPreservingSelection();
|
||||
|
||||
/**
|
||||
@@ -557,7 +555,6 @@ public:
|
||||
/** returns true if aNode is a descendant of our root node */
|
||||
bool IsDescendantOfRoot(nsIDOMNode* inNode);
|
||||
bool IsDescendantOfRoot(nsINode* inNode);
|
||||
bool IsDescendantOfEditorRoot(nsIDOMNode* aNode);
|
||||
bool IsDescendantOfEditorRoot(nsINode* aNode);
|
||||
|
||||
/** returns true if aNode is a container */
|
||||
@@ -601,24 +598,25 @@ public:
|
||||
static bool IsTextNode(nsINode *aNode);
|
||||
|
||||
static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, int32_t aOffset);
|
||||
static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, int32_t aOffset);
|
||||
static nsIContent* GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode,
|
||||
int32_t aOffset);
|
||||
|
||||
static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
|
||||
static nsresult GetStartNodeAndOffset(Selection* aSelection,
|
||||
nsIDOMNode** outStartNode,
|
||||
int32_t* outStartOffset);
|
||||
static nsresult GetStartNodeAndOffset(mozilla::dom::Selection* aSelection,
|
||||
static nsresult GetStartNodeAndOffset(Selection* aSelection,
|
||||
nsINode** aStartNode,
|
||||
int32_t* aStartOffset);
|
||||
static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
|
||||
static nsresult GetEndNodeAndOffset(Selection* aSelection,
|
||||
nsIDOMNode** outEndNode,
|
||||
int32_t* outEndOffset);
|
||||
static nsresult GetEndNodeAndOffset(mozilla::dom::Selection* aSelection,
|
||||
static nsresult GetEndNodeAndOffset(Selection* aSelection,
|
||||
nsINode** aEndNode,
|
||||
int32_t* aEndOffset);
|
||||
#if DEBUG_JOE
|
||||
static void DumpNode(nsIDOMNode *aNode, int32_t indent=0);
|
||||
#endif
|
||||
mozilla::dom::Selection* GetSelection(int16_t aSelectionType =
|
||||
Selection* GetSelection(int16_t aSelectionType =
|
||||
nsISelectionController::SELECTION_NORMAL);
|
||||
|
||||
// Helpers to add a node to the selection.
|
||||
@@ -653,7 +651,7 @@ public:
|
||||
virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
|
||||
|
||||
nsresult HandleInlineSpellCheck(EditAction action,
|
||||
mozilla::dom::Selection* aSelection,
|
||||
Selection* aSelection,
|
||||
nsIDOMNode *previousSelectedNode,
|
||||
int32_t previousSelectedOffset,
|
||||
nsIDOMNode *aStartNode,
|
||||
@@ -664,15 +662,15 @@ public:
|
||||
virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
|
||||
|
||||
// Fast non-refcounting editor root element accessor
|
||||
mozilla::dom::Element *GetRoot();
|
||||
Element* GetRoot();
|
||||
|
||||
// Likewise, but gets the editor's root instead, which is different for HTML
|
||||
// editors
|
||||
virtual mozilla::dom::Element* GetEditorRoot();
|
||||
virtual Element* GetEditorRoot();
|
||||
|
||||
// Likewise, but gets the text control element instead of the root for
|
||||
// plaintext editors
|
||||
mozilla::dom::Element* GetExposedRoot();
|
||||
Element* GetExposedRoot();
|
||||
|
||||
// Accessor methods to flags
|
||||
bool IsPlaintextEditor() const
|
||||
@@ -835,8 +833,8 @@ protected:
|
||||
nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
|
||||
|
||||
RefPtr<nsTransactionManager> mTxnMgr;
|
||||
nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
|
||||
RefPtr<mozilla::dom::Text> mIMETextNode; // current IME text node
|
||||
nsCOMPtr<Element> mRootElement; // cached root node
|
||||
RefPtr<Text> mIMETextNode; // current IME text node
|
||||
nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
|
||||
nsCOMPtr<nsIDOMEventListener> mEventListener;
|
||||
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
|
||||
@@ -851,11 +849,11 @@ protected:
|
||||
|
||||
// various listeners
|
||||
// Listens to all low level actions on the doc
|
||||
nsTArray<mozilla::OwningNonNull<nsIEditActionListener>> mActionListeners;
|
||||
nsTArray<OwningNonNull<nsIEditActionListener>> mActionListeners;
|
||||
// Just notify once per high level change
|
||||
nsTArray<mozilla::OwningNonNull<nsIEditorObserver>> mEditorObservers;
|
||||
nsTArray<OwningNonNull<nsIEditorObserver>> mEditorObservers;
|
||||
// Listen to overall doc state (dirty or not, just created, etc)
|
||||
nsTArray<mozilla::OwningNonNull<nsIDocumentStateListener>> mDocStateListeners;
|
||||
nsTArray<OwningNonNull<nsIDocumentStateListener>> mDocStateListeners;
|
||||
|
||||
nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user