--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -452,20 +452,22 @@ DocManager::CreateDocOrRootAccessible(ns
// Note: don't use AccReorderEvent to avoid coalsecense and special reorder
// events processing.
docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER,
ApplicationAcc());
if (IPCAccessibilityActive()) {
DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
docAcc->SetIPCDoc(ipcDoc);
- nsCOMPtr<nsITabChild> tabChild =
- do_GetInterface(aDocument->GetDocShell());
- static_cast<TabChild*>(tabChild.get())->
- SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
+ nsIDocShell* docShell = aDocument->GetDocShell();
+ if (docShell) {
+ nsCOMPtr<nsITabChild> tabChild = do_GetInterface(docShell);
+ static_cast<TabChild*>(tabChild.get())->
+ SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
+ }
}
} else {
parentDocAcc->BindChildDocument(docAcc);
}
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eDocCreate)) {
logging::DocCreate("document creation finished", aDocument);
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -923,16 +923,18 @@ pref("general.useragent.updates.enabled"
pref("general.useragent.updates.url", "https://dynamicua.cdn.mozilla.net/0/%APP_ID%");
pref("general.useragent.updates.interval", 604800); // 1 week
pref("general.useragent.updates.retry", 86400); // 1 day
// Device ID can be composed of letter, numbers, hyphen ("-") and dot (".")
pref("general.useragent.device_id", "");
// Make <audio> and <video> talk to the AudioChannelService.
pref("media.useAudioChannelService", true);
+// Add Mozilla AudioChannel APIs.
+pref("media.useAudioChannelAPI", true);
pref("b2g.version", @MOZ_B2G_VERSION@);
pref("b2g.osName", @MOZ_B2G_OS_NAME@);
// Disable console buffering to save memory.
pref("consoleservice.buffered", false);
#ifdef MOZ_WIDGET_GONK
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -550,29 +550,31 @@ let settingsToObserve = {
defaultValue: false
},
'devtools.eventlooplag.threshold': 100,
'devtools.remote.wifi.visible': {
resetToPref: true
},
'dom.mozApps.use_reviewer_certs': false,
'dom.mozApps.signed_apps_installable_from': 'https://marketplace.firefox.com',
+ 'dom.serviceWorkers.interception.enabled': true,
+ 'dom.serviceWorkers.testing.enabled': false,
'gfx.layerscope.enabled': false,
'layers.draw-borders': false,
'layers.draw-tile-borders': false,
'layers.dump': false,
'layers.enable-tiles': true,
'layers.effect.invert': false,
'layers.effect.grayscale': false,
- 'layers.effect.contrast': "0.0",
+ 'layers.effect.contrast': '0.0',
+ 'mms.debugging.enabled': false,
'network.debugging.enabled': false,
'privacy.donottrackheader.enabled': false,
'ril.debugging.enabled': false,
'ril.radio.disabled': false,
- 'mms.debugging.enabled': false,
'ril.mms.requestReadReport.enabled': {
prefName: 'dom.mms.requestReadReport',
defaultValue: true
},
'ril.mms.requestStatusReport.enabled': {
prefName: 'dom.mms.requestStatusReport',
defaultValue: false
},
--- a/dom/audiochannel/tests/test_telephonyPolicy.html
+++ b/dom/audiochannel/tests/test_telephonyPolicy.html
@@ -47,16 +47,17 @@ var tests = [
{ "type": "embed-apps", "allow": 1, "context": document },
{ "type": "webapps-manage", "allow": 1, "context": document },
{ "type": "audio-channel-telephony", "allow": 1, "context": document }], runTest);
},
// Preferences
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.browser_frames.oop_by_default", true],
+ ["media.useAudioChannelAPI", true],
["media.useAudioChannelService", true],
["media.defaultAudioChannel", "telephony"],
["dom.mozBrowserFramesEnabled", true],
["network.disable.ipc.security", true]]}, runTest);
},
// Run 2 apps
mainApp,
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -8,17 +8,16 @@
* Base class for all element classes; this provides an implementation
* of DOM Core's nsIDOMElement, implements nsIContent, provides
* utility methods for subclasses, and so forth.
*/
#include "mozilla/ArrayUtils.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
-#include "mozilla/SegmentedVector.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/FragmentOrElement.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStates.h"
@@ -1222,22 +1221,34 @@ FragmentOrElement::FireNodeInserted(nsID
mozAutoSubtreeModified subtree(aDoc, aParent);
(new AsyncEventDispatcher(childContent, mutation))->RunDOMEventWhenSafe();
}
}
}
//----------------------------------------------------------------------
-class ContentUnbinder
+// nsISupports implementation
+
+#define SUBTREE_UNBINDINGS_PER_RUNNABLE 500
+
+class ContentUnbinder : public nsRunnable
{
- static const size_t kSegmentSize = sizeof(void*) * 512;
- typedef SegmentedVector<nsCOMPtr<nsIContent>, kSegmentSize, InfallibleAllocPolicy> ContentArray;
-
- static void UnbindSubtree(nsIContent* aNode)
+public:
+ ContentUnbinder()
+ {
+ mLast = this;
+ }
+
+ ~ContentUnbinder()
+ {
+ Run();
+ }
+
+ void UnbindSubtree(nsIContent* aNode)
{
if (aNode->NodeType() != nsIDOMNode::ELEMENT_NODE &&
aNode->NodeType() != nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
return;
}
FragmentOrElement* container = static_cast<FragmentOrElement*>(aNode);
uint32_t childCount = container->mAttrsAndChildren.ChildCount();
if (childCount) {
@@ -1253,66 +1264,83 @@ class ContentUnbinder
container->mFirstChild = nullptr;
}
UnbindSubtree(child);
child->UnbindFromTree();
}
}
}
- // These two methods are based on DeferredFinalizerImpl.
-
- static void*
- AppendContentUnbinderPointer(void* aData, void* aObject)
+ NS_IMETHOD Run()
{
- ContentArray* contentArray = static_cast<ContentArray*>(aData);
- if (!contentArray) {
- contentArray = new ContentArray();
+ nsAutoScriptBlocker scriptBlocker;
+ uint32_t len = mSubtreeRoots.Length();
+ if (len) {
+ for (uint32_t i = 0; i < len; ++i) {
+ UnbindSubtree(mSubtreeRoots[i]);
+ }
+ mSubtreeRoots.Clear();
}
-
- contentArray->InfallibleAppend(dont_AddRef(static_cast<nsIContent*>(aObject)));
- return contentArray;
+ nsCycleCollector_dispatchDeferredDeletion();
+ if (this == sContentUnbinder) {
+ sContentUnbinder = nullptr;
+ if (mNext) {
+ nsRefPtr<ContentUnbinder> next;
+ next.swap(mNext);
+ sContentUnbinder = next;
+ next->mLast = mLast;
+ mLast = nullptr;
+ NS_DispatchToMainThread(next);
+ }
+ }
+ return NS_OK;
}
- static bool
- DeferredFinalize(uint32_t aSliceBudget, void* aData)
+ static void UnbindAll()
{
- MOZ_ASSERT(aSliceBudget > 0, "nonsensical/useless call with aSliceBudget == 0");
- nsAutoScriptBlocker scriptBlocker;
- ContentArray* contentArray = static_cast<ContentArray*>(aData);
-
- size_t numToRemove = contentArray->Length();
- if (aSliceBudget < numToRemove) {
- numToRemove = aSliceBudget;
+ nsRefPtr<ContentUnbinder> ub = sContentUnbinder;
+ sContentUnbinder = nullptr;
+ while (ub) {
+ ub->Run();
+ ub = ub->mNext;
}
-
- for (size_t i = 0; i < numToRemove; ++i) {
- nsCOMPtr<nsIContent> element = contentArray->GetLast().forget();
- contentArray->PopLast();
- UnbindSubtree(element);
+ }
+
+ static void Append(nsIContent* aSubtreeRoot)
+ {
+ if (!sContentUnbinder) {
+ sContentUnbinder = new ContentUnbinder();
+ nsCOMPtr<nsIRunnable> e = sContentUnbinder;
+ NS_DispatchToMainThread(e);
+ }
+
+ if (sContentUnbinder->mLast->mSubtreeRoots.Length() >=
+ SUBTREE_UNBINDINGS_PER_RUNNABLE) {
+ sContentUnbinder->mLast->mNext = new ContentUnbinder();
+ sContentUnbinder->mLast = sContentUnbinder->mLast->mNext;
}
-
- nsCycleCollector_dispatchDeferredDeletion();
-
- if (contentArray->Length() == 0) {
- delete contentArray;
- return true;
- }
- return false;
+ sContentUnbinder->mLast->mSubtreeRoots.AppendElement(aSubtreeRoot);
}
-public:
- static void
- Append(nsIContent* aSubtreeRoot)
- {
- nsCOMPtr<nsIContent> root = aSubtreeRoot;
- mozilla::DeferredFinalize(AppendContentUnbinderPointer, DeferredFinalize, root.forget().take());
- }
+private:
+ nsAutoTArray<nsCOMPtr<nsIContent>,
+ SUBTREE_UNBINDINGS_PER_RUNNABLE> mSubtreeRoots;
+ nsRefPtr<ContentUnbinder> mNext;
+ ContentUnbinder* mLast;
+ static ContentUnbinder* sContentUnbinder;
};
+ContentUnbinder* ContentUnbinder::sContentUnbinder = nullptr;
+
+void
+FragmentOrElement::ClearContentUnbinder()
+{
+ ContentUnbinder::UnbindAll();
+}
+
NS_IMPL_CYCLE_COLLECTION_CLASS(FragmentOrElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
nsINode::Unlink(tmp);
// The XBL binding is removed by RemoveFromBindingManagerRunnable
// which is dispatched in UnbindFromTree.
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -60,17 +60,17 @@ public:
void NoticeNodeDestruction()
{
mNode = nullptr;
}
private:
~nsNodeWeakReference();
- nsINode* mNode;
+ nsINode* MOZ_NON_OWNING_REF mNode;
};
/**
* Tearoff to use for nodes to implement nsISupportsWeakReference
*/
class nsNodeSupportsWeakRefTearoff final : public nsISupportsWeakReference
{
public:
@@ -210,16 +210,17 @@ public:
return mRefCnt.IsPurple();
}
virtual void RemovePurple() override
{
mRefCnt.RemovePurple();
}
+ static void ClearContentUnbinder();
static bool CanSkip(nsINode* aNode, bool aRemovingAllowed);
static bool CanSkipInCC(nsINode* aNode);
static bool CanSkipThis(nsINode* aNode);
static void RemoveBlackMarkedNode(nsINode* aNode);
static void MarkNodeChildren(nsINode* aNode);
static void InitCCCallbacks();
static void MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
void *aData);
--- a/dom/base/nsCCUncollectableMarker.cpp
+++ b/dom/base/nsCCUncollectableMarker.cpp
@@ -313,16 +313,18 @@ MarkWindowList(nsISimpleEnumerator* aWin
}
}
nsresult
nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
+ Element::ClearContentUnbinder();
+
nsCOMPtr<nsIObserverService> obs =
mozilla::services::GetObserverService();
if (!obs)
return NS_ERROR_FAILURE;
// No need for kungFuDeathGrip here, yay observerservice!
obs->RemoveObserver(this, "xpcom-shutdown");
obs->RemoveObserver(this, "cycle-collector-begin");
@@ -337,16 +339,19 @@ nsCCUncollectableMarker::Observe(nsISupp
!strcmp(aTopic, "cycle-collector-forget-skippable"), "wrong topic");
// JS cleanup can be slow. Do it only if there has been a GC.
bool cleanupJS =
nsJSContext::CleanupsSinceLastGC() == 0 &&
!strcmp(aTopic, "cycle-collector-forget-skippable");
bool prepareForCC = !strcmp(aTopic, "cycle-collector-begin");
+ if (prepareForCC) {
+ Element::ClearContentUnbinder();
+ }
// Increase generation to effectively unmark all current objects
if (!++sGeneration) {
++sGeneration;
}
nsFocusManager::MarkUncollectableForCCGeneration(sGeneration);
--- a/dom/base/nsIMutationObserver.h
+++ b/dom/base/nsIMutationObserver.h
@@ -57,26 +57,26 @@ struct CharacterDataChangeInfo
/**
* The net result is that mChangeStart characters at the beginning of the
* text remained as they were. The next mChangeEnd - mChangeStart characters
* were removed, and mReplaceLength characters were inserted in their place.
* The text that used to begin at mChangeEnd now begins at
* mChangeStart + mReplaceLength.
*/
- struct Details {
+ struct MOZ_STACK_CLASS Details {
enum {
eMerge, // two text nodes are merged as a result of normalize()
eSplit // a text node is split as a result of splitText()
} mType;
/**
* For eMerge it's the text node that will be removed, for eSplit it's the
* new text node.
*/
- nsIContent* mNextSibling;
+ nsIContent* MOZ_NON_OWNING_REF mNextSibling;
};
/**
* Used for splitText() and normalize(), otherwise null.
*/
Details* mDetails;
};
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -773,17 +773,20 @@ protected:
// Cache the URI when mDoc is cleared.
nsCOMPtr<nsIURI> mDocumentURI; // strong
nsCOMPtr<nsIURI> mDocBaseURI; // strong
nsCOMPtr<mozilla::dom::EventTarget> mParentTarget; // strong
// These members are only used on outer windows.
nsCOMPtr<mozilla::dom::Element> mFrameElement;
- nsIDocShell *mDocShell; // Weak Reference
+ // This reference is used by the subclass nsGlobalWindow, and cleared in it's
+ // DetachFromDocShell() method. This method is called by nsDocShell::Destroy(),
+ // which is called before the nsDocShell is destroyed.
+ nsIDocShell* MOZ_NON_OWNING_REF mDocShell; // Weak Reference
// mPerformance is only used on inner windows.
nsRefPtr<nsPerformance> mPerformance;
uint32_t mModalStateDepth;
// These variables are only used on inner windows.
nsTimeout *mRunningTimeout;
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -41,25 +41,16 @@
class nsIJSID;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
template<typename DataType> class MozMap;
-struct SelfRef
-{
- SelfRef() : ptr(nullptr) {}
- explicit SelfRef(nsISupports *p) : ptr(p) {}
- ~SelfRef() { NS_IF_RELEASE(ptr); }
-
- nsISupports* ptr;
-};
-
nsresult
UnwrapArgImpl(JS::Handle<JSObject*> src, const nsIID& iid, void** ppArg);
/** Convert a jsval to an XPCOM pointer. */
template <class Interface>
inline nsresult
UnwrapArg(JS::Handle<JSObject*> src, Interface** ppArg)
{
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -450,16 +450,19 @@ EventStateManager::ReleaseCurrentIMECont
}
mIMEContentObserver = nullptr;
}
void
EventStateManager::OnStartToObserveContent(
IMEContentObserver* aIMEContentObserver)
{
+ if (mIMEContentObserver == aIMEContentObserver) {
+ return;
+ }
ReleaseCurrentIMEContentObserver();
mIMEContentObserver = aIMEContentObserver;
}
void
EventStateManager::OnStopObservingContent(
IMEContentObserver* aIMEContentObserver)
{
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1071,16 +1071,21 @@ static bool IsAutoplayEnabled()
return Preferences::GetBool("media.autoplay.enabled");
}
static bool UseAudioChannelService()
{
return Preferences::GetBool("media.useAudioChannelService");
}
+static bool UseAudioChannelAPI()
+{
+ return Preferences::GetBool("media.useAudioChannelAPI");
+}
+
void HTMLMediaElement::UpdatePreloadAction()
{
PreloadAction nextAction = PRELOAD_UNDEFINED;
// If autoplay is set, or we're playing, we should always preload data,
// as we'll need it to play.
if ((IsAutoplayEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) ||
!mPaused)
{
@@ -4440,21 +4445,25 @@ nsresult HTMLMediaElement::UpdateChannel
(aCanPlay != AUDIO_CHANNEL_STATE_FADED && mAudioChannelFaded)) {
mAudioChannelFaded = !mAudioChannelFaded;
SetVolumeInternal();
}
// We have to mute this channel.
if (aCanPlay == AUDIO_CHANNEL_STATE_MUTED && !(mMuted & MUTED_BY_AUDIO_CHANNEL)) {
SetMutedInternal(mMuted | MUTED_BY_AUDIO_CHANNEL);
- DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
+ if (UseAudioChannelAPI()) {
+ DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
+ }
} else if (aCanPlay != AUDIO_CHANNEL_STATE_MUTED &&
(mMuted & MUTED_BY_AUDIO_CHANNEL)) {
SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_CHANNEL);
- DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
+ if (UseAudioChannelAPI()) {
+ DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
+ }
}
SuspendOrResumeElement(mMuted & MUTED_BY_AUDIO_CHANNEL, false);
return NS_OK;
}
void HTMLMediaElement::UpdateAudioChannelPlayingState()
{
--- a/dom/inputmethod/Keyboard.jsm
+++ b/dom/inputmethod/Keyboard.jsm
@@ -258,17 +258,17 @@ this.Keyboard = {
case 'Keyboard:SetComposition':
this.setComposition(msg);
break;
case 'Keyboard:EndComposition':
this.endComposition(msg);
break;
case 'Keyboard:Register':
this._keyboardMM = mm;
- if (kbID !== null) {
+ if (kbID) {
// keyboard identifies itself, use its kbID
// this msg would be async, so no need to return
this._keyboardID = kbID;
}else{
// generate the id for the keyboard
this._keyboardID = this._nextKeyboardID;
this._nextKeyboardID++;
// this msg is sync,
--- a/dom/inputmethod/MozKeyboard.js
+++ b/dom/inputmethod/MozKeyboard.js
@@ -14,84 +14,115 @@ Cu.import("resource://gre/modules/DOMReq
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1", "nsISyncMessageSender");
XPCOMUtils.defineLazyServiceGetter(this, "tm",
"@mozilla.org/thread-manager;1", "nsIThreadManager");
/*
- * A WeakMap to map input method iframe window to its active status and kbID.
+ * A WeakMap to map input method iframe window to
+ * it's active status, kbID, and ipcHelper.
*/
let WindowMap = {
// WeakMap of <window, object> pairs.
_map: null,
/*
+ * Set the object associated to the window and return it.
+ */
+ _getObjForWin: function(win) {
+ if (!this._map) {
+ this._map = new WeakMap();
+ }
+ if (this._map.has(win)) {
+ return this._map.get(win);
+ } else {
+ let obj = {
+ active: false,
+ kbID: undefined,
+ ipcHelper: null
+ };
+ this._map.set(win, obj);
+
+ return obj;
+ }
+ },
+
+ /*
* Check if the given window is active.
*/
isActive: function(win) {
if (!this._map || !win) {
return false;
}
- let obj = this._map.get(win);
- if (obj && 'active' in obj) {
- return obj.active;
- }else{
- return false;
- }
+ return this._getObjForWin(win).active;
},
/*
* Set the active status of the given window.
*/
setActive: function(win, isActive) {
if (!win) {
return;
}
- if (!this._map) {
- this._map = new WeakMap();
- }
- if (!this._map.has(win)) {
- this._map.set(win, {});
- }
- this._map.get(win).active = isActive;
+ let obj = this._getObjForWin(win);
+ obj.active = isActive;
},
/*
- * Get the keyboard ID (assigned by Keyboard.ksm) of the given window.
+ * Get the keyboard ID (assigned by Keyboard.jsm) of the given window.
*/
getKbID: function(win) {
if (!this._map || !win) {
- return null;
+ return undefined;
}
- let obj = this._map.get(win);
- if (obj && 'kbID' in obj) {
- return obj.kbID;
- }else{
- return null;
- }
+ let obj = this._getObjForWin(win);
+ return obj.kbID;
},
/*
- * Set the keyboard ID (assigned by Keyboard.ksm) of the given window.
+ * Set the keyboard ID (assigned by Keyboard.jsm) of the given window.
*/
setKbID: function(win, kbID) {
if (!win) {
return;
}
- if (!this._map) {
- this._map = new WeakMap();
+ let obj = this._getObjForWin(win);
+ obj.kbID = kbID;
+ },
+
+ /*
+ * Get InputContextDOMRequestIpcHelper instance attached to this window.
+ */
+ getInputContextIpcHelper: function(win) {
+ if (!win) {
+ return;
+ }
+ let obj = this._getObjForWin(win);
+ if (!obj.ipcHelper) {
+ obj.ipcHelper = new InputContextDOMRequestIpcHelper(win);
}
- if (!this._map.has(win)) {
- this._map.set(win, {});
+ return obj.ipcHelper;
+ },
+
+ /*
+ * Unset InputContextDOMRequestIpcHelper instance.
+ */
+ unsetInputContextIpcHelper: function(win) {
+ if (!win) {
+ return;
}
- this._map.get(win).kbID = kbID;
+ let obj = this._getObjForWin(win);
+ if (!obj.ipcHelper) {
+ return;
+ }
+ obj.ipcHelper = null;
}
};
let cpmmSendAsyncMessageWithKbID = function (self, msg, data) {
data.kbID = WindowMap.getKbID(self._window);
cpmm.sendAsyncMessage(msg, data);
};
@@ -327,19 +358,19 @@ MozInputMethod.prototype = {
// a GetContext:Result:OK event, and we can initialize ourselves.
// Otherwise silently ignored.
// get keyboard ID from Keyboard.jsm,
// or if we already have it, get it from our map
// Note: if we need to get it from Keyboard.jsm,
// we have to use a synchronous message
var kbID = WindowMap.getKbID(this._window);
- if (kbID !== null) {
+ if (kbID) {
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:Register', {});
- }else{
+ } else {
let res = cpmm.sendSyncMessage('Keyboard:Register', {});
WindowMap.setKbID(this._window, res[0]);
}
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:GetContext', {});
} else {
// Deactive current input method.
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:Unregister', {});
@@ -412,16 +443,71 @@ MozInputMethod.prototype = {
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
callback(resolverId);
});
}
};
/**
* ==============================================
+ * InputContextDOMRequestIpcHelper
+ * ==============================================
+ */
+function InputContextDOMRequestIpcHelper(win) {
+ this.initDOMRequestHelper(win,
+ ["Keyboard:GetText:Result:OK",
+ "Keyboard:GetText:Result:Error",
+ "Keyboard:SetSelectionRange:Result:OK",
+ "Keyboard:ReplaceSurroundingText:Result:OK",
+ "Keyboard:SendKey:Result:OK",
+ "Keyboard:SendKey:Result:Error",
+ "Keyboard:SetComposition:Result:OK",
+ "Keyboard:EndComposition:Result:OK",
+ "Keyboard:SequenceError"]);
+}
+
+InputContextDOMRequestIpcHelper.prototype = {
+ __proto__: DOMRequestIpcHelper.prototype,
+ _inputContext: null,
+
+ attachInputContext: function(inputCtx) {
+ if (this._inputContext) {
+ throw new Error("InputContextDOMRequestIpcHelper: detach the context first.");
+ }
+
+ this._inputContext = inputCtx;
+ },
+
+ // Unset ourselves when the window is destroyed.
+ uninit: function() {
+ WindowMap.unsetInputContextIpcHelper(this._window);
+ },
+
+ detachInputContext: function() {
+ // All requests that are still pending need to be invalidated
+ // because the context is no longer valid.
+ this.forEachPromiseResolver(k => {
+ this.takePromiseResolver(k).reject("InputContext got destroyed");
+ });
+
+ this._inputContext = null;
+ },
+
+ receiveMessage: function(msg) {
+ if (!this._inputContext) {
+ dump('InputContextDOMRequestIpcHelper received message without context attached.\n');
+ return;
+ }
+
+ this._inputContext.receiveMessage(msg);
+ }
+};
+
+ /**
+ * ==============================================
* InputContext
* ==============================================
*/
function MozInputContext(ctx) {
this._context = {
inputtype: ctx.type,
inputmode: ctx.inputmode,
lang: ctx.lang,
@@ -433,78 +519,63 @@ function MozInputContext(ctx) {
textBeforeCursor: ctx.textBeforeCursor,
textAfterCursor: ctx.textAfterCursor
};
this._contextId = ctx.contextId;
}
MozInputContext.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
_window: null,
_context: null,
_contextId: -1,
+ _ipcHelper: null,
classID: Components.ID("{1e38633d-d08b-4867-9944-afa5c648adb6}"),
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver,
Ci.nsISupportsWeakReference
]),
init: function ic_init(win) {
this._window = win;
- this._utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- this.initDOMRequestHelper(win,
- ["Keyboard:GetText:Result:OK",
- "Keyboard:GetText:Result:Error",
- "Keyboard:SetSelectionRange:Result:OK",
- "Keyboard:ReplaceSurroundingText:Result:OK",
- "Keyboard:SendKey:Result:OK",
- "Keyboard:SendKey:Result:Error",
- "Keyboard:SetComposition:Result:OK",
- "Keyboard:EndComposition:Result:OK",
- "Keyboard:SequenceError"]);
+
+ this._ipcHelper = WindowMap.getInputContextIpcHelper(win);
+ this._ipcHelper.attachInputContext(this);
},
destroy: function ic_destroy() {
- let self = this;
-
- // All requests that are still pending need to be invalidated
- // because the context is no longer valid.
- this.forEachPromiseResolver(function(k) {
- self.takePromiseResolver(k).reject("InputContext got destroyed");
- });
- this.destroyDOMRequestHelper();
-
// A consuming application might still hold a cached version of
// this object. After destroying all methods will throw because we
// cannot create new promises anymore, but we still hold
// (outdated) information in the context. So let's clear that out.
for (var k in this._context) {
if (this._context.hasOwnProperty(k)) {
this._context[k] = null;
}
}
+ this._ipcHelper.detachInputContext();
+ this._ipcHelper = null;
+
this._window = null;
},
receiveMessage: function ic_receiveMessage(msg) {
if (!msg || !msg.json) {
dump('InputContext received message without data\n');
return;
}
let json = msg.json;
- let resolver = this.takePromiseResolver(json.requestId);
+ let resolver = this._ipcHelper.takePromiseResolver(json.requestId);
if (!resolver) {
+ dump('InputContext received invalid requestId.\n');
return;
}
// Update context first before resolving promise to avoid race condition
if (json.selectioninfo) {
this.updateSelectionContext(json.selectioninfo, true);
}
@@ -710,20 +781,20 @@ MozInputContext.prototype = {
requestId: resolverId,
text: text || ''
});
});
},
_sendPromise: function(callback) {
let self = this;
- return this.createPromise(function(resolve, reject) {
- let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
+ return this._ipcHelper.createPromise(function(resolve, reject) {
+ let resolverId = self._ipcHelper.getPromiseResolverId({ resolve: resolve, reject: reject });
if (!WindowMap.isActive(self._window)) {
- self.removePromiseResolver(resolverId);
+ self._ipcHelper.removePromiseResolver(resolverId);
reject('Input method is not active.');
return;
}
callback(resolverId);
});
}
};
--- a/dom/inputmethod/forms.js
+++ b/dom/inputmethod/forms.js
@@ -666,17 +666,18 @@ let FormAssistant = {
handleFocus: function fa_handleFocus(target) {
if (this.focusedElement === target)
return;
if (target instanceof HTMLOptionElement)
target = target.parentNode;
this.setFocusedElement(target);
- this.isHandlingFocus = this.sendInputState(target);
+ this.sendInputState(target);
+ this.isHandlingFocus = true;
},
unhandleFocus: function fa_unhandleFocus() {
this.setFocusedElement(null);
this.isHandlingFocus = false;
sendAsyncMessage("Forms:Input", { "type": "blur" });
},
@@ -685,40 +686,33 @@ let FormAssistant = {
element instanceof HTMLTextAreaElement)
return true;
if (element instanceof HTMLOptionElement &&
element.parentNode instanceof HTMLSelectElement)
return true;
return (element instanceof HTMLInputElement &&
- !this.ignoredInputTypes.has(element.type));
+ !this.ignoredInputTypes.has(element.type) &&
+ !element.readOnly);
},
getTopLevelEditable: function fa_getTopLevelEditable(element) {
function retrieveTopLevelEditable(element) {
while (element && !isContentEditable(element))
element = element.parentNode;
return element;
}
return retrieveTopLevelEditable(element) || element;
},
sendInputState: function(element) {
- // FIXME/bug 729623: work around apparent bug in the IME manager
- // in gecko.
- let readonly = element.getAttribute("readonly");
- if (readonly) {
- return false;
- }
-
sendAsyncMessage("Forms:Input", getJSON(element, this._focusCounter));
- return true;
},
getSelectionInfo: function fa_getSelectionInfo() {
let element = this.focusedElement;
let range = getSelectionRange(element);
let text = isContentEditable(element) ? getContentEditableText(element)
: element.value;
--- a/dom/inputmethod/mochitest/mochitest.ini
+++ b/dom/inputmethod/mochitest/mochitest.ini
@@ -15,13 +15,14 @@ support-files =
[test_bug949059.html]
[test_bug953044.html]
[test_bug960946.html]
[test_bug978918.html]
[test_bug1026997.html]
[test_bug1043828.html]
[test_bug1059163.html]
[test_bug1066515.html]
+[test_bug1175399.html]
[test_sendkey_cancel.html]
[test_sync_edit.html]
[test_two_inputs.html]
[test_two_selects.html]
[test_unload.html]
--- a/dom/inputmethod/mochitest/test_bug1043828.html
+++ b/dom/inputmethod/mochitest/test_bug1043828.html
@@ -27,17 +27,17 @@ function kbFrameScript() {
var ctx = content.navigator.mozInputMethod.inputcontext;
if (ctx) {
var p = ctx.getText();
p.then(function(){
sendAsyncMessage('test:InputMethod:getText:Resolve');
}, function(e){
sendAsyncMessage('test:InputMethod:getText:Reject');
});
- }else{
+ } else {
dump("Could not get inputcontext") ;
}
}
addMessageListener('test:InputMethod:getText:Do', function(){
tryGetText();
});
}
@@ -98,17 +98,17 @@ function runTest() {
handleEvent: function(){
keyboardB.removeEventListener('mozbrowserloadend', this);
mmKeyboardB = SpecialPowers.getBrowserFrameMessageManager(keyboardB);
mmKeyboardB.loadFrameScript('data:,(' + kbFrameScript.toString() + ')();', false);
mmKeyboardB.addMessageListener('test:InputMethod:getText:Resolve', function() {
- ok(true, 'getText() was resolved');
+ info('getText() was resolved');
inputmethod_cleanup();
});
mmKeyboardB.addMessageListener('test:InputMethod:getText:Reject', function() {
ok(false, 'getText() was rejected');
inputmethod_cleanup();
});
@@ -119,64 +119,68 @@ function runTest() {
};
keyboardB.addEventListener('mozbrowserloadend', handler);
});
}
// STEP 2: Set keyboard A active
function step2() {
+ info('step2');
let req = keyboardA.setInputMethodActive(true);
req.onsuccess = function(){
setTimeout(function(){
step3();
}, WAIT_TIME);
};
req.onerror = function(){
ok(false, 'setInputMethodActive failed: ' + this.error.name);
inputmethod_cleanup();
};
}
// STEP 3: Set keyboard B active
function step3() {
+ info('step3');
let req = keyboardB.setInputMethodActive(true);
req.onsuccess = function(){
setTimeout(function(){
step4();
}, WAIT_TIME);
};
req.onerror = function(){
ok(false, 'setInputMethodActive failed: ' + this.error.name);
inputmethod_cleanup();
};
}
// STEP 4: Set keyboard A inactive
function step4() {
+ info('step4');
let req = keyboardA.setInputMethodActive(false);
req.onsuccess = function(){
setTimeout(function(){
step5();
}, WAIT_TIME);
};
req.onerror = function(){
ok(false, 'setInputMethodActive failed: ' + this.error.name);
inputmethod_cleanup();
};
}
// STEP 5: getText
function step5() {
+ info('step5');
mmKeyboardB.sendAsyncMessage('test:InputMethod:getText:Do');
}
step1();
}
</script>
</pre>
new file mode 100644
--- /dev/null
+++ b/dom/inputmethod/mochitest/test_bug1175399.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1175399
+-->
+<head>
+ <title>Test focus when page unloads</title>
+ <script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1175399">Mozilla Bug 1175399</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+
+inputmethod_setup(function() {
+ runTest();
+});
+
+let appFrameScript = function appFrameScript() {
+ let input = content.document.body.firstElementChild;
+ input.focus();
+
+ content.setTimeout(function() {
+ sendAsyncMessage('test:step');
+ });
+};
+
+function runTest() {
+ let im = navigator.mozInputMethod;
+
+ // Set current page as an input method.
+ SpecialPowers.wrap(im).setActive(true);
+
+ let iframe = document.createElement('iframe');
+ iframe.src = 'data:text/html,<html><body><input value="First" readonly></body></html>';
+ iframe.setAttribute('mozbrowser', true);
+ document.body.appendChild(iframe);
+
+ let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
+ im.oninputcontextchange = function() {
+ is(false, 'should not receive inputcontextchange event');
+ };
+
+ iframe.addEventListener('mozbrowserloadend', function() {
+ mm.addMessageListener('test:step', function() {
+ let inputcontext = navigator.mozInputMethod.inputcontext;
+ is(inputcontext, null, 'inputcontext is null');
+
+ inputmethod_cleanup();
+ });
+ mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
+ });
+}
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -156,27 +156,16 @@ EnsureMinCDMVersion(mozIGeckoMediaPlugin
return MediaKeySystemStatus::Error;
}
if (!hasPlugin) {
aOutMessage = NS_LITERAL_CSTRING("CDM is not installed");
return MediaKeySystemStatus::Cdm_not_installed;
}
- if (aMinCdmVersion == NO_CDM_VERSION) {
- return MediaKeySystemStatus::Available;
- }
-
- nsresult rv;
- int32_t version = versionStr.ToInteger(&rv);
- if (NS_FAILED(rv) || version < 0 || aMinCdmVersion > version) {
- aOutMessage = NS_LITERAL_CSTRING("Installed CDM version insufficient");
- return MediaKeySystemStatus::Cdm_insufficient_version;
- }
-
#ifdef XP_WIN
if (aKeySystem.EqualsLiteral("com.adobe.access") ||
aKeySystem.EqualsLiteral("com.adobe.primetime")) {
// Verify that anti-virus hasn't "helpfully" deleted the Adobe GMP DLL,
// as we suspect may happen (Bug 1160382).
bool somethingMissing = false;
if (!AdobePluginDLLExists(versionStr)) {
aOutMessage = NS_LITERAL_CSTRING("Adobe DLL was expected to be on disk but was not");
@@ -192,16 +181,24 @@ EnsureMinCDMVersion(mozIGeckoMediaPlugin
// Firefox will try to download the plugin next time the updater runs.
Preferences::ClearUser("media.gmp-eme-adobe.lastUpdate");
Preferences::ClearUser("media.gmp-eme-adobe.version");
return MediaKeySystemStatus::Cdm_not_installed;
}
}
#endif
+ nsresult rv;
+ int32_t version = versionStr.ToInteger(&rv);
+ if (aMinCdmVersion != NO_CDM_VERSION &&
+ (NS_FAILED(rv) || version < 0 || aMinCdmVersion > version)) {
+ aOutMessage = NS_LITERAL_CSTRING("Installed CDM version insufficient");
+ return MediaKeySystemStatus::Cdm_insufficient_version;
+ }
+
return MediaKeySystemStatus::Available;
}
/* static */
MediaKeySystemStatus
MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
int32_t aMinCdmVersion,
nsACString& aOutMessage)
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -178,17 +178,17 @@ GMPParent::LoadProcess()
return NS_ERROR_FAILURE;
}
LOGD("%s: Sent StartPlugin to child process", __FUNCTION__);
}
mState = GMPStateLoaded;
// Hold a self ref while the child process is alive. This ensures that
- // during shutdown the GMPParent stays we stay alive long enough to
+ // during shutdown the GMPParent stays alive long enough to
// terminate the child process.
MOZ_ASSERT(!mHoldingSelfRef);
mHoldingSelfRef = true;
AddRef();
return NS_OK;
}
@@ -207,16 +207,17 @@ AbortWaitingForGMPAsyncShutdown(nsITimer
if (service) {
service->AsyncShutdownComplete(parent);
}
}
nsresult
GMPParent::EnsureAsyncShutdownTimeoutSet()
{
+ MOZ_ASSERT(mAsyncShutdownRequired);
if (mAsyncShutdownTimeout) {
return NS_OK;
}
nsresult rv;
mAsyncShutdownTimeout = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -230,19 +231,21 @@ GMPParent::EnsureAsyncShutdownTimeoutSet
}
int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT;
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
if (service) {
timeout = service->AsyncShutdownTimeoutMs();
}
- return mAsyncShutdownTimeout->InitWithFuncCallback(
+ rv = mAsyncShutdownTimeout->InitWithFuncCallback(
&AbortWaitingForGMPAsyncShutdown, this, timeout,
nsITimer::TYPE_ONE_SHOT);
+ unused << NS_WARN_IF(NS_FAILED(rv));
+ return rv;
}
bool
GMPParent::RecvPGMPContentChildDestroyed()
{
--mGMPContentChildCount;
if (!IsUsed()) {
#if defined(MOZ_CRASHREPORTER)
@@ -281,27 +284,35 @@ GMPParent::CloseIfUnused()
if (!mAsyncShutdownInProgress) {
LOGD("%s: sending async shutdown notification", __FUNCTION__);
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AnnotateCrashReport(
nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
NS_LITERAL_CSTRING("Sent BeginAsyncShutdown"));
#endif
mAsyncShutdownInProgress = true;
- if (!SendBeginAsyncShutdown() ||
- NS_FAILED(EnsureAsyncShutdownTimeoutSet())) {
+ if (!SendBeginAsyncShutdown()) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AnnotateCrashReport(
nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
- NS_LITERAL_CSTRING("Could not send BeginAsyncShutdown - Aborting"));
+ NS_LITERAL_CSTRING("Could not send BeginAsyncShutdown - Aborting async shutdown"));
+#endif
+ AbortAsyncShutdown();
+ } else if (NS_FAILED(EnsureAsyncShutdownTimeoutSet())) {
+#if defined(MOZ_CRASHREPORTER)
+ CrashReporter::AnnotateCrashReport(
+ nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
+ NS_LITERAL_CSTRING("Could not start timer after sending BeginAsyncShutdown - Aborting async shutdown"));
#endif
AbortAsyncShutdown();
}
}
} else {
+ // No async-shutdown, kill async-shutdown timer started in CloseActive().
+ AbortAsyncShutdown();
// Any async shutdown must be complete. Shutdown GMPStorage.
for (size_t i = mStorage.Length(); i > 0; i--) {
mStorage[i - 1]->Shutdown();
}
Shutdown();
}
}
}
@@ -341,17 +352,48 @@ GMPParent::CloseActive(bool aDieWhenUnlo
mState = GMPStateUnloading;
}
if (mState != GMPStateNotLoaded && IsUsed()) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AnnotateCrashReport(
nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
nsPrintfCString("Sent CloseActive, content children to close: %u", mGMPContentChildCount));
#endif
- unused << SendCloseActive();
+ if (!SendCloseActive()) {
+#if defined(MOZ_CRASHREPORTER)
+ CrashReporter::AnnotateCrashReport(
+ nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
+ NS_LITERAL_CSTRING("Could not send CloseActive - Aborting async shutdown"));
+#endif
+ AbortAsyncShutdown();
+ } else if (IsUsed()) {
+ // We're expecting RecvPGMPContentChildDestroyed's -> Start async-shutdown timer now if needed.
+ if (mAsyncShutdownRequired && NS_FAILED(EnsureAsyncShutdownTimeoutSet())) {
+#if defined(MOZ_CRASHREPORTER)
+ CrashReporter::AnnotateCrashReport(
+ nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
+ NS_LITERAL_CSTRING("Could not start timer after sending CloseActive - Aborting async shutdown"));
+#endif
+ AbortAsyncShutdown();
+ }
+ } else {
+ // We're not expecting any RecvPGMPContentChildDestroyed
+ // -> Call CloseIfUnused() now, to run async shutdown if necessary.
+ // Note that CloseIfUnused() may have already been called from a prior
+ // RecvPGMPContentChildDestroyed(), however depending on the state at
+ // that time, it might not have proceeded with shutdown; And calling it
+ // again after shutdown is fine because after the first one we'll be in
+ // GMPStateNotLoaded.
+#if defined(MOZ_CRASHREPORTER)
+ CrashReporter::AnnotateCrashReport(
+ nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this),
+ NS_LITERAL_CSTRING("Content children already destroyed"));
+#endif
+ CloseIfUnused();
+ }
}
}
void
GMPParent::MarkForDeletion()
{
mDeleteProcessOnlyOnUnload = true;
mIsBlockingDeletion = true;
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -30,16 +30,17 @@
#include "StereoPannerNode.h"
#include "ChannelMergerNode.h"
#include "ChannelSplitterNode.h"
#include "MediaStreamAudioDestinationNode.h"
#include "WaveShaperNode.h"
#include "PeriodicWave.h"
#include "ConvolverNode.h"
#include "OscillatorNode.h"
+#include "blink/PeriodicWave.h"
#include "nsNetUtil.h"
#include "AudioStream.h"
#include "mozilla/dom/Promise.h"
namespace mozilla {
namespace dom {
// 0 is a special value that MediaStreams use to denote they are not part of a
@@ -1045,10 +1046,53 @@ AudioContext::CollectReports(nsIHandleRe
}
double
AudioContext::ExtraCurrentTime() const
{
return mDestination->ExtraCurrentTime();
}
+BasicWaveFormCache*
+AudioContext::GetBasicWaveFormCache()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!mBasicWaveFormCache) {
+ mBasicWaveFormCache = new BasicWaveFormCache(SampleRate());
+ }
+ return mBasicWaveFormCache;
+}
+
+BasicWaveFormCache::BasicWaveFormCache(uint32_t aSampleRate)
+ : mSampleRate(aSampleRate)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+BasicWaveFormCache::~BasicWaveFormCache()
+{ }
+
+WebCore::PeriodicWave*
+BasicWaveFormCache::GetBasicWaveForm(OscillatorType aType)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+ if (aType == OscillatorType::Sawtooth) {
+ if (!mSawtooth) {
+ mSawtooth = WebCore::PeriodicWave::createSawtooth(mSampleRate);
+ }
+ return mSawtooth;
+ } else if (aType == OscillatorType::Square) {
+ if (!mSquare) {
+ mSquare = WebCore::PeriodicWave::createSquare(mSampleRate);
+ }
+ return mSquare;
+ } else if (aType == OscillatorType::Triangle) {
+ if (!mTriangle) {
+ mTriangle = WebCore::PeriodicWave::createTriangle(mSampleRate);
+ }
+ return mTriangle;
+ } else {
+ MOZ_ASSERT(false, "Not reached");
+ return nullptr;
+ }
+}
+
}
}
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -22,16 +22,20 @@
#include "nsIMemoryReporter.h"
// X11 has a #define for CurrentTime. Unbelievable :-(.
// See dom/media/DOMMediaStream.h for more fun!
#ifdef CurrentTime
#undef CurrentTime
#endif
+namespace WebCore {
+ class PeriodicWave;
+};
+
class nsPIDOMWindow;
namespace mozilla {
class DOMMediaStream;
class ErrorResult;
class MediaStream;
class MediaStreamGraph;
@@ -60,16 +64,35 @@ class MediaStreamAudioDestinationNode;
class MediaStreamAudioSourceNode;
class OscillatorNode;
class PannerNode;
class ScriptProcessorNode;
class StereoPannerNode;
class WaveShaperNode;
class PeriodicWave;
class Promise;
+enum class OscillatorType : uint32_t;
+
+// This is addrefed by the OscillatorNodeEngine on the main thread
+// and then used from the MSG thread.
+// It can be released either from the graph thread or the main thread.
+class BasicWaveFormCache
+{
+public:
+ explicit BasicWaveFormCache(uint32_t aSampleRate);
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BasicWaveFormCache)
+ WebCore::PeriodicWave* GetBasicWaveForm(OscillatorType aType);
+private:
+ ~BasicWaveFormCache();
+ nsRefPtr<WebCore::PeriodicWave> mSawtooth;
+ nsRefPtr<WebCore::PeriodicWave> mSquare;
+ nsRefPtr<WebCore::PeriodicWave> mTriangle;
+ uint32_t mSampleRate;
+};
+
/* This runnable allows the MSG to notify the main thread when audio is actually
* flowing */
class StateChangeTask final : public nsRunnable
{
public:
/* This constructor should be used when this event is sent from the main
* thread. */
@@ -289,16 +312,18 @@ public:
double StreamTimeToDOMTime(double aTime) const
{
return aTime + ExtraCurrentTime();
}
void OnStateChanged(void* aPromise, AudioContextState aNewState);
+ BasicWaveFormCache* GetBasicWaveFormCache();
+
IMPL_EVENT_HANDLER(mozinterruptbegin)
IMPL_EVENT_HANDLER(mozinterruptend)
private:
/**
* Returns the amount of extra time added to the current time of the
* AudioDestinationNode's MediaStream to get this AudioContext's currentTime.
* Must be subtracted from all DOM API parameter times that are on the same
@@ -334,16 +359,18 @@ private:
// they are resolved, so we can safely pass them accross threads.
nsTArray<nsRefPtr<Promise>> mPromiseGripArray;
// See RegisterActiveNode. These will keep the AudioContext alive while it
// is rendering and the window remains alive.
nsTHashtable<nsRefPtrHashKey<AudioNode> > mActiveNodes;
// Hashsets containing all the PannerNodes, to compute the doppler shift.
// These are weak pointers.
nsTHashtable<nsPtrHashKey<PannerNode> > mPannerNodes;
+ // Cache to avoid recomputing basic waveforms all the time.
+ nsRefPtr<BasicWaveFormCache> mBasicWaveFormCache;
// Number of channels passed in the OfflineAudioContext ctor.
uint32_t mNumberOfChannels;
// Number of nodes that currently exist for this AudioContext
int32_t mNodeCount;
bool mIsOffline;
bool mIsStarted;
bool mIsShutDown;
// Close has been called, reject suspend and resume call.
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -288,16 +288,21 @@ private:
bool mLastInputMuted;
};
static bool UseAudioChannelService()
{
return Preferences::GetBool("media.useAudioChannelService");
}
+static bool UseAudioChannelAPI()
+{
+ return Preferences::GetBool("media.useAudioChannelAPI");
+}
+
class EventProxyHandler final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
explicit EventProxyHandler(nsIDOMEventListener* aNode)
{
MOZ_ASSERT(aNode);
@@ -538,19 +543,21 @@ AudioDestinationNode::CanPlayChanged(int
bool playing = aCanPlay == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL;
if (playing == mAudioChannelAgentPlaying) {
return NS_OK;
}
mAudioChannelAgentPlaying = playing;
SetCanPlay(playing);
- Context()->DispatchTrustedEvent(
- playing ? NS_LITERAL_STRING("mozinterruptend")
- : NS_LITERAL_STRING("mozinterruptbegin"));
+ if (UseAudioChannelAPI()) {
+ Context()->DispatchTrustedEvent(
+ playing ? NS_LITERAL_STRING("mozinterruptend")
+ : NS_LITERAL_STRING("mozinterruptbegin"));
+ }
return NS_OK;
}
NS_IMETHODIMP
AudioDestinationNode::WindowVolumeChanged()
{
MOZ_ASSERT(mAudioChannelAgent);
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -35,16 +35,18 @@ public:
// Keep the default values in sync with OscillatorNode::OscillatorNode.
, mFrequency(440.f)
, mDetune(0.f)
, mType(OscillatorType::Sine)
, mPhase(0.)
, mRecomputeParameters(true)
, mCustomLength(0)
{
+ MOZ_ASSERT(NS_IsMainThread());
+ mBasicWaveFormCache = aDestination->Context()->GetBasicWaveFormCache();
}
void SetSourceStream(AudioNodeStream* aSource)
{
mSource = aSource;
}
enum Parameters {
@@ -99,23 +101,19 @@ public:
mPeriodicWave = nullptr;
mRecomputeParameters = true;
}
switch (mType) {
case OscillatorType::Sine:
mPhase = 0.0;
break;
case OscillatorType::Square:
- mPeriodicWave = WebCore::PeriodicWave::createSquare(mSource->SampleRate());
- break;
case OscillatorType::Triangle:
- mPeriodicWave = WebCore::PeriodicWave::createTriangle(mSource->SampleRate());
- break;
case OscillatorType::Sawtooth:
- mPeriodicWave = WebCore::PeriodicWave::createSawtooth(mSource->SampleRate());
+ mPeriodicWave = mBasicWaveFormCache->GetBasicWaveForm(mType);
break;
case OscillatorType::Custom:
break;
default:
NS_ERROR("Bad OscillatorNodeEngine type parameter.");
}
// End type switch.
break;
@@ -366,18 +364,19 @@ public:
AudioParamTimeline mFrequency;
AudioParamTimeline mDetune;
OscillatorType mType;
float mPhase;
float mFinalFrequency;
float mPhaseIncrement;
bool mRecomputeParameters;
nsRefPtr<ThreadSharedFloatArrayBufferList> mCustom;
+ nsRefPtr<BasicWaveFormCache> mBasicWaveFormCache;
uint32_t mCustomLength;
- nsAutoPtr<WebCore::PeriodicWave> mPeriodicWave;
+ nsRefPtr<WebCore::PeriodicWave> mPeriodicWave;
};
OscillatorNode::OscillatorNode(AudioContext* aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
, mType(OscillatorType::Sine)
--- a/dom/media/webaudio/PeriodicWave.h
+++ b/dom/media/webaudio/PeriodicWave.h
@@ -7,17 +7,16 @@
#ifndef PeriodicWave_h_
#define PeriodicWave_h_
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "AudioContext.h"
#include "AudioNodeEngine.h"
-#include "nsAutoPtr.h"
namespace mozilla {
namespace dom {
class PeriodicWave final : public nsWrapperCache
{
public:
--- a/dom/media/webaudio/blink/PeriodicWave.cpp
+++ b/dom/media/webaudio/blink/PeriodicWave.cpp
@@ -35,58 +35,68 @@ const unsigned PeriodicWaveSize = 4096;
const unsigned NumberOfRanges = 36; // There should be 3 * log2(PeriodicWaveSize) 1/3 octave ranges.
const float CentsPerRange = 1200 / 3; // 1/3 Octave.
using namespace mozilla;
using mozilla::dom::OscillatorType;
namespace WebCore {
-PeriodicWave* PeriodicWave::create(float sampleRate,
- const float* real,
- const float* imag,
- size_t numberOfComponents)
+already_AddRefed<PeriodicWave>
+PeriodicWave::create(float sampleRate,
+ const float* real,
+ const float* imag,
+ size_t numberOfComponents)
{
bool isGood = real && imag && numberOfComponents > 0 &&
numberOfComponents <= PeriodicWaveSize;
MOZ_ASSERT(isGood);
if (isGood) {
- PeriodicWave* periodicWave = new PeriodicWave(sampleRate);
+ nsRefPtr<PeriodicWave> periodicWave =
+ new PeriodicWave(sampleRate);
periodicWave->createBandLimitedTables(real, imag, numberOfComponents);
- return periodicWave;
+ return periodicWave.forget();
}
- return 0;
+ return nullptr;
}
-PeriodicWave* PeriodicWave::createSine(float sampleRate)
+already_AddRefed<PeriodicWave>
+PeriodicWave::createSine(float sampleRate)
{
- PeriodicWave* periodicWave = new PeriodicWave(sampleRate);
- periodicWave->generateBasicWaveform(OscillatorType::Sine);
- return periodicWave;
+ nsRefPtr<PeriodicWave> periodicWave =
+ new PeriodicWave(sampleRate);
+ periodicWave->generateBasicWaveform(OscillatorType::Sine);
+ return periodicWave.forget();
}
-PeriodicWave* PeriodicWave::createSquare(float sampleRate)
+already_AddRefed<PeriodicWave>
+PeriodicWave::createSquare(float sampleRate)
{
- PeriodicWave* periodicWave = new PeriodicWave(sampleRate);
- periodicWave->generateBasicWaveform(OscillatorType::Square);
- return periodicWave;
+ nsRefPtr<PeriodicWave> periodicWave =
+ new PeriodicWave(sampleRate);
+ periodicWave->generateBasicWaveform(OscillatorType::Square);
+ return periodicWave.forget();
}
-PeriodicWave* PeriodicWave::createSawtooth(float sampleRate)
+already_AddRefed<PeriodicWave>
+PeriodicWave::createSawtooth(float sampleRate)
{
- PeriodicWave* periodicWave = new PeriodicWave(sampleRate);
- periodicWave->generateBasicWaveform(OscillatorType::Sawtooth);
- return periodicWave;
+ nsRefPtr<PeriodicWave> periodicWave =
+ new PeriodicWave(sampleRate);
+ periodicWave->generateBasicWaveform(OscillatorType::Sawtooth);
+ return periodicWave.forget();
}
-PeriodicWave* PeriodicWave::createTriangle(float sampleRate)
+already_AddRefed<PeriodicWave>
+PeriodicWave::createTriangle(float sampleRate)
{
- PeriodicWave* periodicWave = new PeriodicWave(sampleRate);
- periodicWave->generateBasicWaveform(OscillatorType::Triangle);
- return periodicWave;
+ nsRefPtr<PeriodicWave> periodicWave =
+ new PeriodicWave(sampleRate);
+ periodicWave->generateBasicWaveform(OscillatorType::Triangle);
+ return periodicWave.forget();
}
PeriodicWave::PeriodicWave(float sampleRate)
: m_sampleRate(sampleRate)
, m_periodicWaveSize(PeriodicWaveSize)
, m_numberOfRanges(NumberOfRanges)
, m_centsPerRange(CentsPerRange)
{
--- a/dom/media/webaudio/blink/PeriodicWave.h
+++ b/dom/media/webaudio/blink/PeriodicWave.h
@@ -37,27 +37,29 @@
namespace WebCore {
typedef AlignedTArray<float> AlignedAudioFloatArray;
typedef nsTArray<float> AudioFloatArray;
class PeriodicWave {
public:
- static PeriodicWave* createSine(float sampleRate);
- static PeriodicWave* createSquare(float sampleRate);
- static PeriodicWave* createSawtooth(float sampleRate);
- static PeriodicWave* createTriangle(float sampleRate);
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebCore::PeriodicWave);
+
+ static already_AddRefed<PeriodicWave> createSine(float sampleRate);
+ static already_AddRefed<PeriodicWave> createSquare(float sampleRate);
+ static already_AddRefed<PeriodicWave> createSawtooth(float sampleRate);
+ static already_AddRefed<PeriodicWave> createTriangle(float sampleRate);
// Creates an arbitrary periodic wave given the frequency components
// (Fourier coefficients).
- static PeriodicWave* create(float sampleRate,
- const float* real,
- const float* imag,
- size_t numberOfComponents);
+ static already_AddRefed<PeriodicWave> create(float sampleRate,
+ const float* real,
+ const float* imag,
+ size_t numberOfComponents);
// Returns pointers to the lower and higher wave data for the pitch range
// containing the given fundamental frequency. These two tables are in
// adjacent "pitch" ranges where the higher table will have the maximum
// number of partials which won't alias when played back at this
// fundamental frequency. The lower wave is the next range containing fewer
// partials than the higher wave. Interpolation between these two tables
// can be made according to tableInterpolationFactor. Where values
@@ -70,16 +72,17 @@ public:
unsigned periodicWaveSize() const { return m_periodicWaveSize; }
float sampleRate() const { return m_sampleRate; }
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:
explicit PeriodicWave(float sampleRate);
+ ~PeriodicWave() {}
void generateBasicWaveform(mozilla::dom::OscillatorType);
float m_sampleRate;
unsigned m_periodicWaveSize;
unsigned m_numberOfRanges;
float m_centsPerRange;
--- a/dom/media/webaudio/test/browser_mozAudioChannel.js
+++ b/dom/media/webaudio/test/browser_mozAudioChannel.js
@@ -30,16 +30,17 @@ function eventListener(evt) {
function test() {
waitForExplicitFinish();
let testURL = "http://mochi.test:8888/browser/" +
"dom/media/webaudio/test/browser_mozAudioChannel.html";
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", "content" ],
+ ["media.useAudioChannelAPI", true ],
["media.useAudioChannelService", true ]]},
function() {
let tab1 = gBrowser.addTab(testURL);
gBrowser.selectedTab = tab1;
whenBrowserLoaded(tab1.linkedBrowser, function() {
let doc = tab1.linkedBrowser.contentDocument;
tab1.linkedBrowser.contentWindow.addEventListener('testmozchannel', eventListener, false);
--- a/dom/media/webaudio/test/browser_mozAudioChannel_muted.js
+++ b/dom/media/webaudio/test/browser_mozAudioChannel_muted.js
@@ -30,16 +30,17 @@ function whenBrowserUnloaded(aBrowser, a
function test() {
waitForExplicitFinish();
let testURL = "http://mochi.test:8888/browser/" +
"dom/media/webaudio/test/browser_mozAudioChannel_muted.html";
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", "content" ],
+ ["media.useAudioChannelAPI", true ],
["media.useAudioChannelService", true ]]},
function() {
let tab1 = gBrowser.addTab(testURL);
gBrowser.selectedTab = tab1;
whenBrowserLoaded(tab1.linkedBrowser, function() {
let doc = tab1.linkedBrowser.contentDocument;
is(doc.getElementById("mozAudioChannelTest").textContent, "READY",
--- a/dom/media/webaudio/test/test_mozaudiochannel.html
+++ b/dom/media/webaudio/test/test_mozaudiochannel.html
@@ -136,16 +136,17 @@ function runTest() {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
-SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true ]]}, runTest);
+SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true ],
+ ["media.useAudioChannelService", true ]]}, runTest);
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(5);
</script>
</pre>
</body>
</html>
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2848,18 +2848,17 @@ PluginInstanceChild::CreateOptSurface(vo
gfxXlibSurface::Create(screen, xfmt,
gfxIntSize(mWindow.width,
mWindow.height));
return mCurrentSurface != nullptr;
}
#endif
#ifdef XP_WIN
- if (mSurfaceType == gfxSurfaceType::Win32 ||
- mSurfaceType == gfxSurfaceType::D2D) {
+ if (mSurfaceType == gfxSurfaceType::Win32) {
bool willHaveTransparentPixels = mIsTransparent && !mBackground;
SharedDIBSurface* s = new SharedDIBSurface();
if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
mWindow.width, mWindow.height,
willHaveTransparentPixels))
return false;
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -45,18 +45,19 @@ class PromiseInit;
class PromiseNativeHandler;
class PromiseDebugging;
class Promise;
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
class PromiseReportRejectFeature : public workers::WorkerFeature
{
- // The Promise that owns this feature.
- Promise* mPromise;
+ // PromiseReportRejectFeature is held by an nsAutoPtr on the Promise which
+ // means that this object will be destroyed before the Promise is destroyed.
+ Promise* MOZ_NON_OWNING_REF mPromise;
public:
explicit PromiseReportRejectFeature(Promise* aPromise)
: mPromise(aPromise)
{
MOZ_ASSERT(mPromise);
}
--- a/dom/webidl/AudioContext.webidl
+++ b/dom/webidl/AudioContext.webidl
@@ -90,23 +90,23 @@ interface AudioContext : EventTarget {
[NewObject, Throws]
PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
};
// Mozilla extensions
partial interface AudioContext {
// Read AudioChannel.webidl for more information about this attribute.
- [Pref="media.useAudioChannelService"]
+ [Pref="media.useAudioChannelAPI"]
readonly attribute AudioChannel mozAudioChannelType;
// These 2 events are dispatched when the AudioContext object is muted by
// the AudioChannelService. It's call 'interrupt' because when this event is
// dispatched on a HTMLMediaElement, the audio stream is paused.
- [Pref="media.useAudioChannelService"]
+ [Pref="media.useAudioChannelAPI"]
attribute EventHandler onmozinterruptbegin;
- [Pref="media.useAudioChannelService"]
+ [Pref="media.useAudioChannelAPI"]
attribute EventHandler onmozinterruptend;
// This method is for test only.
[ChromeOnly] AudioChannel testAudioChannelInAudioNodeStream();
};
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3539,22 +3539,48 @@ bool
WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
JSContext* aCx, uint64_t aMessagePortSerial,
JSAutoStructuredCloneBuffer&& aBuffer,
WorkerStructuredCloneClosure& aClosure)
{
AssertIsOnMainThread();
JSAutoStructuredCloneBuffer buffer(Move(aBuffer));
+ const JSStructuredCloneCallbacks* callbacks =
+ WorkerStructuredCloneCallbacks(true);
+
+ class MOZ_STACK_CLASS AutoCloneBufferCleaner final
+ {
+ public:
+ AutoCloneBufferCleaner(JSAutoStructuredCloneBuffer& aBuffer,
+ const JSStructuredCloneCallbacks* aCallbacks,
+ WorkerStructuredCloneClosure& aClosure)
+ : mBuffer(aBuffer)
+ , mCallbacks(aCallbacks)
+ , mClosure(aClosure)
+ {}
+
+ ~AutoCloneBufferCleaner()
+ {
+ mBuffer.clear(mCallbacks, &mClosure);
+ }
+
+ private:
+ JSAutoStructuredCloneBuffer& mBuffer;
+ const JSStructuredCloneCallbacks* mCallbacks;
+ WorkerStructuredCloneClosure& mClosure;
+ };
WorkerStructuredCloneClosure closure;
closure.mClonedObjects.SwapElements(aClosure.mClonedObjects);
MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty());
closure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers);
+ AutoCloneBufferCleaner bufferCleaner(buffer, callbacks, closure);
+
SharedWorker* sharedWorker;
if (!mSharedWorkers.Get(aMessagePortSerial, &sharedWorker)) {
// SharedWorker has already been unregistered?
return true;
}
nsRefPtr<MessagePort> port = sharedWorker->Port();
NS_ASSERTION(port, "SharedWorkers always have a port!");
@@ -3572,18 +3598,16 @@ WorkerPrivateParent<Derived>::DispatchMe
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> data(cx);
if (!buffer.read(cx, &data, WorkerStructuredCloneCallbacks(true),
&closure)) {
return false;
}
- buffer.clear();
-
nsRefPtr<MessageEvent> event = new MessageEvent(port, nullptr, nullptr);
nsresult rv =
event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, data,
EmptyString(), EmptyString(), nullptr);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
return false;
}
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -654,19 +654,16 @@ DrawTargetCairo::GetType() const
case CAIRO_SURFACE_TYPE_WIN32:
case CAIRO_SURFACE_TYPE_BEOS:
case CAIRO_SURFACE_TYPE_OS2:
case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
case CAIRO_SURFACE_TYPE_SCRIPT:
case CAIRO_SURFACE_TYPE_RECORDING:
case CAIRO_SURFACE_TYPE_DRM:
case CAIRO_SURFACE_TYPE_SUBSURFACE:
-#ifdef CAIRO_HAS_D2D_SURFACE
- case CAIRO_SURFACE_TYPE_D2D:
-#endif
case CAIRO_SURFACE_TYPE_TEE: // included to silence warning about unhandled enum value
return DrawTargetType::SOFTWARE_RASTER;
default:
MOZ_CRASH("Unsupported cairo surface type");
}
}
MOZ_ASSERT(false, "Could not determine DrawTargetType for DrawTargetCairo");
return DrawTargetType::SOFTWARE_RASTER;
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -45,17 +45,22 @@ DrawTargetD2D1::~DrawTargetD2D1()
// MarkIndependent is running.
RefPtr<SourceSurfaceD2D1> deathGrip = mSnapshot;
// mSnapshot can be treated as independent of this DrawTarget since we know
// this DrawTarget won't change again.
deathGrip->MarkIndependent();
// mSnapshot will be cleared now.
}
- mDC->EndDraw();
+ if (mDC) {
+ // The only way mDC can be null is if Init failed, but it can happen and the
+ // destructor is the only place where we need to check for it since the
+ // DrawTarget will destroyed right after Init fails.
+ mDC->EndDraw();
+ }
// Targets depending on us can break that dependency, since we're obviously not going to
// be modified in the future.
for (auto iter = mDependentTargets.begin();
iter != mDependentTargets.end(); iter++) {
(*iter)->mDependingOnTargets.erase(this);
}
// Our dependencies on other targets no longer matter.
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -27,17 +27,16 @@
#include "mozilla/gfx/2D.h"
#ifdef XP_MACOSX
#include "mozilla/gfx/QuartzSupport.h"
#include "MacIOSurfaceImage.h"
#endif
#ifdef XP_WIN
-#include "gfxD2DSurface.h"
#include "gfxWindowsPlatform.h"
#include <d3d10_1.h>
#include "D3D9SurfaceImage.h"
#include "D3D11ShareHandleImage.h"
#endif
namespace mozilla {
namespace layers {
--- a/gfx/layers/apz/test/test_basic_pan.html
+++ b/gfx/layers/apz/test/test_basic_pan.html
@@ -40,17 +40,19 @@ window.onload = function() {
// Dropping the touch slop to 0 makes the tests easier to write because
// we can just do a one-pixel drag to get over the pan threshold rather
// than having to hard-code some larger value.
["apz.touch_start_tolerance", "0.0"],
// The B2G emulator is hella slow, and needs more than 300ms to run the
// main-thread code that deals with layerizing subframes and running
// touch listeners. In my local runs this needs to be at least 1000.
- ["apz.content_response_timeout", "5000"]
+ // On try this sometimes needs to be as long as 8 seconds (bug 1176798)
+ // so we make it 15 seconds just to be extra safe.
+ ["apz.content_response_timeout", "15000"]
]
}, testDone);
};
</script>
</head>
<body>
</body>
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -69,17 +69,17 @@ ContentClient::CreateContentClient(Compo
backend != LayersBackend::LAYERS_BASIC) {
return nullptr;
}
bool useDoubleBuffering = false;
#ifdef XP_WIN
if (backend == LayersBackend::LAYERS_D3D11) {
- useDoubleBuffering = !!gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
+ useDoubleBuffering = !!gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
} else
#endif
#ifdef MOZ_WIDGET_GTK
// We can't use double buffering when using image content with
// Xrender support on Linux, as ContentHostDoubleBuffered is not
// suited for direct uploads to the server.
if (!gfxPlatformGtk::GetPlatform()->UseImageOffscreenSurfaces() ||
!gfxPlatformGtk::GetPlatform()->UseXRender())
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -339,28 +339,28 @@ TextureClient::CreateForDrawing(ISurface
int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
#endif
#ifdef XP_WIN
LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
if (parentBackend == LayersBackend::LAYERS_D3D11 &&
(aMoz2DBackend == gfx::BackendType::DIRECT2D ||
aMoz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
- gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
+ gfxWindowsPlatform::GetPlatform()->GetD3D10Device() &&
aSize.width <= maxTextureSize &&
aSize.height <= maxTextureSize) {
texture = new TextureClientD3D11(aAllocator, aFormat, aTextureFlags);
}
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
aMoz2DBackend == gfx::BackendType::CAIRO &&
aAllocator->IsSameProcess() &&
aSize.width <= maxTextureSize &&
aSize.height <= maxTextureSize) {
if (gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
- texture = new CairoTextureClientD3D9(aAllocator, aFormat, aTextureFlags);
+ texture = new TextureClientD3D9(aAllocator, aFormat, aTextureFlags);
}
}
if (!texture && aFormat == SurfaceFormat::B8G8R8X8 &&
aAllocator->IsSameProcess() &&
aMoz2DBackend == gfx::BackendType::CAIRO) {
if (aAllocator->IsSameProcess()) {
texture = new TextureClientMemoryDIB(aAllocator, aFormat, aTextureFlags);
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -497,17 +497,17 @@ protected:
void MarkInvalid() { mValid = false; }
/**
* Should only be called *once* per texture, in TextureClient::InitIPDLActor.
* Some texture implementations rely on the fact that the descriptor will be
* deserialized.
* Calling ToSurfaceDescriptor again after it has already returned true,
* or never constructing a TextureHost with aDescriptor may result in a memory
- * leak (see CairoTextureClientD3D9 for example).
+ * leak (see TextureClientD3D9 for example).
*/
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
ISurfaceAllocator* GetAllocator()
{
return mAllocator;
}
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -4,17 +4,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TextureD3D11.h"
#include "CompositorD3D11.h"
#include "gfxContext.h"
#include "Effects.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "gfxWindowsPlatform.h"
-#include "gfxD2DSurface.h"
#include "gfx2DGlue.h"
#include "gfxPrefs.h"
#include "ReadbackManagerD3D11.h"
#include "mozilla/gfx/Logging.h"
namespace mozilla {
using namespace gfx;
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -156,17 +156,17 @@ CompositingRenderTargetD3D9::BindRenderT
IntSize
CompositingRenderTargetD3D9::GetSize() const
{
return TextureSourceD3D9::GetSize();
}
/**
- * Helper method for DataToTexture and SurfaceToTexture.
+ * Helper method for DataToTexture.
* The last three params are out params.
* Returns the created texture, or null if we fail.
*/
already_AddRefed<IDirect3DTexture9>
TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager,
const IntSize &aSize,
_D3DFORMAT aFormat,
RefPtr<IDirect3DSurface9>& aSurface,
@@ -198,17 +198,17 @@ TextureSourceD3D9::InitTextures(DeviceMa
gfxCriticalError() << "Failed to lock rect initialize texture in D3D9 " << hexa(hr);
return nullptr;
}
return result.forget();
}
/**
- * Helper method for DataToTexture and SurfaceToTexture.
+ * Helper method for DataToTexture.
*/
static void
FinishTextures(DeviceManagerD3D9* aDeviceManager,
IDirect3DTexture9* aTexture,
IDirect3DSurface9* aSurface)
{
if (!aDeviceManager) {
return;
@@ -269,57 +269,16 @@ TextureSourceD3D9::TextureToTexture(Devi
HRESULT hr = aDeviceManager->device()->UpdateTexture(aTexture, texture);
if (FAILED(hr)) {
return nullptr;
}
return texture.forget();
}
-already_AddRefed<IDirect3DTexture9>
-TextureSourceD3D9::SurfaceToTexture(DeviceManagerD3D9* aDeviceManager,
- gfxWindowsSurface* aSurface,
- const IntSize& aSize,
- _D3DFORMAT aFormat)
-{
- RefPtr<IDirect3DSurface9> surface;
- D3DLOCKED_RECT lockedRect;
-
- RefPtr<IDirect3DTexture9> texture = InitTextures(aDeviceManager, aSize, aFormat,
- surface, lockedRect);
- if (!texture) {
- return nullptr;
- }
-
- {
- RefPtr<DrawTarget> dt =
- Factory::CreateDrawTargetForData(BackendType::CAIRO,
- reinterpret_cast<unsigned char*>(lockedRect.pBits),
- aSize, lockedRect.Pitch,
- gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aSurface->GetContentType()));
-
- if (dt) {
- NativeSurface nativeSurf;
- nativeSurf.mSize = aSize;
- nativeSurf.mType = NativeSurfaceType::CAIRO_SURFACE;
- // We don't know that this is actually the right format, but it's the best
- // we can get for the content type. In practice this probably always works.
- nativeSurf.mFormat = dt->GetFormat();
- nativeSurf.mSurface = aSurface->CairoSurface();
-
- RefPtr<SourceSurface> surf = dt->CreateSourceSurfaceFromNativeSurface(nativeSurf);
- dt->CopySurface(surf, IntRect(IntPoint(), aSize), IntPoint());
- }
- }
-
- FinishTextures(aDeviceManager, texture, surface);
-
- return texture.forget();
-}
-
DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
CompositorD3D9* aCompositor,
TextureFlags aFlags,
StereoMode aStereoMode)
: mFormat(aFormat)
, mCompositor(aCompositor)
, mCurrentTile(0)
, mFlags(aFlags)
@@ -435,91 +394,16 @@ DataTextureSourceD3D9::Update(gfx::DataS
return false;
}
}
}
return true;
}
-bool
-DataTextureSourceD3D9::Update(gfxWindowsSurface* aSurface)
-{
- MOZ_ASSERT(aSurface);
- if (!mCompositor || !mCompositor->device()) {
- NS_WARNING("No D3D device to update the texture.");
- return false;
- }
- mSize = aSurface->GetSize();
-
- uint32_t bpp = 0;
-
- _D3DFORMAT format = D3DFMT_A8R8G8B8;
- mFormat = ImageFormatToSurfaceFormat(
- gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType()));
- switch (mFormat) {
- case SurfaceFormat::B8G8R8X8:
- format = D3DFMT_X8R8G8B8;
- bpp = 4;
- break;
- case SurfaceFormat::B8G8R8A8:
- format = D3DFMT_A8R8G8B8;
- bpp = 4;
- break;
- case SurfaceFormat::A8:
- format = D3DFMT_A8;
- bpp = 1;
- break;
- default:
- NS_WARNING("Bad image format");
- return false;
- }
-
- int32_t maxSize = mCompositor->GetMaxTextureSize();
- DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
- if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
- (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
- mTexture = SurfaceToTexture(deviceManager, aSurface, mSize, format);
-
- if (!mTexture) {
- NS_WARNING("Could not upload texture");
- Reset();
- return false;
- }
- mIsTiled = false;
- } else {
- mIsTiled = true;
- uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
- GetRequiredTilesD3D9(mSize.height, maxSize);
- mTileTextures.resize(tileCount);
- mTexture = nullptr;
- nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
-
- for (uint32_t i = 0; i < tileCount; i++) {
- IntRect tileRect = GetTileRect(i);
- unsigned char* data = imgSurface->Data() +
- tileRect.y * imgSurface->Stride() +
- tileRect.x * bpp;
- mTileTextures[i] = DataToTexture(deviceManager,
- data,
- imgSurface->Stride(),
- IntSize(tileRect.width, tileRect.height),
- format,
- bpp);
- if (!mTileTextures[i]) {
- NS_WARNING("Could not upload texture");
- Reset();
- return false;
- }
- }
- }
-
- return true;
-}
-
void
DataTextureSourceD3D9::SetCompositor(Compositor* aCompositor)
{
MOZ_ASSERT(aCompositor);
CompositorD3D9* d3dCompositor = static_cast<CompositorD3D9*>(aCompositor);
if (mCompositor && mCompositor != d3dCompositor) {
Reset();
}
@@ -553,49 +437,49 @@ DataTextureSourceD3D9::GetTileRect(uint3
}
IntRect
DataTextureSourceD3D9::GetTileRect()
{
return GetTileRect(mCurrentTile);
}
-CairoTextureClientD3D9::CairoTextureClientD3D9(ISurfaceAllocator* aAllocator,
- gfx::SurfaceFormat aFormat,
- TextureFlags aFlags)
+TextureClientD3D9::TextureClientD3D9(ISurfaceAllocator* aAllocator,
+ gfx::SurfaceFormat aFormat,
+ TextureFlags aFlags)
: TextureClient(aAllocator, aFlags)
, mFormat(aFormat)
, mIsLocked(false)
, mNeedsClear(false)
, mNeedsClearWhite(false)
, mLockRect(false)
{
- MOZ_COUNT_CTOR(CairoTextureClientD3D9);
+ MOZ_COUNT_CTOR(TextureClientD3D9);
}
-CairoTextureClientD3D9::~CairoTextureClientD3D9()
+TextureClientD3D9::~TextureClientD3D9()
{
- MOZ_COUNT_DTOR(CairoTextureClientD3D9);
+ MOZ_COUNT_DTOR(TextureClientD3D9);
}
already_AddRefed<TextureClient>
-CairoTextureClientD3D9::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
+TextureClientD3D9::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
{
- RefPtr<TextureClient> tex = new CairoTextureClientD3D9(mAllocator, mFormat,
- mFlags | aFlags);
+ RefPtr<TextureClient> tex = new TextureClientD3D9(mAllocator, mFormat,
+ mFlags | aFlags);
if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
return nullptr;
}
return tex.forget();
}
bool
-CairoTextureClientD3D9::Lock(OpenMode aMode)
+TextureClientD3D9::Lock(OpenMode aMode)
{
MOZ_ASSERT(!mIsLocked);
if (!IsValid() || !IsAllocated()) {
return false;
}
if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
// If the device has failed then we should not lock the surface,
@@ -642,95 +526,91 @@ CairoTextureClientD3D9::Lock(OpenMode aM
mDrawTarget->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
mNeedsClearWhite = false;
}
return true;
}
void
-CairoTextureClientD3D9::Unlock()
+TextureClientD3D9::Unlock()
{
MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
if (!mIsLocked) {
return;
}
if (mDrawTarget) {
mDrawTarget->Flush();
mDrawTarget = nullptr;
}
if (mLockRect) {
mD3D9Surface->UnlockRect();
mLockRect = false;
}
- if (mSurface) {
- mSurface = nullptr;
- }
mIsLocked = false;
}
bool
-CairoTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+TextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated()) {
return false;
}
mTexture->AddRef(); // Release in TextureHostD3D9::TextureHostD3D9
aOutDescriptor = SurfaceDescriptorD3D9(reinterpret_cast<uintptr_t>(mTexture.get()));
return true;
}
gfx::DrawTarget*
-CairoTextureClientD3D9::BorrowDrawTarget()
+TextureClientD3D9::BorrowDrawTarget()
{
MOZ_ASSERT(mIsLocked && mD3D9Surface);
if (!mIsLocked || !mD3D9Surface) {
NS_WARNING("Calling BorrowDrawTarget on an Unlocked TextureClient");
return nullptr;
}
if (mDrawTarget) {
return mDrawTarget;
}
if (ContentForFormat(mFormat) == gfxContentType::COLOR) {
- mSurface = new gfxWindowsSurface(mD3D9Surface);
- if (!mSurface || mSurface->CairoStatus()) {
+ nsRefPtr<gfxASurface> surface = new gfxWindowsSurface(mD3D9Surface);
+ if (!surface || surface->CairoStatus()) {
NS_WARNING("Could not create surface for d3d9 surface");
- mSurface = nullptr;
return nullptr;
}
+ mDrawTarget =
+ gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, mSize);
} else {
// gfxWindowsSurface don't support transparency so we can't use the d3d9
// windows surface optimization.
// Instead we have to use a gfxImageSurface and fallback for font drawing.
D3DLOCKED_RECT rect;
HRESULT hr = mD3D9Surface->LockRect(&rect, nullptr, 0);
if (FAILED(hr) || !rect.pBits) {
gfxCriticalError() << "Failed to lock rect borrowing the target in D3D9 " << hexa(hr);
return nullptr;
}
- mSurface = new gfxImageSurface((uint8_t*)rect.pBits, mSize,
- rect.Pitch, SurfaceFormatToImageFormat(mFormat));
+ mDrawTarget =
+ gfxPlatform::GetPlatform()->CreateDrawTargetForData((uint8_t*)rect.pBits, mSize,
+ rect.Pitch, mFormat);
mLockRect = true;
}
- mDrawTarget =
- gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
-
return mDrawTarget;
}
bool
-CairoTextureClientD3D9::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
+TextureClientD3D9::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
{
MOZ_ASSERT(!IsAllocated());
mSize = aSize;
_D3DFORMAT format = SurfaceFormatToD3D9Format(mFormat);
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
if (!deviceManager ||
!(mTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_SYSTEMMEM, nullptr))) {
@@ -822,17 +702,17 @@ SharedTextureClientD3D9::ToSurfaceDescri
TextureHostD3D9::TextureHostD3D9(TextureFlags aFlags,
const SurfaceDescriptorD3D9& aDescriptor)
: TextureHost(aFlags)
, mFormat(SurfaceFormat::UNKNOWN)
, mIsLocked(false)
{
mTexture = reinterpret_cast<IDirect3DTexture9*>(aDescriptor.texture());
MOZ_ASSERT(mTexture);
- mTexture->Release(); // see AddRef in CairoTextureClientD3D9::ToSurfaceDescriptor
+ mTexture->Release(); // see AddRef in TextureClientD3D9::ToSurfaceDescriptor
MOZ_ASSERT(mTexture);
D3DSURFACE_DESC desc;
HRESULT hr = mTexture->GetLevelDesc(0, &desc);
if (!FAILED(hr)) {
mFormat = D3D9FormatToSurfaceFormat(desc.Format);
mSize.width = desc.Width;
mSize.height = desc.Height;
}
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -71,22 +71,16 @@ protected:
// aTexture should be in SYSTEMMEM, returns a texture in the default
// pool (that is, in video memory).
already_AddRefed<IDirect3DTexture9> TextureToTexture(
DeviceManagerD3D9* aDeviceManager,
IDirect3DTexture9* aTexture,
const gfx::IntSize& aSize,
_D3DFORMAT aFormat);
- already_AddRefed<IDirect3DTexture9> SurfaceToTexture(
- DeviceManagerD3D9* aDeviceManager,
- gfxWindowsSurface* aSurface,
- const gfx::IntSize& aSize,
- _D3DFORMAT aFormat);
-
gfx::IntSize mSize;
// Linked list of all objects holding d3d9 textures.
TextureSourceD3D9* mPreviousHost;
TextureSourceD3D9* mNextHost;
// The device manager that created our textures.
DeviceManagerD3D9* mCreatingDeviceManager;
@@ -157,45 +151,41 @@ public:
mCurrentTile = 0;
}
/**
* Copy the content of aTexture using the GPU.
*/
bool UpdateFromTexture(IDirect3DTexture9* aTexture, const nsIntRegion* aRegion);
- // To use with DIBTextureHostD3D9
-
- bool Update(gfxWindowsSurface* aSurface);
-
protected:
gfx::IntRect GetTileRect(uint32_t aTileIndex) const;
void Reset();
std::vector< RefPtr<IDirect3DTexture9> > mTileTextures;
RefPtr<CompositorD3D9> mCompositor;
gfx::SurfaceFormat mFormat;
uint32_t mCurrentTile;
TextureFlags mFlags;
bool mIsTiled;
bool mIterating;
};
/**
- * Can only be drawn into through Cairo and need a D3D9 context on the client side.
+ * Needs a D3D9 context on the client side.
* The corresponding TextureHost is TextureHostD3D9.
*/
-class CairoTextureClientD3D9 : public TextureClient
+class TextureClientD3D9 : public TextureClient
{
public:
- CairoTextureClientD3D9(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
+ TextureClientD3D9(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
TextureFlags aFlags);
- virtual ~CairoTextureClientD3D9();
+ virtual ~TextureClientD3D9();
// TextureClient
virtual bool IsAllocated() const override { return !!mTexture; }
virtual bool Lock(OpenMode aOpenMode) override;
virtual void Unlock() override;
@@ -220,17 +210,16 @@ public:
virtual already_AddRefed<TextureClient>
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
private:
RefPtr<IDirect3DTexture9> mTexture;
nsRefPtr<IDirect3DSurface9> mD3D9Surface;
RefPtr<gfx::DrawTarget> mDrawTarget;
- nsRefPtr<gfxASurface> mSurface;
gfx::IntSize mSize;
gfx::SurfaceFormat mFormat;
bool mIsLocked;
bool mNeedsClear;
bool mNeedsClearWhite;
bool mLockRect;
};
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -22,19 +22,16 @@
#include "gfxRect.h"
#include "cairo.h"
#include <algorithm>
#ifdef CAIRO_HAS_WIN32_SURFACE
#include "gfxWindowsSurface.h"
#endif
-#ifdef CAIRO_HAS_D2D_SURFACE
-#include "gfxD2DSurface.h"
-#endif
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
#ifdef CAIRO_HAS_QUARTZ_SURFACE
#include "gfxQuartzSurface.h"
#include "gfxQuartzImageSurface.h"
@@ -174,21 +171,16 @@ gfxASurface::Wrap (cairo_surface_t *csur
result = new gfxImageSurface(csurf);
}
#ifdef CAIRO_HAS_WIN32_SURFACE
else if (stype == CAIRO_SURFACE_TYPE_WIN32 ||
stype == CAIRO_SURFACE_TYPE_WIN32_PRINTING) {
result = new gfxWindowsSurface(csurf);
}
#endif
-#ifdef CAIRO_HAS_D2D_SURFACE
- else if (stype == CAIRO_SURFACE_TYPE_D2D) {
- result = new gfxD2DSurface(csurf);
- }
-#endif
#ifdef MOZ_X11
else if (stype == CAIRO_SURFACE_TYPE_XLIB) {
result = new gfxXlibSurface(csurf);
}
#endif
#ifdef CAIRO_HAS_QUARTZ_SURFACE
else if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
result = new gfxQuartzSurface(csurf, aSize);
@@ -563,25 +555,20 @@ static const SurfaceMemoryReporterAttrs
{"gfx-surface-recording", nullptr},
{"gfx-surface-vg", nullptr},
{"gfx-surface-gl", nullptr},
{"gfx-surface-drm", nullptr},
{"gfx-surface-tee", nullptr},
{"gfx-surface-xml", nullptr},
{"gfx-surface-skia", nullptr},
{"gfx-surface-subsurface", nullptr},
- {"gfx-surface-d2d", nullptr},
};
PR_STATIC_ASSERT(MOZ_ARRAY_LENGTH(sSurfaceMemoryReporterAttrs) ==
size_t(gfxSurfaceType::Max));
-#ifdef CAIRO_HAS_D2D_SURFACE
-PR_STATIC_ASSERT(uint32_t(CAIRO_SURFACE_TYPE_D2D) ==
- uint32_t(gfxSurfaceType::D2D));
-#endif
PR_STATIC_ASSERT(uint32_t(CAIRO_SURFACE_TYPE_SKIA) ==
uint32_t(gfxSurfaceType::Skia));
/* Surface size memory reporting */
static int64_t gSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)] = { 0 };
class SurfaceMemoryReporter final : public nsIMemoryReporter
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -429,16 +429,21 @@ CreateBlurMask(const IntSize& aRectSize,
static already_AddRefed<SourceSurface>
CreateBoxShadow(DrawTarget& aDT, SourceSurface* aBlurMask, const gfxRGBA& aShadowColor)
{
IntSize blurredSize = aBlurMask->GetSize();
gfxPlatform* platform = gfxPlatform::GetPlatform();
RefPtr<DrawTarget> boxShadowDT =
platform->CreateOffscreenContentDrawTarget(blurredSize, SurfaceFormat::B8G8R8A8);
+
+ if (!boxShadowDT) {
+ return nullptr;
+ }
+
MOZ_ASSERT(boxShadowDT->GetType() == aDT.GetType());
ColorPattern shadowColor(ToDeviceColor(aShadowColor));
boxShadowDT->MaskSurface(shadowColor, aBlurMask, Point(0, 0));
return boxShadowDT->Snapshot();
}
SourceSurface*
@@ -470,16 +475,20 @@ GetBlur(DrawTarget& aDT,
RefPtr<SourceSurface> blurMask =
CreateBlurMask(aRectSize, aCornerRadii, aBlurRadius, aExtendDestBy, aSlice, aDT);
if (!blurMask) {
return nullptr;
}
RefPtr<SourceSurface> boxShadow = CreateBoxShadow(aDT, blurMask, aShadowColor);
+ if (!boxShadow) {
+ return nullptr;
+ }
+
CacheBlur(aDT, minSize, aBlurRadius, aCornerRadii, aShadowColor, aExtendDestBy, boxShadow);
return boxShadow;
}
void
gfxAlphaBoxBlur::ShutdownBlurCache()
{
delete gBlurCache;
deleted file mode 100644
--- a/gfx/thebes/gfxD2DSurface.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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 "gfxD2DSurface.h"
-#include "cairo.h"
-#include "cairo-win32.h"
-#include "gfxWindowsPlatform.h"
-
-gfxD2DSurface::gfxD2DSurface(HWND aWnd, gfxContentType aContent)
-{
- Init(cairo_d2d_surface_create_for_hwnd(
- gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
- aWnd,
- (cairo_content_t)(int)aContent));
-}
-
-gfxD2DSurface::gfxD2DSurface(HANDLE handle, gfxContentType aContent)
-{
- Init(cairo_d2d_surface_create_for_handle(
- gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
- handle,
- (cairo_content_t)(int)aContent));
-}
-
-gfxD2DSurface::gfxD2DSurface(ID3D10Texture2D *texture, gfxContentType aContent)
-{
- Init(cairo_d2d_surface_create_for_texture(
- gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
- texture,
- (cairo_content_t)(int)aContent));
-}
-
-gfxD2DSurface::gfxD2DSurface(cairo_surface_t *csurf)
-{
- Init(csurf, true);
-}
-
-gfxD2DSurface::gfxD2DSurface(const mozilla::gfx::IntSize& size,
- gfxImageFormat imageFormat)
-{
- Init(cairo_d2d_surface_create(
- gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
- (cairo_format_t)(int)imageFormat,
- size.width, size.height));
-}
-
-gfxD2DSurface::~gfxD2DSurface()
-{
-}
-
-void
-gfxD2DSurface::Present()
-{
- cairo_d2d_present_backbuffer(CairoSurface());
-}
-
-void
-gfxD2DSurface::Scroll(const nsIntPoint &aDelta, const mozilla::gfx::IntRect &aClip)
-{
- cairo_rectangle_t rect;
- rect.x = aClip.x;
- rect.y = aClip.y;
- rect.width = aClip.width;
- rect.height = aClip.height;
- cairo_d2d_scroll(CairoSurface(), aDelta.x, aDelta.y, &rect);
-}
-
-ID3D10Texture2D*
-gfxD2DSurface::GetTexture()
-{
- return cairo_d2d_surface_get_texture(CairoSurface());
-}
-
-HDC
-gfxD2DSurface::GetDC(bool aRetainContents)
-{
- return cairo_d2d_get_dc(CairoSurface(), aRetainContents);
-}
-
-void
-gfxD2DSurface::ReleaseDC(const mozilla::gfx::IntRect *aUpdatedRect)
-{
- if (!aUpdatedRect) {
- return cairo_d2d_release_dc(CairoSurface(), nullptr);
- }
-
- cairo_rectangle_int_t rect;
- rect.x = aUpdatedRect->x;
- rect.y = aUpdatedRect->y;
- rect.width = aUpdatedRect->width;
- rect.height = aUpdatedRect->height;
- cairo_d2d_release_dc(CairoSurface(), &rect);
-}
-
-const mozilla::gfx::IntSize gfxD2DSurface::GetSize() const
-{
- return mozilla::gfx::IntSize(cairo_d2d_surface_get_width(mSurface),
- cairo_d2d_surface_get_height(mSurface));
-}
\ No newline at end of file
deleted file mode 100644
--- a/gfx/thebes/gfxD2DSurface.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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 GFX_D2DSURFACE_H
-#define GFX_D2DSURFACE_H
-
-#include "gfxASurface.h"
-#include "nsPoint.h"
-
-#include <windows.h>
-
-struct ID3D10Texture2D;
-
-class gfxD2DSurface : public gfxASurface {
-public:
-
- gfxD2DSurface(HWND wnd,
- gfxContentType aContent);
-
- gfxD2DSurface(const mozilla::gfx::IntSize& size,
- gfxImageFormat imageFormat = gfxImageFormat::RGB24);
-
- gfxD2DSurface(HANDLE handle, gfxContentType aContent);
-
- gfxD2DSurface(ID3D10Texture2D *texture, gfxContentType aContent);
-
- gfxD2DSurface(cairo_surface_t *csurf);
-
- virtual ~gfxD2DSurface();
-
- void Present();
- void Scroll(const nsIntPoint &aDelta, const mozilla::gfx::IntRect &aClip);
-
- virtual const mozilla::gfx::IntSize GetSize() const;
-
- ID3D10Texture2D *GetTexture();
-
- HDC GetDC(bool aRetainContents);
- void ReleaseDC(const mozilla::gfx::IntRect *aUpdatedRect);
-};
-
-#endif /* GFX_D2DSURFACE_H */
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -26,17 +26,16 @@
#endif
#include "nsXULAppAPI.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#if defined(XP_WIN)
#include "gfxWindowsPlatform.h"
-#include "gfxD2DSurface.h"
#elif defined(XP_MACOSX)
#include "gfxPlatformMac.h"
#include "gfxQuartzSurface.h"
#elif defined(MOZ_WIDGET_GTK)
#include "gfxPlatformGtk.h"
#elif defined(MOZ_WIDGET_QT)
#include "gfxQtPlatform.h"
#elif defined(ANDROID)
@@ -907,31 +906,16 @@ gfxPlatform::GetSourceSurfaceForSurface(
// strong reference back to srcBuffer, creating a reference loop and a
// memory leak. Not caching is fine since wrapping is cheap enough (no
// copying) so we can just wrap again next time we're called.
return aTarget->CreateSourceSurfaceFromNativeSurface(surf);
}
RefPtr<SourceSurface> srcBuffer;
-#ifdef XP_WIN
- if (aSurface->GetType() == gfxSurfaceType::D2D &&
- format != SurfaceFormat::A8) {
- NativeSurface surf;
- surf.mFormat = format;
- surf.mType = NativeSurfaceType::D3D10_TEXTURE;
- surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
- surf.mSize = aSurface->GetSize();
- mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
- if (dt) {
- dt->Flush();
- }
- srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
- }
-#endif
// Currently no other DrawTarget types implement CreateSourceSurfaceFromNativeSurface
if (!srcBuffer) {
// If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
// the same data, then optimize it for aTarget:
RefPtr<DataSourceSurface> surf = GetWrappedDataSourceSurface(aSurface);
if (surf) {
srcBuffer = aTarget->OptimizeSourceSurface(surf);
--- a/gfx/thebes/gfxTypes.h
+++ b/gfx/thebes/gfxTypes.h
@@ -77,17 +77,16 @@ enum class gfxSurfaceType {
Recording,
VG,
GL,
DRM,
Tee,
XML,
Skia,
Subsurface,
- D2D,
Max
};
enum class gfxContentType {
COLOR = 0x1000,
ALPHA = 0x2000,
COLOR_ALPHA = 0x3000,
SENTINEL = 0xffff
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -50,18 +50,16 @@
#include "gfxTextRun.h"
#include "gfxUserFontSet.h"
#include "nsWindowsHelpers.h"
#include "gfx2DGlue.h"
#include <string>
#ifdef CAIRO_HAS_D2D_SURFACE
-#include "gfxD2DSurface.h"
-
#include <d3d10_1.h>
#include "mozilla/gfx/2D.h"
#include "nsMemory.h"
#endif
#include <d3d11.h>
@@ -111,48 +109,16 @@ DCFromDrawTarget::DCFromDrawTarget(DrawT
#ifdef CAIRO_HAS_D2D_SURFACE
static const char *kFeatureLevelPref =
"gfx.direct3d.last_used_feature_level_idx";
static const int kSupportedFeatureLevels[] =
{ D3D10_FEATURE_LEVEL_10_1, D3D10_FEATURE_LEVEL_10_0 };
-class GfxD2DSurfaceReporter final : public nsIMemoryReporter
-{
- ~GfxD2DSurfaceReporter() {}
-
-public:
- NS_DECL_ISUPPORTS
-
- NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
- nsISupports* aData, bool aAnonymize)
- {
- nsresult rv;
-
- int64_t amount = cairo_d2d_get_image_surface_cache_usage();
- rv = MOZ_COLLECT_REPORT(
- "gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES, amount,
- "Memory used by the Direct2D internal surface cache.");
- NS_ENSURE_SUCCESS(rv, rv);
-
- cairo_device_t *device =
- gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
- amount = device ? cairo_d2d_get_surface_vram_usage(device) : 0;
- rv = MOZ_COLLECT_REPORT(
- "gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES, amount,
- "Video memory used by D2D surfaces.");
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
- }
-};
-
-NS_IMPL_ISUPPORTS(GfxD2DSurfaceReporter, nsIMemoryReporter)
-
#endif
class GfxD2DVramReporter final : public nsIMemoryReporter
{
~GfxD2DVramReporter() {}
public:
NS_DECL_ISUPPORTS
@@ -416,20 +382,16 @@ gfxWindowsPlatform::gfxWindowsPlatform()
mUsingGDIFonts = false;
/*
* Initialize COM
*/
CoInitialize(nullptr);
-#ifdef CAIRO_HAS_D2D_SURFACE
- RegisterStrongMemoryReporter(new GfxD2DSurfaceReporter());
- mD2DDevice = nullptr;
-#endif
RegisterStrongMemoryReporter(new GfxD2DVramReporter());
if (gfxPrefs::Direct2DUse1_1()) {
InitD3D11Devices();
}
UpdateRenderMode();
@@ -438,28 +400,21 @@ gfxWindowsPlatform::gfxWindowsPlatform()
RegisterStrongMemoryReporter(new D3D9TextureReporter());
RegisterStrongMemoryReporter(new D3D9SurfaceImageReporter());
RegisterStrongMemoryReporter(new D3D9SharedTextureReporter());
}
gfxWindowsPlatform::~gfxWindowsPlatform()
{
mDeviceManager = nullptr;
+ mD3D10Device = nullptr;
mD3D11Device = nullptr;
mD3D11ContentDevice = nullptr;
mD3D11ImageBridgeDevice = nullptr;
- // not calling FT_Done_FreeType because cairo may still hold references to
- // these FT_Faces. See bug 458169.
-#ifdef CAIRO_HAS_D2D_SURFACE
- if (mD2DDevice) {
- cairo_release_device(mD2DDevice);
- }
-#endif
-
mozilla::gfx::Factory::D2DCleanup();
mAdapter = nullptr;
/*
* Uninitialize COM
*/
CoUninitialize();
@@ -543,22 +498,22 @@ gfxWindowsPlatform::UpdateRenderMode()
tryD2D = false;
}
ID3D11Device *device = GetD3D11Device();
if (isVistaOrHigher && !InSafeMode() && tryD2D && device &&
mDoesD3D11TextureSharingWork) {
VerifyD2DDevice(d2dForceEnabled);
- if (mD2DDevice && GetD3D11Device()) {
+ if (mD3D10Device && GetD3D11Device()) {
mRenderMode = RENDER_DIRECT2D;
mUseDirectWrite = true;
}
} else {
- mD2DDevice = nullptr;
+ mD3D10Device = nullptr;
}
#endif
#ifdef CAIRO_HAS_DWRITE_FONT
// Enable when it's preffed on -and- we're using Vista or higher. Or when
// we're going to use D2D.
if (!mDWriteFactory && (mUseDirectWrite && isVistaOrHigher)) {
mozilla::ScopedGfxFeatureReporter reporter("DWrite");
@@ -626,34 +581,37 @@ gfxWindowsPlatform::CreateDevice(nsRefPt
nsModuleHandle d3d10module(LoadLibrarySystem32(L"d3d10_1.dll"));
if (!d3d10module)
return E_FAIL;
decltype(D3D10CreateDevice1)* createD3DDevice =
(decltype(D3D10CreateDevice1)*) GetProcAddress(d3d10module, "D3D10CreateDevice1");
if (!createD3DDevice)
return E_FAIL;
- nsRefPtr<ID3D10Device1> device;
+ ID3D10Device1* device = nullptr;
HRESULT hr =
createD3DDevice(adapter1, D3D10_DRIVER_TYPE_HARDWARE, nullptr,
#ifdef DEBUG
// This isn't set because of bug 1078411
// D3D10_CREATE_DEVICE_DEBUG |
#endif
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
static_cast<D3D10_FEATURE_LEVEL1>(kSupportedFeatureLevels[featureLevelIndex]),
- D3D10_1_SDK_VERSION, getter_AddRefs(device));
+ D3D10_1_SDK_VERSION, &device);
// If we fail here, the DirectX version or video card probably
// changed. We previously could use 10.1 but now we can't
// anymore. Revert back to doing a 10.0 check first before
// the 10.1 check.
if (device) {
- mD2DDevice = cairo_d2d_create_device_from_d3d10device(device);
+ mD3D10Device = device;
+
+ // Leak the module while the D3D 10 device is being used.
+ d3d10module.disown();
// Setup a pref for future launch optimizaitons when in main process.
if (XRE_IsParentProcess()) {
Preferences::SetInt(kFeatureLevelPref, featureLevelIndex);
}
}
return device ? S_OK : hr;
@@ -664,33 +622,29 @@ void
gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
{
#ifdef CAIRO_HAS_D2D_SURFACE
DriverInitCrashDetection detectCrashes;
if (detectCrashes.DisableAcceleration()) {
return;
}
- if (mD2DDevice) {
- ID3D10Device1 *device = cairo_d2d_device_get_device(mD2DDevice);
-
- if (SUCCEEDED(device->GetDeviceRemovedReason())) {
+ if (mD3D10Device) {
+ if (SUCCEEDED(mD3D10Device->GetDeviceRemovedReason())) {
return;
}
- mD2DDevice = nullptr;
+ mD3D10Device = nullptr;
// Surface cache needs to be invalidated since it may contain vector
// images rendered with our old, broken D2D device.
SurfaceCache::DiscardAll();
}
mozilla::ScopedGfxFeatureReporter reporter("D2D", aAttemptForce);
- nsRefPtr<ID3D10Device1> device;
-
int supportedFeatureLevelsCount = ArrayLength(kSupportedFeatureLevels);
nsRefPtr<IDXGIAdapter1> adapter1 = GetDXGIAdapter();
if (!adapter1) {
// Unable to create adapter, abort acceleration.
return;
}
@@ -719,23 +673,19 @@ gfxWindowsPlatform::VerifyD2DDevice(bool
hr = CreateDevice(adapter1, i);
// If it failed then we don't have new hardware
if (FAILED(hr)) {
break;
}
}
}
- if (!mD2DDevice && aAttemptForce) {
- mD2DDevice = cairo_d2d_create_device();
- }
-
- if (mD2DDevice) {
+ if (mD3D10Device) {
reporter.SetSuccessful();
- mozilla::gfx::Factory::SetDirect3D10Device(cairo_d2d_device_get_device(mD2DDevice));
+ mozilla::gfx::Factory::SetDirect3D10Device(mD3D10Device);
}
ScopedGfxFeatureReporter reporter1_1("D2D1.1");
if (Factory::SupportsD2D1()) {
reporter1_1.SetSuccessful();
}
#endif
@@ -774,27 +724,21 @@ gfxWindowsPlatform::CreatePlatformFontLi
already_AddRefed<gfxASurface>
gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& size,
gfxContentType contentType)
{
nsRefPtr<gfxASurface> surf = nullptr;
#ifdef CAIRO_HAS_WIN32_SURFACE
- if (mRenderMode == RENDER_GDI)
+ if (mRenderMode == RENDER_GDI || mRenderMode == RENDER_DIRECT2D)
surf = new gfxWindowsSurface(size,
OptimalFormatForContent(contentType));
#endif
-#ifdef CAIRO_HAS_D2D_SURFACE
- if (mRenderMode == RENDER_DIRECT2D)
- surf = new gfxD2DSurface(size,
- OptimalFormatForContent(contentType));
-#endif
-
if (!surf || surf->CairoStatus()) {
surf = new gfxImageSurface(size,
OptimalFormatForContent(contentType));
}
return surf.forget();
}
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -235,20 +235,17 @@ public:
IDWriteRenderingParams *GetRenderingParams(TextRenderingMode aRenderMode)
{ return mRenderingParams[aRenderMode]; }
#else
inline bool DWriteEnabled() { return false; }
#endif
void OnDeviceManagerDestroy(mozilla::layers::DeviceManagerD3D9* aDeviceManager);
mozilla::layers::DeviceManagerD3D9* GetD3D9DeviceManager();
IDirect3DDevice9* GetD3D9Device();
-#ifdef CAIRO_HAS_D2D_SURFACE
- cairo_device_t *GetD2DDevice() { return mD2DDevice; }
- ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; }
-#endif
+ ID3D10Device1 *GetD3D10Device() { return mD3D10Device; }
ID3D11Device *GetD3D11Device();
ID3D11Device *GetD3D11ContentDevice();
// Device to be used on the ImageBridge thread
ID3D11Device *GetD3D11ImageBridgeDevice();
// Create a D3D11 device to be used for DXVA decoding.
already_AddRefed<ID3D11Device> CreateD3D11DecoderDevice();
@@ -286,21 +283,19 @@ private:
bool mUsingGDIFonts;
#ifdef CAIRO_HAS_DWRITE_FONT
nsRefPtr<IDWriteFactory> mDWriteFactory;
nsRefPtr<IDWriteTextAnalyzer> mDWriteAnalyzer;
nsRefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];
DWRITE_MEASURING_MODE mMeasuringMode;
#endif
-#ifdef CAIRO_HAS_D2D_SURFACE
- cairo_device_t *mD2DDevice;
-#endif
mozilla::RefPtr<IDXGIAdapter1> mAdapter;
nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
+ mozilla::RefPtr<ID3D10Device1> mD3D10Device;
mozilla::RefPtr<ID3D11Device> mD3D11Device;
mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
mozilla::RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
bool mD3D11DeviceInitialized;
mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
bool mIsWARP;
bool mHasDeviceReset;
bool mDoesD3D11TextureSharingWork;
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -157,17 +157,16 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt
]
SOURCES += [
'gfxQtNativeRenderer.cpp',
'gfxXlibSurface.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += [
- 'gfxD2DSurface.h',
'gfxDWriteFonts.h',
'gfxGDIFont.h',
'gfxGDIFontList.h',
'gfxPDFSurface.h',
'gfxPlatformFontList.h',
'gfxWindowsNativeDrawing.h',
'gfxWindowsPlatform.h',
'gfxWindowsSurface.h',
@@ -180,17 +179,16 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wi
'gfxWindowsPlatform.cpp',
'gfxWindowsSurface.cpp',
]
if CONFIG['MOZ_ENABLE_DWRITE_FONT']:
UNIFIED_SOURCES += [
'gfxDWriteFontList.cpp',
]
SOURCES += [
- 'gfxD2DSurface.cpp',
'gfxDWriteCommon.cpp',
'gfxDWriteFonts.cpp',
]
# Are we targeting x86 or x64? If so, build gfxAlphaRecoverySSE2.cpp.
if CONFIG['INTEL_ARCHITECTURE']:
SOURCES += ['gfxAlphaRecoverySSE2.cpp']
# The file uses SSE2 intrinsics, so it needs special compile flags on some
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -187,17 +187,17 @@ class JS_PUBLIC_API(JSAutoStructuredClon
JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other);
JSAutoStructuredCloneBuffer& operator=(JSAutoStructuredCloneBuffer&& other);
~JSAutoStructuredCloneBuffer() { clear(); }
uint64_t* data() const { return data_; }
size_t nbytes() const { return nbytes_; }
- void clear();
+ void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
// Copy some memory. It will be automatically freed by the destructor.
bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
// Adopt some memory. It will be automatically freed by the destructor.
// data must have been allocated by the JS engine (e.g., extracted via
// JSAutoStructuredCloneBuffer::steal).
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -10306,18 +10306,20 @@ IonBuilder::getPropTryConstant(bool* emi
if (!types->mightBeMIRType(MIRType_Object)) {
// If we have not observed an object result here, don't look for a
// singleton constant.
trackOptimizationOutcome(TrackedOutcome::NotObject);
return true;
}
JSObject* singleton = testSingletonPropertyTypes(obj, name);
- if (!singleton)
- return true;
+ if (!singleton) {
+ trackOptimizationOutcome(TrackedOutcome::NotSingleton);
+ return true;
+ }
// Property access is a known constant -- safe to emit.
obj->setImplicitlyUsedUnchecked();
pushConstant(ObjectValue(*singleton));
trackOptimizationSuccess();
*emitted = true;
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -54,17 +54,17 @@ MacroAssembler::PushWithPatch(ImmWord wo
CodeOffsetLabel
MacroAssembler::PushWithPatch(ImmPtr imm)
{
return PushWithPatch(ImmWord(uintptr_t(imm.value)));
}
// ===============================================================
-// Call functions.
+// Simple call functions.
void
MacroAssembler::call(const CallSiteDesc& desc, const Register reg)
{
call(reg);
append(desc, currentOffset(), framePushed());
}
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -345,19 +345,27 @@ class MacroAssembler : public MacroAssem
void reserveStack(uint32_t amount) PER_ARCH;
void freeStack(uint32_t amount);
// Warning: This method does not update the framePushed() counter.
void freeStack(Register amount);
public:
// ===============================================================
- // Call functions.
+ // Simple call functions.
- using MacroAssemblerSpecific::call; // legacy
+ void call(Register reg) PER_ARCH;
+ void call(const Address& addr) PER_ARCH ONLY_X86_X64;
+ void call(Label* label) PER_ARCH;
+ void call(ImmWord imm) PER_ARCH;
+ // Call a target native function, which is neither traceable nor movable.
+ void call(ImmPtr imm) PER_ARCH;
+ void call(AsmJSImmPtr imm) PER_ARCH;
+ // Call a target JitCode, which must be traceable, and may be movable.
+ void call(JitCode* c) PER_ARCH;
inline void call(const CallSiteDesc& desc, const Register reg);
inline void call(const CallSiteDesc& desc, Label* label);
public:
// Emits a test of a value against all types in a TypeSet. A scratch
// register is required.
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -1633,19 +1633,16 @@ class Assembler : public AssemblerShared
void Bind(uint8_t* rawCode, AbsoluteLabel* label, const void* address);
// See Bind
size_t labelOffsetToPatchOffset(size_t offset) {
return actualOffset(offset);
}
- void call(Label* label);
- void call(void* target);
-
void as_bkpt();
public:
static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
static bool SupportsFloatingPoint() {
return HasVFP();
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4117,41 +4117,41 @@ MacroAssemblerARMCompat::callWithABI(voi
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerARMCompat::callWithABI(AsmJSImmPtr imm, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust, /* callFromAsmJS = */ true);
- call(imm);
+ asMasm().call(imm);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerARMCompat::callWithABI(const Address& fun, MoveOp::Type result)
{
// Load the callee in r12, no instruction between the ldr and call should
// clobber it. Note that we can't use fun.base because it may be one of the
// IntArg registers clobbered before the call.
ma_ldr(fun, r12);
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(r12);
+ asMasm().call(r12);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerARMCompat::callWithABI(Register fun, MoveOp::Type result)
{
// Load the callee in r12, as above.
ma_mov(fun, r12);
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(r12);
+ asMasm().call(r12);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerARMCompat::handleFailureWithHandlerTail(void* handler)
{
// Reserve space for exception information.
int size = (sizeof(ResumeFromException) + 7) & ~7;
@@ -5085,16 +5085,24 @@ MacroAssemblerARMCompat::profilerEnterFr
}
void
MacroAssemblerARMCompat::profilerExitFrame()
{
branch(GetJitContext()->runtime->jitRuntime()->getProfilerExitFrameTail());
}
+void
+MacroAssemblerARMCompat::callAndPushReturnAddress(Label* label)
+{
+ AutoForbidPools afp(this, 2);
+ ma_push(pc);
+ asMasm().call(label);
+}
+
MacroAssembler&
MacroAssemblerARMCompat::asMasm()
{
return *static_cast<MacroAssembler*>(this);
}
const MacroAssembler&
MacroAssemblerARMCompat::asMasm() const
@@ -5235,8 +5243,60 @@ MacroAssembler::Pop(const ValueOperand&
void
MacroAssembler::reserveStack(uint32_t amount)
{
if (amount)
ma_sub(Imm32(amount), sp);
adjustFrame(amount);
}
+
+// ===============================================================
+// Simple call functions.
+
+void
+MacroAssembler::call(Register reg)
+{
+ as_blx(reg);
+}
+
+void
+MacroAssembler::call(Label* label)
+{
+ // For now, assume that it'll be nearby?
+ as_bl(label, Always);
+}
+
+void
+MacroAssembler::call(ImmWord imm)
+{
+ call(ImmPtr((void*)imm.value));
+}
+
+void
+MacroAssembler::call(ImmPtr imm)
+{
+ BufferOffset bo = m_buffer.nextOffset();
+ addPendingJump(bo, imm, Relocation::HARDCODED);
+ ma_call(imm);
+}
+
+void
+MacroAssembler::call(AsmJSImmPtr imm)
+{
+ movePtr(imm, CallReg);
+ call(CallReg);
+}
+
+void
+MacroAssembler::call(JitCode* c)
+{
+ BufferOffset bo = m_buffer.nextOffset();
+ addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
+ RelocStyle rs;
+ if (HasMOVWT())
+ rs = L_MOVWT;
+ else
+ rs = L_LDR;
+
+ ma_movPatchable(ImmPtr(c->raw()), ScratchRegister, Always, rs);
+ ma_callJitHalfPush(ScratchRegister);
+}
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -533,17 +533,16 @@ class MacroAssemblerARMCompat : public M
MoveResolver moveResolver_;
public:
MacroAssemblerARMCompat()
: inCall_(false)
{ }
public:
- using MacroAssemblerARM::call;
// Jumps + other functions that should be called from non-arm specific
// code. Basically, an x86 front end on top of the ARM code.
void j(Condition code , Label* dest)
{
as_b(dest, code);
}
void j(Label* dest)
@@ -562,52 +561,17 @@ class MacroAssemblerARMCompat : public M
}
void mov(Register src, Address dest) {
MOZ_CRASH("NYI-IC");
}
void mov(Address src, Register dest) {
MOZ_CRASH("NYI-IC");
}
- void call(const Register reg) {
- as_blx(reg);
- }
- void call(Label* label) {
- // For now, assume that it'll be nearby?
- as_bl(label, Always);
- }
- void call(ImmWord imm) {
- call(ImmPtr((void*)imm.value));
- }
- void call(ImmPtr imm) {
- BufferOffset bo = m_buffer.nextOffset();
- addPendingJump(bo, imm, Relocation::HARDCODED);
- ma_call(imm);
- }
- void call(AsmJSImmPtr imm) {
- movePtr(imm, CallReg);
- call(CallReg);
- }
- void call(JitCode* c) {
- BufferOffset bo = m_buffer.nextOffset();
- addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
- RelocStyle rs;
- if (HasMOVWT())
- rs = L_MOVWT;
- else
- rs = L_LDR;
-
- ma_movPatchable(ImmPtr(c->raw()), ScratchRegister, Always, rs);
- ma_callJitHalfPush(ScratchRegister);
- }
- void callAndPushReturnAddress(Label* label) {
- AutoForbidPools afp(this, 2);
- ma_push(pc);
- call(label);
- }
+ void callAndPushReturnAddress(Label* label);
void branch(JitCode* c) {
BufferOffset bo = m_buffer.nextOffset();
addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
RelocStyle rs;
if (HasMOVWT())
rs = L_MOVWT;
else
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -51,21 +51,38 @@ MacroAssemblerCompat::buildFakeExitFrame
leaveNoPool();
MOZ_ASSERT(framePushed() == initialDepth + ExitFrameLayout::Size());
*offset = pseudoReturnOffset;
}
void
+MacroAssemblerCompat::callWithExitFrame(Label* target)
+{
+ uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
+ Push(Imm32(descriptor)); // descriptor
+ asMasm().call(target);
+}
+
+void
MacroAssemblerCompat::callWithExitFrame(JitCode* target)
{
uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
asMasm().Push(Imm32(descriptor));
- call(target);
+ asMasm().call(target);
+}
+
+void
+MacroAssemblerCompat::callWithExitFrame(JitCode* target, Register dynStack)
+{
+ add32(Imm32(framePushed()), dynStack);
+ makeFrameDescriptor(dynStack, JitFrame_IonJS);
+ Push(dynStack); // descriptor
+ asMasm().call(target);
}
void
MacroAssembler::alignFrameForICArguments(MacroAssembler::AfterICSaveLive& aic)
{
// Exists for MIPS compatibility.
}
@@ -436,48 +453,48 @@ MacroAssemblerCompat::callWithABI(void*
AssertValidABIFunctionType(passedArgTypes_);
# endif
ABIFunctionType type = ABIFunctionType(passedArgTypes_);
fun = vixl::Simulator::RedirectNativeFunction(fun, type);
#endif // JS_SIMULATOR_ARM64
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(ImmPtr(fun));
+ asMasm().call(ImmPtr(fun));
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerCompat::callWithABI(Register fun, MoveOp::Type result)
{
movePtr(fun, ip0);
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(ip0);
+ asMasm().call(ip0);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerCompat::callWithABI(AsmJSImmPtr imm, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(imm);
+ asMasm().call(imm);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerCompat::callWithABI(Address fun, MoveOp::Type result)
{
loadPtr(fun, ip0);
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(ip0);
+ asMasm().call(ip0);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerCompat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
@@ -679,10 +696,62 @@ MacroAssembler::Pop(const Register reg)
void
MacroAssembler::Pop(const ValueOperand& val)
{
pop(val);
adjustFrame(-1 * int64_t(sizeof(int64_t)));
}
+// ===============================================================
+// Simple call functions.
+
+void
+MacroAssembler::call(Register reg)
+{
+ syncStackPtr();
+ Blr(ARMRegister(reg, 64));
+}
+
+void
+MacroAssembler::call(Label* label)
+{
+ syncStackPtr();
+ Bl(label);
+}
+
+void
+MacroAssembler::call(ImmWord imm)
+{
+ call(ImmPtr((void*)imm.value));
+}
+
+void
+MacroAssembler::call(ImmPtr imm)
+{
+ syncStackPtr();
+ movePtr(imm, ip0);
+ Blr(vixl::ip0);
+}
+
+void
+MacroAssembler::call(AsmJSImmPtr imm)
+{
+ vixl::UseScratchRegisterScope temps(this);
+ const Register scratch = temps.AcquireX().asUnsized();
+ syncStackPtr();
+ movePtr(imm, scratch);
+ call(scratch);
+}
+
+void
+MacroAssembler::call(JitCode* c)
+{
+ vixl::UseScratchRegisterScope temps(this);
+ const ARMRegister scratch64 = temps.AcquireX();
+ syncStackPtr();
+ BufferOffset off = immPool64(scratch64, uint64_t(c->raw()));
+ addPendingJump(off, ImmPtr(c->raw()), Relocation::JITCODE);
+ blr(scratch64);
+}
+
} // namespace jit
} // namespace js
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -2701,24 +2701,16 @@ class MacroAssemblerCompat : public vixl
void handleFailureWithHandlerTail(void* handler);
// FIXME: This is the same on all platforms. Can be common code?
void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
lshiftPtr(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
orPtr(Imm32(type), frameSizeReg);
}
- void callWithExitFrame(JitCode* target, Register dynStack) {
- add32(Imm32(framePushed()), dynStack);
- makeFrameDescriptor(dynStack, JitFrame_IonJS);
- Push(dynStack); // descriptor
-
- call(target);
- }
-
// FIXME: See CodeGeneratorX64 calls to noteAsmJSGlobalAccess.
void patchAsmJSGlobalAccess(CodeOffsetLabel patchAt, uint8_t* code,
uint8_t* globalData, unsigned globalDataOffset)
{
MOZ_CRASH("patchAsmJSGlobalAccess");
}
void memIntToValue(const Address& src, const Address& dest) {
@@ -2732,82 +2724,30 @@ class MacroAssemblerCompat : public vixl
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label);
// Builds an exit frame on the stack, with a return address to an internal
// non-function. Returns offset to be passed to markSafepointAt().
void buildFakeExitFrame(Register scratch, uint32_t* offset);
- void callWithExitFrame(Label* target) {
- uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
- Push(Imm32(descriptor)); // descriptor
-
- call(target);
- }
-
+ void callWithExitFrame(Label* target);
void callWithExitFrame(JitCode* target);
+ void callWithExitFrame(JitCode* target, Register dynStack);
void callJit(Register callee) {
// AArch64 cannot read from the PC, so pushing must be handled callee-side.
syncStackPtr();
Blr(ARMRegister(callee, 64));
}
void appendCallSite(const CallSiteDesc& desc) {
MOZ_CRASH("appendCallSite");
}
- void call(const CallSiteDesc& desc, Label* label) {
- syncStackPtr();
- call(label);
- append(desc, currentOffset(), framePushed_);
- }
- void call(const CallSiteDesc& desc, Register reg) {
- syncStackPtr();
- call(reg);
- append(desc, currentOffset(), framePushed_);
- }
- void call(const CallSiteDesc& desc, AsmJSImmPtr imm) {
- syncStackPtr();
- call(imm);
- append(desc, currentOffset(), framePushed_);
- }
-
- void call(AsmJSImmPtr imm) {
- vixl::UseScratchRegisterScope temps(this);
- const Register scratch = temps.AcquireX().asUnsized();
- syncStackPtr();
- movePtr(imm, scratch);
- call(scratch);
- }
-
- void call(Register target) {
- syncStackPtr();
- Blr(ARMRegister(target, 64));
- }
- // Call a target JitCode, which must be traceable, and may be movable.
- void call(JitCode* target) {
- vixl::UseScratchRegisterScope temps(this);
- const ARMRegister scratch64 = temps.AcquireX();
- syncStackPtr();
- BufferOffset off = immPool64(scratch64, uint64_t(target->raw()));
- addPendingJump(off, ImmPtr(target->raw()), Relocation::JITCODE);
- blr(scratch64);
- }
- // Call a target native function, which is neither traceable nor movable.
- void call(ImmPtr target) {
- syncStackPtr();
- movePtr(target, ip0);
- Blr(vixl::ip0);
- }
- void call(Label* target) {
- syncStackPtr();
- Bl(target);
- }
void callExit(AsmJSImmPtr imm, uint32_t stackArgBytes) {
MOZ_CRASH("callExit");
}
void callJitFromAsmJS(Register reg) {
Blr(ARMRegister(reg, 64));
}
--- a/js/src/jit/mips/MacroAssembler-mips.cpp
+++ b/js/src/jit/mips/MacroAssembler-mips.cpp
@@ -3440,42 +3440,42 @@ MacroAssemblerMIPSCompat::callWithABI(vo
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerMIPSCompat::callWithABI(AsmJSImmPtr imm, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust, /* callFromAsmJS = */ true);
- call(imm);
+ asMasm().call(imm);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerMIPSCompat::callWithABI(const Address& fun, MoveOp::Type result)
{
// Load the callee in t9, no instruction between the lw and call
// should clobber it. Note that we can't use fun.base because it may
// be one of the IntArg registers clobbered before the call.
ma_lw(t9, Address(fun.base, fun.offset));
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(t9);
+ asMasm().call(t9);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerMIPSCompat::callWithABI(Register fun, MoveOp::Type result)
{
// Load the callee in t9, as above.
ma_move(t9, fun);
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(t9);
+ asMasm().call(t9);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerMIPSCompat::handleFailureWithHandlerTail(void* handler)
{
// Reserve space for exception information.
int size = (sizeof(ResumeFromException) + ABIStackAlignment) & ~(ABIStackAlignment - 1);
@@ -3771,8 +3771,54 @@ MacroAssembler::Pop(const ValueOperand&
void
MacroAssembler::reserveStack(uint32_t amount)
{
if (amount)
ma_subu(StackPointer, StackPointer, Imm32(amount));
adjustFrame(amount);
}
+
+// ===============================================================
+// Simple call functions.
+
+void
+MacroAssembler::call(Register reg)
+{
+ as_jalr(reg);
+ as_nop();
+}
+
+void
+MacroAssembler::call(Label* label)
+{
+ ma_bal(label);
+}
+
+void
+MacroAssembler::call(AsmJSImmPtr target)
+{
+ movePtr(target, CallReg);
+ call(CallReg);
+}
+
+void
+MacroAssembler::call(ImmWord target)
+{
+ call(ImmPtr((void*)target.value));
+}
+
+void
+MacroAssembler::call(ImmPtr target)
+{
+ BufferOffset bo = m_buffer.nextOffset();
+ addPendingJump(bo, target, Relocation::HARDCODED);
+ ma_call(target);
+}
+
+void
+MacroAssembler::call(JitCode* c)
+{
+ BufferOffset bo = m_buffer.nextOffset();
+ addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
+ ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw()));
+ ma_callJitHalfPush(ScratchRegister);
+}
--- a/js/src/jit/mips/MacroAssembler-mips.h
+++ b/js/src/jit/mips/MacroAssembler-mips.h
@@ -400,44 +400,16 @@ class MacroAssemblerMIPSCompat : public
}
void mov(Register src, Address dest) {
MOZ_CRASH("NYI-IC");
}
void mov(Address src, Register dest) {
MOZ_CRASH("NYI-IC");
}
- void call(const Register reg) {
- as_jalr(reg);
- as_nop();
- }
-
- void call(Label* label) {
- ma_bal(label);
- }
-
- void call(ImmWord imm) {
- call(ImmPtr((void*)imm.value));
- }
- void call(ImmPtr imm) {
- BufferOffset bo = m_buffer.nextOffset();
- addPendingJump(bo, imm, Relocation::HARDCODED);
- ma_call(imm);
- }
- void call(AsmJSImmPtr imm) {
- movePtr(imm, CallReg);
- call(CallReg);
- }
- void call(JitCode* c) {
- BufferOffset bo = m_buffer.nextOffset();
- addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
- ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw()));
- ma_callJitHalfPush(ScratchRegister);
- }
-
void callAndPushReturnAddress(Label* label) {
ma_callJitHalfPush(label);
}
void branch(JitCode* c) {
BufferOffset bo = m_buffer.nextOffset();
addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw()));
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -318,26 +318,26 @@ MacroAssemblerX64::callWithABIPost(uint3
inCall_ = false;
}
void
MacroAssemblerX64::callWithABI(void* fun, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(ImmPtr(fun));
+ asMasm().call(ImmPtr(fun));
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX64::callWithABI(AsmJSImmPtr imm, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(imm);
+ asMasm().call(imm);
callWithABIPost(stackAdjust, result);
}
static bool
IsIntArgReg(Register reg)
{
for (uint32_t i = 0; i < NumIntArgRegs; i++) {
if (IntArgRegs[i] == reg)
@@ -356,17 +356,17 @@ MacroAssemblerX64::callWithABI(Address f
moveResolver_.addMove(MoveOperand(fun.base), MoveOperand(r10), MoveOp::GENERAL);
fun.base = r10;
}
MOZ_ASSERT(!IsIntArgReg(fun.base));
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(Operand(fun));
+ asMasm().call(fun);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX64::callWithABI(Register fun, MoveOp::Type result)
{
if (IsIntArgReg(fun)) {
// Callee register may be clobbered for an argument. Move the callee to
@@ -374,17 +374,17 @@ MacroAssemblerX64::callWithABI(Register
moveResolver_.addMove(MoveOperand(fun), MoveOperand(r10), MoveOp::GENERAL);
fun = r10;
}
MOZ_ASSERT(!IsIntArgReg(fun));
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(Operand(fun));
+ asMasm().call(fun);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX64::handleFailureWithHandlerTail(void* handler)
{
// Reserve space for exception information.
subq(Imm32(sizeof(ResumeFromException)), rsp);
@@ -508,17 +508,17 @@ MacroAssemblerX64::storeUnboxedValue(Con
MIRType slotType);
void
MacroAssemblerX64::callWithExitFrame(JitCode* target, Register dynStack)
{
addPtr(Imm32(asMasm().framePushed()), dynStack);
makeFrameDescriptor(dynStack, JitFrame_IonJS);
asMasm().Push(dynStack);
- call(target);
+ asMasm().call(target);
}
void
MacroAssemblerX64::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != ScratchReg);
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -84,17 +84,16 @@ class MacroAssemblerX64 : public MacroAs
SimdMap simdMap_;
void setupABICall(uint32_t arg);
protected:
MoveResolver moveResolver_;
public:
- using MacroAssemblerX86Shared::call;
using MacroAssemblerX86Shared::callWithExitFrame;
using MacroAssemblerX86Shared::branch32;
using MacroAssemblerX86Shared::branchTest32;
using MacroAssemblerX86Shared::load32;
using MacroAssemblerX86Shared::store32;
MacroAssemblerX64()
: inCall_(false)
@@ -103,23 +102,16 @@ class MacroAssemblerX64 : public MacroAs
// The buffer is about to be linked, make sure any constant pools or excess
// bookkeeping has been flushed to the instruction stream.
void finish();
/////////////////////////////////////////////////////////////////
// X64 helpers.
/////////////////////////////////////////////////////////////////
- void call(ImmWord target) {
- mov(target, rax);
- call(rax);
- }
- void call(ImmPtr target) {
- call(ImmWord(uintptr_t(target.value)));
- }
void writeDataRelocation(const Value& val) {
if (val.isMarkable()) {
gc::Cell* cell = reinterpret_cast<gc::Cell*>(val.toGCThing());
if (cell && gc::IsInsideNursery(cell))
embedsNurseryPointers_ = true;
dataRelocations_.writeUnsigned(masm.currentOffset());
}
}
--- a/js/src/jit/x64/SharedICHelpers-x64.h
+++ b/js/src/jit/x64/SharedICHelpers-x64.h
@@ -37,17 +37,17 @@ EmitCallIC(CodeOffsetLabel* patchOffset,
CodeOffsetLabel offset = masm.movWithPatch(ImmWord(-1), ICStubReg);
*patchOffset = offset;
// Load stub pointer into ICStubReg
masm.loadPtr(Address(ICStubReg, (int32_t) ICEntry::offsetOfFirstStub()),
ICStubReg);
// Call the stubcode.
- masm.call(Operand(ICStubReg, ICStub::offsetOfStubCode()));
+ masm.call(Address(ICStubReg, ICStub::offsetOfStubCode()));
}
inline void
EmitEnterTypeMonitorIC(MacroAssembler& masm,
size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
{
// This is expected to be called from within an IC, when ICStubReg
// is properly initialized to point to the stub.
@@ -225,17 +225,17 @@ EmitCallTypeUpdateIC(MacroAssembler& mas
masm.push(ICStubReg);
// This is expected to be called from within an IC, when ICStubReg
// is properly initialized to point to the stub.
masm.loadPtr(Address(ICStubReg, (int32_t) ICUpdatedStub::offsetOfFirstUpdateStub()),
ICStubReg);
// Call the stubcode.
- masm.call(Operand(ICStubReg, ICStub::offsetOfStubCode()));
+ masm.call(Address(ICStubReg, ICStub::offsetOfStubCode()));
// Restore the old stub reg.
masm.pop(ICStubReg);
// The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
// value in R0 type-checked properly or not.
Label success;
masm.cmp32(R1.scratchReg(), Imm32(1));
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -160,16 +160,34 @@ MacroAssemblerX86Shared::branchNegativeZ
Register scratch,
Label* label)
{
vmovd(reg, scratch);
cmp32(scratch, Imm32(1));
j(Overflow, label);
}
+void
+MacroAssemblerX86Shared::callJit(Register callee)
+{
+ call(callee);
+}
+
+void
+MacroAssemblerX86Shared::callJitFromAsmJS(Register callee)
+{
+ call(callee);
+}
+
+void
+MacroAssemblerX86Shared::callAndPushReturnAddress(Label* label)
+{
+ call(label);
+}
+
MacroAssembler&
MacroAssemblerX86Shared::asMasm()
{
return *static_cast<MacroAssembler*>(this);
}
const MacroAssembler&
MacroAssemblerX86Shared::asMasm() const
@@ -345,8 +363,55 @@ MacroAssembler::Pop(FloatRegister reg)
}
void
MacroAssembler::Pop(const ValueOperand& val)
{
popValue(val);
framePushed_ -= sizeof(Value);
}
+
+// ===============================================================
+// Simple call functions.
+
+void
+MacroAssembler::call(Register reg)
+{
+ Assembler::call(reg);
+}
+
+void
+MacroAssembler::call(Label* label)
+{
+ Assembler::call(label);
+}
+
+void
+MacroAssembler::call(const Address& addr)
+{
+ Assembler::call(Operand(addr.base, addr.offset));
+}
+
+void
+MacroAssembler::call(AsmJSImmPtr target)
+{
+ mov(target, eax);
+ Assembler::call(eax);
+}
+
+void
+MacroAssembler::call(ImmWord target)
+{
+ mov(target, eax);
+ Assembler::call(eax);
+}
+
+void
+MacroAssembler::call(ImmPtr target)
+{
+ call(ImmWord(uintptr_t(target.value)));
+}
+
+void
+MacroAssembler::call(JitCode* target)
+{
+ Assembler::call(target);
+}
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
@@ -1428,29 +1428,19 @@ class MacroAssemblerX86Shared : public A
}
// Builds an exit frame on the stack, with a return address to an internal
// non-function. Returns offset to be passed to markSafepointAt().
void buildFakeExitFrame(Register scratch, uint32_t* offset);
void callWithExitFrame(Label* target);
void callWithExitFrame(JitCode* target);
- void callJit(Register callee) {
- call(callee);
- }
- void callJitFromAsmJS(Register callee) {
- call(callee);
- }
- void call(AsmJSImmPtr target) {
- mov(target, eax);
- call(eax);
- }
- void callAndPushReturnAddress(Label* label) {
- call(label);
- }
+ void callJit(Register callee);
+ void callJitFromAsmJS(Register callee);
+ void callAndPushReturnAddress(Label* label);
void checkStackAlignment() {
// Exists for ARM compatibility.
}
CodeOffsetLabel labelForPatch() {
return CodeOffsetLabel(size());
}
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -323,44 +323,44 @@ MacroAssemblerX86::callWithABIPost(uint3
inCall_ = false;
}
void
MacroAssemblerX86::callWithABI(void* fun, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(ImmPtr(fun));
+ asMasm().call(ImmPtr(fun));
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX86::callWithABI(AsmJSImmPtr fun, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(fun);
+ asMasm().call(fun);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX86::callWithABI(const Address& fun, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(Operand(fun));
+ asMasm().call(fun);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX86::callWithABI(Register fun, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
- call(Operand(fun));
+ asMasm().call(fun);
callWithABIPost(stackAdjust, result);
}
void
MacroAssemblerX86::handleFailureWithHandlerTail(void* handler)
{
// Reserve space for exception information.
subl(Imm32(sizeof(ResumeFromException)), esp);
@@ -501,17 +501,17 @@ MacroAssemblerX86::storeUnboxedValue(Con
MIRType slotType);
void
MacroAssemblerX86::callWithExitFrame(JitCode* target, Register dynStack)
{
addPtr(ImmWord(asMasm().framePushed()), dynStack);
makeFrameDescriptor(dynStack, JitFrame_IonJS);
asMasm().Push(dynStack);
- call(target);
+ asMasm().call(target);
}
void
MacroAssemblerX86::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label* label)
{
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
--- a/js/src/jit/x86/SharedICHelpers-x86.h
+++ b/js/src/jit/x86/SharedICHelpers-x86.h
@@ -38,17 +38,17 @@ EmitCallIC(CodeOffsetLabel* patchOffset,
*patchOffset = offset;
// Load stub pointer into ICStubReg
masm.loadPtr(Address(ICStubReg, (int32_t) ICEntry::offsetOfFirstStub()),
ICStubReg);
// Load stubcode pointer from BaselineStubEntry into ICTailCallReg
// ICTailCallReg will always be unused in the contexts where ICs are called.
- masm.call(Operand(ICStubReg, ICStub::offsetOfStubCode()));
+ masm.call(Address(ICStubReg, ICStub::offsetOfStubCode()));
}
inline void
EmitEnterTypeMonitorIC(MacroAssembler& masm,
size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
{
// This is expected to be called from within an IC, when ICStubReg
// is properly initialized to point to the stub.
@@ -231,17 +231,17 @@ EmitCallTypeUpdateIC(MacroAssembler& mas
masm.push(ICStubReg);
// This is expected to be called from within an IC, when ICStubReg
// is properly initialized to point to the stub.
masm.loadPtr(Address(ICStubReg, (int32_t) ICUpdatedStub::offsetOfFirstUpdateStub()),
ICStubReg);
// Call the stubcode.
- masm.call(Operand(ICStubReg, ICStub::offsetOfStubCode()));
+ masm.call(Address(ICStubReg, ICStub::offsetOfStubCode()));
// Restore the old stub reg.
masm.pop(ICStubReg);
// The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
// value in R0 type-checked properly or not.
Label success;
masm.cmp32(R1.scratchReg(), Imm32(1));
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -269,17 +269,17 @@ JitRuntime::generateEnterJIT(JSContext*
// The call will push the return address on the stack, thus we check that
// the stack would be aligned once the call is complete.
masm.assertStackAlignment(JitStackAlignment, sizeof(uintptr_t));
/***************************************************************
Call passed-in code, get return value and fill in the
passed in return value pointer
***************************************************************/
- masm.call(Operand(ebp, ARG_JITCODE));
+ masm.call(Address(ebp, ARG_JITCODE));
if (type == EnterJitBaseline) {
// Baseline OSR will return here.
masm.bind(returnLabel.src());
masm.addCodeLabel(returnLabel);
}
// Pop arguments off the stack.
--- a/js/src/vm/SharedTypedArrayObject.cpp
+++ b/js/src/vm/SharedTypedArrayObject.cpp
@@ -2,16 +2,17 @@
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 "vm/SharedTypedArrayObject.h"
#include "mozilla/Alignment.h"
+#include "mozilla/Attributes.h"
#include "mozilla/PodOperations.h"
#include <string.h>
#ifndef XP_WIN
# include <sys/mman.h>
#endif
#include "jsapi.h"
@@ -92,17 +93,17 @@ class SharedTypedArrayObjectTemplate : p
// This is the max value of 'byteOffset': one below the length.
static const uint32_t MAX_BYTEOFFSET = MAX_LENGTH - 1;
public:
typedef NativeType ElementType;
typedef SharedTypedArrayObjectTemplate<NativeType> ThisTypedArrayObject;
typedef SharedArrayBufferObject BufferType;
- static Scalar::Type ArrayTypeID() { return TypeIDOfType<NativeType>(); }
+ static MOZ_CONSTEXPR Scalar::Type ArrayTypeID() { return TypeIDOfType<NativeType>::id; }
static bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
static bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
static const size_t BYTES_PER_ELEMENT = sizeof(ElementType);
static inline const Class* protoClass()
{
return &SharedTypedArrayObject::protoClasses[ArrayTypeID()];
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1979,27 +1979,33 @@ JSAutoStructuredCloneBuffer::operator=(J
MOZ_ASSERT(&other != this);
clear();
ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_);
return *this;
}
void
-JSAutoStructuredCloneBuffer::clear()
+JSAutoStructuredCloneBuffer::clear(const JSStructuredCloneCallbacks* optionalCallbacks,
+ void* optionalClosure)
{
- if (data_) {
- if (ownTransferables_ == OwnsTransferablesIfAny)
- DiscardTransferables(data_, nbytes_, callbacks_, closure_);
- ownTransferables_ = NoTransferables;
- js_free(data_);
- data_ = nullptr;
- nbytes_ = 0;
- version_ = 0;
- }
+ if (!data_)
+ return;
+
+ const JSStructuredCloneCallbacks* callbacks =
+ optionalCallbacks ? optionalCallbacks : callbacks_;
+ void* closure = optionalClosure ? optionalClosure : closure_;
+
+ if (ownTransferables_ == OwnsTransferablesIfAny)
+ DiscardTransferables(data_, nbytes_, callbacks, closure);
+ ownTransferables_ = NoTransferables;
+ js_free(data_);
+ data_ = nullptr;
+ nbytes_ = 0;
+ version_ = 0;
}
bool
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version)
{
// transferable objects cannot be copied
if (StructuredCloneHasTransferObjects(data_, nbytes_))
return false;
--- a/js/src/vm/TypedArrayCommon.h
+++ b/js/src/vm/TypedArrayCommon.h
@@ -51,26 +51,26 @@ ValueIsLength(const Value& v, uint32_t*
*len = length;
return true;
}
return false;
}
-template<typename NativeType> static inline Scalar::Type TypeIDOfType();
-template<> inline Scalar::Type TypeIDOfType<int8_t>() { return Scalar::Int8; }
-template<> inline Scalar::Type TypeIDOfType<uint8_t>() { return Scalar::Uint8; }
-template<> inline Scalar::Type TypeIDOfType<int16_t>() { return Scalar::Int16; }
-template<> inline Scalar::Type TypeIDOfType<uint16_t>() { return Scalar::Uint16; }
-template<> inline Scalar::Type TypeIDOfType<int32_t>() { return Scalar::Int32; }
-template<> inline Scalar::Type TypeIDOfType<uint32_t>() { return Scalar::Uint32; }
-template<> inline Scalar::Type TypeIDOfType<float>() { return Scalar::Float32; }
-template<> inline Scalar::Type TypeIDOfType<double>() { return Scalar::Float64; }
-template<> inline Scalar::Type TypeIDOfType<uint8_clamped>() { return Scalar::Uint8Clamped; }
+template<typename NativeType> struct TypeIDOfType;
+template<> struct TypeIDOfType<int8_t> { static const Scalar::Type id = Scalar::Int8; };
+template<> struct TypeIDOfType<uint8_t> { static const Scalar::Type id = Scalar::Uint8; };
+template<> struct TypeIDOfType<int16_t> { static const Scalar::Type id = Scalar::Int16; };
+template<> struct TypeIDOfType<uint16_t> { static const Scalar::Type id = Scalar::Uint16; };
+template<> struct TypeIDOfType<int32_t> { static const Scalar::Type id = Scalar::Int32; };
+template<> struct TypeIDOfType<uint32_t> { static const Scalar::Type id = Scalar::Uint32; };
+template<> struct TypeIDOfType<float> { static const Scalar::Type id = Scalar::Float32; };
+template<> struct TypeIDOfType<double> { static const Scalar::Type id = Scalar::Float64; };
+template<> struct TypeIDOfType<uint8_clamped> { static const Scalar::Type id = Scalar::Uint8Clamped; };
inline bool
IsAnyTypedArray(JSObject* obj)
{
return obj->is<TypedArrayObject>() || obj->is<SharedTypedArrayObject>();
}
inline uint32_t
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -63,25 +63,16 @@ using JS::ToUint32;
* the subclasses.
*/
TypedArrayLayout TypedArrayObject::layout_(false, // shared
true, // neuterable
&TypedArrayObject::classes[0],
&TypedArrayObject::classes[Scalar::MaxTypedArrayViewType]);
-TypedArrayLayout::TypedArrayLayout(bool isShared, bool isNeuterable, const Class* firstClass,
- const Class* maxClass)
- : isShared_(isShared)
- , isNeuterable_(isNeuterable)
- , firstClass_(firstClass)
- , maxClass_(maxClass)
-{
-}
-
/* static */ int
TypedArrayLayout::lengthOffset()
{
return NativeObject::getFixedSlotOffset(LENGTH_SLOT);
}
/* static */ int
TypedArrayLayout::dataOffset()
@@ -201,17 +192,17 @@ namespace {
template<typename NativeType>
class TypedArrayObjectTemplate : public TypedArrayObject
{
friend class TypedArrayObject;
public:
typedef NativeType ElementType;
- static Scalar::Type ArrayTypeID() { return TypeIDOfType<NativeType>(); }
+ static MOZ_CONSTEXPR Scalar::Type ArrayTypeID() { return TypeIDOfType<NativeType>::id; }
static bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
static bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
static const size_t BYTES_PER_ELEMENT = sizeof(NativeType);
static JSObject*
createPrototype(JSContext* cx, JSProtoKey key)
{
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -2,16 +2,18 @@
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 vm_TypedArrayObject_h
#define vm_TypedArrayObject_h
+#include "mozilla/Attributes.h"
+
#include "jsobj.h"
#include "gc/Barrier.h"
#include "js/Class.h"
#include "vm/ArrayBufferObject.h"
typedef struct JSProperty JSProperty;
@@ -38,17 +40,23 @@ namespace js {
class TypedArrayLayout
{
const bool isShared_;
const bool isNeuterable_;
const Class* firstClass_;
const Class* maxClass_;
public:
- TypedArrayLayout(bool isShared, bool isNeuterable, const Class* firstClass, const Class* maxClass);
+ MOZ_CONSTEXPR TypedArrayLayout(bool isShared, bool isNeuterable,
+ const Class* firstClass, const Class* maxClass)
+ : isShared_(isShared)
+ , isNeuterable_(isNeuterable)
+ , firstClass_(firstClass)
+ , maxClass_(maxClass)
+ {}
// Underlying (Shared)ArrayBufferObject.
static const size_t BUFFER_SLOT = 0;
static_assert(BUFFER_SLOT == JS_TYPEDARRAYLAYOUT_BUFFER_SLOT,
"self-hosted code with burned-in constants must get the "
"right buffer slot");
// Slot containing length of the view in number of typed elements.
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1780,8 +1780,11 @@ FontFaceSet::UserFontSet::CreateUserFont
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
{
nsRefPtr<gfxUserFontEntry> entry =
new FontFace::Entry(this, aFontFaceSrcList, aWeight, aStretch, aItalicStyle,
aFeatureSettings, aLanguageOverride, aUnicodeRanges);
return entry.forget();
}
+
+#undef LOG_ENABLED
+#undef LOG
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -121,16 +121,17 @@ UNIFIED_SOURCES += [
'CSSRuleList.cpp',
'CSSStyleSheet.cpp',
'CSSVariableDeclarations.cpp',
'CSSVariableResolver.cpp',
'CSSVariableValues.cpp',
'Declaration.cpp',
'ErrorReporter.cpp',
'FontFace.cpp',
+ 'FontFaceSet.cpp',
'FontFaceSetIterator.cpp',
'ImageLoader.cpp',
'IncrementalClearCOMRuleArray.cpp',
'Loader.cpp',
'MediaQueryList.cpp',
'nsAnimationManager.cpp',
'nsComputedDOMStyle.cpp',
'nsCSSAnonBoxes.cpp',
@@ -167,20 +168,18 @@ UNIFIED_SOURCES += [
'nsTransitionManager.cpp',
'RuleNodeCacheConditions.cpp',
'RuleProcessorCache.cpp',
'StyleAnimationValue.cpp',
'StyleRule.cpp',
'SVGAttrAnimationRuleProcessor.cpp',
]
-# FontFaceSet.cpp needs to be built separately because it redefines LOG.
# nsCSSRuleProcessor.cpp needs to be built separately because it uses plarena.h.
SOURCES += [
- 'FontFaceSet.cpp',
'nsCSSRuleProcessor.cpp',
]
EXTRA_COMPONENTS += [
'CSSUnprefixingService.js',
'CSSUnprefixingService.manifest',
]
--- a/mobile/android/chrome/content/WebappRT.js
+++ b/mobile/android/chrome/content/WebappRT.js
@@ -30,16 +30,17 @@ let WebappRT = {
pref("extensions.enabledScopes", 1),
// Auto-disable any add-ons that are "dropped in" to the profile
pref("extensions.autoDisableScopes", 1),
// Disable add-on installation via the web-exposed APIs
pref("xpinstall.enabled", false),
// Set a future policy version to avoid the telemetry prompt.
pref("toolkit.telemetry.prompted", 999),
pref("toolkit.telemetry.notifiedOptOut", 999),
+ pref("media.useAudioChannelAPI", true),
pref("media.useAudioChannelService", true),
pref("dom.mozTCPSocket.enabled", true),
// Enabled system messages for web activity support
pref("dom.sysmsg.enabled", true),
],
init: function(aStatus, aUrl, aCallback) {
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -177,17 +177,19 @@ nsWindow::DumpWindows(const nsTArray<nsW
nsWindow::nsWindow() :
mIsVisible(false),
mParent(nullptr),
mIMEMaskSelectionUpdate(false),
mIMEMaskEventsCount(1), // Mask IME events since there's no focus yet
mIMERanges(new TextRangeArray()),
mIMEUpdatingContext(false),
- mIMESelectionChanged(false)
+ mIMESelectionChanged(false),
+ mAwaitingFullScreen(false),
+ mIsFullScreen(false)
{
}
nsWindow::~nsWindow()
{
gTopLevelWindows.RemoveElement(this);
ALOG("nsWindow %p destructor", (void*)this);
if (mLayerManager == sLayerManager) {
@@ -489,16 +491,22 @@ nsWindow::Resize(double aX,
if (needSizeDispatch)
OnSizeChanged(gfxIntSize(aWidth, aHeight));
// Should we skip honoring aRepaint here?
if (aRepaint && FindTopLevel() == nsWindow::TopWindow())
RedrawAll();
+ nsIWidgetListener* listener = GetWidgetListener();
+ if (mAwaitingFullScreen && listener) {
+ listener->FullscreenChanged(mIsFullScreen);
+ mAwaitingFullScreen = false;
+ }
+
return NS_OK;
}
void
nsWindow::SetZIndex(int32_t aZIndex)
{
ALOG("nsWindow[%p]::SetZIndex %d ignored", (void*)this, aZIndex);
}
@@ -625,17 +633,17 @@ NS_IMETHODIMP
nsWindow::GetScreenBounds(nsIntRect &aRect)
{
LayoutDeviceIntPoint p = WidgetToScreenOffset();
aRect.x = p.x;
aRect.y = p.y;
aRect.width = mBounds.width;
aRect.height = mBounds.height;
-
+
return NS_OK;
}
LayoutDeviceIntPoint
nsWindow::WidgetToScreenOffset()
{
LayoutDeviceIntPoint p(0, 0);
nsWindow *w = this;
@@ -667,16 +675,18 @@ nsWindow::DispatchEvent(WidgetGUIEvent*
return mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
}
return nsEventStatus_eIgnore;
}
NS_IMETHODIMP
nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*)
{
+ mIsFullScreen = aFullScreen;
+ mAwaitingFullScreen = true;
GeckoAppShell::SetFullScreen(aFullScreen);
return NS_OK;
}
NS_IMETHODIMP
nsWindow::SetWindowClass(const nsAString& xulWinType)
{
return NS_OK;
@@ -2105,17 +2115,17 @@ nsWindow::SetInputContext(const InputCon
}
ALOGIME("IME: SetInputContext: s=0x%X, 0x%X, action=0x%X, 0x%X",
aContext.mIMEState.mEnabled, aContext.mIMEState.mOpen,
aAction.mCause, aAction.mFocusChange);
// Ensure that opening the virtual keyboard is allowed for this specific
// InputContext depending on the content.ime.strict.policy pref
- if (aContext.mIMEState.mEnabled != IMEState::DISABLED &&
+ if (aContext.mIMEState.mEnabled != IMEState::DISABLED &&
aContext.mIMEState.mEnabled != IMEState::PLUGIN &&
Preferences::GetBool("content.ime.strict_policy", false) &&
!aAction.ContentGotFocusByTrustedCause() &&
!aAction.UserMightRequestOpenVKB()) {
return;
}
IMEState::Enabled enabled = aContext.mIMEState.mEnabled;
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -226,16 +226,19 @@ protected:
bool mIMEMaskSelectionUpdate;
int32_t mIMEMaskEventsCount; // Mask events when > 0
nsRefPtr<mozilla::TextRangeArray> mIMERanges;
bool mIMEUpdatingContext;
nsAutoTArray<mozilla::AndroidGeckoEvent, 8> mIMEKeyEvents;
nsAutoTArray<IMEChange, 4> mIMETextChanges;
bool mIMESelectionChanged;
+ bool mAwaitingFullScreen;
+ bool mIsFullScreen;
+
InputContext mInputContext;
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) override;
static void DumpWindows();
static void DumpWindows(const nsTArray<nsWindow*>& wins, int indent = 0);
static void LogWindow(nsWindow *win, int index, int indent);