зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland
This commit is contained in:
Коммит
5d8f1744bf
|
@ -789,8 +789,16 @@ pref("browser.selfsupport.url", "https://self-repair.mozilla.org/%LOCALE%/repair
|
|||
pref("browser.sessionstore.resume_from_crash", true);
|
||||
pref("browser.sessionstore.resume_session_once", false);
|
||||
|
||||
// minimal interval between two save operations in milliseconds
|
||||
pref("browser.sessionstore.interval", 15000);
|
||||
// Minimal interval between two save operations in milliseconds (while the user is active).
|
||||
pref("browser.sessionstore.interval", 15000); // 15 seconds
|
||||
|
||||
// Minimal interval between two save operations in milliseconds (while the user is idle).
|
||||
pref("browser.sessionstore.interval.idle", 3600000); // 1h
|
||||
|
||||
// Time (ms) before we assume that the user is idle and that we don't need to
|
||||
// collect/save the session quite as often.
|
||||
pref("browser.sessionstore.idleDelay", 180000); // 3 minutes
|
||||
|
||||
// on which sites to save text data, POSTDATA and cookies
|
||||
// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
|
||||
pref("browser.sessionstore.privacy_level", 0);
|
||||
|
|
|
@ -247,8 +247,6 @@ var whitelist = new Set([
|
|||
{file: "resource://gre/modules/PropertyListUtils.jsm", platforms: ["linux", "win"]},
|
||||
// Bug 1351093
|
||||
{file: "resource://gre/modules/Sntp.jsm"},
|
||||
// Bug 1351980
|
||||
{file: "resource://gre/modules/UserAgentOverrides.jsm"},
|
||||
// Bug 1351097
|
||||
{file: "resource://gre/modules/accessibility/AccessFu.jsm"},
|
||||
// Bug 1351099
|
||||
|
|
|
@ -34,7 +34,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
|
|||
RemotePrompt:false, SelfSupportBackend:false, SessionStore:false,
|
||||
ShellService:false, SimpleServiceDiscovery:false, TabCrashHandler:false,
|
||||
Task:false, UITour:false, WebChannel:false,
|
||||
WindowsRegistry:false, webrtcUI:false */
|
||||
WindowsRegistry:false, webrtcUI:false, UserAgentOverrides: false */
|
||||
|
||||
/**
|
||||
* IF YOU ADD OR REMOVE FROM THIS LIST, PLEASE UPDATE THE LIST ABOVE AS WELL.
|
||||
|
@ -89,6 +89,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
|
|||
["WebChannel", "resource://gre/modules/WebChannel.jsm"],
|
||||
["WindowsRegistry", "resource://gre/modules/WindowsRegistry.jsm"],
|
||||
["webrtcUI", "resource:///modules/webrtcUI.jsm"],
|
||||
["UserAgentOverrides", "resource://gre/modules/UserAgentOverrides.jsm"],
|
||||
].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource));
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
|
@ -431,6 +432,8 @@ BrowserGlue.prototype = {
|
|||
// and e10s are active together.
|
||||
E10SAccessibilityCheck.init();
|
||||
}
|
||||
|
||||
UserAgentOverrides.init();
|
||||
},
|
||||
|
||||
// cleanup (called on application shutdown)
|
||||
|
@ -470,6 +473,8 @@ BrowserGlue.prototype = {
|
|||
os.removeObserver(this, "browser-search-engine-modified");
|
||||
os.removeObserver(this, "flash-plugin-hang");
|
||||
os.removeObserver(this, "xpi-signature-changed");
|
||||
|
||||
UserAgentOverrides.uninit();
|
||||
},
|
||||
|
||||
_onAppDefaults: function BG__onAppDefaults() {
|
||||
|
|
|
@ -30,22 +30,27 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
// Minimal interval between two save operations (in milliseconds).
|
||||
XPCOMUtils.defineLazyGetter(this, "gInterval", function() {
|
||||
const PREF = "browser.sessionstore.interval";
|
||||
|
||||
// Observer that updates the cached value when the preference changes.
|
||||
Services.prefs.addObserver(PREF, () => {
|
||||
this.gInterval = Services.prefs.getIntPref(PREF);
|
||||
|
||||
// Cancel any pending runs and call runDelayed() with
|
||||
// zero to apply the newly configured interval.
|
||||
SessionSaverInternal.cancel();
|
||||
SessionSaverInternal.runDelayed(0);
|
||||
}, false);
|
||||
|
||||
return Services.prefs.getIntPref(PREF);
|
||||
});
|
||||
/*
|
||||
* Minimal interval between two save operations (in milliseconds).
|
||||
*
|
||||
* To save system resources, we generally do not save changes immediately when
|
||||
* a change is detected. Rather, we wait a little to see if this change is
|
||||
* followed by other changes, in which case only the last write is necessary.
|
||||
* This delay is defined by "browser.sessionstore.interval".
|
||||
*
|
||||
* Furthermore, when the user is not actively using the computer, webpages
|
||||
* may still perform changes that require (re)writing to sessionstore, e.g.
|
||||
* updating Session Cookies or DOM Session Storage, or refreshing, etc. We
|
||||
* expect that these changes are much less critical to the user and do not
|
||||
* need to be saved as often. In such cases, we increase the delay to
|
||||
* "browser.sessionstore.interval.idle".
|
||||
*
|
||||
* When the user returns to the computer, if a save is pending, we reschedule
|
||||
* it to happen soon, with "browser.sessionstore.interval".
|
||||
*/
|
||||
const PREF_INTERVAL_ACTIVE = "browser.sessionstore.interval";
|
||||
const PREF_INTERVAL_IDLE = "browser.sessionstore.interval.idle";
|
||||
const PREF_IDLE_DELAY = "browser.sessionstore.idleDelay";
|
||||
|
||||
// Notify observers about a given topic with a given subject.
|
||||
function notify(subject, topic) {
|
||||
|
@ -118,6 +123,36 @@ var SessionSaverInternal = {
|
|||
*/
|
||||
_lastSaveTime: 0,
|
||||
|
||||
/**
|
||||
* `true` if the user has been idle for at least
|
||||
* `SessionSaverInternal._intervalWhileIdle` ms. Idleness is computed
|
||||
* with `nsIIdleService`.
|
||||
*/
|
||||
_isIdle: false,
|
||||
|
||||
/**
|
||||
* `true` if the user was idle when we last scheduled a delayed save.
|
||||
* See `_isIdle` for details on idleness.
|
||||
*/
|
||||
_wasIdle: false,
|
||||
|
||||
/**
|
||||
* Minimal interval between two save operations (in ms), while the user
|
||||
* is active.
|
||||
*/
|
||||
_intervalWhileActive: null,
|
||||
|
||||
/**
|
||||
* Minimal interval between two save operations (in ms), while the user
|
||||
* is idle.
|
||||
*/
|
||||
_intervalWhileIdle: null,
|
||||
|
||||
/**
|
||||
* How long before we assume that the user is idle (ms).
|
||||
*/
|
||||
_idleDelay: null,
|
||||
|
||||
/**
|
||||
* Immediately saves the current session to disk.
|
||||
*/
|
||||
|
@ -141,9 +176,11 @@ var SessionSaverInternal = {
|
|||
}
|
||||
|
||||
// Interval until the next disk operation is allowed.
|
||||
delay = Math.max(this._lastSaveTime + gInterval - Date.now(), delay, 0);
|
||||
let interval = this._isIdle ? this._intervalWhileIdle : this._intervalWhileActive;
|
||||
delay = Math.max(this._lastSaveTime + interval - Date.now(), delay, 0);
|
||||
|
||||
// Schedule a state save.
|
||||
this._wasIdle = this._isIdle;
|
||||
this._timeoutID = setTimeout(() => this._saveStateAsync(), delay);
|
||||
},
|
||||
|
||||
|
@ -163,6 +200,29 @@ var SessionSaverInternal = {
|
|||
this._timeoutID = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Observe idle/ active notifications.
|
||||
*/
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "idle":
|
||||
this._isIdle = true;
|
||||
break;
|
||||
case "active":
|
||||
this._isIdle = false;
|
||||
if (this._timeoutID && this._wasIdle) {
|
||||
// A state save has been scheduled while we were idle.
|
||||
// Replace it by an active save.
|
||||
clearTimeout(this._timeoutID);
|
||||
this._timeoutID = null;
|
||||
this.runDelayed();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected change value ${topic}`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Saves the current session state. Collects data and writes to disk.
|
||||
*
|
||||
|
@ -268,3 +328,33 @@ var SessionSaverInternal = {
|
|||
}, console.error);
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(SessionSaverInternal, "_intervalWhileActive", PREF_INTERVAL_ACTIVE,
|
||||
15000 /* 15 seconds */, () => {
|
||||
// Cancel any pending runs and call runDelayed() with
|
||||
// zero to apply the newly configured interval.
|
||||
SessionSaverInternal.cancel();
|
||||
SessionSaverInternal.runDelayed(0);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(SessionSaverInternal, "_intervalWhileIdle", PREF_INTERVAL_IDLE,
|
||||
3600000 /* 1 h */);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(SessionSaverInternal, "_idleDelay", PREF_IDLE_DELAY,
|
||||
180000 /* 3 minutes */, (key, previous, latest) => {
|
||||
// Update the idle observer for the new `PREF_IDLE_DELAY` value. Here we need
|
||||
// to re-fetch the service instead of the original one in use; This is for a
|
||||
// case that the Mock service in the unit test needs to be fetched to
|
||||
// replace the original one.
|
||||
var idleService = Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService);
|
||||
if (previous != undefined) {
|
||||
idleService.removeIdleObserver(SessionSaverInternal, previous);
|
||||
}
|
||||
if (latest != undefined) {
|
||||
idleService.addIdleObserver(SessionSaverInternal, latest);
|
||||
}
|
||||
});
|
||||
|
||||
var idleService = Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService);
|
||||
idleService.addIdleObserver(SessionSaverInternal, SessionSaverInternal._idleDelay);
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ skip-if = true # Needs to be rewritten as Marionette test, bug 995916
|
|||
[browser_739805.js]
|
||||
[browser_819510_perwindowpb.js]
|
||||
skip-if = (os == 'win' && bits == 64) # Bug 1284312
|
||||
[browser_not_collect_when_idle.js]
|
||||
|
||||
# Disabled for frequent intermittent failures
|
||||
[browser_464620_a.js]
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/** Test for Bug 1305950 **/
|
||||
|
||||
Cu.import("resource://testing-common/MockRegistrar.jsm", this);
|
||||
|
||||
// The mock idle service.
|
||||
var idleService = {
|
||||
_observers: new Set(),
|
||||
_activity: {
|
||||
addCalls: [],
|
||||
removeCalls: [],
|
||||
observerFires: [],
|
||||
},
|
||||
|
||||
_reset() {
|
||||
this._observers.clear();
|
||||
this._activity.addCalls = [];
|
||||
this._activity.removeCalls = [];
|
||||
this._activity.observerFires = [];
|
||||
},
|
||||
|
||||
_fireObservers(state) {
|
||||
for (let observer of this._observers.values()) {
|
||||
observer.observe(observer, state, null);
|
||||
this._activity.observerFires.push(state);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIdleService]),
|
||||
idleTime: 19999,
|
||||
|
||||
addIdleObserver(observer, time) {
|
||||
this._observers.add(observer);
|
||||
this._activity.addCalls.push(time);
|
||||
},
|
||||
|
||||
removeIdleObserver(observer, time) {
|
||||
this._observers.delete(observer);
|
||||
this._activity.removeCalls.push(time);
|
||||
}
|
||||
};
|
||||
|
||||
add_task(async function testIntervalChanges() {
|
||||
const PREF_SS_INTERVAL = 2000;
|
||||
|
||||
// We speed up the interval between session saves to ensure that the test
|
||||
// runs quickly.
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", PREF_SS_INTERVAL);
|
||||
|
||||
// Increase `idleDelay` to 1 day to update the pre-registered idle observer
|
||||
// in "real" idle service to avoid possible interference, especially for the
|
||||
// CI server environment.
|
||||
Services.prefs.setIntPref("browser.sessionstore.idleDelay", 86400000);
|
||||
|
||||
// Mock an idle service.
|
||||
let fakeIdleService = MockRegistrar.register("@mozilla.org/widget/idleservice;1", idleService);
|
||||
idleService._reset();
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
MockRegistrar.unregister(fakeIdleService);
|
||||
});
|
||||
|
||||
// Hook idle/active observer to mock idle service by changing pref `idleDelay`
|
||||
// to a whatever value, which will not be used.
|
||||
Services.prefs.setIntPref("browser.sessionstore.idleDelay", 5000000);
|
||||
|
||||
// Wait a `sessionstore-state-write-complete` event from any previous
|
||||
// scheduled state write. This is needed since the `_lastSaveTime` in
|
||||
// runDelayed() should be set at least once, or the `_isIdle` flag will not
|
||||
// become effective.
|
||||
// We wait at most 30 sec which is about as long as the timeout for the
|
||||
// regular whole test case, and we don't expect the write event comes fast
|
||||
// enough for an immediate `waitForSaveState()` from now.
|
||||
await new Promise(function(resolve, reject) {
|
||||
waitForTopic("sessionstore-state-write-complete", 30 * 1000, function(isSuccessful) {
|
||||
if (!isSuccessful) {
|
||||
reject(new Error("Timeout: didn't get any `sessionstore-state-write-complete` event"));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
info("Got the state write event, start to test idle mode...");
|
||||
|
||||
// Enter the "idle mode" (raise the `_isIdle` flag) by firing idle
|
||||
// observer of mock idle service.
|
||||
idleService._fireObservers("idle");
|
||||
|
||||
// Cancel any possible state save, which is not related with this test to
|
||||
// avoid interference.
|
||||
SessionSaver.cancel();
|
||||
|
||||
let p1 = promiseSaveState();
|
||||
|
||||
// Schedule a state write, which is expeced to be postponed after about
|
||||
// `browser.sessionstore.interval.idle` ms, since the idle flag was just set.
|
||||
SessionSaver.runDelayed(0);
|
||||
|
||||
// We expect `p1` hits the timeout.
|
||||
await Assert.rejects(p1, null, "[Test 1A] No state write during idle.");
|
||||
|
||||
// Test again for better reliability. Same, we expect following promise hits
|
||||
// the timeout.
|
||||
await Assert.rejects(promiseSaveState(), null, "[Test 1B] Again: No state write during idle.");
|
||||
|
||||
// Back to the active mode.
|
||||
info("Start to test active mode...");
|
||||
idleService._fireObservers("active");
|
||||
|
||||
await new Promise(function(resolve, reject) {
|
||||
waitForTopic("sessionstore-state-write-complete", PREF_SS_INTERVAL + 10000, function(isSuccessful) {
|
||||
if (!isSuccessful) {
|
||||
reject(new Error("Timeout: didn't get any `sessionstore-state-write-complete` event"));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
info("[Test 2] Has state write during active.");
|
||||
});
|
||||
|
|
@ -247,13 +247,13 @@ function waitForSaveState(aCallback) {
|
|||
return waitForTopic("sessionstore-state-write-complete", timeout, aCallback);
|
||||
}
|
||||
function promiseSaveState() {
|
||||
return new Promise(resolve => {
|
||||
return new Promise((resolve, reject) => {
|
||||
waitForSaveState(isSuccessful => {
|
||||
if (!isSuccessful) {
|
||||
throw new Error("timeout");
|
||||
reject(new Error("Save state timeout"));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -433,5 +433,6 @@ function enableServiceWorkerDebugging() {
|
|||
["dom.ipc.processCount", 1],
|
||||
]};
|
||||
SpecialPowers.pushPrefEnv(options, done);
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -46,14 +46,14 @@ public:
|
|||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
NS_DECL_NSIBFCACHEENTRY
|
||||
|
||||
nsExpirationState *GetExpirationState() { return &mExpirationState; }
|
||||
|
||||
private:
|
||||
~nsSHEntryShared();
|
||||
|
||||
friend class nsSHEntry;
|
||||
|
||||
friend class HistoryTracker;
|
||||
friend class nsExpirationTracker<nsSHEntryShared, 3>;
|
||||
nsExpirationState *GetExpirationState() { return &mExpirationState; }
|
||||
|
||||
static already_AddRefed<nsSHEntryShared> Duplicate(nsSHEntryShared* aEntry);
|
||||
|
||||
|
|
|
@ -56,11 +56,11 @@ extern mozilla::LazyLogModule gContentSinkLogModuleInfo;
|
|||
#define SINK_LOG_TEST(_lm, _bit) (int((_lm)->Level()) & (_bit))
|
||||
|
||||
#define SINK_TRACE(_lm, _bit, _args) \
|
||||
PR_BEGIN_MACRO \
|
||||
do { \
|
||||
if (SINK_LOG_TEST(_lm, _bit)) { \
|
||||
PR_LogPrint _args; \
|
||||
printf_stderr _args; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
#define SINK_TRACE(_lm, _bit, _args)
|
||||
|
|
|
@ -315,7 +315,9 @@ nsDOMWindowUtils::Redraw(uint32_t aCount, uint32_t *aDurationOut)
|
|||
rootFrame->InvalidateFrame();
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
|
||||
XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), False);
|
||||
if (!gfxPlatform::IsHeadless()) {
|
||||
XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), False);
|
||||
}
|
||||
#endif
|
||||
|
||||
*aDurationOut = PR_IntervalToMilliseconds(PR_IntervalNow() - iStart);
|
||||
|
|
|
@ -1203,8 +1203,9 @@ nsDOMStyleSheetSetList::EnsureFresh()
|
|||
}
|
||||
|
||||
// ==================================================================
|
||||
nsIDocument::SelectorCache::SelectorCache()
|
||||
: nsExpirationTracker<SelectorCacheKey, 4>(1000, "nsIDocument::SelectorCache")
|
||||
nsIDocument::SelectorCache::SelectorCache(nsIEventTarget* aEventTarget)
|
||||
: nsExpirationTracker<SelectorCacheKey, 4>(
|
||||
1000, "nsIDocument::SelectorCache", aEventTarget)
|
||||
{ }
|
||||
|
||||
nsIDocument::SelectorCache::~SelectorCache()
|
||||
|
|
|
@ -1068,7 +1068,7 @@ public:
|
|||
: public nsExpirationTracker<SelectorCacheKey, 4>
|
||||
{
|
||||
public:
|
||||
SelectorCache();
|
||||
explicit SelectorCache(nsIEventTarget* aEventTarget);
|
||||
|
||||
// CacheList takes ownership of aSelectorList.
|
||||
void CacheList(const nsAString& aSelector, nsCSSSelectorList* aSelectorList);
|
||||
|
@ -1091,9 +1091,12 @@ public:
|
|||
nsClassHashtable<nsStringHashKey, nsCSSSelectorList> mTable;
|
||||
};
|
||||
|
||||
SelectorCache& GetSelectorCache()
|
||||
{
|
||||
return mSelectorCache;
|
||||
SelectorCache& GetSelectorCache() {
|
||||
if (!mSelectorCache) {
|
||||
mSelectorCache =
|
||||
new SelectorCache(EventTargetFor(mozilla::TaskCategory::Other));
|
||||
}
|
||||
return *mSelectorCache;
|
||||
}
|
||||
// Get the root <html> element, or return null if there isn't one (e.g.
|
||||
// if the root isn't <html>)
|
||||
|
@ -2916,7 +2919,8 @@ protected:
|
|||
private:
|
||||
mutable std::bitset<eDeprecatedOperationCount> mDeprecationWarnedAbout;
|
||||
mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
|
||||
SelectorCache mSelectorCache;
|
||||
// Lazy-initialization to have mDocGroup initialized in prior to mSelectorCache.
|
||||
nsAutoPtr<SelectorCache> mSelectorCache;
|
||||
|
||||
protected:
|
||||
~nsIDocument();
|
||||
|
|
|
@ -2225,25 +2225,47 @@ ScopedLazyBind::UnwrapImpl()
|
|||
|
||||
////////////////////////////////////////
|
||||
|
||||
void
|
||||
Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
|
||||
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
|
||||
uint32_t* const out_intSize)
|
||||
bool
|
||||
Intersect(const int32_t srcSize, const int32_t read0, const int32_t readSize,
|
||||
int32_t* const out_intRead0, int32_t* const out_intWrite0,
|
||||
int32_t* const out_intSize)
|
||||
{
|
||||
// Only >0 if dstStartInSrc is >0:
|
||||
// 0 3 // src coords
|
||||
// | [========] // dst box
|
||||
// ^--^
|
||||
*out_intStartInSrc = std::max<int32_t>(0, dstStartInSrc);
|
||||
MOZ_ASSERT(srcSize >= 0);
|
||||
MOZ_ASSERT(readSize >= 0);
|
||||
const auto read1 = int64_t(read0) + readSize;
|
||||
|
||||
// Only >0 if dstStartInSrc is <0:
|
||||
//-6 0 // src coords
|
||||
// [=====|==] // dst box
|
||||
// ^-----^
|
||||
*out_intStartInDst = std::max<int32_t>(0, 0 - dstStartInSrc);
|
||||
int32_t intRead0 = read0; // Clearly doesn't need validation.
|
||||
int64_t intWrite0 = 0;
|
||||
int64_t intSize = readSize;
|
||||
|
||||
int32_t intEndInSrc = std::min<int32_t>(srcSize, dstStartInSrc + dstSize);
|
||||
*out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
|
||||
if (read1 <= 0 || read0 >= srcSize) {
|
||||
// Disjoint ranges.
|
||||
intSize = 0;
|
||||
} else {
|
||||
if (read0 < 0) {
|
||||
const auto diff = int64_t(0) - read0;
|
||||
MOZ_ASSERT(diff >= 0);
|
||||
intRead0 = 0;
|
||||
intWrite0 = diff;
|
||||
intSize -= diff;
|
||||
}
|
||||
if (read1 > srcSize) {
|
||||
const auto diff = int64_t(read1) - srcSize;
|
||||
MOZ_ASSERT(diff >= 0);
|
||||
intSize -= diff;
|
||||
}
|
||||
|
||||
if (!CheckedInt<int32_t>(intWrite0).isValid() ||
|
||||
!CheckedInt<int32_t>(intSize).isValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*out_intRead0 = intRead0;
|
||||
*out_intWrite0 = intWrite0;
|
||||
*out_intSize = intSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2164,10 +2164,9 @@ private:
|
|||
|
||||
////
|
||||
|
||||
void
|
||||
Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
|
||||
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
|
||||
uint32_t* const out_intSize);
|
||||
bool
|
||||
Intersect(int32_t srcSize, int32_t read0, int32_t readSize, int32_t* out_intRead0,
|
||||
int32_t* out_intWrite0, int32_t* out_intSize);
|
||||
|
||||
////
|
||||
|
||||
|
|
|
@ -1556,18 +1556,32 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
|
|||
return;
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
int32_t readX, readY;
|
||||
int32_t writeX, writeY;
|
||||
int32_t rwWidth, rwHeight;
|
||||
if (!Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth) ||
|
||||
!Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight))
|
||||
{
|
||||
ErrorOutOfMemory("readPixels: Bad subrect selection.");
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Now that the errors are out of the way, on to actually reading!
|
||||
|
||||
OnBeforeReadCall();
|
||||
|
||||
uint32_t readX, readY;
|
||||
uint32_t writeX, writeY;
|
||||
uint32_t rwWidth, rwHeight;
|
||||
Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
|
||||
Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
|
||||
if (!rwWidth || !rwHeight) {
|
||||
// Disjoint rects, so we're done already.
|
||||
DummyReadFramebufferOperation("readPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
|
||||
if (uint32_t(rwWidth) == width &&
|
||||
uint32_t(rwHeight) == height)
|
||||
{
|
||||
DoReadPixelsAndConvert(srcFormat->format, x, y, width, height, packFormat,
|
||||
packType, dest, dataLen, rowStride);
|
||||
return;
|
||||
|
@ -1586,12 +1600,6 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
|
|||
////////////////////////////////////
|
||||
// Read only the in-bounds pixels.
|
||||
|
||||
if (!rwWidth || !rwHeight) {
|
||||
// There aren't any, so we're 'done'.
|
||||
DummyReadFramebufferOperation("readPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsWebGL2()) {
|
||||
if (!mPixelStore_PackRowLength) {
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH,
|
||||
|
@ -1611,7 +1619,7 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
|
|||
|
||||
uint8_t* row = (uint8_t*)dest + writeX * bytesPerPixel;
|
||||
row += writeY * rowStride;
|
||||
for (uint32_t j = 0; j < rwHeight; j++) {
|
||||
for (uint32_t j = 0; j < uint32_t(rwHeight); j++) {
|
||||
DoReadPixelsAndConvert(srcFormat->format, readX, readY+j, rwWidth, 1,
|
||||
packFormat, packType, row, dataLen, rowStride);
|
||||
row += rowStride;
|
||||
|
|
|
@ -2011,11 +2011,15 @@ DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
|
|||
|
||||
////
|
||||
|
||||
uint32_t readX, readY;
|
||||
uint32_t writeX, writeY;
|
||||
uint32_t rwWidth, rwHeight;
|
||||
Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth);
|
||||
Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
|
||||
int32_t readX, readY;
|
||||
int32_t writeX, writeY;
|
||||
int32_t rwWidth, rwHeight;
|
||||
if (!Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth) ||
|
||||
!Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight))
|
||||
{
|
||||
webgl->ErrorOutOfMemory("%s: Bad subrect selection.", funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
writeX += xOffset;
|
||||
writeY += yOffset;
|
||||
|
@ -2028,7 +2032,7 @@ DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
|
|||
if (!isSubImage) {
|
||||
UniqueBuffer buffer;
|
||||
|
||||
if (rwWidth != dstWidth || rwHeight != dstHeight) {
|
||||
if (uint32_t(rwWidth) != dstWidth || uint32_t(rwHeight) != dstHeight) {
|
||||
const auto& pi = idealUnpack->ToPacking();
|
||||
CheckedUint32 byteCount = BytesPerPixel(pi);
|
||||
byteCount *= dstWidth;
|
||||
|
|
|
@ -746,6 +746,10 @@ ContentParent::IsMaxProcessCountReached(const nsAString& aContentProcessType)
|
|||
/*static*/ void
|
||||
ContentParent::ReleaseCachedProcesses()
|
||||
{
|
||||
if (!GetPoolSize(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We might want to extend this for other process types as well in the future...
|
||||
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
|
|
|
@ -14,16 +14,11 @@
|
|||
#include "prenv.h"
|
||||
#include "mozilla/SizePrintfMacros.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern mozilla::LazyLogModule gMediaDemuxerLog;
|
||||
#define ADTSLOG(msg, ...) \
|
||||
MOZ_LOG(gMediaDemuxerLog, LogLevel::Debug, ("ADTSDemuxer " msg, ##__VA_ARGS__))
|
||||
#define ADTSLOGV(msg, ...) \
|
||||
MOZ_LOG(gMediaDemuxerLog, LogLevel::Verbose, ("ADTSDemuxer " msg, ##__VA_ARGS__))
|
||||
#else
|
||||
#define ADTSLOG(msg, ...) do {} while (false)
|
||||
#define ADTSLOGV(msg, ...) do {} while (false)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace adts {
|
||||
|
|
|
@ -17,16 +17,11 @@
|
|||
#include "TimeUnits.h"
|
||||
#include "prenv.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern mozilla::LazyLogModule gMediaDemuxerLog;
|
||||
#define MP3LOG(msg, ...) \
|
||||
MOZ_LOG(gMediaDemuxerLog, LogLevel::Debug, ("MP3Demuxer " msg, ##__VA_ARGS__))
|
||||
#define MP3LOGV(msg, ...) \
|
||||
MOZ_LOG(gMediaDemuxerLog, LogLevel::Verbose, ("MP3Demuxer " msg, ##__VA_ARGS__))
|
||||
#else
|
||||
#define MP3LOG(msg, ...)
|
||||
#define MP3LOGV(msg, ...)
|
||||
#endif
|
||||
|
||||
using mozilla::media::TimeUnit;
|
||||
using mozilla::media::TimeInterval;
|
||||
|
|
|
@ -128,9 +128,7 @@ public:
|
|||
|
||||
StaticRefPtr<MediaMemoryTracker> MediaMemoryTracker::sUniqueInstance;
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
LazyLogModule gMediaTimerLog("MediaTimer");
|
||||
#endif
|
||||
|
||||
void
|
||||
MediaDecoder::InitStatics()
|
||||
|
|
|
@ -15,16 +15,11 @@
|
|||
#include "VideoUtils.h"
|
||||
#include "TimeUnits.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern mozilla::LazyLogModule gMediaDemuxerLog;
|
||||
#define LOG(msg, ...) \
|
||||
MOZ_LOG(gMediaDemuxerLog, LogLevel::Debug, ("FlacDemuxer " msg, ##__VA_ARGS__))
|
||||
#define LOGV(msg, ...) \
|
||||
MOZ_LOG(gMediaDemuxerLog, LogLevel::Verbose, ("FlacDemuxer " msg, ##__VA_ARGS__))
|
||||
#else
|
||||
#define LOG(msg, ...) do {} while (false)
|
||||
#define LOGV(msg, ...) do {} while (false)
|
||||
#endif
|
||||
|
||||
using namespace mozilla::media;
|
||||
|
||||
|
|
|
@ -48,16 +48,18 @@ namespace camera {
|
|||
// called "VideoCapture". On Windows this is a thread with an event loop
|
||||
// suitable for UI access.
|
||||
|
||||
// InputObserver is owned by CamerasParent, and it has a ref to CamerasParent
|
||||
void InputObserver::OnDeviceChange() {
|
||||
LOG((__PRETTY_FUNCTION__));
|
||||
MOZ_ASSERT(mParent);
|
||||
|
||||
RefPtr<InputObserver> self(this);
|
||||
RefPtr<nsIRunnable> ipc_runnable =
|
||||
media::NewRunnableFrom([this]() -> nsresult {
|
||||
if (mParent->IsShuttingDown()) {
|
||||
media::NewRunnableFrom([self]() -> nsresult {
|
||||
if (self->mParent->IsShuttingDown()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
Unused << mParent->SendDeviceChange();
|
||||
Unused << self->mParent->SendDeviceChange();
|
||||
return NS_OK;
|
||||
});
|
||||
|
||||
|
@ -354,11 +356,11 @@ CamerasParent::SetupEngine(CaptureEngine aCapEngine)
|
|||
return false;
|
||||
}
|
||||
|
||||
InputObserver** observer = mObservers.AppendElement(new InputObserver(this));
|
||||
RefPtr<InputObserver>* observer = mObservers.AppendElement(new InputObserver(this));
|
||||
auto device_info = engine->get()->GetOrCreateVideoCaptureDeviceInfo();
|
||||
MOZ_ASSERT(device_info);
|
||||
if (device_info) {
|
||||
device_info->RegisterVideoInputFeedBack(**observer);
|
||||
device_info->RegisterVideoInputFeedBack(*(observer->get()));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -398,9 +400,7 @@ CamerasParent::CloseEngines()
|
|||
}
|
||||
}
|
||||
|
||||
for (InputObserver* observer : mObservers) {
|
||||
delete observer;
|
||||
}
|
||||
// the observers hold references to us
|
||||
mObservers.Clear();
|
||||
|
||||
mWebRTCAlive = false;
|
||||
|
|
|
@ -69,6 +69,8 @@ private:
|
|||
class InputObserver : public webrtc::VideoInputFeedBack
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InputObserver)
|
||||
|
||||
explicit InputObserver(CamerasParent* aParent)
|
||||
: mParent(aParent) {};
|
||||
virtual void OnDeviceChange();
|
||||
|
@ -76,6 +78,8 @@ public:
|
|||
friend CamerasParent;
|
||||
|
||||
private:
|
||||
~InputObserver() {}
|
||||
|
||||
RefPtr<CamerasParent> mParent;
|
||||
};
|
||||
|
||||
|
@ -161,7 +165,7 @@ protected:
|
|||
// Above 2 are PBackground only, but this is potentially
|
||||
// read cross-thread.
|
||||
mozilla::Atomic<bool> mWebRTCAlive;
|
||||
nsTArray<InputObserver*> mObservers;
|
||||
nsTArray<RefPtr<InputObserver>> mObservers;
|
||||
};
|
||||
|
||||
PCamerasParent* CreateCamerasParent();
|
||||
|
|
|
@ -151,11 +151,9 @@ static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_s
|
|||
|
||||
#define kPluginRegistryFilename NS_LITERAL_CSTRING("pluginreg.dat")
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
LazyLogModule nsPluginLogging::gNPNLog(NPN_LOG_NAME);
|
||||
LazyLogModule nsPluginLogging::gNPPLog(NPP_LOG_NAME);
|
||||
LazyLogModule nsPluginLogging::gPluginLog(PLUGIN_LOG_NAME);
|
||||
#endif
|
||||
|
||||
// #defines for plugin cache and prefs
|
||||
#define NS_PREF_MAX_NUM_CACHED_INSTANCES "browser.plugins.max_num_cached_plugins"
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#ifndef PLUGIN_LOGGING // allow external override
|
||||
#define PLUGIN_LOGGING 1 // master compile-time switch for pluging logging
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Basic Plugin Logging Usage Instructions
|
||||
//
|
||||
|
@ -43,8 +39,6 @@
|
|||
// https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Gecko_Logging
|
||||
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
|
||||
class nsPluginLogging
|
||||
{
|
||||
public:
|
||||
|
@ -53,38 +47,10 @@ public:
|
|||
static mozilla::LazyLogModule gPluginLog; // general plugin log
|
||||
};
|
||||
|
||||
#endif // PLUGIN_LOGGING
|
||||
|
||||
// Quick-use macros
|
||||
#ifdef PLUGIN_LOGGING
|
||||
#define NPN_PLUGIN_LOG(a, b) \
|
||||
PR_BEGIN_MACRO \
|
||||
MOZ_LOG(nsPluginLogging::gNPNLog, a, b); \
|
||||
PR_LogFlush(); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define NPN_PLUGIN_LOG(a, b)
|
||||
#endif
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
#define NPP_PLUGIN_LOG(a, b) \
|
||||
PR_BEGIN_MACRO \
|
||||
MOZ_LOG(nsPluginLogging::gNPPLog, a, b); \
|
||||
PR_LogFlush(); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define NPP_PLUGIN_LOG(a, b)
|
||||
#endif
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
#define PLUGIN_LOG(a, b) \
|
||||
PR_BEGIN_MACRO \
|
||||
MOZ_LOG(nsPluginLogging::gPluginLog, a, b); \
|
||||
PR_LogFlush(); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define PLUGIN_LOG(a, b)
|
||||
#endif
|
||||
#define NPN_PLUGIN_LOG(a, b) MOZ_LOG(nsPluginLogging::gNPNLog, a, b)
|
||||
#define NPP_PLUGIN_LOG(a, b) MOZ_LOG(nsPluginLogging::gNPPLog, a, b)
|
||||
#define PLUGIN_LOG(a, b) MOZ_LOG(nsPluginLogging::gPluginLog, a, b)
|
||||
|
||||
#endif // nsPluginLogging_h__
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ interface CommandEvent : Event {
|
|||
readonly attribute DOMString? command;
|
||||
|
||||
void initCommandEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
DOMString? command);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional DOMString? command = null);
|
||||
};
|
||||
|
|
|
@ -31,9 +31,9 @@ dictionary CompositionEventInit : UIEventInit {
|
|||
partial interface CompositionEvent
|
||||
{
|
||||
void initCompositionEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
Window? viewArg,
|
||||
DOMString? dataArg,
|
||||
DOMString localeArg);
|
||||
optional boolean canBubbleArg = false,
|
||||
optional boolean cancelableArg = false,
|
||||
optional Window? viewArg = null,
|
||||
optional DOMString? dataArg = null,
|
||||
optional DOMString localeArg = "");
|
||||
};
|
||||
|
|
|
@ -19,9 +19,9 @@ interface CustomEvent : Event
|
|||
// initCustomEvent is a Gecko specific deprecated method.
|
||||
[Throws]
|
||||
void initCustomEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
any detail);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional any detail = null);
|
||||
};
|
||||
|
||||
dictionary CustomEventInit : EventInit
|
||||
|
|
|
@ -48,10 +48,10 @@ dictionary DeviceMotionEventInit : EventInit {
|
|||
// Mozilla extensions.
|
||||
partial interface DeviceMotionEvent {
|
||||
void initDeviceMotionEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
DeviceAccelerationInit acceleration,
|
||||
DeviceAccelerationInit accelerationIncludingGravity,
|
||||
DeviceRotationRateInit rotationRate,
|
||||
double? interval);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional DeviceAccelerationInit acceleration,
|
||||
optional DeviceAccelerationInit accelerationIncludingGravity,
|
||||
optional DeviceRotationRateInit rotationRate,
|
||||
optional double? interval = null);
|
||||
};
|
||||
|
|
|
@ -14,12 +14,12 @@ interface DeviceOrientationEvent : Event
|
|||
|
||||
// initDeviceOrientationEvent is a Gecko specific deprecated method.
|
||||
void initDeviceOrientationEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
double? alpha,
|
||||
double? beta,
|
||||
double? gamma,
|
||||
boolean absolute);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional double? alpha = null,
|
||||
optional double? beta = null,
|
||||
optional double? gamma = null,
|
||||
optional boolean absolute = false);
|
||||
};
|
||||
|
||||
dictionary DeviceOrientationEventInit : EventInit
|
||||
|
|
|
@ -10,21 +10,21 @@ interface DragEvent : MouseEvent
|
|||
readonly attribute DataTransfer? dataTransfer;
|
||||
|
||||
void initDragEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Window? aView,
|
||||
long aDetail,
|
||||
long aScreenX,
|
||||
long aScreenY,
|
||||
long aClientX,
|
||||
long aClientY,
|
||||
boolean aCtrlKey,
|
||||
boolean aAltKey,
|
||||
boolean aShiftKey,
|
||||
boolean aMetaKey,
|
||||
unsigned short aButton,
|
||||
EventTarget? aRelatedTarget,
|
||||
DataTransfer? aDataTransfer);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Window? aView = null,
|
||||
optional long aDetail = 0,
|
||||
optional long aScreenX = 0,
|
||||
optional long aScreenY = 0,
|
||||
optional long aClientX = 0,
|
||||
optional long aClientY = 0,
|
||||
optional boolean aCtrlKey = false,
|
||||
optional boolean aAltKey = false,
|
||||
optional boolean aShiftKey = false,
|
||||
optional boolean aMetaKey = false,
|
||||
optional unsigned short aButton = 0,
|
||||
optional EventTarget? aRelatedTarget = null,
|
||||
optional DataTransfer? aDataTransfer = null);
|
||||
};
|
||||
|
||||
dictionary DragEventInit : MouseEventInit
|
||||
|
|
|
@ -50,7 +50,9 @@ interface Event {
|
|||
[Pure]
|
||||
readonly attribute DOMHighResTimeStamp timeStamp;
|
||||
|
||||
void initEvent(DOMString type, boolean bubbles, boolean cancelable);
|
||||
void initEvent(DOMString type,
|
||||
optional boolean bubbles = false,
|
||||
optional boolean cancelable = false);
|
||||
attribute boolean cancelBubble;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ interface HashChangeEvent : Event
|
|||
readonly attribute DOMString newURL;
|
||||
|
||||
void initHashChangeEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
DOMString oldURLArg,
|
||||
DOMString newURLArg);
|
||||
optional boolean canBubbleArg = false,
|
||||
optional boolean cancelableArg = false,
|
||||
optional DOMString oldURLArg = "",
|
||||
optional DOMString newURLArg = "");
|
||||
};
|
||||
|
||||
dictionary HashChangeEventInit : EventInit
|
||||
|
|
|
@ -225,13 +225,13 @@ interface KeyEvent
|
|||
const unsigned long DOM_VK_WIN_OEM_CLEAR = 0xFE;
|
||||
|
||||
void initKeyEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Window? view,
|
||||
boolean ctrlKey,
|
||||
boolean altKey,
|
||||
boolean shiftKey,
|
||||
boolean metaKey,
|
||||
unsigned long keyCode,
|
||||
unsigned long charCode);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Window? view = null,
|
||||
optional boolean ctrlKey = false,
|
||||
optional boolean altKey = false,
|
||||
optional boolean shiftKey = false,
|
||||
optional boolean metaKey = false,
|
||||
optional unsigned long keyCode = 0,
|
||||
optional unsigned long charCode = 0);
|
||||
};
|
||||
|
|
|
@ -43,10 +43,14 @@ interface MessageEvent : Event {
|
|||
[Pure, Cached, Frozen]
|
||||
readonly attribute sequence<MessagePort> ports;
|
||||
|
||||
void initMessageEvent(DOMString type, boolean bubbles, boolean cancelable,
|
||||
any data, DOMString origin, DOMString lastEventId,
|
||||
MessageEventSource? source,
|
||||
sequence<MessagePort> ports);
|
||||
void initMessageEvent(DOMString type,
|
||||
optional boolean bubbles = false,
|
||||
optional boolean cancelable = false,
|
||||
optional any data = null,
|
||||
optional DOMString origin = "",
|
||||
optional DOMString lastEventId = "",
|
||||
optional MessageEventSource? source = null,
|
||||
optional sequence<MessagePort> ports = []);
|
||||
};
|
||||
|
||||
dictionary MessageEventInit : EventInit {
|
||||
|
|
|
@ -38,21 +38,21 @@ interface MouseEvent : UIEvent {
|
|||
readonly attribute long movementY;
|
||||
|
||||
// Deprecated in DOM Level 3:
|
||||
void initMouseEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
Window? viewArg,
|
||||
long detailArg,
|
||||
long screenXArg,
|
||||
long screenYArg,
|
||||
long clientXArg,
|
||||
long clientYArg,
|
||||
boolean ctrlKeyArg,
|
||||
boolean altKeyArg,
|
||||
boolean shiftKeyArg,
|
||||
boolean metaKeyArg,
|
||||
short buttonArg,
|
||||
EventTarget? relatedTargetArg);
|
||||
void initMouseEvent(DOMString typeArg,
|
||||
optional boolean canBubbleArg = false,
|
||||
optional boolean cancelableArg = false,
|
||||
optional Window? viewArg = null,
|
||||
optional long detailArg = 0,
|
||||
optional long screenXArg = 0,
|
||||
optional long screenYArg = 0,
|
||||
optional long clientXArg = 0,
|
||||
optional long clientYArg = 0,
|
||||
optional boolean ctrlKeyArg = false,
|
||||
optional boolean altKeyArg = false,
|
||||
optional boolean shiftKeyArg = false,
|
||||
optional boolean metaKeyArg = false,
|
||||
optional short buttonArg = 0,
|
||||
optional EventTarget? relatedTargetArg = null);
|
||||
// Introduced in DOM Level 3:
|
||||
boolean getModifierState(DOMString keyArg);
|
||||
};
|
||||
|
@ -91,23 +91,23 @@ partial interface MouseEvent
|
|||
|
||||
readonly attribute unsigned short mozInputSource;
|
||||
|
||||
void initNSMouseEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
Window? viewArg,
|
||||
long detailArg,
|
||||
long screenXArg,
|
||||
long screenYArg,
|
||||
long clientXArg,
|
||||
long clientYArg,
|
||||
boolean ctrlKeyArg,
|
||||
boolean altKeyArg,
|
||||
boolean shiftKeyArg,
|
||||
boolean metaKeyArg,
|
||||
short buttonArg,
|
||||
EventTarget? relatedTargetArg,
|
||||
float pressure,
|
||||
unsigned short inputSourceArg);
|
||||
void initNSMouseEvent(DOMString typeArg,
|
||||
optional boolean canBubbleArg = false,
|
||||
optional boolean cancelableArg = false,
|
||||
optional Window? viewArg = null,
|
||||
optional long detailArg = 0,
|
||||
optional long screenXArg = 0,
|
||||
optional long screenYArg = 0,
|
||||
optional long clientXArg = 0,
|
||||
optional long clientYArg = 0,
|
||||
optional boolean ctrlKeyArg = false,
|
||||
optional boolean altKeyArg = false,
|
||||
optional boolean shiftKeyArg = false,
|
||||
optional boolean metaKeyArg = false,
|
||||
optional short buttonArg = 0,
|
||||
optional EventTarget? relatedTargetArg = null,
|
||||
optional float pressure = 0,
|
||||
optional unsigned short inputSourceArg = 0);
|
||||
[ChromeOnly]
|
||||
readonly attribute boolean hitCluster; // True when touch occurs in a cluster of links
|
||||
|
||||
|
|
|
@ -12,19 +12,19 @@ interface MouseScrollEvent : MouseEvent
|
|||
readonly attribute long axis;
|
||||
|
||||
void initMouseScrollEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Window? view,
|
||||
long detail,
|
||||
long screenX,
|
||||
long screenY,
|
||||
long clientX,
|
||||
long clientY,
|
||||
boolean ctrlKey,
|
||||
boolean altKey,
|
||||
boolean shiftKey,
|
||||
boolean metaKey,
|
||||
unsigned short button,
|
||||
EventTarget? relatedTarget,
|
||||
long axis);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Window? view = null,
|
||||
optional long detail = 0,
|
||||
optional long screenX = 0,
|
||||
optional long screenY = 0,
|
||||
optional long clientX = 0,
|
||||
optional long clientY = 0,
|
||||
optional boolean ctrlKey = false,
|
||||
optional boolean altKey = false,
|
||||
optional boolean shiftKey = false,
|
||||
optional boolean metaKey = false,
|
||||
optional short button = 0,
|
||||
optional EventTarget? relatedTarget = null,
|
||||
optional long axis = 0);
|
||||
};
|
||||
|
|
|
@ -23,11 +23,11 @@ interface MutationEvent : Event
|
|||
|
||||
[Throws]
|
||||
void initMutationEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Node? relatedNode,
|
||||
DOMString prevValue,
|
||||
DOMString newValue,
|
||||
DOMString attrName,
|
||||
unsigned short attrChange);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Node? relatedNode = null,
|
||||
optional DOMString prevValue = "",
|
||||
optional DOMString newValue = "",
|
||||
optional DOMString attrName = "",
|
||||
optional unsigned short attrChange = 0);
|
||||
};
|
||||
|
|
|
@ -12,12 +12,12 @@ interface ScrollAreaEvent : UIEvent
|
|||
readonly attribute float height;
|
||||
|
||||
void initScrollAreaEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Window? view,
|
||||
long detail,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Window? view = null,
|
||||
optional long detail = 0,
|
||||
optional float x = 0,
|
||||
optional float y = 0,
|
||||
optional float width = 0,
|
||||
optional float height = 0);
|
||||
};
|
||||
|
|
|
@ -25,22 +25,22 @@ interface SimpleGestureEvent : MouseEvent
|
|||
readonly attribute unsigned long clickCount;
|
||||
|
||||
void initSimpleGestureEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
Window? viewArg,
|
||||
long detailArg,
|
||||
long screenXArg,
|
||||
long screenYArg,
|
||||
long clientXArg,
|
||||
long clientYArg,
|
||||
boolean ctrlKeyArg,
|
||||
boolean altKeyArg,
|
||||
boolean shiftKeyArg,
|
||||
boolean metaKeyArg,
|
||||
unsigned short buttonArg,
|
||||
EventTarget? relatedTargetArg,
|
||||
unsigned long allowedDirectionsArg,
|
||||
unsigned long directionArg,
|
||||
double deltaArg,
|
||||
unsigned long clickCount);
|
||||
optional boolean canBubbleArg = false,
|
||||
optional boolean cancelableArg = false,
|
||||
optional Window? viewArg = null,
|
||||
optional long detailArg = 0,
|
||||
optional long screenXArg = 0,
|
||||
optional long screenYArg = 0,
|
||||
optional long clientXArg = 0,
|
||||
optional long clientYArg = 0,
|
||||
optional boolean ctrlKeyArg = false,
|
||||
optional boolean altKeyArg = false,
|
||||
optional boolean shiftKeyArg = false,
|
||||
optional boolean metaKeyArg = false,
|
||||
optional short buttonArg = 0,
|
||||
optional EventTarget? relatedTargetArg = null,
|
||||
optional unsigned long allowedDirectionsArg = 0,
|
||||
optional unsigned long directionArg = 0,
|
||||
optional double deltaArg = 0,
|
||||
optional unsigned long clickCount = 0);
|
||||
};
|
||||
|
|
|
@ -21,13 +21,13 @@ interface StorageEvent : Event
|
|||
|
||||
// Bug 1016053 - This is not spec compliant.
|
||||
void initStorageEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
DOMString? key,
|
||||
DOMString? oldValue,
|
||||
DOMString? newValue,
|
||||
DOMString? url,
|
||||
Storage? storageArea);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional DOMString? key = null,
|
||||
optional DOMString? oldValue = null,
|
||||
optional DOMString? newValue = null,
|
||||
optional DOMString? url = null,
|
||||
optional Storage? storageArea = null);
|
||||
};
|
||||
|
||||
dictionary StorageEventInit : EventInit
|
||||
|
|
|
@ -15,6 +15,6 @@ interface TimeEvent : Event
|
|||
readonly attribute long detail;
|
||||
readonly attribute WindowProxy? view;
|
||||
void initTimeEvent(DOMString aType,
|
||||
Window? aView,
|
||||
long aDetail);
|
||||
optional Window? aView = null,
|
||||
optional long aDetail = 0);
|
||||
};
|
||||
|
|
|
@ -23,15 +23,15 @@ interface TouchEvent : UIEvent {
|
|||
readonly attribute boolean shiftKey;
|
||||
|
||||
void initTouchEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Window? view,
|
||||
long detail,
|
||||
boolean ctrlKey,
|
||||
boolean altKey,
|
||||
boolean shiftKey,
|
||||
boolean metaKey,
|
||||
TouchList? touches,
|
||||
TouchList? targetTouches,
|
||||
TouchList? changedTouches);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Window? view = null,
|
||||
optional long detail = 0,
|
||||
optional boolean ctrlKey = false,
|
||||
optional boolean altKey = false,
|
||||
optional boolean shiftKey = false,
|
||||
optional boolean metaKey = false,
|
||||
optional TouchList? touches = null,
|
||||
optional TouchList? targetTouches = null,
|
||||
optional TouchList? changedTouches = null);
|
||||
};
|
||||
|
|
|
@ -16,10 +16,10 @@ interface UIEvent : Event
|
|||
readonly attribute WindowProxy? view;
|
||||
readonly attribute long detail;
|
||||
void initUIEvent(DOMString aType,
|
||||
boolean aCanBubble,
|
||||
boolean aCancelable,
|
||||
Window? aView,
|
||||
long aDetail);
|
||||
optional boolean aCanBubble = false,
|
||||
optional boolean aCancelable = false,
|
||||
optional Window? aView = null,
|
||||
optional long aDetail = 0);
|
||||
};
|
||||
|
||||
// Additional DOM0 properties.
|
||||
|
|
|
@ -15,13 +15,13 @@ interface XULCommandEvent : UIEvent
|
|||
readonly attribute Event? sourceEvent;
|
||||
|
||||
void initCommandEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
Window? view,
|
||||
long detail,
|
||||
boolean ctrlKey,
|
||||
boolean altKey,
|
||||
boolean shiftKey,
|
||||
boolean metaKey,
|
||||
Event? sourceEvent);
|
||||
optional boolean canBubble = false,
|
||||
optional boolean cancelable = false,
|
||||
optional Window? view = null,
|
||||
optional long detail = 0,
|
||||
optional boolean ctrlKey = false,
|
||||
optional boolean altKey = false,
|
||||
optional boolean shiftKey = false,
|
||||
optional boolean metaKey = false,
|
||||
optional Event? sourceEvent = null);
|
||||
};
|
||||
|
|
|
@ -180,7 +180,7 @@ struct BasicLogger
|
|||
#else
|
||||
#if defined(MOZ_LOGGING)
|
||||
if (MOZ_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) {
|
||||
PR_LogPrint("%s%s", aString.c_str(), aNoNewline ? "" : "\n");
|
||||
MOZ_LOG(GetGFX2DLog(), PRLogLevelForLevel(aLevel), ("%s%s", aString.c_str(), aNoNewline ? "" : "\n"));
|
||||
} else
|
||||
#endif
|
||||
if ((LoggingPrefs::sGfxLogLevel >= LOG_DEBUG_PRLOG) ||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "gfxASurface.h" // for gfxASurface, etc
|
||||
#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete[], etc
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -111,7 +112,13 @@ BasicPlanarYCbCrImage::CopyData(const Data& aData)
|
|||
|
||||
gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format);
|
||||
mStride = gfxASurface::FormatStrideForWidth(iFormat, size.width);
|
||||
mDecodedBuffer = AllocateBuffer(size.height * mStride);
|
||||
mozilla::CheckedInt32 requiredBytes =
|
||||
mozilla::CheckedInt32(size.height) * mozilla::CheckedInt32(mStride);
|
||||
if (!requiredBytes.isValid()) {
|
||||
// invalid size
|
||||
return false;
|
||||
}
|
||||
mDecodedBuffer = AllocateBuffer(requiredBytes.value());
|
||||
if (!mDecodedBuffer) {
|
||||
// out of memory
|
||||
return false;
|
||||
|
|
|
@ -502,9 +502,9 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
|
|||
severity = 1.f;
|
||||
}
|
||||
mLayerManager->VisualFrameWarning(severity);
|
||||
PR_LogPrint("LayerTransactionParent::RecvUpdate transaction from process %d took %f ms",
|
||||
OtherPid(),
|
||||
latency.ToMilliseconds());
|
||||
printf_stderr("LayerTransactionParent::RecvUpdate transaction from process %d took %f ms",
|
||||
OtherPid(),
|
||||
latency.ToMilliseconds());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -775,7 +775,7 @@ PreparePattern(FcPattern* aPattern, bool aIsPrinterFont)
|
|||
cairo_ft_font_options_substitute(options, aPattern);
|
||||
cairo_font_options_destroy(options);
|
||||
FcPatternAddBool(aPattern, PRINTING_FC_PROPERTY, FcTrue);
|
||||
} else {
|
||||
} else if (!gfxPlatform::IsHeadless()) {
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
ApplyGdkScreenFontOptions(aPattern);
|
||||
|
||||
|
|
|
@ -836,6 +836,12 @@ gfxPlatform::InitMoz2DLogging()
|
|||
gfx::Factory::Init(cfg);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
gfxPlatform::IsHeadless()
|
||||
{
|
||||
return PR_GetEnv("MOZ_HEADLESS");
|
||||
}
|
||||
|
||||
static bool sLayersIPCIsUp = false;
|
||||
|
||||
/* static */ void
|
||||
|
|
|
@ -185,6 +185,8 @@ public:
|
|||
|
||||
static void InitMoz2DLogging();
|
||||
|
||||
static bool IsHeadless();
|
||||
|
||||
/**
|
||||
* Create an offscreen surface of the given dimensions
|
||||
* and image format.
|
||||
|
|
|
@ -73,12 +73,14 @@ static cairo_user_data_key_t cairo_gdk_drawable_key;
|
|||
|
||||
gfxPlatformGtk::gfxPlatformGtk()
|
||||
{
|
||||
gtk_init(nullptr, nullptr);
|
||||
if (!gfxPlatform::IsHeadless()) {
|
||||
gtk_init(nullptr, nullptr);
|
||||
}
|
||||
|
||||
mMaxGenericSubstitutions = UNINITIALIZED_VALUE;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (!gfxPlatform::IsHeadless() && XRE_IsParentProcess()) {
|
||||
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
|
||||
mozilla::Preferences::GetBool("gfx.xrender.enabled"))
|
||||
{
|
||||
|
@ -97,7 +99,7 @@ gfxPlatformGtk::gfxPlatformGtk()
|
|||
contentMask, BackendType::CAIRO);
|
||||
|
||||
#ifdef MOZ_X11
|
||||
if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
|
||||
if (gfxPlatform::IsHeadless() && GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
|
||||
mCompositorDisplay = XOpenDisplay(nullptr);
|
||||
MOZ_ASSERT(mCompositorDisplay, "Failed to create compositor display!");
|
||||
} else {
|
||||
|
|
|
@ -423,20 +423,22 @@ public:
|
|||
void InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
|
||||
|
||||
InsertOutcome Insert(NotNull<ISurfaceProvider*> aProvider,
|
||||
bool aSetAvailable)
|
||||
bool aSetAvailable,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
// If this is a duplicate surface, refuse to replace the original.
|
||||
// XXX(seth): Calling Lookup() and then RemoveEntry() does the lookup
|
||||
// twice. We'll make this more efficient in bug 1185137.
|
||||
LookupResult result = Lookup(aProvider->GetImageKey(),
|
||||
aProvider->GetSurfaceKey(),
|
||||
aAutoLock,
|
||||
/* aMarkUsed = */ false);
|
||||
if (MOZ_UNLIKELY(result)) {
|
||||
return InsertOutcome::FAILURE_ALREADY_PRESENT;
|
||||
}
|
||||
|
||||
if (result.Type() == MatchType::PENDING) {
|
||||
RemoveEntry(aProvider->GetImageKey(), aProvider->GetSurfaceKey());
|
||||
RemoveEntry(aProvider->GetImageKey(), aProvider->GetSurfaceKey(), aAutoLock);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(result.Type() == MatchType::NOT_FOUND ||
|
||||
|
@ -456,7 +458,7 @@ public:
|
|||
while (cost > mAvailableCost) {
|
||||
MOZ_ASSERT(!mCosts.IsEmpty(),
|
||||
"Removed everything and it still won't fit");
|
||||
Remove(mCosts.LastElement().Surface());
|
||||
Remove(mCosts.LastElement().Surface(), aAutoLock);
|
||||
}
|
||||
|
||||
// Locate the appropriate per-image cache. If there's not an existing cache
|
||||
|
@ -488,12 +490,13 @@ public:
|
|||
// Insert.
|
||||
MOZ_ASSERT(cost <= mAvailableCost, "Inserting despite too large a cost");
|
||||
cache->Insert(surface);
|
||||
StartTracking(surface);
|
||||
StartTracking(surface, aAutoLock);
|
||||
|
||||
return InsertOutcome::SUCCESS;
|
||||
}
|
||||
|
||||
void Remove(NotNull<CachedSurface*> aSurface)
|
||||
void Remove(NotNull<CachedSurface*> aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
ImageKey imageKey = aSurface->GetImageKey();
|
||||
|
||||
|
@ -505,7 +508,7 @@ public:
|
|||
static_cast<Image*>(imageKey)->OnSurfaceDiscarded(aSurface->GetSurfaceKey());
|
||||
}
|
||||
|
||||
StopTracking(aSurface);
|
||||
StopTracking(aSurface, aAutoLock);
|
||||
cache->Remove(aSurface);
|
||||
|
||||
// Remove the per-image cache if it's unneeded now. (Keep it if the image is
|
||||
|
@ -515,7 +518,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void StartTracking(NotNull<CachedSurface*> aSurface)
|
||||
void StartTracking(NotNull<CachedSurface*> aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
CostEntry costEntry = aSurface->GetCostEntry();
|
||||
MOZ_ASSERT(costEntry.GetCost() <= mAvailableCost,
|
||||
|
@ -530,11 +534,12 @@ public:
|
|||
mCosts.InsertElementSorted(costEntry);
|
||||
// This may fail during XPCOM shutdown, so we need to ensure the object is
|
||||
// tracked before calling RemoveObject in StopTracking.
|
||||
mExpirationTracker.AddObject(aSurface);
|
||||
mExpirationTracker.AddObjectLocked(aSurface, aAutoLock);
|
||||
}
|
||||
}
|
||||
|
||||
void StopTracking(NotNull<CachedSurface*> aSurface)
|
||||
void StopTracking(NotNull<CachedSurface*> aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
CostEntry costEntry = aSurface->GetCostEntry();
|
||||
|
||||
|
@ -546,7 +551,7 @@ public:
|
|||
"Shouldn't have a cost entry for a locked surface");
|
||||
} else {
|
||||
if (MOZ_LIKELY(aSurface->GetExpirationState()->IsTracked())) {
|
||||
mExpirationTracker.RemoveObject(aSurface);
|
||||
mExpirationTracker.RemoveObjectLocked(aSurface, aAutoLock);
|
||||
} else {
|
||||
// Our call to AddObject must have failed in StartTracking; most likely
|
||||
// we're in XPCOM shutdown right now.
|
||||
|
@ -565,6 +570,7 @@ public:
|
|||
|
||||
LookupResult Lookup(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey,
|
||||
const StaticMutexAutoLock& aAutoLock,
|
||||
bool aMarkUsed = true)
|
||||
{
|
||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
|
@ -587,12 +593,12 @@ public:
|
|||
if (!drawableSurface) {
|
||||
// The surface was released by the operating system. Remove the cache
|
||||
// entry as well.
|
||||
Remove(WrapNotNull(surface));
|
||||
Remove(WrapNotNull(surface), aAutoLock);
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
if (aMarkUsed) {
|
||||
MarkUsed(WrapNotNull(surface), WrapNotNull(cache));
|
||||
MarkUsed(WrapNotNull(surface), WrapNotNull(cache), aAutoLock);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(surface->GetSurfaceKey() == aSurfaceKey,
|
||||
|
@ -601,7 +607,8 @@ public:
|
|||
}
|
||||
|
||||
LookupResult LookupBestMatch(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
const SurfaceKey& aSurfaceKey,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache) {
|
||||
|
@ -632,7 +639,7 @@ public:
|
|||
|
||||
// The surface was released by the operating system. Remove the cache
|
||||
// entry as well.
|
||||
Remove(WrapNotNull(surface));
|
||||
Remove(WrapNotNull(surface), aAutoLock);
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(matchType == MatchType::EXACT,
|
||||
|
@ -644,7 +651,7 @@ public:
|
|||
surface->GetSurfaceKey().Flags() == aSurfaceKey.Flags());
|
||||
|
||||
if (matchType == MatchType::EXACT) {
|
||||
MarkUsed(WrapNotNull(surface), WrapNotNull(cache));
|
||||
MarkUsed(WrapNotNull(surface), WrapNotNull(cache), aAutoLock);
|
||||
}
|
||||
|
||||
return LookupResult(Move(drawableSurface), matchType);
|
||||
|
@ -660,7 +667,8 @@ public:
|
|||
return size_t(mMaxCost);
|
||||
}
|
||||
|
||||
void SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider)
|
||||
void SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
if (!aProvider->Availability().IsPlaceholder()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Calling SurfaceAvailable on non-placeholder");
|
||||
|
@ -673,7 +681,7 @@ public:
|
|||
// surface first, but it's fine either way.
|
||||
// XXX(seth): This could be implemented more efficiently; we should be able
|
||||
// to just update our data structures without reinserting.
|
||||
Insert(aProvider, /* aSetAvailable = */ true);
|
||||
Insert(aProvider, /* aSetAvailable = */ true, aAutoLock);
|
||||
}
|
||||
|
||||
void LockImage(const ImageKey aImageKey)
|
||||
|
@ -690,7 +698,7 @@ public:
|
|||
// image should arrange for Lookup() to touch them if they are still useful.
|
||||
}
|
||||
|
||||
void UnlockImage(const ImageKey aImageKey)
|
||||
void UnlockImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache || !cache->IsLocked()) {
|
||||
|
@ -698,10 +706,10 @@ public:
|
|||
}
|
||||
|
||||
cache->SetLocked(false);
|
||||
DoUnlockSurfaces(WrapNotNull(cache), /* aStaticOnly = */ false);
|
||||
DoUnlockSurfaces(WrapNotNull(cache), /* aStaticOnly = */ false, aAutoLock);
|
||||
}
|
||||
|
||||
void UnlockEntries(const ImageKey aImageKey)
|
||||
void UnlockEntries(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache || !cache->IsLocked()) {
|
||||
|
@ -711,10 +719,10 @@ public:
|
|||
// (Note that we *don't* unlock the per-image cache here; that's the
|
||||
// difference between this and UnlockImage.)
|
||||
DoUnlockSurfaces(WrapNotNull(cache),
|
||||
/* aStaticOnly = */ !gfxPrefs::ImageMemAnimatedDiscardable());
|
||||
/* aStaticOnly = */ !gfxPrefs::ImageMemAnimatedDiscardable(), aAutoLock);
|
||||
}
|
||||
|
||||
void RemoveImage(const ImageKey aImageKey)
|
||||
void RemoveImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache) {
|
||||
|
@ -727,7 +735,7 @@ public:
|
|||
// small, performance should be good, but if usage patterns change we should
|
||||
// change the data structure used for mCosts.
|
||||
for (auto iter = cache->ConstIter(); !iter.Done(); iter.Next()) {
|
||||
StopTracking(WrapNotNull(iter.UserData()));
|
||||
StopTracking(WrapNotNull(iter.UserData()), aAutoLock);
|
||||
}
|
||||
|
||||
// The per-image cache isn't needed anymore, so remove it as well.
|
||||
|
@ -735,17 +743,17 @@ public:
|
|||
mImageCaches.Remove(aImageKey);
|
||||
}
|
||||
|
||||
void DiscardAll()
|
||||
void DiscardAll(const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
// Remove in order of cost because mCosts is an array and the other data
|
||||
// structures are all hash tables. Note that locked surfaces are not
|
||||
// removed, since they aren't present in mCosts.
|
||||
while (!mCosts.IsEmpty()) {
|
||||
Remove(mCosts.LastElement().Surface());
|
||||
Remove(mCosts.LastElement().Surface(), aAutoLock);
|
||||
}
|
||||
}
|
||||
|
||||
void DiscardForMemoryPressure()
|
||||
void DiscardForMemoryPressure(const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
// Compute our discardable cost. Since locked surfaces aren't discardable,
|
||||
// we exclude them.
|
||||
|
@ -760,28 +768,29 @@ public:
|
|||
|
||||
if (targetCost > mMaxCost - mLockedCost) {
|
||||
MOZ_ASSERT_UNREACHABLE("Target cost is more than we can discard");
|
||||
DiscardAll();
|
||||
DiscardAll(aAutoLock);
|
||||
return;
|
||||
}
|
||||
|
||||
// Discard surfaces until we've reduced our cost to our target cost.
|
||||
while (mAvailableCost < targetCost) {
|
||||
MOZ_ASSERT(!mCosts.IsEmpty(), "Removed everything and still not done");
|
||||
Remove(mCosts.LastElement().Surface());
|
||||
Remove(mCosts.LastElement().Surface(), aAutoLock);
|
||||
}
|
||||
}
|
||||
|
||||
void LockSurface(NotNull<CachedSurface*> aSurface)
|
||||
void LockSurface(NotNull<CachedSurface*> aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
if (aSurface->IsPlaceholder() || aSurface->IsLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StopTracking(aSurface);
|
||||
StopTracking(aSurface, aAutoLock);
|
||||
|
||||
// Lock the surface. This can fail.
|
||||
aSurface->SetLocked(true);
|
||||
StartTracking(aSurface);
|
||||
StartTracking(aSurface, aAutoLock);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
|
@ -848,16 +857,18 @@ private:
|
|||
}
|
||||
|
||||
void MarkUsed(NotNull<CachedSurface*> aSurface,
|
||||
NotNull<ImageSurfaceCache*> aCache)
|
||||
NotNull<ImageSurfaceCache*> aCache,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
if (aCache->IsLocked()) {
|
||||
LockSurface(aSurface);
|
||||
LockSurface(aSurface, aAutoLock);
|
||||
} else {
|
||||
mExpirationTracker.MarkUsed(aSurface);
|
||||
mExpirationTracker.MarkUsedLocked(aSurface, aAutoLock);
|
||||
}
|
||||
}
|
||||
|
||||
void DoUnlockSurfaces(NotNull<ImageSurfaceCache*> aCache, bool aStaticOnly)
|
||||
void DoUnlockSurfaces(NotNull<ImageSurfaceCache*> aCache, bool aStaticOnly,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
// Unlock all the surfaces the per-image cache is holding.
|
||||
for (auto iter = aCache->ConstIter(); !iter.Done(); iter.Next()) {
|
||||
|
@ -868,14 +879,15 @@ private:
|
|||
if (aStaticOnly && surface->GetSurfaceKey().Playback() != PlaybackType::eStatic) {
|
||||
continue;
|
||||
}
|
||||
StopTracking(surface);
|
||||
StopTracking(surface, aAutoLock);
|
||||
surface->SetLocked(false);
|
||||
StartTracking(surface);
|
||||
StartTracking(surface, aAutoLock);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveEntry(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
const SurfaceKey& aSurfaceKey,
|
||||
const StaticMutexAutoLock& aAutoLock)
|
||||
{
|
||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache) {
|
||||
|
@ -887,23 +899,29 @@ private:
|
|||
return; // Lookup in the per-image cache missed.
|
||||
}
|
||||
|
||||
Remove(WrapNotNull(surface));
|
||||
Remove(WrapNotNull(surface), aAutoLock);
|
||||
}
|
||||
|
||||
struct SurfaceTracker : public nsExpirationTracker<CachedSurface, 2>
|
||||
struct SurfaceTracker : public ExpirationTrackerImpl<CachedSurface, 2,
|
||||
StaticMutex,
|
||||
StaticMutexAutoLock>
|
||||
{
|
||||
explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
|
||||
: nsExpirationTracker<CachedSurface, 2>(aSurfaceCacheExpirationTimeMS,
|
||||
"SurfaceTracker")
|
||||
: ExpirationTrackerImpl<CachedSurface, 2,
|
||||
StaticMutex, StaticMutexAutoLock>(
|
||||
aSurfaceCacheExpirationTimeMS, "SurfaceTracker")
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual void NotifyExpired(CachedSurface* aSurface) override
|
||||
void NotifyExpiredLocked(CachedSurface* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock) override
|
||||
{
|
||||
StaticMutexAutoLock lock(sInstanceMutex);
|
||||
if (sInstance) {
|
||||
sInstance->Remove(WrapNotNull(aSurface));
|
||||
}
|
||||
sInstance->Remove(WrapNotNull(aSurface), aAutoLock);
|
||||
}
|
||||
|
||||
StaticMutex& GetMutex() override
|
||||
{
|
||||
return sInstanceMutex;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -917,7 +935,7 @@ private:
|
|||
{
|
||||
StaticMutexAutoLock lock(sInstanceMutex);
|
||||
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
|
||||
sInstance->DiscardForMemoryPressure();
|
||||
sInstance->DiscardForMemoryPressure(lock);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1019,7 +1037,7 @@ SurfaceCache::Lookup(const ImageKey aImageKey,
|
|||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
return sInstance->Lookup(aImageKey, aSurfaceKey);
|
||||
return sInstance->Lookup(aImageKey, aSurfaceKey, lock);
|
||||
}
|
||||
|
||||
/* static */ LookupResult
|
||||
|
@ -1031,7 +1049,7 @@ SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
|
|||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
return sInstance->LookupBestMatch(aImageKey, aSurfaceKey);
|
||||
return sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock);
|
||||
}
|
||||
|
||||
/* static */ InsertOutcome
|
||||
|
@ -1042,7 +1060,7 @@ SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
|
|||
return InsertOutcome::FAILURE;
|
||||
}
|
||||
|
||||
return sInstance->Insert(aProvider, /* aSetAvailable = */ false);
|
||||
return sInstance->Insert(aProvider, /* aSetAvailable = */ false, lock);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
@ -1076,7 +1094,7 @@ SurfaceCache::SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider)
|
|||
return;
|
||||
}
|
||||
|
||||
sInstance->SurfaceAvailable(aProvider);
|
||||
sInstance->SurfaceAvailable(aProvider, lock);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
@ -1093,7 +1111,7 @@ SurfaceCache::UnlockImage(const ImageKey aImageKey)
|
|||
{
|
||||
StaticMutexAutoLock lock(sInstanceMutex);
|
||||
if (sInstance) {
|
||||
return sInstance->UnlockImage(aImageKey);
|
||||
return sInstance->UnlockImage(aImageKey, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1102,7 +1120,7 @@ SurfaceCache::UnlockEntries(const ImageKey aImageKey)
|
|||
{
|
||||
StaticMutexAutoLock lock(sInstanceMutex);
|
||||
if (sInstance) {
|
||||
return sInstance->UnlockEntries(aImageKey);
|
||||
return sInstance->UnlockEntries(aImageKey, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1111,7 +1129,7 @@ SurfaceCache::RemoveImage(const ImageKey aImageKey)
|
|||
{
|
||||
StaticMutexAutoLock lock(sInstanceMutex);
|
||||
if (sInstance) {
|
||||
sInstance->RemoveImage(aImageKey);
|
||||
sInstance->RemoveImage(aImageKey, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1120,7 +1138,7 @@ SurfaceCache::DiscardAll()
|
|||
{
|
||||
StaticMutexAutoLock lock(sInstanceMutex);
|
||||
if (sInstance) {
|
||||
sInstance->DiscardAll();
|
||||
sInstance->DiscardAll(lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "NullPrincipal.h"
|
||||
#include "nsIURL.h"
|
||||
#include "prlink.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsIconChannel,
|
||||
nsIRequest,
|
||||
|
@ -308,6 +309,10 @@ nsIconChannel::Init(nsIURI* aURI)
|
|||
nsCOMPtr<nsIMozIconURI> iconURI = do_QueryInterface(aURI);
|
||||
NS_ASSERTION(iconURI, "URI is not an nsIMozIconURI");
|
||||
|
||||
if (gfxPlatform::IsHeadless()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsAutoCString stockIcon;
|
||||
iconURI->GetStockIcon(stockIcon);
|
||||
if (stockIcon.IsEmpty()) {
|
||||
|
|
|
@ -121,7 +121,7 @@ std::wstring SysInfo::GetEnvVar(const wchar_t* var) {
|
|||
|
||||
// static
|
||||
std::string SysInfo::OperatingSystemName() {
|
||||
utsname info;
|
||||
struct utsname info;
|
||||
if (uname(&info) < 0) {
|
||||
NOTREACHED();
|
||||
return "";
|
||||
|
@ -131,7 +131,7 @@ std::string SysInfo::OperatingSystemName() {
|
|||
|
||||
// static
|
||||
std::string SysInfo::CPUArchitecture() {
|
||||
utsname info;
|
||||
struct utsname info;
|
||||
if (uname(&info) < 0) {
|
||||
NOTREACHED();
|
||||
return "";
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#if defined(OS_MACOSX)
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
@ -39,8 +40,14 @@
|
|||
#include "mozilla/ipc/Faulty.h"
|
||||
#endif
|
||||
|
||||
// Work around possible OS limitations.
|
||||
// Use OS specific iovec array limit where it's possible.
|
||||
#if defined(IOV_MAX)
|
||||
static const size_t kMaxIOVecSize = IOV_MAX;
|
||||
#elif defined(ANDROID)
|
||||
static const size_t kMaxIOVecSize = 256;
|
||||
#else
|
||||
static const size_t kMaxIOVecSize = 16;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
#include "GeckoTaskTracerImpl.h"
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace js {
|
|||
/* 2^32-2, inclusive */
|
||||
const uint32_t MAX_ARRAY_INDEX = 4294967294u;
|
||||
|
||||
inline bool
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IdIsIndex(jsid id, uint32_t* indexp)
|
||||
{
|
||||
if (JSID_IS_INT(id)) {
|
||||
|
@ -31,7 +31,11 @@ IdIsIndex(jsid id, uint32_t* indexp)
|
|||
if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
|
||||
return false;
|
||||
|
||||
return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp);
|
||||
JSAtom* atom = JSID_TO_ATOM(id);
|
||||
if (atom->length() == 0 || !JS7_ISDEC(atom->latin1OrTwoByteChar(0)))
|
||||
return false;
|
||||
|
||||
return js::StringIsArrayIndex(atom, indexp);
|
||||
}
|
||||
|
||||
// The methods below only create dense boxed arrays.
|
||||
|
|
|
@ -456,6 +456,58 @@ NativeObject::create(JSContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap
|
|||
return nobj;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
NativeObject::updateSlotsForSpan(JSContext* cx, size_t oldSpan, size_t newSpan)
|
||||
{
|
||||
MOZ_ASSERT(oldSpan != newSpan);
|
||||
|
||||
size_t oldCount = dynamicSlotsCount(numFixedSlots(), oldSpan, getClass());
|
||||
size_t newCount = dynamicSlotsCount(numFixedSlots(), newSpan, getClass());
|
||||
|
||||
if (oldSpan < newSpan) {
|
||||
if (oldCount < newCount && !growSlots(cx, oldCount, newCount))
|
||||
return false;
|
||||
|
||||
if (newSpan == oldSpan + 1)
|
||||
initSlotUnchecked(oldSpan, UndefinedValue());
|
||||
else
|
||||
initializeSlotRange(oldSpan, newSpan - oldSpan);
|
||||
} else {
|
||||
/* Trigger write barriers on the old slots before reallocating. */
|
||||
prepareSlotRangeForOverwrite(newSpan, oldSpan);
|
||||
invalidateSlotRange(newSpan, oldSpan - newSpan);
|
||||
|
||||
if (oldCount > newCount)
|
||||
shrinkSlots(cx, oldCount, newCount);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
NativeObject::setLastProperty(JSContext* cx, Shape* shape)
|
||||
{
|
||||
MOZ_ASSERT(!inDictionaryMode());
|
||||
MOZ_ASSERT(!shape->inDictionary());
|
||||
MOZ_ASSERT(shape->zone() == zone());
|
||||
MOZ_ASSERT(shape->numFixedSlots() == numFixedSlots());
|
||||
MOZ_ASSERT(shape->getObjectClass() == getClass());
|
||||
|
||||
size_t oldSpan = lastProperty()->slotSpan();
|
||||
size_t newSpan = shape->slotSpan();
|
||||
|
||||
if (oldSpan == newSpan) {
|
||||
shape_ = shape;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(!updateSlotsForSpan(cx, oldSpan, newSpan)))
|
||||
return false;
|
||||
|
||||
shape_ = shape;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
|
||||
static inline PlainObject*
|
||||
CopyInitializerObject(JSContext* cx, HandlePlainObject baseobj, NewObjectKind newKind = GenericObject)
|
||||
|
|
|
@ -299,58 +299,6 @@ js::NativeObject::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class*
|
|||
return slots;
|
||||
}
|
||||
|
||||
inline bool
|
||||
NativeObject::updateSlotsForSpan(JSContext* cx, size_t oldSpan, size_t newSpan)
|
||||
{
|
||||
MOZ_ASSERT(oldSpan != newSpan);
|
||||
|
||||
size_t oldCount = dynamicSlotsCount(numFixedSlots(), oldSpan, getClass());
|
||||
size_t newCount = dynamicSlotsCount(numFixedSlots(), newSpan, getClass());
|
||||
|
||||
if (oldSpan < newSpan) {
|
||||
if (oldCount < newCount && !growSlots(cx, oldCount, newCount))
|
||||
return false;
|
||||
|
||||
if (newSpan == oldSpan + 1)
|
||||
initSlotUnchecked(oldSpan, UndefinedValue());
|
||||
else
|
||||
initializeSlotRange(oldSpan, newSpan - oldSpan);
|
||||
} else {
|
||||
/* Trigger write barriers on the old slots before reallocating. */
|
||||
prepareSlotRangeForOverwrite(newSpan, oldSpan);
|
||||
invalidateSlotRange(newSpan, oldSpan - newSpan);
|
||||
|
||||
if (oldCount > newCount)
|
||||
shrinkSlots(cx, oldCount, newCount);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeObject::setLastProperty(JSContext* cx, Shape* shape)
|
||||
{
|
||||
MOZ_ASSERT(!inDictionaryMode());
|
||||
MOZ_ASSERT(!shape->inDictionary());
|
||||
MOZ_ASSERT(shape->zone() == zone());
|
||||
MOZ_ASSERT(shape->numFixedSlots() == numFixedSlots());
|
||||
MOZ_ASSERT(shape->getObjectClass() == getClass());
|
||||
|
||||
size_t oldSpan = lastProperty()->slotSpan();
|
||||
size_t newSpan = shape->slotSpan();
|
||||
|
||||
if (oldSpan == newSpan) {
|
||||
shape_ = shape;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!updateSlotsForSpan(cx, oldSpan, newSpan))
|
||||
return false;
|
||||
|
||||
shape_ = shape;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
NativeObject::setLastPropertyShrinkFixedSlots(Shape* shape)
|
||||
{
|
||||
|
@ -1091,23 +1039,22 @@ js::NativeLookupOwnProperty<NoGC>(JSContext* cx, NativeObject* const& obj, const
|
|||
|
||||
/*** [[DefineOwnProperty]] ***********************************************************************/
|
||||
|
||||
static inline bool
|
||||
CallAddPropertyHook(JSContext* cx, HandleNativeObject obj, HandleShape shape,
|
||||
HandleValue value)
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
CallAddPropertyHook(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value)
|
||||
{
|
||||
if (JSAddPropertyOp addProperty = obj->getClass()->getAddProperty()) {
|
||||
JSAddPropertyOp addProperty = obj->getClass()->getAddProperty();
|
||||
if (MOZ_UNLIKELY(addProperty)) {
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
|
||||
RootedId id(cx, shape->propid());
|
||||
if (!CallJSAddPropertyOp(cx, addProperty, obj, id, value)) {
|
||||
NativeObject::removeProperty(cx, obj, shape->propid());
|
||||
NativeObject::removeProperty(cx, obj, id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
CallAddPropertyHookDense(JSContext* cx, HandleNativeObject obj, uint32_t index,
|
||||
HandleValue value)
|
||||
{
|
||||
|
@ -1120,7 +1067,8 @@ CallAddPropertyHookDense(JSContext* cx, HandleNativeObject obj, uint32_t index,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (JSAddPropertyOp addProperty = obj->getClass()->getAddProperty()) {
|
||||
JSAddPropertyOp addProperty = obj->getClass()->getAddProperty();
|
||||
if (MOZ_UNLIKELY(addProperty)) {
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
|
||||
if (!obj->maybeCopyElementsForWrite(cx))
|
||||
|
@ -1228,7 +1176,10 @@ PurgeEnvironmentChain(JSContext* cx, HandleObject obj, HandleId id)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
enum class IsAddOrChange { Add, AddOrChange };
|
||||
|
||||
template <IsAddOrChange AddOrChange>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
AddOrChangeProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc)
|
||||
{
|
||||
|
@ -1257,8 +1208,16 @@ AddOrChangeProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
}
|
||||
}
|
||||
|
||||
RootedShape shape(cx, NativeObject::putProperty(cx, obj, id, desc.getter(), desc.setter(),
|
||||
SHAPE_INVALID_SLOT, desc.attributes(), 0));
|
||||
// If we know this is a new property we can call addProperty instead of
|
||||
// the slower putProperty.
|
||||
Shape* shape;
|
||||
if (AddOrChange == IsAddOrChange::Add) {
|
||||
shape = NativeObject::addProperty(cx, obj, id, desc.getter(), desc.setter(),
|
||||
SHAPE_INVALID_SLOT, desc.attributes(), 0);
|
||||
} else {
|
||||
shape = NativeObject::putProperty(cx, obj, id, desc.getter(), desc.setter(),
|
||||
SHAPE_INVALID_SLOT, desc.attributes(), 0);
|
||||
}
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
|
@ -1282,7 +1241,7 @@ AddOrChangeProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
}
|
||||
}
|
||||
|
||||
return CallAddPropertyHook(cx, obj, shape, desc.value());
|
||||
return CallAddPropertyHook(cx, obj, id, desc.value());
|
||||
}
|
||||
|
||||
static bool IsConfigurable(unsigned attrs) { return (attrs & JSPROP_PERMANENT) == 0; }
|
||||
|
@ -1481,7 +1440,7 @@ js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
// Fill in missing desc fields with defaults.
|
||||
CompletePropertyDescriptor(&desc);
|
||||
|
||||
if (!AddOrChangeProperty(cx, obj, id, desc))
|
||||
if (!AddOrChangeProperty<IsAddOrChange::Add>(cx, obj, id, desc))
|
||||
return false;
|
||||
return result.succeed();
|
||||
}
|
||||
|
@ -1627,7 +1586,7 @@ js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
}
|
||||
|
||||
// Step 10.
|
||||
if (!AddOrChangeProperty(cx, obj, id, desc))
|
||||
if (!AddOrChangeProperty<IsAddOrChange::AddOrChange>(cx, obj, id, desc))
|
||||
return false;
|
||||
return result.succeed();
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ class NativeObject : public ShapedObject
|
|||
|
||||
// Update the last property, keeping the number of allocated slots in sync
|
||||
// with the object's new slot span.
|
||||
bool setLastProperty(JSContext* cx, Shape* shape);
|
||||
MOZ_ALWAYS_INLINE bool setLastProperty(JSContext* cx, Shape* shape);
|
||||
|
||||
// As for setLastProperty(), but allows the number of fixed slots to
|
||||
// change. This can only be used when fixed slots are being erased from the
|
||||
|
@ -735,8 +735,6 @@ class NativeObject : public ShapedObject
|
|||
void freeSlot(JSContext* cx, uint32_t slot);
|
||||
|
||||
private:
|
||||
static Shape* getChildPropertyOnDictionary(JSContext* cx, HandleNativeObject obj,
|
||||
HandleShape parent, MutableHandle<StackShape> child);
|
||||
static Shape* getChildProperty(JSContext* cx, HandleNativeObject obj,
|
||||
HandleShape parent, MutableHandle<StackShape> child);
|
||||
|
||||
|
@ -881,7 +879,7 @@ class NativeObject : public ShapedObject
|
|||
static const uint32_t MAX_FIXED_SLOTS = 16;
|
||||
|
||||
protected:
|
||||
inline bool updateSlotsForSpan(JSContext* cx, size_t oldSpan, size_t newSpan);
|
||||
MOZ_ALWAYS_INLINE bool updateSlotsForSpan(JSContext* cx, size_t oldSpan, size_t newSpan);
|
||||
|
||||
private:
|
||||
void prepareElementRangeForOverwrite(size_t start, size_t end) {
|
||||
|
|
|
@ -291,8 +291,9 @@ Shape::replaceLastProperty(JSContext* cx, StackBaseShape& base,
|
|||
* one of lastProperty() or lastProperty()->parent.
|
||||
*/
|
||||
/* static */ Shape*
|
||||
NativeObject::getChildPropertyOnDictionary(JSContext* cx, HandleNativeObject obj,
|
||||
HandleShape parent, MutableHandle<StackShape> child)
|
||||
NativeObject::getChildProperty(JSContext* cx,
|
||||
HandleNativeObject obj, HandleShape parent,
|
||||
MutableHandle<StackShape> child)
|
||||
{
|
||||
/*
|
||||
* Shared properties have no slot, but slot_ will reflect that of parent.
|
||||
|
@ -325,11 +326,9 @@ NativeObject::getChildPropertyOnDictionary(JSContext* cx, HandleNativeObject obj
|
|||
}
|
||||
}
|
||||
|
||||
RootedShape shape(cx);
|
||||
|
||||
if (obj->inDictionaryMode()) {
|
||||
MOZ_ASSERT(parent == obj->lastProperty());
|
||||
shape = child.isAccessorShape() ? Allocate<AccessorShape>(cx) : Allocate<Shape>(cx);
|
||||
Shape* shape = child.isAccessorShape() ? Allocate<AccessorShape>(cx) : Allocate<Shape>(cx);
|
||||
if (!shape)
|
||||
return nullptr;
|
||||
if (child.hasSlot() && child.slot() >= obj->lastProperty()->base()->slotSpan()) {
|
||||
|
@ -339,28 +338,16 @@ NativeObject::getChildPropertyOnDictionary(JSContext* cx, HandleNativeObject obj
|
|||
}
|
||||
}
|
||||
shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
|
||||
return shape;
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
/* static */ Shape*
|
||||
NativeObject::getChildProperty(JSContext* cx,
|
||||
HandleNativeObject obj, HandleShape parent,
|
||||
MutableHandle<StackShape> child)
|
||||
{
|
||||
Shape* shape = getChildPropertyOnDictionary(cx, obj, parent, child);
|
||||
|
||||
if (!obj->inDictionaryMode()) {
|
||||
shape = cx->zone()->propertyTree().getChild(cx, parent, child);
|
||||
if (!shape)
|
||||
return nullptr;
|
||||
//MOZ_ASSERT(shape->parent == parent);
|
||||
//MOZ_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
|
||||
if (!obj->setLastProperty(cx, shape))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Shape* shape = cx->zone()->propertyTree().getChild(cx, parent, child);
|
||||
if (!shape)
|
||||
return nullptr;
|
||||
//MOZ_ASSERT(shape->parent == parent);
|
||||
//MOZ_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
|
||||
if (!obj->setLastProperty(cx, shape))
|
||||
return nullptr;
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
@ -431,6 +418,7 @@ NativeObject::addProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
MOZ_ASSERT(getter != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
MOZ_ASSERT(obj->nonProxyIsExtensible());
|
||||
MOZ_ASSERT(!obj->containsPure(id));
|
||||
|
||||
AutoKeepShapeTables keep(cx);
|
||||
ShapeTable::Entry* entry = nullptr;
|
||||
|
|
|
@ -296,9 +296,14 @@ this.XPCOMUtils = {
|
|||
* The name of the preference to read.
|
||||
* @param aDefaultValue
|
||||
* The default value to use, if the preference is not defined.
|
||||
* @param aOnUpdate
|
||||
* A function to call upon update. Receives as arguments
|
||||
* `(aPreference, previousValue, newValue)`
|
||||
*/
|
||||
defineLazyPreferenceGetter: function XPCU_defineLazyPreferenceGetter(
|
||||
aObject, aName, aPreference, aDefaultValue = null)
|
||||
aObject, aName, aPreference,
|
||||
aDefaultValue = null,
|
||||
aOnUpdate = null)
|
||||
{
|
||||
// Note: We need to keep a reference to this observer alive as long
|
||||
// as aObject is alive. This means that all of our getters need to
|
||||
|
@ -312,7 +317,18 @@ this.XPCOMUtils = {
|
|||
|
||||
observe(subject, topic, data) {
|
||||
if (data == aPreference) {
|
||||
this.value = undefined;
|
||||
if (aOnUpdate) {
|
||||
let previous = this.value;
|
||||
|
||||
// Fetch and cache value.
|
||||
this.value = undefined;
|
||||
let latest = lazyGetter();
|
||||
aOnUpdate(data, previous, latest);
|
||||
} else {
|
||||
|
||||
// Empty cache, next call to the getter will cause refetch.
|
||||
this.value = undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace mozilla {
|
|||
|
||||
void
|
||||
FramePropertyTable::SetInternal(
|
||||
const nsIFrame* aFrame, UntypedDescriptor aProperty, void* aValue)
|
||||
nsIFrame* aFrame, UntypedDescriptor aProperty, void* aValue)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ASSERTION(aFrame, "Null frame?");
|
||||
|
@ -22,6 +22,7 @@ FramePropertyTable::SetInternal(
|
|||
if (mLastFrame != aFrame || !mLastEntry) {
|
||||
mLastFrame = aFrame;
|
||||
mLastEntry = mEntries.PutEntry(aFrame);
|
||||
aFrame->AddStateBits(NS_FRAME_HAS_PROPERTIES);
|
||||
}
|
||||
Entry* entry = mLastEntry;
|
||||
|
||||
|
@ -63,7 +64,8 @@ FramePropertyTable::SetInternal(
|
|||
|
||||
void*
|
||||
FramePropertyTable::GetInternal(
|
||||
const nsIFrame* aFrame, UntypedDescriptor aProperty, bool* aFoundResult)
|
||||
const nsIFrame* aFrame, UntypedDescriptor aProperty, bool aSkipBitCheck,
|
||||
bool* aFoundResult)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "Null frame?");
|
||||
NS_ASSERTION(aProperty, "Null property?");
|
||||
|
@ -72,6 +74,10 @@ FramePropertyTable::GetInternal(
|
|||
*aFoundResult = false;
|
||||
}
|
||||
|
||||
if (!aSkipBitCheck && !(aFrame->GetStateBits() & NS_FRAME_HAS_PROPERTIES)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We can end up here during parallel style traversal, in which case the main
|
||||
// thread is blocked. Reading from the cache is fine on any thread, but we
|
||||
// only want to write to it in the main-thread case.
|
||||
|
@ -82,6 +88,8 @@ FramePropertyTable::GetInternal(
|
|||
mLastEntry = entry;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(entry || aSkipBitCheck,
|
||||
"NS_FRAME_HAS_PROPERTIES bit should match whether entry exists");
|
||||
if (!entry)
|
||||
return nullptr;
|
||||
|
||||
|
@ -111,7 +119,8 @@ FramePropertyTable::GetInternal(
|
|||
|
||||
void*
|
||||
FramePropertyTable::RemoveInternal(
|
||||
const nsIFrame* aFrame, UntypedDescriptor aProperty, bool* aFoundResult)
|
||||
nsIFrame* aFrame, UntypedDescriptor aProperty, bool aSkipBitCheck,
|
||||
bool* aFoundResult)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ASSERTION(aFrame, "Null frame?");
|
||||
|
@ -121,11 +130,17 @@ FramePropertyTable::RemoveInternal(
|
|||
*aFoundResult = false;
|
||||
}
|
||||
|
||||
if (!aSkipBitCheck && !(aFrame->GetStateBits() & NS_FRAME_HAS_PROPERTIES)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mLastFrame != aFrame) {
|
||||
mLastFrame = aFrame;
|
||||
mLastEntry = mEntries.GetEntry(aFrame);
|
||||
}
|
||||
Entry* entry = mLastEntry;
|
||||
MOZ_ASSERT(entry || aSkipBitCheck,
|
||||
"NS_FRAME_HAS_PROPERTIES bit should match whether entry exists");
|
||||
if (!entry)
|
||||
return nullptr;
|
||||
|
||||
|
@ -136,6 +151,7 @@ FramePropertyTable::RemoveInternal(
|
|||
// Here it's ok to use RemoveEntry() -- which may resize mEntries --
|
||||
// because we null mLastEntry at the same time.
|
||||
mEntries.RemoveEntry(entry);
|
||||
aFrame->RemoveStateBits(NS_FRAME_HAS_PROPERTIES);
|
||||
mLastEntry = nullptr;
|
||||
if (aFoundResult) {
|
||||
*aFoundResult = true;
|
||||
|
@ -176,14 +192,14 @@ FramePropertyTable::RemoveInternal(
|
|||
|
||||
void
|
||||
FramePropertyTable::DeleteInternal(
|
||||
const nsIFrame* aFrame, UntypedDescriptor aProperty)
|
||||
nsIFrame* aFrame, UntypedDescriptor aProperty, bool aSkipBitCheck)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ASSERTION(aFrame, "Null frame?");
|
||||
NS_ASSERTION(aProperty, "Null property?");
|
||||
|
||||
bool found;
|
||||
void* v = RemoveInternal(aFrame, aProperty, &found);
|
||||
void* v = RemoveInternal(aFrame, aProperty, aSkipBitCheck, &found);
|
||||
if (found) {
|
||||
PropertyValue pv(aProperty, v);
|
||||
pv.DestroyValueFor(aFrame);
|
||||
|
@ -206,11 +222,17 @@ FramePropertyTable::DeleteAllForEntry(Entry* aEntry)
|
|||
}
|
||||
|
||||
void
|
||||
FramePropertyTable::DeleteAllFor(const nsIFrame* aFrame)
|
||||
FramePropertyTable::DeleteAllFor(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "Null frame?");
|
||||
|
||||
if (!(aFrame->GetStateBits() & NS_FRAME_HAS_PROPERTIES)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Entry* entry = mEntries.GetEntry(aFrame);
|
||||
MOZ_ASSERT(entry,
|
||||
"NS_FRAME_HAS_PROPERTIES bit should match whether entry exists");
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
|
@ -226,6 +248,8 @@ FramePropertyTable::DeleteAllFor(const nsIFrame* aFrame)
|
|||
// mLastEntry points into mEntries, so we use RawRemoveEntry() which will not
|
||||
// resize mEntries.
|
||||
mEntries.RawRemoveEntry(entry);
|
||||
|
||||
// Don't bother unsetting NS_FRAME_HAS_PROPERTIES, since aFrame is going away
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -165,7 +165,7 @@ public:
|
|||
* is destroyed.
|
||||
*/
|
||||
template<typename T>
|
||||
void Set(const nsIFrame* aFrame, Descriptor<T> aProperty,
|
||||
void Set(nsIFrame* aFrame, Descriptor<T> aProperty,
|
||||
PropertyType<T> aValue)
|
||||
{
|
||||
void* ptr = ReinterpretHelper<T>::ToPointer(aValue);
|
||||
|
@ -188,12 +188,25 @@ public:
|
|||
*
|
||||
* - Calling Has() before Set() in cases where we don't want to overwrite
|
||||
* an existing value for the frame property.
|
||||
*
|
||||
* The HasSkippingBitCheck variant doesn't test NS_FRAME_HAS_PROPERTIES
|
||||
* on aFrame, so it is safe to call after aFrame has been destroyed as
|
||||
* long as, since that destruction happened, it isn't possible for a
|
||||
* new frame to have been created and the same property added.
|
||||
*/
|
||||
template<typename T>
|
||||
bool Has(const nsIFrame* aFrame, Descriptor<T> aProperty)
|
||||
{
|
||||
bool foundResult = false;
|
||||
mozilla::Unused << GetInternal(aFrame, aProperty, &foundResult);
|
||||
mozilla::Unused << GetInternal(aFrame, aProperty, false, &foundResult);
|
||||
return foundResult;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool HasSkippingBitCheck(const nsIFrame* aFrame, Descriptor<T> aProperty)
|
||||
{
|
||||
bool foundResult = false;
|
||||
mozilla::Unused << GetInternal(aFrame, aProperty, true, &foundResult);
|
||||
return foundResult;
|
||||
}
|
||||
|
||||
|
@ -212,7 +225,7 @@ public:
|
|||
PropertyType<T> Get(const nsIFrame* aFrame, Descriptor<T> aProperty,
|
||||
bool* aFoundResult = nullptr)
|
||||
{
|
||||
void* ptr = GetInternal(aFrame, aProperty, aFoundResult);
|
||||
void* ptr = GetInternal(aFrame, aProperty, false, aFoundResult);
|
||||
return ReinterpretHelper<T>::FromPointer(ptr);
|
||||
}
|
||||
/**
|
||||
|
@ -228,10 +241,10 @@ public:
|
|||
* 'property value is null'.
|
||||
*/
|
||||
template<typename T>
|
||||
PropertyType<T> Remove(const nsIFrame* aFrame, Descriptor<T> aProperty,
|
||||
PropertyType<T> Remove(nsIFrame* aFrame, Descriptor<T> aProperty,
|
||||
bool* aFoundResult = nullptr)
|
||||
{
|
||||
void* ptr = RemoveInternal(aFrame, aProperty, aFoundResult);
|
||||
void* ptr = RemoveInternal(aFrame, aProperty, false, aFoundResult);
|
||||
return ReinterpretHelper<T>::FromPointer(ptr);
|
||||
}
|
||||
/**
|
||||
|
@ -239,17 +252,29 @@ public:
|
|||
* hashtable lookup (using the frame as the key) and a linear search
|
||||
* through the properties of that frame. If the frame has no such
|
||||
* property, nothing happens.
|
||||
*
|
||||
* The DeleteSkippingBitCheck variant doesn't test
|
||||
* NS_FRAME_HAS_PROPERTIES on aFrame, so it is safe to call after
|
||||
* aFrame has been destroyed as long as, since that destruction
|
||||
* happened, it isn't possible for a new frame to have been created
|
||||
* and the same property added.
|
||||
*/
|
||||
template<typename T>
|
||||
void Delete(const nsIFrame* aFrame, Descriptor<T> aProperty)
|
||||
void Delete(nsIFrame* aFrame, Descriptor<T> aProperty)
|
||||
{
|
||||
DeleteInternal(aFrame, aProperty);
|
||||
DeleteInternal(aFrame, aProperty, false);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteSkippingBitCheck(nsIFrame* aFrame, Descriptor<T> aProperty)
|
||||
{
|
||||
DeleteInternal(aFrame, aProperty, true);
|
||||
}
|
||||
/**
|
||||
* Remove and destroy all property values for a frame. This requires one
|
||||
* hashtable lookup (using the frame as the key).
|
||||
*/
|
||||
void DeleteAllFor(const nsIFrame* aFrame);
|
||||
void DeleteAllFor(nsIFrame* aFrame);
|
||||
/**
|
||||
* Remove and destroy all property values for all frames.
|
||||
*/
|
||||
|
@ -258,16 +283,17 @@ public:
|
|||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
protected:
|
||||
void SetInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty,
|
||||
void SetInternal(nsIFrame* aFrame, UntypedDescriptor aProperty,
|
||||
void* aValue);
|
||||
|
||||
void* GetInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty,
|
||||
bool* aFoundResult);
|
||||
bool aSkipBitCheck, bool* aFoundResult);
|
||||
|
||||
void* RemoveInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty,
|
||||
bool* aFoundResult);
|
||||
void* RemoveInternal(nsIFrame* aFrame, UntypedDescriptor aProperty,
|
||||
bool aSkipBitCheck, bool* aFoundResult);
|
||||
|
||||
void DeleteInternal(const nsIFrame* aFrame, UntypedDescriptor aProperty);
|
||||
void DeleteInternal(nsIFrame* aFrame, UntypedDescriptor aProperty,
|
||||
bool aSkipBitCheck);
|
||||
|
||||
template<typename T>
|
||||
struct ReinterpretHelper
|
||||
|
@ -392,22 +418,21 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* This class encapsulates the properties of a frame.
|
||||
* The FrameProperties/ConstFrameProperties class encapsulates the
|
||||
* properties of a frame.
|
||||
*
|
||||
* However, since frame properties are like member variables, we have
|
||||
* different versions for whether the frame is |const|, sharing a common
|
||||
* base class.
|
||||
*
|
||||
* CVnsIFrame is either |nsIFrame| or |const nsIFrame|.
|
||||
*/
|
||||
class FrameProperties {
|
||||
template<class CVnsIFrame>
|
||||
class FramePropertiesBase {
|
||||
public:
|
||||
template<typename T> using Descriptor = FramePropertyTable::Descriptor<T>;
|
||||
template<typename T> using PropertyType = FramePropertyTable::PropertyType<T>;
|
||||
|
||||
FrameProperties(FramePropertyTable* aTable, const nsIFrame* aFrame)
|
||||
: mTable(aTable), mFrame(aFrame) {}
|
||||
|
||||
template<typename T>
|
||||
void Set(Descriptor<T> aProperty, PropertyType<T> aValue) const
|
||||
{
|
||||
mTable->Set(mFrame, aProperty, aValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Has(Descriptor<T> aProperty) const
|
||||
{
|
||||
|
@ -420,21 +445,49 @@ public:
|
|||
{
|
||||
return mTable->Get(mFrame, aProperty, aFoundResult);
|
||||
}
|
||||
|
||||
protected:
|
||||
FramePropertiesBase(FramePropertyTable* aTable, CVnsIFrame* aFrame)
|
||||
: mTable(aTable), mFrame(aFrame) {}
|
||||
|
||||
FramePropertyTable* const mTable;
|
||||
CVnsIFrame* const mFrame;
|
||||
};
|
||||
|
||||
class ConstFrameProperties : public FramePropertiesBase<const nsIFrame> {
|
||||
public:
|
||||
ConstFrameProperties(FramePropertyTable* aTable, const nsIFrame* aFrame)
|
||||
: FramePropertiesBase(aTable, aFrame)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class FrameProperties : public FramePropertiesBase<nsIFrame> {
|
||||
public:
|
||||
FrameProperties(FramePropertyTable* aTable, nsIFrame* aFrame)
|
||||
: FramePropertiesBase(aTable, aFrame)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Set(Descriptor<T> aProperty, PropertyType<T> aValue) const
|
||||
{
|
||||
mTable->Set(mFrame, aProperty, aValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
PropertyType<T> Remove(Descriptor<T> aProperty,
|
||||
bool* aFoundResult = nullptr) const
|
||||
{
|
||||
return mTable->Remove(mFrame, aProperty, aFoundResult);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Delete(Descriptor<T> aProperty)
|
||||
void Delete(Descriptor<T> aProperty) const
|
||||
{
|
||||
mTable->Delete(mFrame, aProperty);
|
||||
}
|
||||
|
||||
private:
|
||||
FramePropertyTable* mTable;
|
||||
const nsIFrame* mFrame;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -6003,8 +6003,6 @@ PresShell::MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
|
|||
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(aFrame);
|
||||
if (scrollFrame) {
|
||||
scrollFrame->NotifyApproximateFrameVisibilityUpdate();
|
||||
|
||||
bool ignoreDisplayPort = false;
|
||||
if (nsLayoutUtils::IsMissingDisplayPortBaseRect(aFrame->GetContent())) {
|
||||
// We can properly set the base rect for root scroll frames on top level
|
||||
|
@ -6023,6 +6021,8 @@ PresShell::MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
|
|||
}
|
||||
}
|
||||
|
||||
scrollFrame->NotifyApproximateFrameVisibilityUpdate(ignoreDisplayPort);
|
||||
|
||||
nsRect displayPort;
|
||||
bool usingDisplayport = !ignoreDisplayPort &&
|
||||
nsLayoutUtils::GetDisplayPortForVisibilityTesting(
|
||||
|
|
|
@ -1396,7 +1396,8 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
|||
break;
|
||||
}
|
||||
|
||||
const nsStyleChangeData& data = aChangeList[i];
|
||||
nsStyleChangeData& mutable_data = aChangeList[i];
|
||||
const nsStyleChangeData& data = mutable_data;
|
||||
nsIFrame* frame = data.mFrame;
|
||||
nsIContent* content = data.mContent;
|
||||
nsChangeHint hint = data.mHint;
|
||||
|
@ -1407,7 +1408,11 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
|||
"Reflow hint bits set without actually asking for a reflow");
|
||||
|
||||
// skip any frame that has been destroyed due to a ripple effect
|
||||
if (frame && !propTable->Get(frame, ChangeListProperty())) {
|
||||
if (frame && !propTable->HasSkippingBitCheck(frame, ChangeListProperty())) {
|
||||
// Null out the pointer since the frame was already destroyed.
|
||||
// This is important so we don't try to delete its
|
||||
// ChangeListProperty() below.
|
||||
mutable_data.mFrame = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1475,6 +1480,11 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
|||
}
|
||||
|
||||
if (hint & nsChangeHint_ReconstructFrame) {
|
||||
// We're about to destroy data.mFrame, so null out the pointer.
|
||||
// This is important so we don't try to delete its
|
||||
// ChangeListProperty() below.
|
||||
mutable_data.mFrame = nullptr;
|
||||
|
||||
// If we ever start passing true here, be careful of restyles
|
||||
// that involve a reframe and animations. In particular, if the
|
||||
// restyle we're processing here is an animation restyle, but
|
||||
|
@ -1664,7 +1674,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
|||
// is not in fact in a consistent state.
|
||||
for (const nsStyleChangeData& data : aChangeList) {
|
||||
if (data.mFrame) {
|
||||
propTable->Delete(data.mFrame, ChangeListProperty());
|
||||
propTable->DeleteSkippingBitCheck(data.mFrame, ChangeListProperty());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -1702,7 +1702,7 @@ nsIFrame::GetVisibility() const
|
|||
}
|
||||
|
||||
bool isSet = false;
|
||||
FrameProperties props = Properties();
|
||||
ConstFrameProperties props = Properties();
|
||||
uint32_t visibleCount = props.Get(VisibilityStateProperty(), &isSet);
|
||||
|
||||
MOZ_ASSERT(isSet, "Should have a VisibilityStateProperty value "
|
||||
|
@ -9982,8 +9982,9 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
|
|||
parentReflowInput(aPresContext, parentFrame, aRenderingContext,
|
||||
LogicalSize(parentWM, parentSize),
|
||||
ReflowInput::DUMMY_PARENT_REFLOW_STATE);
|
||||
parentFrame->RemoveStateBits(~nsFrameState(0));
|
||||
parentFrame->AddStateBits(savedState);
|
||||
const nsFrameState bitsToLeaveUntouched = NS_FRAME_HAS_PROPERTIES;
|
||||
parentFrame->RemoveStateBits(~bitsToLeaveUntouched);
|
||||
parentFrame->AddStateBits(savedState & ~bitsToLeaveUntouched);
|
||||
|
||||
// This may not do very much useful, but it's probably worth trying.
|
||||
if (parentSize.width != NS_INTRINSICSIZE)
|
||||
|
@ -10543,7 +10544,7 @@ nsFrame::Trace(const char* aMethod, bool aEnter)
|
|||
if (NS_FRAME_LOG_TEST(sFrameLogModule, NS_FRAME_TRACE_CALLS)) {
|
||||
char tagbuf[40];
|
||||
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
||||
PR_LogPrint("%s: %s %s", tagbuf, aEnter ? "enter" : "exit", aMethod);
|
||||
printf_stderr("%s: %s %s", tagbuf, aEnter ? "enter" : "exit", aMethod);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10553,7 +10554,7 @@ nsFrame::Trace(const char* aMethod, bool aEnter, nsReflowStatus aStatus)
|
|||
if (NS_FRAME_LOG_TEST(sFrameLogModule, NS_FRAME_TRACE_CALLS)) {
|
||||
char tagbuf[40];
|
||||
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
||||
PR_LogPrint("%s: %s %s, status=%scomplete%s",
|
||||
printf_stderr("%s: %s %s, status=%scomplete%s",
|
||||
tagbuf, aEnter ? "enter" : "exit", aMethod,
|
||||
aStatus.IsIncomplete() ? "not" : "",
|
||||
(aStatus.NextInFlowNeedsReflow()) ? "+reflow" : "");
|
||||
|
@ -10573,7 +10574,7 @@ nsFrame::TraceMsg(const char* aFormatString, ...)
|
|||
|
||||
char tagbuf[40];
|
||||
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
||||
PR_LogPrint("%s: %s", tagbuf, argbuf);
|
||||
printf_stderr("%s: %s", tagbuf, argbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
* PRLogModuleInfo.level field to be a bitfield. Each bit controls a
|
||||
* specific type of logging. Each logging operation has associated
|
||||
* inline methods defined below.
|
||||
*
|
||||
* Due to the redefinition of the level field we cannot use MOZ_LOG directly
|
||||
* as that will cause assertions due to invalid log levels.
|
||||
*/
|
||||
#define NS_FRAME_TRACE_CALLS 0x1
|
||||
#define NS_FRAME_TRACE_PUSH_PULL 0x2
|
||||
|
@ -36,7 +39,7 @@
|
|||
#define NS_FRAME_LOG(_bit,_args) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (NS_FRAME_LOG_TEST(nsFrame::sFrameLogModule,_bit)) { \
|
||||
PR_LogPrint _args; \
|
||||
printf_stderr _args; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
|
|
|
@ -270,6 +270,9 @@ FRAME_STATE_BIT(Generic, 54, NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)
|
|||
// a stylo tree traversal.
|
||||
FRAME_STATE_BIT(Generic, 55, NS_FRAME_OWNS_ANON_BOXES)
|
||||
|
||||
// Frame has properties in the nsIFrame::Properties() hash.
|
||||
FRAME_STATE_BIT(Generic, 56, NS_FRAME_HAS_PROPERTIES)
|
||||
|
||||
// Set for all descendants of MathML sub/supscript elements (other than the
|
||||
// base frame) to indicate that the SSTY font feature should be used.
|
||||
FRAME_STATE_BIT(Generic, 58, NS_FRAME_MATHML_SCRIPT_DESCENDANT)
|
||||
|
|
|
@ -2717,12 +2717,17 @@ ScrollFrameHelper::ScheduleSyntheticMouseMove()
|
|||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::NotifyApproximateFrameVisibilityUpdate()
|
||||
ScrollFrameHelper::NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort)
|
||||
{
|
||||
mLastUpdateFramesPos = GetScrollPosition();
|
||||
mHadDisplayPortAtLastFrameUpdate =
|
||||
nsLayoutUtils::GetDisplayPort(mOuter->GetContent(),
|
||||
&mDisplayPortAtLastFrameUpdate);
|
||||
if (aIgnoreDisplayPort) {
|
||||
mHadDisplayPortAtLastFrameUpdate = false;
|
||||
mDisplayPortAtLastFrameUpdate = nsRect();
|
||||
} else {
|
||||
mHadDisplayPortAtLastFrameUpdate =
|
||||
nsLayoutUtils::GetDisplayPort(mOuter->GetContent(),
|
||||
&mDisplayPortAtLastFrameUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -3238,7 +3243,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
const nsDisplayListSet& aLists)
|
||||
{
|
||||
if (aBuilder->IsForFrameVisibility()) {
|
||||
NotifyApproximateFrameVisibilityUpdate();
|
||||
NotifyApproximateFrameVisibilityUpdate(false);
|
||||
}
|
||||
|
||||
mOuter->DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
|
|
|
@ -405,7 +405,7 @@ public:
|
|||
bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort);
|
||||
void NotifyApproximateFrameVisibilityUpdate();
|
||||
void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort);
|
||||
bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(nsRect* aDisplayPort);
|
||||
|
||||
bool AllowDisplayPortExpiration();
|
||||
|
@ -943,8 +943,8 @@ public:
|
|||
bool aAllowCreateDisplayPort) override {
|
||||
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
|
||||
}
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate() override {
|
||||
mHelper.NotifyApproximateFrameVisibilityUpdate();
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) override {
|
||||
mHelper.NotifyApproximateFrameVisibilityUpdate(aIgnoreDisplayPort);
|
||||
}
|
||||
virtual bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(nsRect* aDisplayPort) override {
|
||||
return mHelper.GetDisplayPortAtLastApproximateFrameVisibilityUpdate(aDisplayPort);
|
||||
|
@ -1463,8 +1463,8 @@ public:
|
|||
bool aAllowCreateDisplayPort) override {
|
||||
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
|
||||
}
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate() override {
|
||||
mHelper.NotifyApproximateFrameVisibilityUpdate();
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) override {
|
||||
mHelper.NotifyApproximateFrameVisibilityUpdate(aIgnoreDisplayPort);
|
||||
}
|
||||
virtual bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(nsRect* aDisplayPort) override {
|
||||
return mHelper.GetDisplayPortAtLastApproximateFrameVisibilityUpdate(aDisplayPort);
|
||||
|
|
|
@ -577,6 +577,7 @@ public:
|
|||
using Visibility = mozilla::Visibility;
|
||||
|
||||
typedef mozilla::FrameProperties FrameProperties;
|
||||
typedef mozilla::ConstFrameProperties ConstFrameProperties;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
typedef mozilla::layout::FrameChildList ChildList;
|
||||
typedef mozilla::layout::FrameChildListID ChildListID;
|
||||
|
@ -3251,10 +3252,14 @@ public:
|
|||
return mContent == aParentContent;
|
||||
}
|
||||
|
||||
FrameProperties Properties() const {
|
||||
FrameProperties Properties() {
|
||||
return FrameProperties(PresContext()->PropertyTable(), this);
|
||||
}
|
||||
|
||||
ConstFrameProperties Properties() const {
|
||||
return ConstFrameProperties(PresContext()->PropertyTable(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if and only if this frame obeys visibility:hidden.
|
||||
* if it does not, then nsContainerFrame will hide its view even though
|
||||
|
|
|
@ -452,8 +452,10 @@ public:
|
|||
|
||||
/**
|
||||
* Notification that this scroll frame is getting its frame visibility updated.
|
||||
* aIgnoreDisplayPort indicates that the display port was ignored (because
|
||||
* there was no suitable base rect)
|
||||
*/
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate() = 0;
|
||||
virtual void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if this scroll frame had a display port at the last frame
|
||||
|
|
|
@ -63,9 +63,6 @@
|
|||
#include "nsAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
#define FORCE_PR_LOG 1 /* Allow logging in the release build */
|
||||
#endif /* MOZ_LOGGING */
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -3204,7 +3204,7 @@ protected:
|
|||
const nsStyleText* mTextStyle;
|
||||
const nsTextFragment* mFrag;
|
||||
const nsIFrame* mLineContainer;
|
||||
const nsTextFrame* mFrame;
|
||||
nsTextFrame* mFrame;
|
||||
gfxSkipCharsIterator mStart; // Offset in original and transformed string
|
||||
const gfxSkipCharsIterator mTempIterator;
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ FindCellProperty(const nsIFrame* aCellFrame,
|
|||
nsTArray<int8_t>* propertyData = nullptr;
|
||||
|
||||
while (currentFrame) {
|
||||
FrameProperties props = currentFrame->Properties();
|
||||
ConstFrameProperties props = currentFrame->Properties();
|
||||
propertyData = props.Get(aFrameProperty);
|
||||
bool frameIsTable = (currentFrame->GetType() == nsGkAtoms::tableFrame);
|
||||
|
||||
|
|
|
@ -2306,6 +2306,12 @@ nsDisplayItem* nsDisplayList::RemoveBottom() {
|
|||
void nsDisplayList::DeleteAll() {
|
||||
nsDisplayItem* item;
|
||||
while ((item = RemoveBottom()) != nullptr) {
|
||||
#ifdef NIGHTLY_BUILD
|
||||
if (XRE_IsContentProcess()) {
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::DISPLAY_ITEM_USAGE_COUNT,
|
||||
item->GetType());
|
||||
}
|
||||
#endif
|
||||
item->~nsDisplayItem();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2794,11 +2794,17 @@ nsTableFrame::GetUsedMargin() const
|
|||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(TableBCProperty, BCPropertyData)
|
||||
|
||||
BCPropertyData*
|
||||
nsTableFrame::GetBCProperty(bool aCreateIfNecessary) const
|
||||
nsTableFrame::GetBCProperty() const
|
||||
{
|
||||
return Properties().Get(TableBCProperty());
|
||||
}
|
||||
|
||||
BCPropertyData*
|
||||
nsTableFrame::GetOrCreateBCProperty()
|
||||
{
|
||||
FrameProperties props = Properties();
|
||||
BCPropertyData* value = props.Get(TableBCProperty());
|
||||
if (!value && aCreateIfNecessary) {
|
||||
if (!value) {
|
||||
value = new BCPropertyData();
|
||||
props.Set(TableBCProperty(), value);
|
||||
}
|
||||
|
@ -4247,7 +4253,7 @@ nsTableFrame::AddBCDamageArea(const TableArea& aValue)
|
|||
|
||||
SetNeedToCalcBCBorders(true);
|
||||
// Get the property
|
||||
BCPropertyData* value = GetBCProperty(true);
|
||||
BCPropertyData* value = GetOrCreateBCProperty();
|
||||
if (value) {
|
||||
#ifdef DEBUG
|
||||
VerifyNonNegativeDamageRect(value->mDamageArea);
|
||||
|
@ -4287,7 +4293,7 @@ nsTableFrame::SetFullBCDamageArea()
|
|||
|
||||
SetNeedToCalcBCBorders(true);
|
||||
|
||||
BCPropertyData* value = GetBCProperty(true);
|
||||
BCPropertyData* value = GetOrCreateBCProperty();
|
||||
if (value) {
|
||||
value->mDamageArea = TableArea(0, 0, GetColCount(), GetRowCount());
|
||||
}
|
||||
|
|
|
@ -807,7 +807,8 @@ protected:
|
|||
|
||||
void SetBorderCollapse(bool aValue);
|
||||
|
||||
BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const;
|
||||
BCPropertyData* GetBCProperty() const;
|
||||
BCPropertyData* GetOrCreateBCProperty();
|
||||
void SetFullBCDamageArea();
|
||||
void CalcBCBorders();
|
||||
|
||||
|
|
|
@ -24,7 +24,21 @@
|
|||
static mozilla::LazyLogModule log(n); \
|
||||
return static_cast<mozilla::LogModule*>(log); \
|
||||
}
|
||||
|
||||
#define MOZ_MTLOG(level, b) \
|
||||
do { \
|
||||
if (MOZ_LOG_TEST(getLogModule(), level)) { \
|
||||
std::stringstream str; \
|
||||
str << b; \
|
||||
MOZ_LOG(getLogModule(), level, ("%s", str.str().c_str())); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
// When building mtransport outside of XUL, for example in stand-alone gtests,
|
||||
// PR_Logging needs to be used instead of mozilla logging.
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
#define MOZ_MTLOG_MODULE(n) \
|
||||
static PRLogModuleInfo* getLogModule() { \
|
||||
static PRLogModuleInfo* log; \
|
||||
|
@ -32,15 +46,14 @@
|
|||
log = PR_NewLogModule(n); \
|
||||
return log; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MOZ_MTLOG(level, b) \
|
||||
do { \
|
||||
if (MOZ_LOG_TEST(getLogModule(), level)) { \
|
||||
std::stringstream str; \
|
||||
str << b; \
|
||||
MOZ_LOG(getLogModule(), level, ("%s", str.str().c_str())); \
|
||||
} \
|
||||
#define MOZ_MTLOG(level, b) \
|
||||
do { \
|
||||
if (PR_LOG_TEST(getLogModule(), (PRLogModuleLevel)level)) { \
|
||||
std::stringstream str; \
|
||||
str << b; \
|
||||
PR_LOG(getLogModule(), (PRLogModuleLevel)level, ("%s", str.str().c_str())); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
#endif // logging_h__
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* vim: ts=4 sw=4 expandtab:
|
||||
/* 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/. */
|
||||
|
@ -9,7 +11,6 @@ import org.mozilla.gecko.annotation.RobocopTarget;
|
|||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.mozglue.JNIObject;
|
||||
import org.mozilla.gecko.NativeQueue.StateHolder;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
@ -55,7 +56,7 @@ public final class EventDispatcher extends JNIObject {
|
|||
new HashMap<String, List<BundleEventListener>>(DEFAULT_BACKGROUND_EVENTS_COUNT);
|
||||
|
||||
private boolean mAttachedToGecko;
|
||||
private volatile StateHolder mStateHolder;
|
||||
private final NativeQueue mNativeQueue;
|
||||
|
||||
@ReflectionTarget
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
|
@ -64,22 +65,15 @@ public final class EventDispatcher extends JNIObject {
|
|||
}
|
||||
|
||||
/* package */ EventDispatcher() {
|
||||
mStateHolder = GeckoThread.getStateHolder();
|
||||
mNativeQueue = GeckoThread.getNativeQueue();
|
||||
}
|
||||
|
||||
/* package */ EventDispatcher(final NativeQueue.StateHolder stateHolder) {
|
||||
mStateHolder = stateHolder;
|
||||
}
|
||||
|
||||
/* package */ void setStateHolder(final NativeQueue.StateHolder stateHolder) {
|
||||
mStateHolder = stateHolder;
|
||||
// Force queue flushing.
|
||||
final NativeQueue.State state = mStateHolder.getState();
|
||||
mStateHolder.checkAndSetState(state, state);
|
||||
/* package */ EventDispatcher(final NativeQueue queue) {
|
||||
mNativeQueue = queue;
|
||||
}
|
||||
|
||||
private boolean isReadyForDispatchingToGecko() {
|
||||
return mStateHolder.isReady();
|
||||
return mNativeQueue.isReady();
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko") @Override // JNIObject
|
||||
|
@ -301,8 +295,7 @@ public final class EventDispatcher extends JNIObject {
|
|||
// Gecko, we make a special exception to queue this event until
|
||||
// Gecko(View) is ready. This way, Gecko can first register its
|
||||
// listeners, and accept the event when it is ready.
|
||||
NativeQueue.queueUntil(mStateHolder,
|
||||
mStateHolder.getReadyState(), this, "dispatchToGecko",
|
||||
mNativeQueue.queueUntilReady(this, "dispatchToGecko",
|
||||
String.class, type,
|
||||
GeckoBundle.class, message,
|
||||
EventCallback.class, JavaCallbackDelegate.wrap(callback));
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.mozilla.gecko;
|
|||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.NativeQueue.StateHolder;
|
||||
import org.mozilla.gecko.util.FileUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
|
@ -80,11 +79,11 @@ public class GeckoThread extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
private static final StateHolder sStateHolder =
|
||||
new StateHolder(State.INITIAL, State.RUNNING);
|
||||
private static final NativeQueue sNativeQueue =
|
||||
new NativeQueue(State.INITIAL, State.RUNNING);
|
||||
|
||||
/* package */ static StateHolder getStateHolder() {
|
||||
return sStateHolder;
|
||||
/* package */ static NativeQueue getNativeQueue() {
|
||||
return sNativeQueue;
|
||||
}
|
||||
|
||||
public static final State MIN_STATE = State.INITIAL;
|
||||
|
@ -446,7 +445,7 @@ public class GeckoThread extends Thread {
|
|||
* @return True if the current Gecko thread state matches
|
||||
*/
|
||||
public static boolean isState(final State state) {
|
||||
return sStateHolder.getState().is(state);
|
||||
return sNativeQueue.getState().is(state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,7 +456,7 @@ public class GeckoThread extends Thread {
|
|||
* @return True if the current Gecko thread state matches
|
||||
*/
|
||||
public static boolean isStateAtLeast(final State state) {
|
||||
return sStateHolder.getState().isAtLeast(state);
|
||||
return sNativeQueue.getState().isAtLeast(state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -468,7 +467,7 @@ public class GeckoThread extends Thread {
|
|||
* @return True if the current Gecko thread state matches
|
||||
*/
|
||||
public static boolean isStateAtMost(final State state) {
|
||||
return state.isAtLeast(sStateHolder.getState());
|
||||
return state.isAtLeast(sNativeQueue.getState());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -485,13 +484,13 @@ public class GeckoThread extends Thread {
|
|||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void setState(final State newState) {
|
||||
sStateHolder.setState(newState);
|
||||
sNativeQueue.setState(newState);
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static boolean checkAndSetState(final State expectedState,
|
||||
final State newState) {
|
||||
return sStateHolder.checkAndSetState(expectedState, newState);
|
||||
return sNativeQueue.checkAndSetState(expectedState, newState);
|
||||
}
|
||||
|
||||
@WrapForJNI(stubName = "SpeculativeConnect")
|
||||
|
@ -561,7 +560,7 @@ public class GeckoThread extends Thread {
|
|||
*/
|
||||
public static void queueNativeCall(final Class<?> cls, final String methodName,
|
||||
final Object... args) {
|
||||
NativeQueue.queueUntil(getStateHolder(), State.RUNNING, cls, methodName, args);
|
||||
sNativeQueue.queueUntilReady(cls, methodName, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -569,7 +568,7 @@ public class GeckoThread extends Thread {
|
|||
*/
|
||||
public static void queueNativeCall(final Object obj, final String methodName,
|
||||
final Object... args) {
|
||||
NativeQueue.queueUntil(getStateHolder(), State.RUNNING, obj, methodName, args);
|
||||
sNativeQueue.queueUntilReady(obj, methodName, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -577,7 +576,7 @@ public class GeckoThread extends Thread {
|
|||
*/
|
||||
public static void queueNativeCallUntil(final State state, final Object obj, final String methodName,
|
||||
final Object... args) {
|
||||
NativeQueue.queueUntil(getStateHolder(), state, obj, methodName, args);
|
||||
sNativeQueue.queueUntil(state, obj, methodName, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -585,6 +584,6 @@ public class GeckoThread extends Thread {
|
|||
*/
|
||||
public static void queueNativeCallUntil(final State state, final Class<?> cls, final String methodName,
|
||||
final Object... args) {
|
||||
NativeQueue.queueUntil(getStateHolder(), state, cls, methodName, args);
|
||||
sNativeQueue.queueUntil(state, cls, methodName, args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.mozilla.gecko.annotation.ReflectionTarget;
|
|||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.mozglue.JNIObject;
|
||||
import org.mozilla.gecko.NativeQueue.StateHolder;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
@ -47,7 +46,7 @@ public class GeckoView extends LayerView
|
|||
@WrapForJNI INITIAL(0),
|
||||
@WrapForJNI READY(1);
|
||||
|
||||
private int mRank;
|
||||
private final int mRank;
|
||||
|
||||
private State(int rank) {
|
||||
mRank = rank;
|
||||
|
@ -60,18 +59,16 @@ public class GeckoView extends LayerView
|
|||
|
||||
@Override
|
||||
public boolean isAtLeast(final NativeQueue.State other) {
|
||||
if (other instanceof State) {
|
||||
return mRank >= ((State) other).mRank;
|
||||
}
|
||||
return false;
|
||||
return (other instanceof State) &&
|
||||
mRank >= ((State) other).mRank;
|
||||
}
|
||||
}
|
||||
|
||||
private static final StateHolder sDummyStateHolder =
|
||||
new StateHolder(State.INITIAL, State.READY);
|
||||
private final NativeQueue mNativeQueue =
|
||||
new NativeQueue(State.INITIAL, State.READY);
|
||||
|
||||
private final EventDispatcher mEventDispatcher =
|
||||
new EventDispatcher(sDummyStateHolder);
|
||||
new EventDispatcher(mNativeQueue);
|
||||
|
||||
private ChromeDelegate mChromeDelegate;
|
||||
/* package */ ContentListener mContentListener;
|
||||
|
@ -88,11 +85,12 @@ public class GeckoView extends LayerView
|
|||
@WrapForJNI(dispatchTo = "proxy")
|
||||
protected static final class Window extends JNIObject {
|
||||
@WrapForJNI(skip = true)
|
||||
/* package */ final StateHolder mStateHolder =
|
||||
new StateHolder(State.INITIAL, State.READY);
|
||||
/* package */ NativeQueue mNativeQueue;
|
||||
|
||||
@WrapForJNI(skip = true)
|
||||
/* package */ Window() {}
|
||||
/* package */ Window(final NativeQueue queue) {
|
||||
mNativeQueue = queue;
|
||||
}
|
||||
|
||||
static native void open(Window instance, GeckoView view,
|
||||
Object compositor, EventDispatcher dispatcher,
|
||||
|
@ -109,8 +107,8 @@ public class GeckoView extends LayerView
|
|||
native void loadUri(String uri, int flags);
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private void setState(final State newState) {
|
||||
mStateHolder.setState(newState);
|
||||
private synchronized void setState(final State newState) {
|
||||
mNativeQueue.setState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,7 +285,12 @@ public class GeckoView extends LayerView
|
|||
}
|
||||
|
||||
protected void reattachWindow() {
|
||||
mEventDispatcher.setStateHolder(mWindow.mStateHolder);
|
||||
synchronized (mWindow) {
|
||||
if (mNativeQueue != mWindow.mNativeQueue) {
|
||||
mNativeQueue.setState(mWindow.mNativeQueue.getState());
|
||||
mWindow.mNativeQueue = mNativeQueue;
|
||||
}
|
||||
}
|
||||
|
||||
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
|
||||
mWindow.reattach(this, getCompositor(), mEventDispatcher);
|
||||
|
@ -304,8 +307,7 @@ public class GeckoView extends LayerView
|
|||
|
||||
if (mWindow == null) {
|
||||
// Open a new nsWindow if we didn't have one from before.
|
||||
mWindow = new Window();
|
||||
mEventDispatcher.setStateHolder(mWindow.mStateHolder);
|
||||
mWindow = new Window(mNativeQueue);
|
||||
openWindow();
|
||||
} else {
|
||||
reattachWindow();
|
||||
|
@ -336,7 +338,6 @@ public class GeckoView extends LayerView
|
|||
mWindow, "disposeNative");
|
||||
}
|
||||
|
||||
mEventDispatcher.setStateHolder(sDummyStateHolder);
|
||||
mOnAttachedToWindowCalled = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* vim: ts=4 sw=4 expandtab:
|
||||
* 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/. */
|
||||
|
@ -20,42 +21,34 @@ public class NativeQueue {
|
|||
boolean isAtLeast(final State other);
|
||||
}
|
||||
|
||||
public static class StateHolder {
|
||||
private volatile State mState;
|
||||
private final State mReadyState;
|
||||
private volatile State mState;
|
||||
private final State mReadyState;
|
||||
|
||||
public StateHolder(final State initial, final State ready) {
|
||||
this.mState = initial;
|
||||
this.mReadyState = ready;
|
||||
}
|
||||
public NativeQueue(final State initial, final State ready) {
|
||||
mState = initial;
|
||||
mReadyState = ready;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return getState().isAtLeast(mReadyState);
|
||||
}
|
||||
public boolean isReady() {
|
||||
return getState().isAtLeast(mReadyState);
|
||||
}
|
||||
|
||||
public State getReadyState() {
|
||||
return mReadyState;
|
||||
}
|
||||
public State getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return mState;
|
||||
}
|
||||
public boolean setState(final State newState) {
|
||||
return checkAndSetState(null, newState);
|
||||
}
|
||||
|
||||
public boolean setState(final State newState) {
|
||||
return checkAndSetState(null, newState);
|
||||
}
|
||||
|
||||
public boolean checkAndSetState(final State expectedState,
|
||||
final State newState) {
|
||||
synchronized (NativeQueue.sQueue) {
|
||||
if (expectedState != null && !mState.is(expectedState)) {
|
||||
return false;
|
||||
}
|
||||
NativeQueue.flushQueuedLocked(newState);
|
||||
mState = newState;
|
||||
return true;
|
||||
}
|
||||
public synchronized boolean checkAndSetState(final State expectedState,
|
||||
final State newState) {
|
||||
if (expectedState != null && !mState.is(expectedState)) {
|
||||
return false;
|
||||
}
|
||||
flushQueuedLocked(newState);
|
||||
mState = newState;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class QueuedCall {
|
||||
|
@ -74,7 +67,7 @@ public class NativeQueue {
|
|||
}
|
||||
|
||||
private static final int QUEUED_CALLS_COUNT = 16;
|
||||
/* package */ static final ArrayList<QueuedCall> sQueue =
|
||||
/* package */ final ArrayList<QueuedCall> mQueue =
|
||||
new ArrayList<>(QUEUED_CALLS_COUNT);
|
||||
|
||||
// Invoke the given Method and handle checked Exceptions.
|
||||
|
@ -91,12 +84,11 @@ public class NativeQueue {
|
|||
}
|
||||
|
||||
// Queue a call to the given method.
|
||||
private static void queueNativeCallLocked(final StateHolder stateHolder,
|
||||
final Class<?> cls,
|
||||
final String methodName,
|
||||
final Object obj,
|
||||
final Object[] args,
|
||||
final State state) {
|
||||
private void queueNativeCallLocked(final Class<?> cls,
|
||||
final String methodName,
|
||||
final Object obj,
|
||||
final Object[] args,
|
||||
final State state) {
|
||||
final ArrayList<Class<?>> argTypes = new ArrayList<>(args.length);
|
||||
final ArrayList<Object> argValues = new ArrayList<>(args.length);
|
||||
|
||||
|
@ -135,63 +127,82 @@ public class NativeQueue {
|
|||
throw new UnsupportedOperationException("Not allowed to queue non-native methods");
|
||||
}
|
||||
|
||||
if (stateHolder.getState().isAtLeast(state)) {
|
||||
if (getState().isAtLeast(state)) {
|
||||
invokeMethod(method, obj, argValues.toArray());
|
||||
return;
|
||||
}
|
||||
|
||||
sQueue.add(new QueuedCall(
|
||||
mQueue.add(new QueuedCall(
|
||||
method, obj, argValues.toArray(), state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a call to the given instance method if the given current state does
|
||||
* not satisfy the isReady condition.
|
||||
*
|
||||
* @param obj Object that declares the instance method.
|
||||
* @param methodName Name of the instance method.
|
||||
* @param args Args to call the instance method with; to specify a parameter
|
||||
* type, pass in a Class instance first, followed by the value.
|
||||
*/
|
||||
public synchronized void queueUntilReady(final Object obj,
|
||||
final String methodName,
|
||||
final Object... args) {
|
||||
queueNativeCallLocked(obj.getClass(), methodName, obj, args, mReadyState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a call to the given static method if the given current state does
|
||||
* not satisfy the isReady condition.
|
||||
*
|
||||
* @param cls Class that declares the static method.
|
||||
* @param methodName Name of the instance method.
|
||||
* @param args Args to call the instance method with; to specify a parameter
|
||||
* type, pass in a Class instance first, followed by the value.
|
||||
*/
|
||||
public synchronized void queueUntilReady(final Class<?> cls,
|
||||
final String methodName,
|
||||
final Object... args) {
|
||||
queueNativeCallLocked(cls, methodName, null, args, mReadyState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a call to the given instance method if the given current state does
|
||||
* not satisfy the given state.
|
||||
*
|
||||
* @param stateHolder The state holder used to query the current state.
|
||||
* @param state The state in which the native call could be executed.
|
||||
* @param obj Object that declares the instance method.
|
||||
* @param methodName Name of the instance method.
|
||||
* @param args Args to call the instance method with; to specify a parameter
|
||||
* type, pass in a Class instance first, followed by the value.
|
||||
*/
|
||||
public static void queueUntil(final StateHolder stateHolder,
|
||||
final State state,
|
||||
final Object obj,
|
||||
final String methodName,
|
||||
final Object... args) {
|
||||
synchronized (sQueue) {
|
||||
queueNativeCallLocked(stateHolder, obj.getClass(), methodName, obj,
|
||||
args, state);
|
||||
}
|
||||
public synchronized void queueUntil(final State state, final Object obj,
|
||||
final String methodName,
|
||||
final Object... args) {
|
||||
queueNativeCallLocked(obj.getClass(), methodName, obj, args, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a call to the given static method if the given current state does
|
||||
* not satisfy the given state.
|
||||
*
|
||||
* @param stateHolder The state holder used to query the current state.
|
||||
* @param state The state in which the native call could be executed.
|
||||
* @param cls Class that declares the static method.
|
||||
* @param methodName Name of the instance method.
|
||||
* @param args Args to call the instance method with; to specify a parameter
|
||||
* type, pass in a Class instance first, followed by the value.
|
||||
*/
|
||||
public static void queueUntil(final StateHolder stateHolder,
|
||||
final State state,
|
||||
final Class<?> cls,
|
||||
final String methodName,
|
||||
final Object... args) {
|
||||
synchronized (sQueue) {
|
||||
queueNativeCallLocked(stateHolder, cls, methodName, null, args, state);
|
||||
}
|
||||
public synchronized void queueUntil(final State state, final Class<?> cls,
|
||||
final String methodName,
|
||||
final Object... args) {
|
||||
queueNativeCallLocked(cls, methodName, null, args, state);
|
||||
}
|
||||
|
||||
// Run all queued methods
|
||||
private static void flushQueuedLocked(final State state) {
|
||||
private void flushQueuedLocked(final State state) {
|
||||
int lastSkipped = -1;
|
||||
for (int i = 0; i < sQueue.size(); i++) {
|
||||
final QueuedCall call = sQueue.get(i);
|
||||
for (int i = 0; i < mQueue.size(); i++) {
|
||||
final QueuedCall call = mQueue.get(i);
|
||||
if (call == null) {
|
||||
// We already handled the call.
|
||||
continue;
|
||||
|
@ -202,18 +213,18 @@ public class NativeQueue {
|
|||
continue;
|
||||
}
|
||||
// Mark as handled.
|
||||
sQueue.set(i, null);
|
||||
mQueue.set(i, null);
|
||||
|
||||
invokeMethod(call.method, call.target, call.args);
|
||||
}
|
||||
if (lastSkipped < 0) {
|
||||
// We're done here; release the memory
|
||||
sQueue.clear();
|
||||
sQueue.trimToSize();
|
||||
} else if (lastSkipped < sQueue.size() - 1) {
|
||||
mQueue.clear();
|
||||
mQueue.trimToSize();
|
||||
} else if (lastSkipped < mQueue.size() - 1) {
|
||||
// We skipped some; free up null entries at the end,
|
||||
// but keep all the previous entries for later.
|
||||
sQueue.subList(lastSkipped + 1, sQueue.size()).clear();
|
||||
mQueue.subList(lastSkipped + 1, mQueue.size()).clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,7 +570,7 @@ nsZipArchive::FindInit(const char * aPattern, nsZipFind **aFind)
|
|||
|
||||
default:
|
||||
// undocumented return value from RegExpValid!
|
||||
PR_ASSERT(false);
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
class nsIFile;
|
||||
|
|
|
@ -1599,6 +1599,9 @@ pref("network.http.altsvc.oe", true);
|
|||
// Turn on 0RTT data for TLS 1.3
|
||||
pref("security.tls.enable_0rtt_data", true);
|
||||
|
||||
// the origin extension impacts h2 coalescing
|
||||
pref("network.http.originextension", true);
|
||||
|
||||
pref("network.http.diagnostics", false);
|
||||
|
||||
pref("network.http.pacing.requests.enabled", true);
|
||||
|
|
|
@ -131,15 +131,10 @@ ThrottlingService::AddChannel(nsIHttpChannel *channel)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsAutoCString strKey;
|
||||
nsresult rv = channel->GetChannelId(strKey);
|
||||
uint64_t key;
|
||||
nsresult rv = channel->GetChannelId(&key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsID key;
|
||||
if (!key.Parse(strKey.get())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (mChannelHash.Get(key, nullptr)) {
|
||||
// We already have this channel under our control, not adding it again.
|
||||
MOZ_ASSERT(false, "Trying to throttle an already-throttled channel");
|
||||
|
@ -178,15 +173,10 @@ ThrottlingService::RemoveChannel(nsIHttpChannel *channel)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsAutoCString strKey;
|
||||
nsresult rv = channel->GetChannelId(strKey);
|
||||
uint64_t key;
|
||||
nsresult rv = channel->GetChannelId(&key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsID key;
|
||||
if (!key.Parse(strKey.get())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!mChannelHash.Get(key, nullptr)) {
|
||||
// TODO - warn?
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
|
|
@ -50,7 +50,7 @@ private:
|
|||
uint32_t mSuspendPeriod; // How long we should Suspend() channels for
|
||||
uint32_t mResumePeriod; // How long we should Resume() channels for
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
typedef nsInterfaceHashtable<nsIDHashKey, nsIHttpChannel> ChannelHash;
|
||||
typedef nsInterfaceHashtable<nsUint64HashKey, nsIHttpChannel> ChannelHash;
|
||||
ChannelHash mChannelHash;
|
||||
|
||||
// Used to avoid inconsistencies in the hash and the suspend/resume count of
|
||||
|
|
|
@ -128,7 +128,7 @@ struct HttpChannelOpenArgs
|
|||
bool suspendAfterSynthesizeResponse;
|
||||
bool allowStaleCacheContent;
|
||||
nsCString contentTypeHint;
|
||||
nsCString channelId;
|
||||
uint64_t channelId;
|
||||
uint64_t contentWindowId;
|
||||
nsCString preferredAlternativeType;
|
||||
uint64_t topLevelOuterContentWindowId;
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
|
||||
static ASpdySession *NewSpdySession(uint32_t version, nsISocketTransport *, bool);
|
||||
|
||||
virtual bool TestJoinConnection(const nsACString &hostname, int32_t port) = 0;
|
||||
virtual bool JoinConnection(const nsACString &hostname, int32_t port) = 0;
|
||||
|
||||
// MaybeReTunnel() is called by the connection manager when it cannot
|
||||
// dispatch a tunneled transaction. That might be because the tunnels it
|
||||
// expects to see are dead (and we may or may not be able to make more),
|
||||
|
|
|
@ -670,9 +670,9 @@ private:
|
|||
MakeChannel(nsHttpChannel *chan, TransactionObserver *obs, nsHttpConnectionInfo *ci,
|
||||
nsIURI *uri, uint32_t caps, nsILoadInfo *loadInfo)
|
||||
{
|
||||
nsID channelId;
|
||||
uint64_t channelId;
|
||||
nsLoadFlags flags;
|
||||
if (NS_FAILED(gHttpHandler->NewChannelId(&channelId)) ||
|
||||
if (NS_FAILED(gHttpHandler->NewChannelId(channelId)) ||
|
||||
NS_FAILED(chan->Init(uri, caps, nullptr, 0, nullptr, channelId)) ||
|
||||
NS_FAILED(chan->SetAllowAltSvc(false)) ||
|
||||
NS_FAILED(chan->SetRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_ERROR)) ||
|
||||
|
|
|
@ -67,8 +67,7 @@ nsHttpConnectionMgr::OnMsgPrintDiagnostics(int32_t, ARefBase *)
|
|||
ent->mHalfOpens.Length());
|
||||
mLogData.AppendPrintf(" Coalescing Keys Length = %" PRIuSIZE "\n",
|
||||
ent->mCoalescingKeys.Length());
|
||||
mLogData.AppendPrintf(" Spdy using = %d, preferred = %d\n",
|
||||
ent->mUsingSpdy, ent->mInPreferredHash);
|
||||
mLogData.AppendPrintf(" Spdy using = %d\n", ent->mUsingSpdy);
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < ent->mActiveConns.Length(); ++i) {
|
||||
|
|
|
@ -111,6 +111,7 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
|
|||
, mGoAwayOnPush(false)
|
||||
, mUseH2Deps(false)
|
||||
, mAttemptingEarlyData(attemptingEarlyData)
|
||||
, mOriginFrameActivated(false)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
|
@ -224,7 +225,8 @@ static Http2ControlFx sControlFunctions[] = {
|
|||
Http2Session::RecvGoAway,
|
||||
Http2Session::RecvWindowUpdate,
|
||||
Http2Session::RecvContinuation,
|
||||
Http2Session::RecvAltSvc // extension for type 0x0A
|
||||
Http2Session::RecvAltSvc, // extension for type 0x0A
|
||||
Http2Session::RecvOrigin // extension for type 0x0B
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -1798,26 +1800,23 @@ Http2Session::RecvPushPromise(Http2Session *self)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<nsStandardURL> associatedURL, pushedURL;
|
||||
rv = Http2Stream::MakeOriginURL(associatedStream->Origin(), associatedURL);
|
||||
// does the pushed origin belong on this connection?
|
||||
LOG3(("Http2Session::RecvPushPromise %p origin check %s", self,
|
||||
pushedStream->Origin().get()));
|
||||
RefPtr<nsStandardURL> pushedURL;
|
||||
rv = Http2Stream::MakeOriginURL(pushedStream->Origin(), pushedURL);
|
||||
nsAutoCString pushedHostName;
|
||||
int32_t pushedPort = -1;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = Http2Stream::MakeOriginURL(pushedStream->Origin(), pushedURL);
|
||||
rv = pushedURL->GetHost(pushedHostName);
|
||||
}
|
||||
LOG3(("Http2Session::RecvPushPromise %p checking %s == %s", self,
|
||||
associatedStream->Origin().get(), pushedStream->Origin().get()));
|
||||
bool match = false;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = associatedURL->Equals(pushedURL, &match);
|
||||
rv = pushedURL->GetPort(&pushedPort);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// Fallback to string equality of origins. This won't be guaranteed to be as
|
||||
// liberal as we want it to be, but it will at least be safe
|
||||
match = associatedStream->Origin().Equals(pushedStream->Origin());
|
||||
}
|
||||
if (!match) {
|
||||
LOG3(("Http2Session::RecvPushPromise %p pushed stream mismatched origin "
|
||||
"associated origin %s .. pushed origin %s\n", self,
|
||||
associatedStream->Origin().get(), pushedStream->Origin().get()));
|
||||
if (NS_FAILED(rv) ||
|
||||
!self->TestJoinConnection(pushedHostName, pushedPort)) {
|
||||
LOG3(("Http2Session::RecvPushPromise %p pushed stream mismatched origin %s\n",
|
||||
self, pushedStream->Origin().get()));
|
||||
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, REFUSED_STREAM_ERROR);
|
||||
self->ResetDownstreamState();
|
||||
return NS_OK;
|
||||
|
@ -2291,6 +2290,111 @@ Http2Session::RecvAltSvc(Http2Session *self)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::Received421(nsHttpConnectionInfo *ci)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
LOG3(("Http2Session::Recevied421 %p %d\n", this, mOriginFrameActivated));
|
||||
if (!mOriginFrameActivated || !ci) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString key(ci->GetOrigin());
|
||||
key.Append(':');
|
||||
key.AppendInt(ci->OriginPort());
|
||||
mOriginFrame.Remove(key);
|
||||
LOG3(("Http2Session::Received421 %p key %s removed\n", this, key.get()));
|
||||
}
|
||||
|
||||
// defined as an http2 extension - origin
|
||||
// defines receipt of frame type 0x0b.. http://httpwg.org/http-extensions/origin-frame.html
|
||||
// as this is an extension, never generate protocol error - just ignore problems
|
||||
nsresult
|
||||
Http2Session::RecvOrigin(Http2Session *self)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(self->mInputFrameType == FRAME_TYPE_ORIGIN);
|
||||
LOG3(("Http2Session::RecvOrigin %p Flags 0x%X id 0x%X\n", self,
|
||||
self->mInputFrameFlags, self->mInputFrameID));
|
||||
|
||||
if (self->mInputFrameFlags & 0x0F) {
|
||||
LOG3(("Http2Session::RecvOrigin %p leading flags must be 0", self));
|
||||
self->ResetDownstreamState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (self->mInputFrameID) {
|
||||
LOG3(("Http2Session::RecvOrigin %p not stream 0", self));
|
||||
self->ResetDownstreamState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (self->ConnectionInfo()->UsingProxy()) {
|
||||
LOG3(("Http2Session::RecvOrigin %p must not use proxy", self));
|
||||
self->ResetDownstreamState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!gHttpHandler->AllowOriginExtension()) {
|
||||
LOG3(("Http2Session::RecvOrigin %p origin extension pref'd off", self));
|
||||
self->ResetDownstreamState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t offset = 0;
|
||||
self->mOriginFrameActivated = true;
|
||||
|
||||
while (self->mInputFrameDataSize >= (offset + 2U)) {
|
||||
|
||||
uint16_t originLen = NetworkEndian::readUint16(
|
||||
self->mInputFrameBuffer.get() + kFrameHeaderBytes + offset);
|
||||
LOG3(("Http2Session::RecvOrigin %p origin extension defined as %d bytes\n", self, originLen));
|
||||
if (originLen + 2U + offset > self->mInputFrameDataSize) {
|
||||
LOG3(("Http2Session::RecvOrigin %p origin len too big for frame", self));
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString originString;
|
||||
RefPtr<nsStandardURL> originURL;
|
||||
originString.Assign(self->mInputFrameBuffer.get() + kFrameHeaderBytes + offset + 2, originLen);
|
||||
offset += originLen + 2;
|
||||
if (NS_FAILED(Http2Stream::MakeOriginURL(originString, originURL))){
|
||||
LOG3(("Http2Session::RecvOrigin %p origin frame string %s failed to parse\n", self, originString.get()));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG3(("Http2Session::RecvOrigin %p origin frame string %s parsed OK\n", self, originString.get()));
|
||||
bool isHttps = false;
|
||||
if (NS_FAILED(originURL->SchemeIs("https", &isHttps)) || !isHttps) {
|
||||
LOG3(("Http2Session::RecvOrigin %p origin frame not https\n", self));
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t port = -1;
|
||||
originURL->GetPort(&port);
|
||||
if (port == -1) {
|
||||
port = 443;
|
||||
}
|
||||
// dont use ->GetHostPort because we want explicit 443
|
||||
nsAutoCString host;
|
||||
originURL->GetHost(host);
|
||||
nsAutoCString key(host);
|
||||
key.Append(':');
|
||||
key.AppendInt(port);
|
||||
if (!self->mOriginFrame.Get(key)) {
|
||||
self->mOriginFrame.Put(key, true);
|
||||
RefPtr<nsHttpConnection> conn(self->HttpConnection());
|
||||
MOZ_ASSERT(conn.get());
|
||||
gHttpHandler->ConnMgr()->RegisterOriginCoalescingKey(conn, host, port);
|
||||
} else {
|
||||
LOG3(("Http2Session::RecvOrigin %p origin frame already in set\n", self));
|
||||
}
|
||||
}
|
||||
|
||||
self->ResetDownstreamState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsAHttpTransaction. It is expected that nsHttpConnection is the caller
|
||||
// of these methods
|
||||
|
@ -3848,6 +3952,15 @@ Http2Session::TakeHttpConnection()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsHttpConnection>
|
||||
Http2Session::HttpConnection()
|
||||
{
|
||||
if (mConnection) {
|
||||
return mConnection->HttpConnection();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::GetSecurityCallbacks(nsIInterfaceRequestor **aOut)
|
||||
{
|
||||
|
@ -4005,5 +4118,108 @@ Http2Session::SendPing()
|
|||
Unused << ResumeRecv();
|
||||
}
|
||||
|
||||
bool
|
||||
Http2Session::TestOriginFrame(const nsACString &hostname, int32_t port)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(mOriginFrameActivated);
|
||||
|
||||
nsAutoCString key(hostname);
|
||||
key.Append (':');
|
||||
key.AppendInt(port);
|
||||
bool rv = mOriginFrame.Get(key);
|
||||
LOG3(("TestOriginFrame() hash.get %p %s %d\n", this, key.get(), rv));
|
||||
if (!rv && ConnectionInfo()) {
|
||||
// the SNI is also implicitly in this list, so consult that too
|
||||
nsHttpConnectionInfo *ci = ConnectionInfo();
|
||||
rv = nsCString(hostname).EqualsIgnoreCase(ci->Origin()) && (port == ci->OriginPort());
|
||||
LOG3(("TestOriginFrame() %p sni test %d\n", this, rv));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
Http2Session::TestJoinConnection(const nsACString &hostname, int32_t port)
|
||||
{
|
||||
if (!mConnection || mClosed || mShouldGoAway) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mOriginFrameActivated) {
|
||||
bool originFrameResult = TestOriginFrame(hostname, port);
|
||||
if (!originFrameResult) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG3(("TestJoinConnection %p no origin frame check used.\n", this));
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
bool isJoined = false;
|
||||
|
||||
nsCOMPtr<nsISupports> securityInfo;
|
||||
nsCOMPtr<nsISSLSocketControl> sslSocketControl;
|
||||
|
||||
mConnection->GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
sslSocketControl = do_QueryInterface(securityInfo, &rv);
|
||||
if (NS_FAILED(rv) || !sslSocketControl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// try all the coalescable versions we support.
|
||||
const SpdyInformation *info = gHttpHandler->SpdyInfo();
|
||||
for (uint32_t index = SpdyInformation::kCount; index > 0; --index) {
|
||||
if (info->ProtocolEnabled(index - 1)) {
|
||||
rv = sslSocketControl->TestJoinConnection(info->VersionString[index - 1],
|
||||
hostname, port, &isJoined);
|
||||
if (NS_SUCCEEDED(rv) && isJoined) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Http2Session::JoinConnection(const nsACString &hostname, int32_t port)
|
||||
{
|
||||
if (!mConnection || mClosed || mShouldGoAway) {
|
||||
return false;
|
||||
}
|
||||
if (mOriginFrameActivated) {
|
||||
bool originFrameResult = TestOriginFrame(hostname, port);
|
||||
if (!originFrameResult) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG3(("JoinConnection %p no origin frame check used.\n", this));
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
bool isJoined = false;
|
||||
|
||||
nsCOMPtr<nsISupports> securityInfo;
|
||||
nsCOMPtr<nsISSLSocketControl> sslSocketControl;
|
||||
|
||||
mConnection->GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
sslSocketControl = do_QueryInterface(securityInfo, &rv);
|
||||
if (NS_FAILED(rv) || !sslSocketControl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// try all the coalescable versions we support.
|
||||
const SpdyInformation *info = gHttpHandler->SpdyInfo();
|
||||
for (uint32_t index = SpdyInformation::kCount; index > 0; --index) {
|
||||
if (info->ProtocolEnabled(index - 1)) {
|
||||
rv = sslSocketControl->JoinConnection(info->VersionString[index - 1],
|
||||
hostname, port, &isJoined);
|
||||
if (NS_SUCCEEDED(rv) && isJoined) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
bool CanReuse() override { return !mShouldGoAway && !mClosed; }
|
||||
bool RoomForMoreStreams() override;
|
||||
uint32_t SpdyVersion() override;
|
||||
bool TestJoinConnection(const nsACString &hostname, int32_t port) override;
|
||||
bool JoinConnection(const nsACString &hostname, int32_t port) override;
|
||||
|
||||
// When the connection is active this is called up to once every 1 second
|
||||
// return the interval (in seconds) that the connection next wants to
|
||||
|
@ -89,7 +91,8 @@ public:
|
|||
FRAME_TYPE_WINDOW_UPDATE = 0x8,
|
||||
FRAME_TYPE_CONTINUATION = 0x9,
|
||||
FRAME_TYPE_ALTSVC = 0xA,
|
||||
FRAME_TYPE_LAST = 0xB
|
||||
FRAME_TYPE_ORIGIN = 0xB,
|
||||
FRAME_TYPE_LAST = 0xC
|
||||
};
|
||||
|
||||
// NO_ERROR is a macro defined on windows, so we'll name the HTTP2 goaway
|
||||
|
@ -185,6 +188,7 @@ public:
|
|||
static nsresult RecvWindowUpdate(Http2Session *);
|
||||
static nsresult RecvContinuation(Http2Session *);
|
||||
static nsresult RecvAltSvc(Http2Session *);
|
||||
static nsresult RecvOrigin(Http2Session *);
|
||||
|
||||
char *EnsureOutputBuffer(uint32_t needed);
|
||||
|
||||
|
@ -243,6 +247,9 @@ public:
|
|||
MOZ_MUST_USE bool Do0RTT() override final { return true; }
|
||||
MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged) override final;
|
||||
|
||||
// For use by an HTTP2Stream
|
||||
void Received421(nsHttpConnectionInfo *ci);
|
||||
|
||||
private:
|
||||
|
||||
// These internal states do not correspond to the states of the HTTP/2 specification
|
||||
|
@ -508,6 +515,10 @@ private:
|
|||
// The ID(s) of the stream(s) that we are getting 0RTT data from.
|
||||
nsTArray<uint32_t> m0RTTStreams;
|
||||
|
||||
bool TestOriginFrame(const nsACString &name, int32_t port);
|
||||
bool mOriginFrameActivated;
|
||||
nsDataHashtable<nsCStringHashKey, bool> mOriginFrame;
|
||||
|
||||
private:
|
||||
/// connect tunnels
|
||||
void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);
|
||||
|
|
|
@ -1022,6 +1022,7 @@ Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor,
|
|||
|
||||
nsresult errcode;
|
||||
httpResponseCode = statusString.ToInteger(&errcode);
|
||||
LOG3(("Http2Stream::ConvertResponseHeaders %p response code %d\n", this, httpResponseCode));
|
||||
if (mIsTunnel) {
|
||||
LOG3(("Http2Stream %p Tunnel Response code %d", this, httpResponseCode));
|
||||
if ((httpResponseCode / 100) != 2) {
|
||||
|
@ -1035,6 +1036,11 @@ Http2Stream::ConvertResponseHeaders(Http2Decompressor *decompressor,
|
|||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (httpResponseCode == 421) {
|
||||
// Origin Frame requires 421 to remove this origin from the origin set
|
||||
mSession->Received421(mTransaction->ConnectionInfo());
|
||||
}
|
||||
|
||||
if (aHeadersIn.Length() && aHeadersOut.Length()) {
|
||||
Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_SIZE, aHeadersIn.Length());
|
||||
uint32_t ratio =
|
||||
|
|
|
@ -264,7 +264,7 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||
nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI,
|
||||
const nsID& aChannelId)
|
||||
uint64_t aChannelId)
|
||||
{
|
||||
LOG(("HttpBaseChannel::Init [this=%p]\n", this));
|
||||
|
||||
|
@ -1333,25 +1333,18 @@ HttpBaseChannel::nsContentEncodings::PrepareForNext(void)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetChannelId(nsACString& aChannelId)
|
||||
HttpBaseChannel::GetChannelId(uint64_t *aChannelId)
|
||||
{
|
||||
char id[NSID_LENGTH];
|
||||
mChannelId.ToProvidedString(id);
|
||||
aChannelId.AssignASCII(id);
|
||||
NS_ENSURE_ARG_POINTER(aChannelId);
|
||||
*aChannelId = mChannelId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetChannelId(const nsACString& aChannelId)
|
||||
HttpBaseChannel::SetChannelId(uint64_t aChannelId)
|
||||
{
|
||||
nsID newId;
|
||||
nsAutoCString idStr(aChannelId);
|
||||
if (newId.Parse(idStr.get())) {
|
||||
mChannelId = newId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
mChannelId = aChannelId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HttpBaseChannel::GetTopLevelContentWindowId(uint64_t *aWindowId)
|
||||
|
|
|
@ -115,7 +115,7 @@ public:
|
|||
nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI,
|
||||
const nsID& aChannelId);
|
||||
uint64_t aChannelId);
|
||||
|
||||
// nsIRequest
|
||||
NS_IMETHOD GetName(nsACString& aName) override;
|
||||
|
@ -202,8 +202,8 @@ public:
|
|||
NS_IMETHOD GetIsMainDocumentChannel(bool* aValue) override;
|
||||
NS_IMETHOD SetIsMainDocumentChannel(bool aValue) override;
|
||||
NS_IMETHOD GetProtocolVersion(nsACString & aProtocolVersion) override;
|
||||
NS_IMETHOD GetChannelId(nsACString& aChannelId) override;
|
||||
NS_IMETHOD SetChannelId(const nsACString& aChannelId) override;
|
||||
NS_IMETHOD GetChannelId(uint64_t *aChannelId) override;
|
||||
NS_IMETHOD SetChannelId(uint64_t aChannelId) override;
|
||||
NS_IMETHOD GetTopLevelContentWindowId(uint64_t *aContentWindowId) override;
|
||||
NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override;
|
||||
NS_IMETHOD GetTopLevelOuterContentWindowId(uint64_t *aWindowId) override;
|
||||
|
@ -611,7 +611,7 @@ protected:
|
|||
bool mForceMainDocumentChannel;
|
||||
bool mIsTrackingResource;
|
||||
|
||||
nsID mChannelId;
|
||||
uint64_t mChannelId;
|
||||
|
||||
nsString mIntegrityMetadata;
|
||||
|
||||
|
|
|
@ -1421,7 +1421,7 @@ class Redirect1Event : public ChannelEvent
|
|||
const uint32_t& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead,
|
||||
const nsACString& securityInfoSerialization,
|
||||
const nsACString& channelId)
|
||||
const uint64_t& channelId)
|
||||
: mChild(child)
|
||||
, mRegistrarId(registrarId)
|
||||
, mNewURI(newURI)
|
||||
|
@ -1450,7 +1450,7 @@ class Redirect1Event : public ChannelEvent
|
|||
uint32_t mRedirectFlags;
|
||||
nsHttpResponseHead mResponseHead;
|
||||
nsCString mSecurityInfoSerialization;
|
||||
nsCString mChannelId;
|
||||
uint64_t mChannelId;
|
||||
};
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
@ -1459,7 +1459,7 @@ HttpChannelChild::RecvRedirect1Begin(const uint32_t& registrarId,
|
|||
const uint32_t& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead,
|
||||
const nsCString& securityInfoSerialization,
|
||||
const nsCString& channelId)
|
||||
const uint64_t& channelId)
|
||||
{
|
||||
// TODO: handle security info
|
||||
LOG(("HttpChannelChild::RecvRedirect1Begin [this=%p]\n", this));
|
||||
|
@ -1537,7 +1537,7 @@ HttpChannelChild::Redirect1Begin(const uint32_t& registrarId,
|
|||
const uint32_t& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead,
|
||||
const nsACString& securityInfoSerialization,
|
||||
const nsACString& channelId)
|
||||
const uint64_t& channelId)
|
||||
{
|
||||
LOG(("HttpChannelChild::Redirect1Begin [this=%p]\n", this));
|
||||
|
||||
|
@ -2418,9 +2418,7 @@ HttpChannelChild::ContinueAsyncOpen()
|
|||
EnsureRequestContextID();
|
||||
openArgs.requestContextID() = mRequestContextID;
|
||||
|
||||
char chid[NSID_LENGTH];
|
||||
mChannelId.ToProvidedString(chid);
|
||||
openArgs.channelId().AssignASCII(chid);
|
||||
openArgs.channelId() = mChannelId;
|
||||
|
||||
openArgs.contentWindowId() = contentWindowId;
|
||||
openArgs.topLevelOuterContentWindowId() = mTopLevelOuterContentWindowId;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче