зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound, a=merge
MozReview-Commit-ID: CaSKFN9T7N4
This commit is contained in:
Коммит
bb24138b9d
|
@ -26,8 +26,14 @@ jobs:
|
|||
treeherder-symbol: Nd-OSX
|
||||
target-tasks-method: nightly_macosx
|
||||
run-on-projects:
|
||||
- mozilla-central
|
||||
- date
|
||||
when: [] # never (hook only)
|
||||
when:
|
||||
by-project:
|
||||
# Match buildbot starts for now
|
||||
date: [{hour: 15, minute: 0}]
|
||||
mozilla-central: [{hour: 10, minute: 0}]
|
||||
# No default
|
||||
|
||||
- name: nightly-desktop-win64
|
||||
job:
|
||||
|
|
|
@ -1561,7 +1561,7 @@ pref("extensions.allow-non-mpc-extensions", false);
|
|||
#endif
|
||||
|
||||
// Enable blocking of e10s and e10s-multi for add-on users on beta/release.
|
||||
#ifdef RELEASE_OR_BETA
|
||||
#if defined(RELEASE_OR_BETA) && !defined(MOZ_DEV_EDITION)
|
||||
pref("extensions.e10sBlocksEnabling", true);
|
||||
pref("extensions.e10sMultiBlocksEnabling", true);
|
||||
#endif
|
||||
|
|
|
@ -2459,7 +2459,7 @@
|
|||
// transition in that case.
|
||||
let animate = !aSkipAnimation &&
|
||||
this.tabContainer.getAttribute("overflow") != "true" &&
|
||||
Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled");
|
||||
this.animationsEnabled;
|
||||
if (!animate) {
|
||||
t.setAttribute("fadein", "true");
|
||||
|
||||
|
@ -2814,7 +2814,7 @@
|
|||
this._removingTabs.length > 3 /* don't want lots of concurrent animations */ ||
|
||||
aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ ||
|
||||
window.getComputedStyle(aTab).maxWidth == "0.1px" /* fade-in transition hasn't moved yet */ ||
|
||||
!Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
|
||||
!this.animationsEnabled) {
|
||||
// We're not animating, so we can cancel the animation stopwatch.
|
||||
TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_ANIM_MS", aTab);
|
||||
this._endRemoveTab(aTab);
|
||||
|
@ -5418,6 +5418,9 @@
|
|||
messageManager.addMessageListener("Prerender:Request", this);
|
||||
messageManager.addMessageListener("Prerender:Cancel", this);
|
||||
messageManager.addMessageListener("Prerender:Swap", this);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "animationsEnabled",
|
||||
"toolkit.cosmeticAnimations.enabled", true);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
|
@ -7060,7 +7063,8 @@
|
|||
if (dropIndex && dropIndex > draggedTab._tPos)
|
||||
dropIndex--;
|
||||
|
||||
if (oldTranslateX && oldTranslateX != newTranslateX) {
|
||||
let animate = this.tabbrowser.animationsEnabled;
|
||||
if (oldTranslateX && oldTranslateX != newTranslateX && animate) {
|
||||
draggedTab.setAttribute("tabdrop-samewindow", "true");
|
||||
draggedTab.style.transform = "translateX(" + newTranslateX + "px)";
|
||||
let onTransitionEnd = transitionendEvent => {
|
||||
|
|
|
@ -246,6 +246,9 @@ var CustomizableUIInternal = {
|
|||
"home-button",
|
||||
];
|
||||
|
||||
if (AppConstants.MOZ_PHOTON_THEME) {
|
||||
navbarPlacements.push("sidebar-button");
|
||||
}
|
||||
if (AppConstants.MOZ_DEV_EDITION) {
|
||||
navbarPlacements.splice(2, 0, "developer-button");
|
||||
}
|
||||
|
|
|
@ -61,15 +61,9 @@ class ParentDevToolsPanel {
|
|||
this.id = this.panelOptions.id;
|
||||
|
||||
this.onToolboxPanelSelect = this.onToolboxPanelSelect.bind(this);
|
||||
this.onToolboxReady = this.onToolboxReady.bind(this);
|
||||
|
||||
this.panelAdded = false;
|
||||
|
||||
if (this.toolbox.isReady) {
|
||||
this.onToolboxReady();
|
||||
} else {
|
||||
this.toolbox.once("ready", this.onToolboxReady);
|
||||
}
|
||||
this.addPanel();
|
||||
|
||||
this.waitTopLevelContext = new Promise(resolve => {
|
||||
this._resolveTopLevelContext = resolve;
|
||||
|
@ -99,6 +93,8 @@ class ParentDevToolsPanel {
|
|||
return {toolbox, destroy};
|
||||
},
|
||||
});
|
||||
|
||||
this.panelAdded = true;
|
||||
}
|
||||
|
||||
buildPanel(window, toolbox) {
|
||||
|
@ -180,13 +176,6 @@ class ParentDevToolsPanel {
|
|||
};
|
||||
}
|
||||
|
||||
onToolboxReady() {
|
||||
if (!this.panelAdded) {
|
||||
this.panelAdded = true;
|
||||
this.addPanel();
|
||||
}
|
||||
}
|
||||
|
||||
onToolboxPanelSelect(what, id) {
|
||||
if (!this.waitTopLevelContext || !this.panelAdded) {
|
||||
return;
|
||||
|
@ -214,11 +203,9 @@ class ParentDevToolsPanel {
|
|||
throw new Error("Unable to destroy a closed devtools panel");
|
||||
}
|
||||
|
||||
toolbox.off("ready", this.onToolboxReady);
|
||||
|
||||
// Explicitly remove the panel if it is registered and the toolbox is not
|
||||
// closing itself.
|
||||
if (toolbox.isToolRegistered(this.id) && !toolbox._destroyer) {
|
||||
if (this.panelAdded && toolbox.isToolRegistered(this.id) && !toolbox._destroyer) {
|
||||
toolbox.removeAdditionalTool(this.id);
|
||||
}
|
||||
|
||||
|
|
|
@ -1127,9 +1127,9 @@
|
|||
|
||||
<handler event="popuphiding"><![CDATA[
|
||||
this._isHiding = true;
|
||||
setTimeout(() => {
|
||||
Services.tm.dispatchToMainThread(() => {
|
||||
this._isHiding = false;
|
||||
}, 0);
|
||||
});
|
||||
]]></handler>
|
||||
|
||||
<!-- This handles clicks on the topmost "Foo Search" header in the
|
||||
|
|
|
@ -3255,7 +3255,6 @@ var SessionStoreInternal = {
|
|||
}
|
||||
|
||||
let tabbrowser = aWindow.gBrowser;
|
||||
let tabsToRemove = overwriteTabs ? tabbrowser.browsers.length : 0;
|
||||
let newTabCount = winData.tabs.length;
|
||||
var tabs = [];
|
||||
|
||||
|
@ -3266,11 +3265,20 @@ var SessionStoreInternal = {
|
|||
|
||||
// We need to keep track of the initially open tabs so that they
|
||||
// can be moved to the end of the restored tabs.
|
||||
let initialTabs = [];
|
||||
let initialTabs;
|
||||
if (!overwriteTabs && firstWindow) {
|
||||
initialTabs = Array.slice(tabbrowser.tabs);
|
||||
}
|
||||
|
||||
// Get rid of tabs that aren't needed anymore.
|
||||
if (overwriteTabs) {
|
||||
for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) {
|
||||
if (!tabbrowser.tabs[i].selected) {
|
||||
tabbrowser.removeTab(tabbrowser.tabs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let restoreTabsLazily = this._prefBranch.getBoolPref("sessionstore.restore_tabs_lazily") &&
|
||||
this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
|
||||
|
||||
|
@ -3279,61 +3287,67 @@ var SessionStoreInternal = {
|
|||
|
||||
let userContextId = tabData.userContextId;
|
||||
let select = t == selectTab - 1;
|
||||
let createLazyBrowser = restoreTabsLazily && !select && !tabData.pinned;
|
||||
let tab;
|
||||
|
||||
let url = "about:blank";
|
||||
if (createLazyBrowser && tabData.entries && tabData.entries.length) {
|
||||
// Let tabbrowser know the future URI because progress listeners won't
|
||||
// get onLocationChange notification before the browser is inserted.
|
||||
let activeIndex = (tabData.index || tabData.entries.length) - 1;
|
||||
// Ensure the index is in bounds.
|
||||
activeIndex = Math.min(activeIndex, tabData.entries.length - 1);
|
||||
activeIndex = Math.max(activeIndex, 0);
|
||||
url = tabData.entries[activeIndex].url;
|
||||
// Re-use existing selected tab if possible to avoid the overhead of
|
||||
// selecting a new tab.
|
||||
if (select &&
|
||||
tabbrowser.selectedTab.userContextId == userContextId) {
|
||||
tab = tabbrowser.selectedTab;
|
||||
if (!tabData.pinned) {
|
||||
tabbrowser.unpinTab(tab);
|
||||
}
|
||||
tabbrowser.moveTabToEnd();
|
||||
if (aWindow.gMultiProcessBrowser && !tab.linkedBrowser.isRemoteBrowser) {
|
||||
tabbrowser.updateBrowserRemoteness(tab.linkedBrowser, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Setting noInitialLabel is a perf optimization. Rendering tab labels
|
||||
// would make resizing the tabs more expensive as we're adding them.
|
||||
// Each tab will get its initial label set in restoreTab.
|
||||
let tab = tabbrowser.addTab(url,
|
||||
{ createLazyBrowser,
|
||||
skipAnimation: true,
|
||||
noInitialLabel: true,
|
||||
userContextId,
|
||||
skipBackgroundNotify: true });
|
||||
// Add a new tab if needed.
|
||||
if (!tab) {
|
||||
let createLazyBrowser = restoreTabsLazily && !select && !tabData.pinned;
|
||||
|
||||
if (select) {
|
||||
// Select a new tab first to prevent the removeTab loop from changing
|
||||
// the selected tab over and over again.
|
||||
tabbrowser.selectedTab = tab;
|
||||
|
||||
// Remove superfluous tabs.
|
||||
for (let i = 0; i < tabsToRemove; i++) {
|
||||
tabbrowser.removeTab(tabbrowser.tabs[0]);
|
||||
let url = "about:blank";
|
||||
if (createLazyBrowser && tabData.entries && tabData.entries.length) {
|
||||
// Let tabbrowser know the future URI because progress listeners won't
|
||||
// get onLocationChange notification before the browser is inserted.
|
||||
let activeIndex = (tabData.index || tabData.entries.length) - 1;
|
||||
// Ensure the index is in bounds.
|
||||
activeIndex = Math.min(activeIndex, tabData.entries.length - 1);
|
||||
activeIndex = Math.max(activeIndex, 0);
|
||||
url = tabData.entries[activeIndex].url;
|
||||
}
|
||||
|
||||
// Setting noInitialLabel is a perf optimization. Rendering tab labels
|
||||
// would make resizing the tabs more expensive as we're adding them.
|
||||
// Each tab will get its initial label set in restoreTab.
|
||||
tab = tabbrowser.addTab(url,
|
||||
{ createLazyBrowser,
|
||||
skipAnimation: true,
|
||||
noInitialLabel: true,
|
||||
userContextId,
|
||||
skipBackgroundNotify: true });
|
||||
|
||||
if (select) {
|
||||
let leftoverTab = tabbrowser.selectedTab;
|
||||
tabbrowser.selectedTab = tab;
|
||||
tabbrowser.removeTab(leftoverTab);
|
||||
}
|
||||
tabsToRemove = 0;
|
||||
}
|
||||
|
||||
tabs.push(tab);
|
||||
|
||||
if (tabData.hidden) {
|
||||
tabbrowser.hideTab(tabs[t]);
|
||||
tabbrowser.hideTab(tab);
|
||||
}
|
||||
|
||||
if (tabData.pinned) {
|
||||
tabbrowser.pinTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < newTabCount; ++i) {
|
||||
if (winData.tabs[i].pinned) {
|
||||
tabbrowser.pinTab(tabs[i]);
|
||||
} else {
|
||||
// Pinned tabs are clustered at the start of the tab strip. As
|
||||
// soon as we reach a tab that isn't pinned, we know there aren't
|
||||
// any more for this window.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!overwriteTabs && firstWindow) {
|
||||
// Move the originally open tabs to the end
|
||||
// Move the originally open tabs to the end.
|
||||
if (initialTabs) {
|
||||
let endPosition = tabbrowser.tabs.length - 1;
|
||||
for (let i = 0; i < initialTabs.length; i++) {
|
||||
tabbrowser.unpinTab(initialTabs[i]);
|
||||
|
|
|
@ -239,6 +239,7 @@ run-if = e10s
|
|||
run-if = e10s
|
||||
[browser_sessionStoreContainer.js]
|
||||
[browser_windowStateContainer.js]
|
||||
skip-if = os == "linux" && !debug
|
||||
[browser_1234021.js]
|
||||
[browser_remoteness_flip_on_restore.js]
|
||||
run-if = e10s
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/common"
|
||||
. "$topsrcdir/build/mozconfig.no-compile"
|
||||
|
||||
# We need to indicate the target for cross builds
|
||||
ac_add_options --target=x86_64-apple-darwin
|
||||
|
||||
export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
|
||||
export DMG_TOOL=$topsrcdir/dmg/dmg
|
||||
export HFS_TOOL=$topsrcdir/dmg/hfsplus
|
||||
|
||||
ac_add_options --with-l10n-base=../../l10n
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --with-branding=browser/branding/nightly
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/common"
|
||||
. "$topsrcdir/build/mozconfig.no-compile"
|
||||
|
||||
# We need to indicate the target for cross builds
|
||||
ac_add_options --target=x86_64-apple-darwin
|
||||
|
||||
export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
|
||||
export DMG_TOOL=$topsrcdir/dmg/dmg
|
||||
export HFS_TOOL=$topsrcdir/dmg/hfsplus
|
||||
|
||||
ac_add_options --with-l10n-base=../../l10n
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
|
|
@ -14,7 +14,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
const ACTIVITY_STREAM_ENABLED_PREF = "browser.newtabpage.activity-stream.enabled";
|
||||
const BROWSER_READY_NOTIFICATION = "browser-ui-startup-complete";
|
||||
const BROWSER_READY_NOTIFICATION = "browser-delayed-startup-finished";
|
||||
const REASON_SHUTDOWN_ON_PREF_CHANGE = "PREF_OFF";
|
||||
const REASON_STARTUP_ON_PREF_CHANGE = "PREF_ON";
|
||||
const RESOURCE_BASE = "resource://activity-stream";
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* globals Services */
|
||||
"use strict";
|
||||
|
||||
let usablePerfObj;
|
||||
|
||||
let Cu;
|
||||
const isRunningInChrome = typeof Window === "undefined";
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (isRunningInChrome) {
|
||||
Cu = Components.utils;
|
||||
} else {
|
||||
Cu = {import() {}};
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (isRunningInChrome) {
|
||||
// Borrow the high-resolution timer from the hidden window....
|
||||
usablePerfObj = Services.appShell.hiddenDOMWindow.performance;
|
||||
} else { // we must be running in content space
|
||||
usablePerfObj = performance;
|
||||
}
|
||||
|
||||
this._PerfService = function _PerfService(options) {
|
||||
// For testing, so that we can use a fake Window.performance object with
|
||||
// known state.
|
||||
if (options && options.performanceObj) {
|
||||
this._perf = options.performanceObj;
|
||||
} else {
|
||||
this._perf = usablePerfObj;
|
||||
}
|
||||
};
|
||||
|
||||
_PerfService.prototype = {
|
||||
/**
|
||||
* Calls the underlying mark() method on the appropriate Window.performance
|
||||
* object to add a mark with the given name to the appropriate performance
|
||||
* timeline.
|
||||
*
|
||||
* @param {String} name the name to give the current mark
|
||||
* @return {void}
|
||||
*/
|
||||
mark: function mark(str) {
|
||||
this._perf.mark(str);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calls the underlying getEntriesByName on the appropriate Window.performance
|
||||
* object.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {String} type eg "mark"
|
||||
* @return {Array} Performance* objects
|
||||
*/
|
||||
getEntriesByName: function getEntriesByName(name, type) {
|
||||
return this._perf.getEntriesByName(name, type);
|
||||
},
|
||||
|
||||
/**
|
||||
* The timeOrigin property from the appropriate performance object.
|
||||
* Used to ensure that timestamps from the add-on code and the content code
|
||||
* are comparable.
|
||||
*
|
||||
* @return {Number} A double of milliseconds with a precision of 0.5us.
|
||||
*/
|
||||
get timeOrigin() {
|
||||
return this._perf.timeOrigin;
|
||||
},
|
||||
|
||||
/**
|
||||
* This returns the startTime from the most recen!t performance.mark()
|
||||
* with the given name.
|
||||
*
|
||||
* @param {String} name the name to lookup the start time for
|
||||
*
|
||||
* @return {Number} the returned start time, as a DOMHighResTimeStamp
|
||||
*
|
||||
* @throws {Error} "No Marks with the name ..." if none are available
|
||||
*/
|
||||
getMostRecentAbsMarkStartByName(name) {
|
||||
let entries = this.getEntriesByName(name, "mark");
|
||||
|
||||
if (!entries.length) {
|
||||
throw new Error(`No marks with the name ${name}`);
|
||||
}
|
||||
|
||||
let mostRecentEntry = entries[entries.length - 1];
|
||||
return this._perf.timeOrigin + mostRecentEntry.startTime;
|
||||
}
|
||||
};
|
||||
|
||||
this.perfService = new _PerfService();
|
||||
this.EXPORTED_SYMBOLS = ["_PerfService", "perfService"];
|
|
@ -63,7 +63,7 @@
|
|||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 17);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 18);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
|
@ -394,6 +394,10 @@ var _require = __webpack_require__(1);
|
|||
|
||||
const at = _require.actionTypes;
|
||||
|
||||
var _require2 = __webpack_require__(15);
|
||||
|
||||
const perfSvc = _require2.perfService;
|
||||
|
||||
|
||||
const VISIBLE = "visible";
|
||||
const VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
||||
|
@ -405,7 +409,7 @@ module.exports = class DetectUserSessionStart {
|
|||
// Overrides for testing
|
||||
this.sendAsyncMessage = options.sendAsyncMessage || window.sendAsyncMessage;
|
||||
this.document = options.document || document;
|
||||
|
||||
this._perfService = options.perfService || perfSvc;
|
||||
this._onVisibilityChange = this._onVisibilityChange.bind(this);
|
||||
}
|
||||
|
||||
|
@ -427,11 +431,19 @@ module.exports = class DetectUserSessionStart {
|
|||
}
|
||||
|
||||
/**
|
||||
* _sendEvent - Sends a message to the main process to indicate the current tab
|
||||
* is now visible to the user.
|
||||
* _sendEvent - Sends a message to the main process to indicate the current
|
||||
* tab is now visible to the user, includes the
|
||||
* visibility-change-event time in ms from the UNIX epoch.
|
||||
*/
|
||||
_sendEvent() {
|
||||
this.sendAsyncMessage("ActivityStream:ContentToMain", { type: at.NEW_TAB_VISIBLE });
|
||||
this._perfService.mark("visibility-change-event");
|
||||
|
||||
let absVisChangeTime = this._perfService.getMostRecentAbsMarkStartByName("visibility-change-event");
|
||||
|
||||
this.sendAsyncMessage("ActivityStream:ContentToMain", {
|
||||
type: at.NEW_TAB_VISIBLE,
|
||||
data: { absVisibilityChangeTime: absVisChangeTime }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -455,7 +467,7 @@ module.exports = class DetectUserSessionStart {
|
|||
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
var _require = __webpack_require__(16);
|
||||
var _require = __webpack_require__(17);
|
||||
|
||||
const createStore = _require.createStore,
|
||||
combineReducers = _require.combineReducers,
|
||||
|
@ -892,7 +904,7 @@ var _require2 = __webpack_require__(3);
|
|||
const injectIntl = _require2.injectIntl,
|
||||
FormattedMessage = _require2.FormattedMessage;
|
||||
|
||||
const classNames = __webpack_require__(15);
|
||||
const classNames = __webpack_require__(16);
|
||||
|
||||
var _require3 = __webpack_require__(1);
|
||||
|
||||
|
@ -1044,7 +1056,12 @@ class Search extends React.Component {
|
|||
}
|
||||
onInputMount(input) {
|
||||
if (input) {
|
||||
this.controller = new ContentSearchUIController(input, input.parentNode, "activity", "newtab");
|
||||
// The first "newtab" parameter here is called the "healthReportKey" and needs
|
||||
// to be "newtab" so that BrowserUsageTelemetry.jsm knows to handle events with
|
||||
// this name, and can add the appropriate telemetry probes for search. Without the
|
||||
// correct name, certain tests like browser_UsageTelemetry_content.js will fail (See
|
||||
// github ticket #2348 for more details)
|
||||
this.controller = new ContentSearchUIController(input, input.parentNode, "newtab", "newtab");
|
||||
addEventListener("ContentSearchClient", this);
|
||||
} else {
|
||||
this.controller = null;
|
||||
|
@ -1052,13 +1069,18 @@ class Search extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not change the ID on the input field, as legacy newtab code
|
||||
* specifically looks for the id 'newtab-search-text' on input fields
|
||||
* in order to execute searches in various tests
|
||||
*/
|
||||
render() {
|
||||
return React.createElement(
|
||||
"form",
|
||||
{ className: "search-wrapper" },
|
||||
React.createElement(
|
||||
"label",
|
||||
{ htmlFor: "search-input", className: "search-label" },
|
||||
{ htmlFor: "newtab-search-text", className: "search-label" },
|
||||
React.createElement(
|
||||
"span",
|
||||
{ className: "sr-only" },
|
||||
|
@ -1066,7 +1088,7 @@ class Search extends React.Component {
|
|||
)
|
||||
),
|
||||
React.createElement("input", {
|
||||
id: "search-input",
|
||||
id: "newtab-search-text",
|
||||
maxLength: "256",
|
||||
placeholder: this.props.intl.formatMessage({ id: "search_web_placeholder" }),
|
||||
ref: this.onInputMount,
|
||||
|
@ -1251,6 +1273,111 @@ module.exports = function shortURL(link) {
|
|||
/* 15 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* globals Services */
|
||||
|
||||
|
||||
let usablePerfObj;
|
||||
|
||||
let Cu;
|
||||
const isRunningInChrome = typeof Window === "undefined";
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (isRunningInChrome) {
|
||||
Cu = Components.utils;
|
||||
} else {
|
||||
Cu = { import() {} };
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (isRunningInChrome) {
|
||||
// Borrow the high-resolution timer from the hidden window....
|
||||
usablePerfObj = Services.appShell.hiddenDOMWindow.performance;
|
||||
} else {
|
||||
// we must be running in content space
|
||||
usablePerfObj = performance;
|
||||
}
|
||||
|
||||
var _PerfService = function _PerfService(options) {
|
||||
// For testing, so that we can use a fake Window.performance object with
|
||||
// known state.
|
||||
if (options && options.performanceObj) {
|
||||
this._perf = options.performanceObj;
|
||||
} else {
|
||||
this._perf = usablePerfObj;
|
||||
}
|
||||
};
|
||||
|
||||
_PerfService.prototype = {
|
||||
/**
|
||||
* Calls the underlying mark() method on the appropriate Window.performance
|
||||
* object to add a mark with the given name to the appropriate performance
|
||||
* timeline.
|
||||
*
|
||||
* @param {String} name the name to give the current mark
|
||||
* @return {void}
|
||||
*/
|
||||
mark: function mark(str) {
|
||||
this._perf.mark(str);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calls the underlying getEntriesByName on the appropriate Window.performance
|
||||
* object.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {String} type eg "mark"
|
||||
* @return {Array} Performance* objects
|
||||
*/
|
||||
getEntriesByName: function getEntriesByName(name, type) {
|
||||
return this._perf.getEntriesByName(name, type);
|
||||
},
|
||||
|
||||
/**
|
||||
* The timeOrigin property from the appropriate performance object.
|
||||
* Used to ensure that timestamps from the add-on code and the content code
|
||||
* are comparable.
|
||||
*
|
||||
* @return {Number} A double of milliseconds with a precision of 0.5us.
|
||||
*/
|
||||
get timeOrigin() {
|
||||
return this._perf.timeOrigin;
|
||||
},
|
||||
|
||||
/**
|
||||
* This returns the startTime from the most recen!t performance.mark()
|
||||
* with the given name.
|
||||
*
|
||||
* @param {String} name the name to lookup the start time for
|
||||
*
|
||||
* @return {Number} the returned start time, as a DOMHighResTimeStamp
|
||||
*
|
||||
* @throws {Error} "No Marks with the name ..." if none are available
|
||||
*/
|
||||
getMostRecentAbsMarkStartByName(name) {
|
||||
let entries = this.getEntriesByName(name, "mark");
|
||||
|
||||
if (!entries.length) {
|
||||
throw new Error(`No marks with the name ${name}`);
|
||||
}
|
||||
|
||||
let mostRecentEntry = entries[entries.length - 1];
|
||||
return this._perf.timeOrigin + mostRecentEntry.startTime;
|
||||
}
|
||||
};
|
||||
|
||||
var perfService = new _PerfService();
|
||||
module.exports = {
|
||||
_PerfService,
|
||||
perfService
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 16 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
||||
Copyright (c) 2016 Jed Watson.
|
||||
Licensed under the MIT License (MIT), see
|
||||
|
@ -1303,13 +1430,13 @@ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|||
|
||||
|
||||
/***/ }),
|
||||
/* 16 */
|
||||
/* 17 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
module.exports = Redux;
|
||||
|
||||
/***/ }),
|
||||
/* 17 */
|
||||
/* 18 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
|
|
@ -861,6 +861,7 @@
|
|||
"header_top_sites": "Top Sites",
|
||||
"header_highlights": "Highlights",
|
||||
"header_stories": "Top Stories",
|
||||
"header_visit_again": "Visit Again",
|
||||
"header_bookmarks": "Recent Bookmarks",
|
||||
"header_bookmarks_placeholder": "You don't have any bookmarks yet.",
|
||||
"header_stories_from": "from",
|
||||
|
@ -903,6 +904,8 @@
|
|||
"settings_pane_highlights_body": "Look back at your recent browsing history and newly created bookmarks.",
|
||||
"settings_pane_bookmarks_header": "Recent Bookmarks",
|
||||
"settings_pane_bookmarks_body": "Your newly created bookmarks in one handy location.",
|
||||
"settings_pane_visit_again_header": "Visit Again",
|
||||
"settings_pane_visit_again_body": "Firefox will show you parts of your browsing history that you might want to remember or get back to.",
|
||||
"settings_pane_pocketstories_header": "Top Stories",
|
||||
"settings_pane_pocketstories_body": "Pocket, a part of the Mozilla family, will help connect you to high-quality content that you may not have found otherwise.",
|
||||
"settings_pane_done_button": "Done",
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
/* 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/. */
|
||||
/* globals Services */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {utils: Cu} = Components;
|
||||
const {interfaces: Ci, utils: Cu} = Components;
|
||||
const {actionTypes: at, actionUtils: au} = Cu.import("resource://activity-stream/common/Actions.jsm", {});
|
||||
const {perfService} = Cu.import("resource://activity-stream/common/PerfService.jsm", {});
|
||||
|
||||
Cu.import("resource://gre/modules/ClientID.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
|
@ -24,6 +27,8 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
}
|
||||
|
||||
async init() {
|
||||
Services.obs.addObserver(this.browserOpenNewtabStart, "browser-open-newtab-start");
|
||||
|
||||
// TelemetrySender adds pref observers, so we initialize it after INIT
|
||||
this.telemetrySender = new TelemetrySender();
|
||||
|
||||
|
@ -31,16 +36,55 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
this.telemetryClientId = id;
|
||||
}
|
||||
|
||||
browserOpenNewtabStart() {
|
||||
perfService.mark("browser-open-newtab-start");
|
||||
}
|
||||
|
||||
/**
|
||||
* addSession - Start tracking a new session
|
||||
*
|
||||
* @param {string} id the portID of the open session
|
||||
* @param {number} absVisChangeTime absolute timestamp of
|
||||
* document.visibilityState becoming visible
|
||||
*/
|
||||
addSession(id) {
|
||||
addSession(id, absVisChangeTime) {
|
||||
// XXX note that there is a race condition here; we're assuming that no
|
||||
// other tab will be interleaving calls to browserOpenNewtabStart and
|
||||
// addSession on this object. For manually created windows, it's hard to
|
||||
// imagine us hitting this race condition.
|
||||
//
|
||||
// However, for session restore, where multiple windows with multiple tabs
|
||||
// might be restored much closer together in time, it's somewhat less hard,
|
||||
// though it should still be pretty rare.
|
||||
//
|
||||
// The fix to this would be making all of the load-trigger notifications
|
||||
// return some data with their notifications, and somehow propagate that
|
||||
// data through closures into the tab itself so that we could match them
|
||||
//
|
||||
// As of this writing (very early days of system add-on perf telemetry),
|
||||
// the hypothesis is that hitting this race should be so rare that makes
|
||||
// more sense to live with the slight data inaccuracy that it would
|
||||
// introduce, rather than doing the correct by complicated thing. It may
|
||||
// well be worth reexamining this hypothesis after we have more experience
|
||||
// with the data.
|
||||
let absBrowserOpenTabStart =
|
||||
perfService.getMostRecentAbsMarkStartByName("browser-open-newtab-start");
|
||||
|
||||
this.sessions.set(id, {
|
||||
start_time: Components.utils.now(),
|
||||
session_id: String(gUUIDGenerator.generateUUID()),
|
||||
page: "about:newtab" // TODO: Handle about:home
|
||||
page: "about:newtab", // TODO: Handle about:home here and in perf below
|
||||
perf: {
|
||||
load_trigger_ts: absBrowserOpenTabStart,
|
||||
load_trigger_type: "menu_plus_or_keyboard",
|
||||
visibility_event_rcvd_ts: absVisChangeTime
|
||||
}
|
||||
});
|
||||
|
||||
let duration = absVisChangeTime - absBrowserOpenTabStart;
|
||||
this.store.dispatch({
|
||||
type: at.TELEMETRY_PERFORMANCE_EVENT,
|
||||
data: {visability_duration: duration}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -119,7 +163,8 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
session_id: session.session_id,
|
||||
page: session.page,
|
||||
session_duration: session.session_duration,
|
||||
action: "activity_stream_session"
|
||||
action: "activity_stream_session",
|
||||
perf: session.perf
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -134,7 +179,8 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
this.init();
|
||||
break;
|
||||
case at.NEW_TAB_VISIBLE:
|
||||
this.addSession(au.getPortIdOfSender(action));
|
||||
this.addSession(au.getPortIdOfSender(action),
|
||||
action.data.absVisibilityChangeTime);
|
||||
break;
|
||||
case at.NEW_TAB_UNLOAD:
|
||||
this.endSession(au.getPortIdOfSender(action));
|
||||
|
@ -152,6 +198,9 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
}
|
||||
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this.browserOpenNewtabStart,
|
||||
"browser-open-newtab-start");
|
||||
|
||||
this.telemetrySender.uninit();
|
||||
this.telemetrySender = null;
|
||||
// TODO: Send any unfinished sessions
|
||||
|
|
|
@ -6,7 +6,6 @@ const {interfaces: Ci, utils: Cu} = Components;
|
|||
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Console.jsm"); // eslint-disable-line no-console
|
||||
|
||||
|
@ -15,9 +14,11 @@ Cu.import("resource://gre/modules/Console.jsm"); // eslint-disable-line no-conso
|
|||
// installed. Though maybe we should just forcibly disable the old add-on?
|
||||
const PREF_BRANCH = "browser.newtabpage.activity-stream.";
|
||||
|
||||
const ENDPOINT_PREF = "telemetry.ping.endpoint";
|
||||
const TELEMETRY_PREF = "telemetry";
|
||||
const LOGGING_PREF = "telemetry.log";
|
||||
const ENDPOINT_PREF = `${PREF_BRANCH}telemetry.ping.endpoint`;
|
||||
const TELEMETRY_PREF = `${PREF_BRANCH}telemetry`;
|
||||
const LOGGING_PREF = `${PREF_BRANCH}telemetry.log`;
|
||||
|
||||
const FHR_UPLOAD_ENABLED_PREF = "datareporting.healthreport.uploadEnabled";
|
||||
|
||||
/**
|
||||
* Observe various notifications and send them to a telemetry endpoint.
|
||||
|
@ -27,10 +28,9 @@ const LOGGING_PREF = "telemetry.log";
|
|||
* inside the Prefs constructor. Typically used from tests
|
||||
* to save off a pointer to a fake Prefs instance so that
|
||||
* stubs and spies can be inspected by the test code.
|
||||
*
|
||||
*/
|
||||
function TelemetrySender(args) {
|
||||
let prefArgs = {branch: PREF_BRANCH};
|
||||
let prefArgs = {};
|
||||
if (args) {
|
||||
if ("prefInitHook" in args) {
|
||||
prefArgs.initHook = args.prefInitHook;
|
||||
|
@ -39,10 +39,14 @@ function TelemetrySender(args) {
|
|||
|
||||
this._prefs = new Preferences(prefArgs);
|
||||
|
||||
this.enabled = this._prefs.get(TELEMETRY_PREF);
|
||||
this._enabled = this._prefs.get(TELEMETRY_PREF);
|
||||
this._onTelemetryPrefChange = this._onTelemetryPrefChange.bind(this);
|
||||
this._prefs.observe(TELEMETRY_PREF, this._onTelemetryPrefChange);
|
||||
|
||||
this._fhrEnabled = this._prefs.get(FHR_UPLOAD_ENABLED_PREF);
|
||||
this._onFhrPrefChange = this._onFhrPrefChange.bind(this);
|
||||
this._prefs.observe(FHR_UPLOAD_ENABLED_PREF, this._onFhrPrefChange);
|
||||
|
||||
this.logging = this._prefs.get(LOGGING_PREF);
|
||||
this._onLoggingPrefChange = this._onLoggingPrefChange.bind(this);
|
||||
this._prefs.observe(LOGGING_PREF, this._onLoggingPrefChange);
|
||||
|
@ -51,13 +55,20 @@ function TelemetrySender(args) {
|
|||
}
|
||||
|
||||
TelemetrySender.prototype = {
|
||||
get enabled() {
|
||||
return this._enabled && this._fhrEnabled;
|
||||
},
|
||||
|
||||
_onLoggingPrefChange(prefVal) {
|
||||
this.logging = prefVal;
|
||||
},
|
||||
|
||||
_onTelemetryPrefChange(prefVal) {
|
||||
this.enabled = prefVal;
|
||||
this._enabled = prefVal;
|
||||
},
|
||||
|
||||
_onFhrPrefChange(prefVal) {
|
||||
this._fhrEnabled = prefVal;
|
||||
},
|
||||
|
||||
async sendPing(data) {
|
||||
|
@ -83,6 +94,7 @@ TelemetrySender.prototype = {
|
|||
try {
|
||||
this._prefs.ignore(TELEMETRY_PREF, this._onTelemetryPrefChange);
|
||||
this._prefs.ignore(LOGGING_PREF, this._onLoggingPrefChange);
|
||||
this._prefs.ignore(FHR_UPLOAD_ENABLED_PREF, this._onFhrPrefChange);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
@ -92,6 +104,7 @@ TelemetrySender.prototype = {
|
|||
this.TelemetrySender = TelemetrySender;
|
||||
this.TelemetrySenderConstants = {
|
||||
ENDPOINT_PREF,
|
||||
FHR_UPLOAD_ENABLED_PREF,
|
||||
TELEMETRY_PREF,
|
||||
LOGGING_PREF
|
||||
};
|
||||
|
|
|
@ -65,14 +65,39 @@ const SessionPing = Joi.object().keys(Object.assign({}, baseKeys, {
|
|||
session_id: baseKeys.session_id.required(),
|
||||
page: baseKeys.page.required(),
|
||||
session_duration: Joi.number().integer().required(),
|
||||
action: Joi.valid("activity_stream_session").required()
|
||||
action: Joi.valid("activity_stream_session").required(),
|
||||
perf: Joi.object().keys({
|
||||
// Timestamp of the action perceived by the user to trigger the load
|
||||
// of this page.
|
||||
//
|
||||
// Not required at least for the error cases where the
|
||||
// observer event doesn't fire
|
||||
load_trigger_ts: Joi.number().positive()
|
||||
.notes(["server counter", "server counter alert"]),
|
||||
|
||||
// What was the perceived trigger of the load action?
|
||||
//
|
||||
// Not required at least for the error cases where the observer event
|
||||
// doesn't fire
|
||||
load_trigger_type: Joi.valid(["menu_plus_or_keyboard"])
|
||||
.notes(["server counter", "server counter alert"]),
|
||||
|
||||
// When the page itself receives an event that document.visibilityState
|
||||
// == visible.
|
||||
//
|
||||
// Not required at least for the (error?) case where the
|
||||
// visibility_event doesn't fire. (It's not clear whether this
|
||||
// can happen in practice, but if it does, we'd like to know about it).
|
||||
visibility_event_rcvd_ts: Joi.number().positive()
|
||||
.notes(["server counter", "server counter alert"])
|
||||
}).required()
|
||||
}));
|
||||
|
||||
function chaiAssertions(_chai, utils) {
|
||||
const {Assertion} = _chai;
|
||||
|
||||
Assertion.addMethod("validate", function(schema, schemaName) {
|
||||
const {error} = Joi.validate(this._obj, schema);
|
||||
const {error} = Joi.validate(this._obj, schema, {allowUnknown: false});
|
||||
this.assert(
|
||||
!error,
|
||||
`Expected to be ${schemaName ? `a valid ${schemaName}` : "valid"} but there were errors: ${error}`
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* globals assert, beforeEach, describe, it */
|
||||
const {_PerfService} = require("common/PerfService.jsm");
|
||||
const {FakePerformance} = require("test/unit/utils.js");
|
||||
|
||||
let perfService;
|
||||
|
||||
describe("_PerfService", () => {
|
||||
let sandbox;
|
||||
let fakePerfObj;
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
fakePerfObj = new FakePerformance();
|
||||
perfService = new _PerfService({performanceObj: fakePerfObj});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe("#getEntriesByName", () => {
|
||||
it("should call getEntriesByName on the appropriate Window.performance",
|
||||
() => {
|
||||
sandbox.spy(fakePerfObj, "getEntriesByName");
|
||||
|
||||
perfService.getEntriesByName("monkey", "mark");
|
||||
|
||||
assert.calledOnce(fakePerfObj.getEntriesByName);
|
||||
assert.calledWithExactly(fakePerfObj.getEntriesByName, "monkey", "mark");
|
||||
});
|
||||
|
||||
it("should return entries with the given name", () => {
|
||||
sandbox.spy(fakePerfObj, "getEntriesByName");
|
||||
perfService.mark("monkey");
|
||||
perfService.mark("dog");
|
||||
|
||||
let marks = perfService.getEntriesByName("monkey", "mark");
|
||||
|
||||
assert.isArray(marks);
|
||||
assert.lengthOf(marks, 1);
|
||||
assert.propertyVal(marks[0], "name", "monkey");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getMostRecentAbsMarkStartByName", () => {
|
||||
it("should throw an error if there is no mark with the given name", () => {
|
||||
function bogusGet() {
|
||||
perfService.getMostRecentAbsMarkStartByName("rheeeet");
|
||||
}
|
||||
|
||||
assert.throws(bogusGet, Error, /No marks with the name/);
|
||||
});
|
||||
|
||||
it("should return the Number from the most recent mark with the given name + the time origin",
|
||||
() => {
|
||||
perfService.mark("dog");
|
||||
perfService.mark("dog");
|
||||
|
||||
let absMarkStart = perfService.getMostRecentAbsMarkStartByName("dog");
|
||||
|
||||
// 2 because we want the result of the 2nd call to mark, and an instance
|
||||
// of FakePerformance just returns the number of time mark has been
|
||||
// called.
|
||||
assert.equal(absMarkStart - perfService.timeOrigin, 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#mark", () => {
|
||||
it("should call the wrapped version of mark", () => {
|
||||
sandbox.spy(fakePerfObj, "mark");
|
||||
|
||||
perfService.mark("monkey");
|
||||
|
||||
assert.calledOnce(fakePerfObj.mark);
|
||||
assert.calledWithExactly(fakePerfObj.mark, "monkey");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#timeOrigin", () => {
|
||||
it("should get the origin of the wrapped performance object", () => {
|
||||
assert.equal(perfService.timeOrigin, 10000); // fake origin from utils.js
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +1,5 @@
|
|||
/* global Services */
|
||||
|
||||
const injector = require("inject!lib/TelemetryFeed.jsm");
|
||||
const {GlobalOverrider} = require("test/unit/utils");
|
||||
const {actionCreators: ac, actionTypes: at} = require("common/Actions.jsm");
|
||||
|
@ -15,10 +17,18 @@ const FAKE_UUID = "{foo-123-foo}";
|
|||
describe("TelemetryFeed", () => {
|
||||
let globals;
|
||||
let sandbox;
|
||||
let store = {getState() { return {App: {version: "1.0.0", locale: "en-US"}}; }};
|
||||
let store = {
|
||||
dispatch() {},
|
||||
getState() { return {App: {version: "1.0.0", locale: "en-US"}}; }
|
||||
};
|
||||
let instance;
|
||||
class TelemetrySender {sendPing() {} uninit() {}}
|
||||
const {TelemetryFeed} = injector({"lib/TelemetrySender.jsm": {TelemetrySender}});
|
||||
class PerfService {getMostRecentAbsMarkStartByName() { return 1234; } mark() {}}
|
||||
const perfService = new PerfService();
|
||||
const {TelemetryFeed} = injector({
|
||||
"lib/TelemetrySender.jsm": {TelemetrySender},
|
||||
"common/PerfService.jsm": {perfService}
|
||||
});
|
||||
|
||||
function addSession(id) {
|
||||
instance.addSession(id);
|
||||
|
@ -47,6 +57,15 @@ describe("TelemetryFeed", () => {
|
|||
await instance.init();
|
||||
assert.equal(instance.telemetryClientId, FAKE_TELEMETRY_ID);
|
||||
});
|
||||
it("should make this.browserOpenNewtabStart() observe browser-open-newtab-start", async () => {
|
||||
sandbox.spy(Services.obs, "addObserver");
|
||||
|
||||
await instance.init();
|
||||
|
||||
assert.calledOnce(Services.obs.addObserver);
|
||||
assert.calledWithExactly(Services.obs.addObserver,
|
||||
instance.browserOpenNewtabStart, "browser-open-newtab-start");
|
||||
});
|
||||
});
|
||||
describe("#addSession", () => {
|
||||
it("should add a session", () => {
|
||||
|
@ -70,6 +89,17 @@ describe("TelemetryFeed", () => {
|
|||
assert.equal(session.page, "about:newtab"); // This is hardcoded for now.
|
||||
});
|
||||
});
|
||||
describe("#browserOpenNewtabStart", () => {
|
||||
it("should call perfService.mark with browser-open-newtab-start", () => {
|
||||
sandbox.stub(perfService, "mark");
|
||||
|
||||
instance.browserOpenNewtabStart();
|
||||
|
||||
assert.calledOnce(perfService.mark);
|
||||
assert.calledWithExactly(perfService.mark, "browser-open-newtab-start");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#endSession", () => {
|
||||
it("should not throw if there is no session for the given port ID", () => {
|
||||
assert.doesNotThrow(() => instance.endSession("doesn't exist"));
|
||||
|
@ -189,7 +219,12 @@ describe("TelemetryFeed", () => {
|
|||
const ping = instance.createSessionEndEvent({
|
||||
session_id: FAKE_UUID,
|
||||
page: "about:newtab",
|
||||
session_duration: 12345
|
||||
session_duration: 12345,
|
||||
perf: {
|
||||
load_trigger_ts: 10,
|
||||
load_trigger_type: "menu_plus_or_keyboard",
|
||||
visibility_event_rcvd_ts: 20
|
||||
}
|
||||
});
|
||||
// Is it valid?
|
||||
assert.validate(ping, SessionPing);
|
||||
|
@ -216,6 +251,17 @@ describe("TelemetryFeed", () => {
|
|||
assert.calledOnce(stub);
|
||||
assert.isNull(instance.telemetrySender);
|
||||
});
|
||||
it("should make this.browserOpenNewtabStart() stop observing browser-open-newtab-start", async () => {
|
||||
await instance.init();
|
||||
sandbox.spy(Services.obs, "removeObserver");
|
||||
sandbox.stub(instance.telemetrySender, "uninit");
|
||||
|
||||
await instance.uninit();
|
||||
|
||||
assert.calledOnce(Services.obs.removeObserver);
|
||||
assert.calledWithExactly(Services.obs.removeObserver,
|
||||
instance.browserOpenNewtabStart, "browser-open-newtab-start");
|
||||
});
|
||||
});
|
||||
describe("#onAction", () => {
|
||||
it("should call .init() on an INIT action", () => {
|
||||
|
@ -225,7 +271,10 @@ describe("TelemetryFeed", () => {
|
|||
});
|
||||
it("should call .addSession() on a NEW_TAB_VISIBLE action", () => {
|
||||
const stub = sandbox.stub(instance, "addSession");
|
||||
instance.onAction(ac.SendToMain({type: at.NEW_TAB_VISIBLE}, "port123"));
|
||||
instance.onAction(ac.SendToMain({
|
||||
type: at.NEW_TAB_VISIBLE,
|
||||
data: {absVisibilityChangeTime: 789}
|
||||
}, "port123"));
|
||||
assert.calledWith(stub, "port123");
|
||||
});
|
||||
it("should call .endSession() on a NEW_TAB_UNLOAD action", () => {
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
const {GlobalOverrider, FakePrefs} = require("test/unit/utils");
|
||||
const {TelemetrySender, TelemetrySenderConstants} = require("lib/TelemetrySender.jsm");
|
||||
const {ENDPOINT_PREF, TELEMETRY_PREF, LOGGING_PREF} = TelemetrySenderConstants;
|
||||
const {ENDPOINT_PREF, FHR_UPLOAD_ENABLED_PREF, TELEMETRY_PREF, LOGGING_PREF} =
|
||||
TelemetrySenderConstants;
|
||||
|
||||
/**
|
||||
* A reference to the fake preferences object created by the TelemetrySender
|
||||
|
@ -13,6 +14,7 @@ let fakePrefs;
|
|||
const prefInitHook = function() {
|
||||
fakePrefs = this; // eslint-disable-line consistent-this
|
||||
};
|
||||
|
||||
const tsArgs = {prefInitHook};
|
||||
|
||||
describe("TelemetrySender", () => {
|
||||
|
@ -48,34 +50,108 @@ describe("TelemetrySender", () => {
|
|||
assert.calledOnce(global.Preferences);
|
||||
});
|
||||
|
||||
it("should set the enabled prop to false if the pref is false", () => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = false;
|
||||
describe("#enabled", () => {
|
||||
let testParams = [
|
||||
{enabledPref: true, fhrPref: true, result: true},
|
||||
{enabledPref: false, fhrPref: true, result: false},
|
||||
{enabledPref: true, fhrPref: false, result: false},
|
||||
{enabledPref: false, fhrPref: false, result: false}
|
||||
];
|
||||
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
function testEnabled(p) {
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = p.enabledPref;
|
||||
FakePrefs.prototype.prefs[FHR_UPLOAD_ENABLED_PREF] = p.fhrPref;
|
||||
|
||||
assert.isFalse(tSender.enabled);
|
||||
});
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
|
||||
it("should set the enabled prop to true if the pref is true", () => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
assert.equal(tSender.enabled, p.result);
|
||||
}
|
||||
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
for (let p of testParams) {
|
||||
it(`should return ${p.result} if the fhrPref is ${p.fhrPref} and telemetry.enabled is ${p.enabledPref}`, () => {
|
||||
testEnabled(p);
|
||||
});
|
||||
}
|
||||
|
||||
assert.isTrue(tSender.enabled);
|
||||
describe("telemetry.enabled pref changes from true to false", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
FakePrefs.prototype.prefs[FHR_UPLOAD_ENABLED_PREF] = true;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
assert.propertyVal(tSender, "enabled", true);
|
||||
});
|
||||
|
||||
it("should set the enabled property to false", () => {
|
||||
fakePrefs.set(TELEMETRY_PREF, false);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("telemetry.enabled pref changes from false to true", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[FHR_UPLOAD_ENABLED_PREF] = true;
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = false;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", false);
|
||||
});
|
||||
|
||||
it("should set the enabled property to true", () => {
|
||||
fakePrefs.set(TELEMETRY_PREF, true);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("FHR enabled pref changes from true to false", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
FakePrefs.prototype.prefs[FHR_UPLOAD_ENABLED_PREF] = true;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
assert.propertyVal(tSender, "enabled", true);
|
||||
});
|
||||
|
||||
it("should set the enabled property to false", () => {
|
||||
fakePrefs.set(FHR_UPLOAD_ENABLED_PREF, false);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("FHR enabled pref changes from false to true", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[FHR_UPLOAD_ENABLED_PREF] = false;
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", false);
|
||||
});
|
||||
|
||||
it("should set the enabled property to true", () => {
|
||||
fakePrefs.set(FHR_UPLOAD_ENABLED_PREF, true);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#sendPing()", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[FHR_UPLOAD_ENABLED_PREF] = true;
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
FakePrefs.prototype.prefs[ENDPOINT_PREF] = fakeEndpointUrl;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
});
|
||||
|
||||
it("should not send if the TelemetrySender is disabled", async () => {
|
||||
tSender.enabled = false;
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = false;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
|
||||
await tSender.sendPing(fakePingJSON);
|
||||
|
||||
|
@ -132,6 +208,15 @@ describe("TelemetrySender", () => {
|
|||
assert.notProperty(fakePrefs.observers, TELEMETRY_PREF);
|
||||
});
|
||||
|
||||
it("should remove the fhrpref listener", () => {
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
assert.property(fakePrefs.observers, FHR_UPLOAD_ENABLED_PREF);
|
||||
|
||||
tSender.uninit();
|
||||
|
||||
assert.notProperty(fakePrefs.observers, FHR_UPLOAD_ENABLED_PREF);
|
||||
});
|
||||
|
||||
it("should remove the telemetry log listener", () => {
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
assert.property(fakePrefs.observers, LOGGING_PREF);
|
||||
|
@ -152,36 +237,6 @@ describe("TelemetrySender", () => {
|
|||
});
|
||||
|
||||
describe("Misc pref changes", () => {
|
||||
describe("telemetry changes from true to false", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
assert.propertyVal(tSender, "enabled", true);
|
||||
});
|
||||
|
||||
it("should set the enabled property to false", () => {
|
||||
fakePrefs.set(TELEMETRY_PREF, false);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("telemetry changes from false to true", () => {
|
||||
beforeEach(() => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = false;
|
||||
tSender = new TelemetrySender(tsArgs);
|
||||
assert.propertyVal(tSender, "enabled", false);
|
||||
});
|
||||
|
||||
it("should set the enabled property to true", () => {
|
||||
fakePrefs.set(TELEMETRY_PREF, true);
|
||||
|
||||
assert.propertyVal(tSender, "enabled", true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("performance.log changes from false to true", () => {
|
||||
it("should change this.logging from false to true", () => {
|
||||
FakePrefs.prototype.prefs = {};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const {GlobalOverrider, FakePrefs} = require("test/unit/utils");
|
||||
const {GlobalOverrider, FakePrefs, FakePerformance} = require("test/unit/utils");
|
||||
const {chaiAssertions} = require("test/schemas/pings");
|
||||
|
||||
const req = require.context(".", true, /\.test\.jsx?$/);
|
||||
|
@ -10,6 +10,7 @@ sinon.assert.expose(assert, {prefix: ""});
|
|||
chai.use(chaiAssertions);
|
||||
|
||||
let overrider = new GlobalOverrider();
|
||||
|
||||
overrider.set({
|
||||
Components: {
|
||||
interfaces: {},
|
||||
|
@ -31,6 +32,7 @@ overrider.set({
|
|||
addMessageListener: (msg, cb) => cb(),
|
||||
removeMessageListener() {}
|
||||
},
|
||||
appShell: {hiddenDOMWindow: {performance: new FakePerformance()}},
|
||||
obs: {
|
||||
addObserver() {},
|
||||
removeObserver() {}
|
||||
|
|
|
@ -116,6 +116,46 @@ FakePrefs.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
function FakePerformance() {}
|
||||
FakePerformance.prototype = {
|
||||
marks: new Map(),
|
||||
now() {
|
||||
return window.performance.now();
|
||||
},
|
||||
timing: {navigationStart: 222222},
|
||||
get timeOrigin() {
|
||||
return 10000;
|
||||
},
|
||||
// XXX assumes type == "mark"
|
||||
getEntriesByName(name, type) {
|
||||
if (this.marks.has(name)) {
|
||||
return this.marks.get(name);
|
||||
}
|
||||
return [];
|
||||
},
|
||||
callsToMark: 0,
|
||||
|
||||
/**
|
||||
* @note The "startTime" for each mark is simply the number of times mark
|
||||
* has been called in this object.
|
||||
*/
|
||||
mark(name) {
|
||||
let markObj = {
|
||||
name,
|
||||
"entryType": "mark",
|
||||
"startTime": ++this.callsToMark,
|
||||
"duration": 0
|
||||
};
|
||||
|
||||
if (this.marks.has(name)) {
|
||||
this.marks.get(name).push(markObj);
|
||||
return;
|
||||
}
|
||||
|
||||
this.marks.set(name, [markObj]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* addNumberReducer - a simple dummy reducer for testing that adds a number
|
||||
*/
|
||||
|
@ -142,6 +182,7 @@ function mountWithIntl(node) {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
FakePerformance,
|
||||
FakePrefs,
|
||||
GlobalOverrider,
|
||||
addNumberReducer,
|
||||
|
|
|
@ -130,9 +130,10 @@ function setCohort(cohortName) {
|
|||
}
|
||||
|
||||
function watchForPrefChanges() {
|
||||
Preferences.observe(PREF_FLASH_STATE, function() {
|
||||
Preferences.observe(PREF_FLASH_STATE, function prefWatcher() {
|
||||
let currentCohort = Preferences.get(PREF_COHORT_NAME, "unknown");
|
||||
setCohort(`user-changed-from-${currentCohort}`);
|
||||
Preferences.ignore(PREF_FLASH_STATE, prefWatcher);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>clicktoplay-rollout@mozilla.org</em:id>
|
||||
<em:version>1.1</em:version>
|
||||
<em:version>1.2</em:version>
|
||||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<script src="chrome://formautofill/content/editProfile.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form>
|
||||
<form autocomplete="off">
|
||||
<label id="given-name-container">
|
||||
<span>First Name</span>
|
||||
<input id="given-name" type="text"/>
|
||||
|
|
|
@ -111,6 +111,7 @@ webextPerms.description.privacy=Read and modify privacy settings
|
|||
webextPerms.description.sessions=Access recently closed tabs
|
||||
webextPerms.description.tabs=Access browser tabs
|
||||
webextPerms.description.topSites=Access browsing history
|
||||
webextPerms.description.unlimitedStorage=Store unlimited amount of client-side data
|
||||
webextPerms.description.webNavigation=Access browser activity during navigation
|
||||
|
||||
webextPerms.hostDescription.allUrls=Access your data for all websites
|
||||
|
|
|
@ -76,6 +76,10 @@ XPCOMUtils.defineLazyGetter(this, "DEFAULT_AREA_PLACEMENTS", function() {
|
|||
],
|
||||
};
|
||||
|
||||
if (AppConstants.MOZ_PHOTON_THEME) {
|
||||
result["nav-bar"].push("sidebar-button");
|
||||
}
|
||||
|
||||
if (gPhotonStructure) {
|
||||
result["widget-overflow-fixed-list"] = [];
|
||||
} else {
|
||||
|
|
|
@ -105,8 +105,7 @@ photonpanelmultiview .panel-banner-item > .toolbarbutton-multiline-text {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
photonpanelmultiview .subviewbutton > .toolbarbutton-icon,
|
||||
photonpanelmultiview .panel-banner-item > .toolbarbutton-multiline-text {
|
||||
photonpanelmultiview .subviewbutton > .toolbarbutton-icon {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1261,8 +1261,13 @@ photonpanelmultiview .subviewbutton > .toolbarbutton-text {
|
|||
photonpanelmultiview .subviewbutton-iconic:not(.subviewbutton-back) > .toolbarbutton-text,
|
||||
photonpanelmultiview .cui-withicon > .toolbarbutton-text,
|
||||
photonpanelmultiview .subviewbutton[image] > .toolbarbutton-text,
|
||||
photonpanelmultiview .subviewbutton[checked="true"] > .toolbarbutton-text,
|
||||
photonpanelmultiview .subviewbutton[checked="true"] > .toolbarbutton-text {
|
||||
padding-inline-start: 8px; /* See '.subviewbutton-iconic > .toolbarbutton-text' rule above. */
|
||||
}
|
||||
|
||||
photonpanelmultiview .panel-banner-item > .toolbarbutton-multiline-text {
|
||||
font: menu;
|
||||
padding: 0;
|
||||
padding-inline-start: 8px; /* See '.subviewbutton-iconic > .toolbarbutton-text' rule above. */
|
||||
}
|
||||
|
||||
|
|
|
@ -155,8 +155,7 @@ photonpanelmultiview .panel-banner-item > .toolbarbutton-multiline-text {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
photonpanelmultiview .subviewbutton > .toolbarbutton-icon,
|
||||
photonpanelmultiview .panel-banner-item > .toolbarbutton-multiline-text {
|
||||
photonpanelmultiview .subviewbutton > .toolbarbutton-icon {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -219,7 +219,9 @@ Toolbox.prototype = {
|
|||
|
||||
set visibleAdditionalTools(tools) {
|
||||
this._visibleAdditionalTools = tools;
|
||||
this._combineAndSortPanelDefinitions();
|
||||
if (this.isReady) {
|
||||
this._combineAndSortPanelDefinitions();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1384,11 +1386,17 @@ Toolbox.prototype = {
|
|||
throw new Error("Tool definition already registered: " +
|
||||
definition.id);
|
||||
}
|
||||
|
||||
this.additionalToolDefinitions.set(definition.id, definition);
|
||||
this.visibleAdditionalTools = [...this.visibleAdditionalTools, definition.id];
|
||||
|
||||
this._combineAndSortPanelDefinitions();
|
||||
this._buildPanelForTool(definition);
|
||||
const buildPanel = () => this._buildPanelForTool(definition);
|
||||
|
||||
if (this.isReady) {
|
||||
buildPanel();
|
||||
} else {
|
||||
this.once("ready", buildPanel);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Redux middleware for debouncing actions.
|
||||
*
|
||||
* Schedules actions with { meta: { debounce: true } } to be delayed
|
||||
* by wait milliseconds. If another action is fired during this
|
||||
* time-frame both actions are inserted into a queue and delayed.
|
||||
* Maximum delay is defined by maxWait argument.
|
||||
*
|
||||
* Handling more actions at once results in better performance since
|
||||
* components need to be re-rendered less often.
|
||||
*
|
||||
* @param string wait Wait for specified amount of milliseconds
|
||||
* before executing an action. The time is used
|
||||
* to collect more actions and handle them all
|
||||
* at once.
|
||||
* @param string maxWait Max waiting time. It's used in case of
|
||||
* a long stream of actions.
|
||||
*/
|
||||
function debounceActions(wait, maxWait) {
|
||||
let queuedActions = [];
|
||||
|
||||
return store => next => {
|
||||
let debounced = debounce(() => {
|
||||
next(batchActions(queuedActions));
|
||||
queuedActions = [];
|
||||
}, wait, maxWait);
|
||||
|
||||
return action => {
|
||||
if (!action.meta || !action.meta.debounce) {
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (!wait || !maxWait) {
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (action.type == BATCH_ACTIONS) {
|
||||
queuedActions.push(...action.actions);
|
||||
} else {
|
||||
queuedActions.push(action);
|
||||
}
|
||||
|
||||
return debounced();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function debounce(cb, wait, maxWait) {
|
||||
let timeout, maxTimeout;
|
||||
let doFunction = () => {
|
||||
clearTimeout(timeout);
|
||||
clearTimeout(maxTimeout);
|
||||
timeout = maxTimeout = null;
|
||||
cb();
|
||||
};
|
||||
|
||||
return () => {
|
||||
return new Promise(resolve => {
|
||||
let onTimeout = () => {
|
||||
doFunction();
|
||||
resolve();
|
||||
};
|
||||
|
||||
clearTimeout(timeout);
|
||||
|
||||
timeout = setTimeout(onTimeout, wait);
|
||||
if (!maxTimeout) {
|
||||
maxTimeout = setTimeout(onTimeout, maxWait);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const BATCH_ACTIONS = Symbol("BATCH_ACTIONS");
|
||||
|
||||
/**
|
||||
* Action creator for action-batching.
|
||||
*/
|
||||
function batchActions(batchedActions, debounceFlag = true) {
|
||||
return {
|
||||
type: BATCH_ACTIONS,
|
||||
meta: { debounce: debounceFlag },
|
||||
actions: batchedActions,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
BATCH_ACTIONS,
|
||||
batchActions,
|
||||
debounceActions,
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'debounce.js',
|
||||
'history.js',
|
||||
'log.js',
|
||||
'promise.js',
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'stringvalidator',
|
||||
]
|
||||
|
||||
modules = []
|
||||
modules += [
|
||||
'immutable.js',
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
# Updating this library
|
||||
|
||||
1. Replace the contents of validator.js with the contents of https://github.com/chriso/validator.js/blob/master/validator.js.
|
||||
|
||||
2. Add the following methods:
|
||||
```
|
||||
// see http://isrc.ifpi.org/en/isrc-standard/code-syntax
|
||||
var isrc = /^[A-Z]{2}[0-9A-Z]{3}\d{2}\d{5}$/;
|
||||
|
||||
function isISRC(str) {
|
||||
assertString(str);
|
||||
return isrc.test(str);
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
var cultureCodes = new Set(["ar", "bg", "ca", "zh-Hans", "cs", "da", "de",
|
||||
"el", "en", "es", "fi", "fr", "he", "hu", "is", "it", "ja", "ko", "nl", "no",
|
||||
"pl", "pt", "rm", "ro", "ru", "hr", "sk", "sq", "sv", "th", "tr", "ur", "id",
|
||||
"uk", "be", "sl", "et", "lv", "lt", "tg", "fa", "vi", "hy", "az", "eu", "hsb",
|
||||
"mk", "tn", "xh", "zu", "af", "ka", "fo", "hi", "mt", "se", "ga", "ms", "kk",
|
||||
"ky", "sw", "tk", "uz", "tt", "bn", "pa", "gu", "or", "ta", "te", "kn", "ml",
|
||||
"as", "mr", "sa", "mn", "bo", "cy", "km", "lo", "gl", "kok", "syr", "si", "iu",
|
||||
"am", "tzm", "ne", "fy", "ps", "fil", "dv", "ha", "yo", "quz", "nso", "ba", "lb",
|
||||
"kl", "ig", "ii", "arn", "moh", "br", "ug", "mi", "oc", "co", "gsw", "sah",
|
||||
"qut", "rw", "wo", "prs", "gd", "ar-SA", "bg-BG", "ca-ES", "zh-TW", "cs-CZ",
|
||||
"da-DK", "de-DE", "el-GR", "en-US", "fi-FI", "fr-FR", "he-IL", "hu-HU", "is-IS",
|
||||
"it-IT", "ja-JP", "ko-KR", "nl-NL", "nb-NO", "pl-PL", "pt-BR", "rm-CH", "ro-RO",
|
||||
"ru-RU", "hr-HR", "sk-SK", "sq-AL", "sv-SE", "th-TH", "tr-TR", "ur-PK", "id-ID",
|
||||
"uk-UA", "be-BY", "sl-SI", "et-EE", "lv-LV", "lt-LT", "tg-Cyrl-TJ", "fa-IR",
|
||||
"vi-VN", "hy-AM", "az-Latn-AZ", "eu-ES", "hsb-DE", "mk-MK", "tn-ZA", "xh-ZA",
|
||||
"zu-ZA", "af-ZA", "ka-GE", "fo-FO", "hi-IN", "mt-MT", "se-NO", "ms-MY", "kk-KZ",
|
||||
"ky-KG", "sw-KE", "tk-TM", "uz-Latn-UZ", "tt-RU", "bn-IN", "pa-IN", "gu-IN",
|
||||
"or-IN", "ta-IN", "te-IN", "kn-IN", "ml-IN", "as-IN", "mr-IN", "sa-IN", "mn-MN",
|
||||
"bo-CN", "cy-GB", "km-KH", "lo-LA", "gl-ES", "kok-IN", "syr-SY", "si-LK",
|
||||
"iu-Cans-CA", "am-ET", "ne-NP", "fy-NL", "ps-AF", "fil-PH", "dv-MV",
|
||||
"ha-Latn-NG", "yo-NG", "quz-BO", "nso-ZA", "ba-RU", "lb-LU", "kl-GL", "ig-NG",
|
||||
"ii-CN", "arn-CL", "moh-CA", "br-FR", "ug-CN", "mi-NZ", "oc-FR", "co-FR",
|
||||
"gsw-FR", "sah-RU", "qut-GT", "rw-RW", "wo-SN", "prs-AF", "gd-GB", "ar-IQ",
|
||||
"zh-CN", "de-CH", "en-GB", "es-MX", "fr-BE", "it-CH", "nl-BE", "nn-NO", "pt-PT",
|
||||
"sr-Latn-CS", "sv-FI", "az-Cyrl-AZ", "dsb-DE", "se-SE", "ga-IE", "ms-BN",
|
||||
"uz-Cyrl-UZ", "bn-BD", "mn-Mong-CN", "iu-Latn-CA", "tzm-Latn-DZ", "quz-EC",
|
||||
"ar-EG", "zh-HK", "de-AT", "en-AU", "es-ES", "fr-CA", "sr-Cyrl-CS", "se-FI",
|
||||
"quz-PE", "ar-LY", "zh-SG", "de-LU", "en-CA", "es-GT", "fr-CH", "hr-BA",
|
||||
"smj-NO", "ar-DZ", "zh-MO", "de-LI", "en-NZ", "es-CR", "fr-LU", "bs-Latn-BA",
|
||||
"smj-SE", "ar-MA", "en-IE", "es-PA", "fr-MC", "sr-Latn-BA", "sma-NO", "ar-TN",
|
||||
"en-ZA", "es-DO", "sr-Cyrl-BA", "sma-SE", "ar-OM", "en-JM", "es-VE",
|
||||
"bs-Cyrl-BA", "sms-FI", "ar-YE", "en-029", "es-CO", "sr-Latn-RS", "smn-FI",
|
||||
"ar-SY", "en-BZ", "es-PE", "sr-Cyrl-RS", "ar-JO", "en-TT", "es-AR", "sr-Latn-ME",
|
||||
"ar-LB", "en-ZW", "es-EC", "sr-Cyrl-ME", "ar-KW", "en-PH", "es-CL", "ar-AE",
|
||||
"es-UY", "ar-BH", "es-PY", "ar-QA", "en-IN", "es-BO", "en-MY", "es-SV", "en-SG",
|
||||
"es-HN", "es-NI", "es-PR", "es-US", "bs-Cyrl", "bs-Latn", "sr-Cyrl", "sr-Latn",
|
||||
"smn", "az-Cyrl", "sms", "zh", "nn", "bs", "az-Latn", "sma", "uz-Cyrl",
|
||||
"mn-Cyrl", "iu-Cans", "zh-Hant", "nb", "sr", "tg-Cyrl", "dsb", "smj", "uz-Latn",
|
||||
"mn-Mong", "iu-Latn", "tzm-Latn", "ha-Latn", "zh-CHS", "zh-CHT"]);
|
||||
|
||||
function isRFC5646(str) {
|
||||
assertString(str);
|
||||
// According to the spec these codes are case sensitive so we can check the
|
||||
// string directly.
|
||||
return cultureCodes.has(str);
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
var semver = /^v?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/i
|
||||
|
||||
function isSemVer(str) {
|
||||
assertString(str);
|
||||
return semver.test(str);
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
var rgbcolor = /^rgb?\(\s*(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*,\s*(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])\s*\)$/i
|
||||
|
||||
function isRGBColor(str) {
|
||||
assertString(str);
|
||||
return rgbcolor.test(str);
|
||||
}
|
||||
```
|
||||
|
||||
3. Add the following to the validator object towards the end of the file:
|
||||
```
|
||||
isISRC: isISRC,
|
||||
isRFC5646: isRFC5646,
|
||||
isSemVer: isSemVer,
|
||||
isRGBColor: isRGBColor,
|
||||
```
|
||||
|
||||
4. Look for the phones array just above the isMobilePhone() method.
|
||||
|
||||
1. Replace the en-HK regex with:
|
||||
```
|
||||
// According to http://www.ofca.gov.hk/filemanager/ofca/en/content_311/no_plan.pdf
|
||||
'en-HK': /^(\+?852-?)?((4(04[01]|06\d|09[3-9]|20\d|2[2-9]\d|3[3-9]\d|[467]\d{2}|5[1-9]\d|81\d|82[1-9]|8[69]\d|92[3-9]|95[2-9]|98\d)|5([1-79]\d{2})|6(0[1-9]\d|[1-9]\d{2})|7(0[1-9]\d|10[4-79]|11[458]|1[24578]\d|13[24-9]|16[0-8]|19[24579]|21[02-79]|2[456]\d|27[13-6]|3[456]\d|37[4578]|39[0146])|8(1[58]\d|2[45]\d|267|27[5-9]|2[89]\d|3[15-9]\d|32[5-8]|[46-9]\d{2}|5[013-9]\d)|9(0[1-9]\d|1[02-9]\d|[2-8]\d{2}))-?\d{4}|7130-?[0124-8]\d{3}|8167-?2\d{3})$/,
|
||||
```
|
||||
2. Add:
|
||||
```
|
||||
'ko-KR': /^((\+?82)[ \-]?)?0?1([0|1|6|7|8|9]{1})[ \-]?\d{3,4}[ \-]?\d{4}$/,
|
||||
'lt-LT': /^(\+370|8)\d{8}$/,
|
||||
```
|
||||
|
||||
5. Replace the isMobilePhone() method with:
|
||||
```
|
||||
function isMobilePhone(str, locale) {
|
||||
assertString(str);
|
||||
if (locale in phones) {
|
||||
return phones[locale].test(str);
|
||||
} else if (locale === 'any') {
|
||||
return !!Object.values(phones).find(phone => phone.test(str));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
6. Delete the notBase64 regex and replace the isBase64 with:
|
||||
```
|
||||
function isBase64(str) {
|
||||
assertString(str);
|
||||
// Value length must be divisible by 4.
|
||||
var len = str.length;
|
||||
if (!len || len % 4 !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (atob(str)) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
7. Do not replace the test files as they have been converted to xpcshell tests. If there are new methods then add their tests to the `test_sanitizers.js` or `test_validators.js` files as appropriate.
|
||||
|
||||
8. To test the library please run the following:
|
||||
```
|
||||
./mach xpcshell-test devtools/client/shared/vendor/stringvalidator/
|
||||
```
|
|
@ -0,0 +1,15 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'util'
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
DevToolsModules(
|
||||
'validator.js',
|
||||
)
|
20
devtools/client/shared/vendor/stringvalidator/tests/unit/head_stringvalidator.js
поставляемый
Normal file
20
devtools/client/shared/vendor/stringvalidator/tests/unit/head_stringvalidator.js
поставляемый
Normal file
|
@ -0,0 +1,20 @@
|
|||
"use strict";
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
|
||||
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { console } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
|
||||
this.validator = require("devtools/client/shared/vendor/stringvalidator/validator");
|
||||
|
||||
function describe(suite, testFunc) {
|
||||
do_print(`\n Test suite: ${suite}`.toUpperCase());
|
||||
testFunc();
|
||||
}
|
||||
|
||||
function it(description, testFunc) {
|
||||
do_print(`\n - ${description}:\n`.toUpperCase());
|
||||
testFunc();
|
||||
}
|
420
devtools/client/shared/vendor/stringvalidator/tests/unit/test_sanitizers.js
поставляемый
Normal file
420
devtools/client/shared/vendor/stringvalidator/tests/unit/test_sanitizers.js
поставляемый
Normal file
|
@ -0,0 +1,420 @@
|
|||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
/*
|
||||
* Copyright 2013 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.md or:
|
||||
* http://opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
function test(options) {
|
||||
var args = options.args || [];
|
||||
|
||||
args.unshift(null);
|
||||
|
||||
Object.keys(options.expect).forEach(function (input) {
|
||||
args[0] = input;
|
||||
|
||||
var result = validator[options.sanitizer](...args);
|
||||
var expected = options.expect[input];
|
||||
let argsString = args.join(', ');
|
||||
|
||||
if (isNaN(result) && !result.length && isNaN(expected)) {
|
||||
ok(true, `validator.${options.sanitizer}(${argsString}) returned "${result}"`);
|
||||
} else {
|
||||
equal(result, expected, `validator.${options.sanitizer}("${argsString}") ` +
|
||||
`returned "${result}"`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
describe('Sanitizers', function () {
|
||||
it('should sanitize boolean strings', function () {
|
||||
test({
|
||||
sanitizer: 'toBoolean',
|
||||
expect: {
|
||||
'0': false,
|
||||
'': false,
|
||||
'1': true,
|
||||
'true': true,
|
||||
'foobar': true,
|
||||
' ': true,
|
||||
},
|
||||
});
|
||||
test({
|
||||
sanitizer: 'toBoolean',
|
||||
args: [true], // strict
|
||||
expect: {
|
||||
'0': false,
|
||||
'': false,
|
||||
'1': true,
|
||||
'true': true,
|
||||
'foobar': false,
|
||||
' ': false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should trim whitespace', function () {
|
||||
test({
|
||||
sanitizer: 'trim',
|
||||
expect: {
|
||||
' \r\n\tfoo \r\n\t ': 'foo',
|
||||
' \r': '',
|
||||
},
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'ltrim',
|
||||
expect: {
|
||||
' \r\n\tfoo \r\n\t ': 'foo \r\n\t ',
|
||||
' \t \n': '',
|
||||
},
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'rtrim',
|
||||
expect: {
|
||||
' \r\n\tfoo \r\n\t ': ' \r\n\tfoo',
|
||||
' \r\n \t': '',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should trim custom characters', function () {
|
||||
test({
|
||||
sanitizer: 'trim',
|
||||
args: ['01'],
|
||||
expect: { '010100201000': '2' },
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'ltrim',
|
||||
args: ['01'],
|
||||
expect: { '010100201000': '201000' },
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'rtrim',
|
||||
args: ['01'],
|
||||
expect: { '010100201000': '0101002' },
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert strings to integers', function () {
|
||||
test({
|
||||
sanitizer: 'toInt',
|
||||
expect: {
|
||||
'3': 3,
|
||||
' 3 ': 3,
|
||||
'2.4': 2,
|
||||
'foo': NaN,
|
||||
},
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'toInt',
|
||||
args: [16],
|
||||
expect: { 'ff': 255 },
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert strings to floats', function () {
|
||||
test({
|
||||
sanitizer: 'toFloat',
|
||||
expect: {
|
||||
'2': 2.0,
|
||||
'2.': 2.0,
|
||||
'-2.5': -2.5,
|
||||
'.5': 0.5,
|
||||
'foo': NaN,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should escape HTML', function () {
|
||||
test({
|
||||
sanitizer: 'escape',
|
||||
expect: {
|
||||
'<script> alert("xss&fun"); </script>':
|
||||
'<script> alert("xss&fun"); </script>',
|
||||
|
||||
"<script> alert('xss&fun'); </script>":
|
||||
'<script> alert('xss&fun'); </script>',
|
||||
|
||||
'Backtick: `':
|
||||
'Backtick: `',
|
||||
|
||||
'Backslash: \\':
|
||||
'Backslash: \',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should unescape HTML', function () {
|
||||
test({
|
||||
sanitizer: 'unescape',
|
||||
expect: {
|
||||
'<script> alert("xss&fun"); </script>':
|
||||
'<script> alert("xss&fun"); </script>',
|
||||
|
||||
'<script> alert('xss&fun'); </script>':
|
||||
"<script> alert('xss&fun'); </script>",
|
||||
|
||||
'Backtick: `':
|
||||
'Backtick: `',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove control characters (<32 and 127)', function () {
|
||||
// Check basic functionality
|
||||
test({
|
||||
sanitizer: 'stripLow',
|
||||
expect: {
|
||||
'foo\x00': 'foo',
|
||||
'\x7Ffoo\x02': 'foo',
|
||||
'\x01\x09': '',
|
||||
'foo\x0A\x0D': 'foo',
|
||||
},
|
||||
});
|
||||
// Unicode safety
|
||||
test({
|
||||
sanitizer: 'stripLow',
|
||||
expect: {
|
||||
'perch\u00e9': 'perch\u00e9',
|
||||
'\u20ac': '\u20ac',
|
||||
'\u2206\x0A': '\u2206',
|
||||
'\ud83d\ude04': '\ud83d\ude04',
|
||||
},
|
||||
});
|
||||
// Preserve newlines
|
||||
test({
|
||||
sanitizer: 'stripLow',
|
||||
args: [true], // keep_new_lines
|
||||
expect: {
|
||||
'foo\x0A\x0D': 'foo\x0A\x0D',
|
||||
'\x03foo\x0A\x0D': 'foo\x0A\x0D',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should sanitize a string based on a whitelist', function () {
|
||||
test({
|
||||
sanitizer: 'whitelist',
|
||||
args: ['abc'],
|
||||
expect: {
|
||||
'abcdef': 'abc',
|
||||
'aaaaaaaaaabbbbbbbbbb': 'aaaaaaaaaabbbbbbbbbb',
|
||||
'a1b2c3': 'abc',
|
||||
' ': '',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should sanitize a string based on a blacklist', function () {
|
||||
test({
|
||||
sanitizer: 'blacklist',
|
||||
args: ['abc'],
|
||||
expect: {
|
||||
'abcdef': 'def',
|
||||
'aaaaaaaaaabbbbbbbbbb': '',
|
||||
'a1b2c3': '123',
|
||||
' ': ' ',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should normalize an email based on domain', function () {
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
expect: {
|
||||
'test@me.com': 'test@me.com',
|
||||
'some.name@gmail.com': 'somename@gmail.com',
|
||||
'some.name@googleMail.com': 'somename@gmail.com',
|
||||
'some.name+extension@gmail.com': 'somename@gmail.com',
|
||||
'some.Name+extension@GoogleMail.com': 'somename@gmail.com',
|
||||
'some.name.middleName+extension@gmail.com': 'somenamemiddlename@gmail.com',
|
||||
'some.name.middleName+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',
|
||||
'some.name.midd.leNa.me.+extension@gmail.com': 'somenamemiddlename@gmail.com',
|
||||
'some.name.midd.leNa.me.+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',
|
||||
'some.name+extension@unknown.com': 'some.name+extension@unknown.com',
|
||||
'hans@m端ller.com': 'hans@m端ller.com',
|
||||
'an invalid email address': false,
|
||||
'': false,
|
||||
'+extension@gmail.com': false,
|
||||
'...@gmail.com': false,
|
||||
'.+extension@googlemail.com': false,
|
||||
'+a@icloud.com': false,
|
||||
'+a@outlook.com': false,
|
||||
'-a@yahoo.com': false,
|
||||
'some.name.midd..leNa...me...+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',
|
||||
'"foo@bar"@baz.com': '"foo@bar"@baz.com',
|
||||
},
|
||||
});
|
||||
|
||||
// Testing all_lowercase switch, should apply to domains not known to be case-insensitive
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{ all_lowercase: false }],
|
||||
expect: {
|
||||
'test@foo.com': 'test@foo.com',
|
||||
'hans@m端ller.com': 'hans@m端ller.com',
|
||||
'test@FOO.COM': 'test@foo.com', // Hostname is always lowercased
|
||||
'blAH@x.com': 'blAH@x.com',
|
||||
// In case of domains that are known to be case-insensitive, there's a separate switch
|
||||
'TEST@me.com': 'test@me.com',
|
||||
'TEST@ME.COM': 'test@me.com',
|
||||
'SOME.name@GMAIL.com': 'somename@gmail.com',
|
||||
'SOME.name.middleName+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',
|
||||
'SOME.name.midd.leNa.me.+extension@gmail.com': 'somenamemiddlename@gmail.com',
|
||||
'SOME.name@gmail.com': 'somename@gmail.com',
|
||||
'SOME.name@yahoo.ca': 'some.name@yahoo.ca',
|
||||
'SOME.name@outlook.ie': 'some.name@outlook.ie',
|
||||
'SOME.name@me.com': 'some.name@me.com',
|
||||
},
|
||||
});
|
||||
|
||||
// Testing *_lowercase
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
all_lowercase: false,
|
||||
gmail_lowercase: false,
|
||||
icloud_lowercase: false,
|
||||
outlookdotcom_lowercase: false,
|
||||
yahoo_lowercase: false,
|
||||
}],
|
||||
expect: {
|
||||
'TEST@FOO.COM': 'TEST@foo.com', // all_lowercase
|
||||
'ME@gMAil.com': 'ME@gmail.com', // gmail_lowercase
|
||||
'ME@me.COM': 'ME@me.com', // icloud_lowercase
|
||||
'ME@icloud.COM': 'ME@icloud.com', // icloud_lowercase
|
||||
'ME@outlook.COM': 'ME@outlook.com', // outlookdotcom_lowercase
|
||||
'JOHN@live.CA': 'JOHN@live.ca', // outlookdotcom_lowercase
|
||||
'ME@ymail.COM': 'ME@ymail.com', // yahoo_lowercase
|
||||
},
|
||||
});
|
||||
|
||||
// Testing all_lowercase
|
||||
// Should overwrite all the *_lowercase options
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
all_lowercase: true,
|
||||
gmail_lowercase: false, // Overruled
|
||||
icloud_lowercase: false, // Overruled
|
||||
outlookdotcom_lowercase: false, // Overruled
|
||||
yahoo_lowercase: false, // Overruled
|
||||
}],
|
||||
expect: {
|
||||
'TEST@FOO.COM': 'test@foo.com', // all_lowercase
|
||||
'ME@gMAil.com': 'me@gmail.com', // gmail_lowercase
|
||||
'ME@me.COM': 'me@me.com', // icloud_lowercase
|
||||
'ME@icloud.COM': 'me@icloud.com', // icloud_lowercase
|
||||
'ME@outlook.COM': 'me@outlook.com', // outlookdotcom_lowercase
|
||||
'JOHN@live.CA': 'john@live.ca', // outlookdotcom_lowercase
|
||||
'ME@ymail.COM': 'me@ymail.com', // yahoo_lowercase
|
||||
},
|
||||
});
|
||||
|
||||
// Testing *_remove_dots
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
gmail_remove_dots: false,
|
||||
}],
|
||||
expect: {
|
||||
'SOME.name@GMAIL.com': 'some.name@gmail.com',
|
||||
'SOME.name+me@GMAIL.com': 'some.name@gmail.com',
|
||||
'my.self@foo.com': 'my.self@foo.com',
|
||||
},
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
gmail_remove_dots: true,
|
||||
}],
|
||||
expect: {
|
||||
'SOME.name@GMAIL.com': 'somename@gmail.com',
|
||||
'SOME.name+me@GMAIL.com': 'somename@gmail.com',
|
||||
'my.self@foo.com': 'my.self@foo.com',
|
||||
},
|
||||
});
|
||||
|
||||
// Testing *_remove_subaddress
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
gmail_remove_subaddress: false,
|
||||
icloud_remove_subaddress: false,
|
||||
outlookdotcom_remove_subaddress: false,
|
||||
yahoo_remove_subaddress: false, // Note Yahoo uses "-"
|
||||
}],
|
||||
expect: {
|
||||
'foo+bar@unknown.com': 'foo+bar@unknown.com',
|
||||
'foo+bar@gmail.com': 'foo+bar@gmail.com', // gmail_remove_subaddress
|
||||
'foo+bar@me.com': 'foo+bar@me.com', // icloud_remove_subaddress
|
||||
'foo+bar@icloud.com': 'foo+bar@icloud.com', // icloud_remove_subaddress
|
||||
'foo+bar@live.fr': 'foo+bar@live.fr', // outlookdotcom_remove_subaddress
|
||||
'foo+bar@hotmail.co.uk': 'foo+bar@hotmail.co.uk', // outlookdotcom_remove_subaddress
|
||||
'foo-bar@yahoo.com': 'foo-bar@yahoo.com', // yahoo_remove_subaddress
|
||||
'foo+bar@yahoo.com': 'foo+bar@yahoo.com', // yahoo_remove_subaddress
|
||||
},
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
gmail_remove_subaddress: true,
|
||||
icloud_remove_subaddress: true,
|
||||
outlookdotcom_remove_subaddress: true,
|
||||
yahoo_remove_subaddress: true, // Note Yahoo uses "-"
|
||||
}],
|
||||
expect: {
|
||||
'foo+bar@unknown.com': 'foo+bar@unknown.com',
|
||||
'foo+bar@gmail.com': 'foo@gmail.com', // gmail_remove_subaddress
|
||||
'foo+bar@me.com': 'foo@me.com', // icloud_remove_subaddress
|
||||
'foo+bar@icloud.com': 'foo@icloud.com', // icloud_remove_subaddress
|
||||
'foo+bar@live.fr': 'foo@live.fr', // outlookdotcom_remove_subaddress
|
||||
'foo+bar@hotmail.co.uk': 'foo@hotmail.co.uk', // outlookdotcom_remove_subaddress
|
||||
'foo-bar@yahoo.com': 'foo@yahoo.com', // yahoo_remove_subaddress
|
||||
'foo+bar@yahoo.com': 'foo+bar@yahoo.com', // yahoo_remove_subaddress
|
||||
},
|
||||
});
|
||||
|
||||
// Testing gmail_convert_googlemaildotcom
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
gmail_convert_googlemaildotcom: false,
|
||||
}],
|
||||
expect: {
|
||||
'SOME.name@GMAIL.com': 'somename@gmail.com',
|
||||
'SOME.name+me@GMAIL.com': 'somename@gmail.com',
|
||||
'SOME.name+me@googlemail.com': 'somename@googlemail.com',
|
||||
'SOME.name+me@googlemail.COM': 'somename@googlemail.com',
|
||||
'SOME.name+me@googlEmail.com': 'somename@googlemail.com',
|
||||
'my.self@foo.com': 'my.self@foo.com',
|
||||
},
|
||||
});
|
||||
|
||||
test({
|
||||
sanitizer: 'normalizeEmail',
|
||||
args: [{
|
||||
gmail_convert_googlemaildotcom: true,
|
||||
}],
|
||||
expect: {
|
||||
'SOME.name@GMAIL.com': 'somename@gmail.com',
|
||||
'SOME.name+me@GMAIL.com': 'somename@gmail.com',
|
||||
'SOME.name+me@googlemail.com': 'somename@gmail.com',
|
||||
'SOME.name+me@googlemail.COM': 'somename@gmail.com',
|
||||
'SOME.name+me@googlEmail.com': 'somename@gmail.com',
|
||||
'my.self@foo.com': 'my.self@foo.com',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
3763
devtools/client/shared/vendor/stringvalidator/tests/unit/test_validators.js
поставляемый
Normal file
3763
devtools/client/shared/vendor/stringvalidator/tests/unit/test_validators.js
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
head = head_stringvalidator.js
|
||||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android'
|
||||
|
||||
[test_sanitizers.js]
|
||||
[test_validators.js]
|
|
@ -0,0 +1,215 @@
|
|||
// // based on node assert, original notice:
|
||||
// // NB: The URL to the CommonJS spec is kept just for tradition.
|
||||
// // node-assert has evolved a lot since then, both in API and behavior.
|
||||
//
|
||||
// // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
||||
// //
|
||||
// // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
||||
// //
|
||||
// // Originally from narwhal.js (http://narwhaljs.org)
|
||||
// // Copyright (c) 2009 Thomas Robinson <280north.com>
|
||||
// //
|
||||
// // Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// // of this software and associated documentation files (the 'Software'), to
|
||||
// // deal in the Software without restriction, including without limitation the
|
||||
// // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// // sell copies of the Software, and to permit persons to whom the Software is
|
||||
// // furnished to do so, subject to the following conditions:
|
||||
// //
|
||||
// // The above copyright notice and this permission notice shall be included in
|
||||
// // all copies or substantial portions of the Software.
|
||||
// //
|
||||
// // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"use strict";
|
||||
|
||||
var regex = /\s*function\s+([^\(\s]*)\s*/;
|
||||
|
||||
var functionsHaveNames = (function () {
|
||||
return function foo() {}.name === "foo";
|
||||
}());
|
||||
|
||||
function assert(value, message) {
|
||||
if (!value) {
|
||||
fail(value, true, message, "==", assert.ok);
|
||||
}
|
||||
}
|
||||
|
||||
assert.equal = function equal(actual, expected, message) {
|
||||
if (actual != expected) {
|
||||
fail(actual, expected, message, "==", assert.equal);
|
||||
}
|
||||
};
|
||||
|
||||
assert.throws = function (block, error, message) {
|
||||
_throws(true, block, error, message);
|
||||
};
|
||||
|
||||
function _throws(shouldThrow, block, expected, message) {
|
||||
var actual;
|
||||
|
||||
if (typeof block !== "function") {
|
||||
throw new TypeError(`"block" argument must be a function`);
|
||||
}
|
||||
|
||||
if (typeof expected === "string") {
|
||||
message = expected;
|
||||
expected = null;
|
||||
}
|
||||
|
||||
actual = _tryBlock(block);
|
||||
|
||||
message = (expected && expected.name ? " (" + expected.name + ")." : ".") +
|
||||
(message ? " " + message : ".");
|
||||
|
||||
if (shouldThrow && !actual) {
|
||||
fail(actual, expected, "Missing expected exception" + message);
|
||||
}
|
||||
|
||||
var userProvidedMessage = typeof message === "string";
|
||||
var isUnwantedException = !shouldThrow && isError(actual);
|
||||
var isUnexpectedException = !shouldThrow && actual && !expected;
|
||||
|
||||
if ((isUnwantedException &&
|
||||
userProvidedMessage &&
|
||||
expectedException(actual, expected)) ||
|
||||
isUnexpectedException) {
|
||||
fail(actual, expected, "Got unwanted exception" + message);
|
||||
}
|
||||
|
||||
if ((shouldThrow && actual && expected &&
|
||||
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
||||
throw actual;
|
||||
}
|
||||
}
|
||||
|
||||
function fail(actual, expected, message, operator, stackStartFunction) {
|
||||
throw new assert.AssertionError({
|
||||
message: message,
|
||||
actual: actual,
|
||||
expected: expected,
|
||||
operator: operator,
|
||||
stackStartFunction: stackStartFunction
|
||||
});
|
||||
}
|
||||
|
||||
assert.fail = fail;
|
||||
|
||||
assert.AssertionError = function AssertionError(options) {
|
||||
this.name = "AssertionError";
|
||||
this.actual = options.actual;
|
||||
this.expected = options.expected;
|
||||
this.operator = options.operator;
|
||||
if (options.message) {
|
||||
this.message = options.message;
|
||||
this.generatedMessage = false;
|
||||
} else {
|
||||
this.message = getMessage(this);
|
||||
this.generatedMessage = true;
|
||||
}
|
||||
var stackStartFunction = options.stackStartFunction || fail;
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, stackStartFunction);
|
||||
} else {
|
||||
// non v8 browsers so we can have a stacktrace
|
||||
var err = new Error();
|
||||
if (err.stack) {
|
||||
var out = err.stack;
|
||||
|
||||
// try to strip useless frames
|
||||
var fn_name = getName(stackStartFunction);
|
||||
var idx = out.indexOf("\n" + fn_name);
|
||||
if (idx >= 0) {
|
||||
// once we have located the function frame
|
||||
// we need to strip out everything before it (and its line)
|
||||
var next_line = out.indexOf("\n", idx + 1);
|
||||
out = out.substring(next_line + 1);
|
||||
}
|
||||
|
||||
this.stack = out;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function expectedException(actual, expected) {
|
||||
if (!actual || !expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Object.prototype.toString.call(expected) == "[object RegExp]") {
|
||||
return expected.test(actual);
|
||||
}
|
||||
|
||||
try {
|
||||
if (actual instanceof expected) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore. The instanceof check doesn"t work for arrow functions.
|
||||
}
|
||||
|
||||
if (Error.isPrototypeOf(expected)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return expected.call({}, actual) === true;
|
||||
}
|
||||
|
||||
function _tryBlock(block) {
|
||||
var error;
|
||||
try {
|
||||
block();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
function isError(obj) {
|
||||
return obj instanceof Error;
|
||||
}
|
||||
|
||||
function isFunction(value) {
|
||||
return typeof value === "function";
|
||||
}
|
||||
|
||||
function getMessage(self) {
|
||||
return truncate(inspect(self.actual), 128) + " " +
|
||||
self.operator + " " +
|
||||
truncate(inspect(self.expected), 128);
|
||||
}
|
||||
|
||||
function getName(func) {
|
||||
if (!isFunction(func)) {
|
||||
return null;
|
||||
}
|
||||
if (functionsHaveNames) {
|
||||
return func.name;
|
||||
}
|
||||
var str = func.toString();
|
||||
var match = str.match(regex);
|
||||
return match && match[1];
|
||||
}
|
||||
|
||||
function truncate(s, n) {
|
||||
if (typeof s === "string") {
|
||||
return s.length < n ? s : s.slice(0, n);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function inspect(something) {
|
||||
if (functionsHaveNames || !isFunction(something)) {
|
||||
throw new Error(something);
|
||||
}
|
||||
var rawname = getName(something);
|
||||
var name = rawname ? ": " + rawname : "";
|
||||
return "[Function" + name + "]";
|
||||
}
|
||||
|
||||
exports.assert = assert;
|
|
@ -0,0 +1,9 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'assert.js',
|
||||
)
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,20 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { BATCH_ACTIONS } = require("../constants");
|
||||
|
||||
function batchActions(batchedActions) {
|
||||
return {
|
||||
type: BATCH_ACTIONS,
|
||||
actions: batchedActions,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
batchActions
|
||||
};
|
|
@ -7,7 +7,6 @@
|
|||
"use strict";
|
||||
|
||||
const actionModules = [
|
||||
require("./enhancers"),
|
||||
require("./filters"),
|
||||
require("./messages"),
|
||||
require("./ui"),
|
||||
|
|
|
@ -10,7 +10,7 @@ const {
|
|||
prepareMessage
|
||||
} = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
|
||||
const { batchActions } = require("devtools/client/webconsole/new-console-output/actions/enhancers");
|
||||
const { batchActions } = require("devtools/client/shared/redux/middleware/debounce");
|
||||
const {
|
||||
MESSAGE_ADD,
|
||||
NETWORK_MESSAGE_UPDATE,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'enhancers.js',
|
||||
'filters.js',
|
||||
'index.js',
|
||||
'messages.js',
|
||||
|
|
|
@ -12,6 +12,7 @@ const {
|
|||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const {
|
||||
getAllMessagesById,
|
||||
getAllMessagesUiById,
|
||||
getAllMessagesTableDataById,
|
||||
getAllNetworkMessagesUpdateById,
|
||||
|
@ -25,6 +26,7 @@ const ConsoleOutput = createClass({
|
|||
displayName: "ConsoleOutput",
|
||||
|
||||
propTypes: {
|
||||
messages: PropTypes.object.isRequired,
|
||||
messagesUi: PropTypes.object.isRequired,
|
||||
serviceContainer: PropTypes.shape({
|
||||
attachRefToHud: PropTypes.func.isRequired,
|
||||
|
@ -77,6 +79,7 @@ const ConsoleOutput = createClass({
|
|||
let {
|
||||
dispatch,
|
||||
visibleMessages,
|
||||
messages,
|
||||
messagesUi,
|
||||
messagesTableData,
|
||||
messagesRepeat,
|
||||
|
@ -85,22 +88,17 @@ const ConsoleOutput = createClass({
|
|||
timestampsVisible,
|
||||
} = this.props;
|
||||
|
||||
let messageNodes = visibleMessages.map((message) => {
|
||||
return (
|
||||
MessageContainer({
|
||||
dispatch,
|
||||
message,
|
||||
key: message.id,
|
||||
serviceContainer,
|
||||
open: messagesUi.includes(message.id),
|
||||
tableData: messagesTableData.get(message.id),
|
||||
indent: message.indent,
|
||||
timestampsVisible,
|
||||
repeat: messagesRepeat[message.id],
|
||||
networkMessageUpdate: networkMessagesUpdate[message.id],
|
||||
})
|
||||
);
|
||||
});
|
||||
let messageNodes = visibleMessages.map((messageId) => MessageContainer({
|
||||
dispatch,
|
||||
key: messageId,
|
||||
serviceContainer,
|
||||
open: messagesUi.includes(messageId),
|
||||
tableData: messagesTableData.get(messageId),
|
||||
timestampsVisible,
|
||||
repeat: messagesRepeat[messageId],
|
||||
networkMessageUpdate: networkMessagesUpdate[messageId],
|
||||
getMessage: () => messages.get(messageId)
|
||||
}));
|
||||
|
||||
return (
|
||||
dom.div({
|
||||
|
@ -128,6 +126,7 @@ function isScrolledToBottom(outputNode, scrollNode) {
|
|||
|
||||
function mapStateToProps(state, props) {
|
||||
return {
|
||||
messages: getAllMessagesById(state),
|
||||
visibleMessages: getVisibleMessages(state),
|
||||
messagesUi: getAllMessagesUiById(state),
|
||||
messagesTableData: getAllMessagesTableDataById(state),
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// React & Redux
|
||||
const {
|
||||
createClass,
|
||||
|
||||
PropTypes
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
|
||||
|
@ -31,20 +30,18 @@ const MessageContainer = createClass({
|
|||
displayName: "MessageContainer",
|
||||
|
||||
propTypes: {
|
||||
message: PropTypes.object.isRequired,
|
||||
open: PropTypes.bool.isRequired,
|
||||
serviceContainer: PropTypes.object.isRequired,
|
||||
indent: PropTypes.number.isRequired,
|
||||
tableData: PropTypes.object,
|
||||
timestampsVisible: PropTypes.bool.isRequired,
|
||||
repeat: PropTypes.number,
|
||||
networkMessageUpdate: PropTypes.object,
|
||||
getMessage: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
open: false,
|
||||
indent: 0,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -52,8 +49,6 @@ const MessageContainer = createClass({
|
|||
const repeatChanged = this.props.repeat !== nextProps.repeat;
|
||||
const openChanged = this.props.open !== nextProps.open;
|
||||
const tableDataChanged = this.props.tableData !== nextProps.tableData;
|
||||
const responseChanged = this.props.message.response !== nextProps.message.response;
|
||||
const totalTimeChanged = this.props.message.totalTime !== nextProps.message.totalTime;
|
||||
const timestampVisibleChanged =
|
||||
this.props.timestampsVisible !== nextProps.timestampsVisible;
|
||||
const networkMessageUpdateChanged =
|
||||
|
@ -62,17 +57,15 @@ const MessageContainer = createClass({
|
|||
return repeatChanged
|
||||
|| openChanged
|
||||
|| tableDataChanged
|
||||
|| responseChanged
|
||||
|| totalTimeChanged
|
||||
|| timestampVisibleChanged
|
||||
|| networkMessageUpdateChanged;
|
||||
},
|
||||
|
||||
render() {
|
||||
const { message } = this.props;
|
||||
const message = this.props.getMessage();
|
||||
|
||||
let MessageComponent = getMessageComponent(message);
|
||||
return MessageComponent(this.props);
|
||||
return MessageComponent(Object.assign({message, indent: message.indent}, this.props));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
|||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
|
||||
const { batchActions } = require("devtools/client/shared/redux/middleware/debounce");
|
||||
const { createContextMenu } = require("devtools/client/webconsole/new-console-output/utils/context-menu");
|
||||
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
|
||||
|
||||
|
@ -172,7 +173,7 @@ NewConsoleOutputWrapper.prototype = {
|
|||
|
||||
dispatchMessagesAdd: function (messages) {
|
||||
const batchedActions = messages.map(message => actions.messageAdd(message));
|
||||
store.dispatch(actions.batchActions(batchedActions));
|
||||
store.dispatch(batchActions(batchedActions));
|
||||
},
|
||||
|
||||
dispatchMessagesClear: function () {
|
||||
|
@ -204,7 +205,7 @@ function batchedMessageAdd(action) {
|
|||
queuedActions.push(action);
|
||||
if (!throttledDispatchTimeout) {
|
||||
throttledDispatchTimeout = setTimeout(() => {
|
||||
store.dispatch(actions.batchActions(queuedActions));
|
||||
store.dispatch(batchActions(queuedActions));
|
||||
queuedActions = [];
|
||||
throttledDispatchTimeout = null;
|
||||
}, 50);
|
||||
|
|
|
@ -30,7 +30,7 @@ function getCurrentGroup(state) {
|
|||
}
|
||||
|
||||
function getVisibleMessages(state) {
|
||||
return state.messages.visibleMessages.map(id => getMessage(state, id));
|
||||
return state.messages.visibleMessages;
|
||||
}
|
||||
|
||||
function getAllRepeatById(state) {
|
||||
|
|
|
@ -12,11 +12,13 @@ const {
|
|||
createStore
|
||||
} = require("devtools/client/shared/vendor/redux");
|
||||
const { thunk } = require("devtools/client/shared/redux/middleware/thunk");
|
||||
const {
|
||||
BATCH_ACTIONS
|
||||
} = require("devtools/client/shared/redux/middleware/debounce");
|
||||
const {
|
||||
MESSAGE_ADD,
|
||||
MESSAGES_CLEAR,
|
||||
REMOVED_MESSAGES_CLEAR,
|
||||
BATCH_ACTIONS,
|
||||
PREFS,
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
const { reducers } = require("./reducers/index");
|
||||
|
|
|
@ -21,7 +21,10 @@ const serviceContainer = require("devtools/client/webconsole/new-console-output/
|
|||
describe("MessageContainer component:", () => {
|
||||
it("pipes data to children as expected", () => {
|
||||
const message = stubPreparedMessages.get("console.log('foobar', 'test')");
|
||||
const rendered = renderComponent(MessageContainer, {message, serviceContainer});
|
||||
const rendered = renderComponent(MessageContainer, {
|
||||
getMessage: () => message,
|
||||
serviceContainer
|
||||
});
|
||||
|
||||
expect(rendered.textContent.includes("foobar")).toBe(true);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
debounceActions,
|
||||
} = require("devtools/client/shared/redux/middleware/debounce");
|
||||
|
||||
describe("Debounce Middleware", () => {
|
||||
let nextArgs = [];
|
||||
const fakeStore = {};
|
||||
const fakeNext = (...args) => {
|
||||
nextArgs.push(args);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
nextArgs = [];
|
||||
});
|
||||
|
||||
it("should pass the intercepted action to next", () => {
|
||||
const fakeAction = {
|
||||
type: "FAKE_ACTION"
|
||||
};
|
||||
|
||||
debounceActions()(fakeStore)(fakeNext)(fakeAction);
|
||||
|
||||
expect(nextArgs.length).toEqual(1);
|
||||
expect(nextArgs[0]).toEqual([fakeAction]);
|
||||
});
|
||||
|
||||
it("should debounce if specified", () => {
|
||||
const fakeAction = {
|
||||
type: "FAKE_ACTION",
|
||||
meta: {
|
||||
debounce: true
|
||||
}
|
||||
};
|
||||
|
||||
const executed = debounceActions(1, 1)(fakeStore)(fakeNext)(fakeAction);
|
||||
expect(nextArgs.length).toEqual(0);
|
||||
|
||||
return executed.then(() => {
|
||||
expect(nextArgs.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("should have no effect if no timeout", () => {
|
||||
const fakeAction = {
|
||||
type: "FAKE_ACTION",
|
||||
meta: {
|
||||
debounce: true
|
||||
}
|
||||
};
|
||||
|
||||
debounceActions()(fakeStore)(fakeNext)(fakeAction);
|
||||
expect(nextArgs.length).toEqual(1);
|
||||
expect(nextArgs[0]).toEqual([fakeAction]);
|
||||
});
|
||||
});
|
|
@ -14,6 +14,7 @@ support-files =
|
|||
test-location-styleeditor-link-1.css
|
||||
test-location-styleeditor-link-2.css
|
||||
test-location-styleeditor-link.html
|
||||
test-network-request.html
|
||||
test-stacktrace-location-debugger-link.html
|
||||
!/devtools/client/framework/test/shared-head.js
|
||||
|
||||
|
@ -38,6 +39,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
|||
[browser_webconsole_location_debugger_link.js]
|
||||
[browser_webconsole_location_scratchpad_link.js]
|
||||
[browser_webconsole_location_styleeditor_link.js]
|
||||
[browser_webconsole_network_messages_click.js]
|
||||
[browser_webconsole_nodes_highlight.js]
|
||||
[browser_webconsole_nodes_select.js]
|
||||
[browser_webconsole_observer_notifications.js]
|
||||
|
|
|
@ -32,7 +32,7 @@ add_task(async function task() {
|
|||
}]
|
||||
});
|
||||
|
||||
await loadDocument(currentTab.linkedBrowser);
|
||||
await loadDocument(currentTab.linkedBrowser, TEST_PATH);
|
||||
info("Document loaded.");
|
||||
|
||||
await onMessageAdded;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,Test that clicking on a network message " +
|
||||
"in the console opens the netmonitor panel.";
|
||||
|
||||
const TEST_FILE = "test-network-request.html";
|
||||
const JSON_TEST_URL = "test-network-request.html";
|
||||
const TEST_PATH = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/";
|
||||
|
||||
const NET_PREF = "devtools.webconsole.filter.net";
|
||||
const XHR_PREF = "devtools.webconsole.filter.netxhr";
|
||||
Services.prefs.setBoolPref(NET_PREF, true);
|
||||
Services.prefs.setBoolPref(XHR_PREF, true);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(NET_PREF);
|
||||
Services.prefs.clearUserPref(XHR_PREF);
|
||||
});
|
||||
|
||||
add_task(async function task() {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
const currentTab = gBrowser.selectedTab;
|
||||
let target = TargetFactory.forTab(currentTab);
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
const documentUrl = TEST_PATH + TEST_FILE;
|
||||
await loadDocument(currentTab.linkedBrowser, documentUrl);
|
||||
info("Document loaded.");
|
||||
|
||||
await testNetmonitorLink(toolbox, hud, documentUrl);
|
||||
|
||||
// Go back to console.
|
||||
await toolbox.selectTool("webconsole");
|
||||
info("console panel open again.");
|
||||
|
||||
// Fire an XHR request.
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
|
||||
content.wrappedJSObject.testXhrGet();
|
||||
});
|
||||
|
||||
const jsonUrl = TEST_PATH + JSON_TEST_URL;
|
||||
await testNetmonitorLink(toolbox, hud, jsonUrl);
|
||||
});
|
||||
|
||||
async function testNetmonitorLink(toolbox, hud, url) {
|
||||
let messageNode = await waitFor(() => findMessage(hud, url));
|
||||
let urlNode = messageNode.querySelector(".url");
|
||||
info("Network message found.");
|
||||
|
||||
let onNetmonitorSelected = new Promise((resolve) => {
|
||||
toolbox.once("netmonitor-selected", (event, panel) => {
|
||||
resolve(panel);
|
||||
});
|
||||
});
|
||||
|
||||
info("Simulate click on the network message url.");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, urlNode);
|
||||
|
||||
const {panelWin} = await onNetmonitorSelected;
|
||||
ok(true, "The netmonitor panel is selected when clicking on the network message");
|
||||
|
||||
let { store, windowRequire } = panelWin;
|
||||
let actions = windowRequire("devtools/client/netmonitor/src/actions/index");
|
||||
let { getSelectedRequest } =
|
||||
windowRequire("devtools/client/netmonitor/src/selectors/index");
|
||||
|
||||
store.dispatch(actions.batchEnable(false));
|
||||
|
||||
await waitUntil(() => {
|
||||
const selected = getSelectedRequest(store.getState());
|
||||
return selected && selected.url === url;
|
||||
});
|
||||
|
||||
ok(true, "The attached url is correct.");
|
||||
}
|
|
@ -24,7 +24,7 @@ add_task(async function () {
|
|||
const currentTab = gBrowser.selectedTab;
|
||||
info("Network panel is open.");
|
||||
|
||||
await loadDocument(currentTab.linkedBrowser);
|
||||
await loadDocument(currentTab.linkedBrowser, TEST_PATH);
|
||||
info("Document loaded.");
|
||||
|
||||
// Test that the request appears in the network panel.
|
||||
|
|
|
@ -180,9 +180,9 @@ function hideContextMenu(hud) {
|
|||
return onPopupHidden;
|
||||
}
|
||||
|
||||
function loadDocument(browser) {
|
||||
function loadDocument(browser, url) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("load", resolve, {capture: true, once: true});
|
||||
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_PATH);
|
||||
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<!-- 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/. -->
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Console HTTP test page</title>
|
||||
<script type="text/javascript">
|
||||
/* exported testXhrGet, testXhrWarn, testXhrPost */
|
||||
"use strict";
|
||||
|
||||
function makeXhr(method, url, requestBody, callback) {
|
||||
let xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open(method, url, true);
|
||||
xmlhttp.onreadystatechange = function () {
|
||||
if (callback && xmlhttp.readyState == 4) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
xmlhttp.send(requestBody);
|
||||
}
|
||||
|
||||
function testXhrGet(callback) {
|
||||
makeXhr("get", "test-data.json", null, callback);
|
||||
}
|
||||
|
||||
function testXhrWarn(callback) {
|
||||
makeXhr("get", "http://example.com/browser/devtools/client/netmonitor/test/sjs_cors-test-server.sjs", null, callback);
|
||||
}
|
||||
|
||||
function testXhrPost(callback) {
|
||||
makeXhr("post", "test-data.json", "Hello world!", callback);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Heads Up Display HTTP Logging Testpage</h1>
|
||||
<h2>This page is used to test the HTTP logging.</h2>
|
||||
|
||||
<form action="https://example.com/browser/devtools/client/webconsole/test/test-network-request.html" method="post">
|
||||
<input name="name" type="text" value="foo bar"><br>
|
||||
<input name="age" type="text" value="144"><br>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -229,8 +229,9 @@ describe("Message reducer:", () => {
|
|||
|
||||
expect(messages.count()).toBe(logLimit);
|
||||
expect(visibleMessages.length).toBe(logLimit);
|
||||
expect(visibleMessages[0].parameters[0]).toBe(`message-0`);
|
||||
expect(visibleMessages[logLimit - 1].parameters[0]).toBe(`message-${logLimit - 1}`);
|
||||
expect(messages.get(visibleMessages[0]).parameters[0]).toBe(`message-0`);
|
||||
expect(messages.get(visibleMessages[logLimit - 1]).parameters[0])
|
||||
.toBe(`message-${logLimit - 1}`);
|
||||
|
||||
// The groups were cleaned up.
|
||||
const groups = getAllGroupsById(getState());
|
||||
|
@ -263,7 +264,7 @@ describe("Message reducer:", () => {
|
|||
const groups = getAllGroupsById(getState());
|
||||
expect(groups.count()).toBe(logLimit);
|
||||
|
||||
expect(visibleMessages[1].parameters[0]).toBe(`message-2-a`);
|
||||
expect(messages.get(visibleMessages[1]).parameters[0]).toBe(`message-2-a`);
|
||||
expect(messages.last().parameters[0]).toBe(`message-${logLimit + 1}-b`);
|
||||
});
|
||||
|
||||
|
@ -299,8 +300,9 @@ describe("Message reducer:", () => {
|
|||
|
||||
const visibleMessages = getVisibleMessages(getState());
|
||||
expect(visibleMessages.length).toBe(logLimit);
|
||||
const lastVisibleMessage = visibleMessages[visibleMessages.length - 1];
|
||||
expect(lastVisibleMessage.parameters[0]).toBe(`group-${logLimit + 1}`);
|
||||
const lastVisibleMessageId = visibleMessages[visibleMessages.length - 1];
|
||||
expect(messages.get(lastVisibleMessageId).parameters[0])
|
||||
.toBe(`group-${logLimit + 1}`);
|
||||
});
|
||||
|
||||
it("does not add null messages to the store", () => {
|
||||
|
|
|
@ -347,7 +347,7 @@ let SourceActor = ActorClassWithSpec(sourceSpec, {
|
|||
}
|
||||
}
|
||||
|
||||
if (isWasm) {
|
||||
if (isWasm && this.dbg.allowWasmBinarySource) {
|
||||
let wasm = this.source.binary;
|
||||
let buffer = wasm.buffer;
|
||||
assert(
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1373712 - Assertions of SpecifiedKeyframeArraysAreEqual(mKeyframes, keyframesCopy) with large color value
|
||||
</title>
|
||||
<meta charset="UTF-8">
|
||||
<script>
|
||||
document.documentElement.animate([{ "color": "hsl(63e292,41%,34%)" }]);
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
|
@ -27,3 +27,4 @@ pref(dom.animations-api.core.enabled,true) load 1334583-1.html
|
|||
pref(dom.animations-api.core.enabled,true) load 1335998-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1343589-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1359658-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1373712-1.html
|
||||
|
|
|
@ -10119,8 +10119,12 @@ nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
|
|||
|
||||
JS::Rooted<JS::Value> result(aCx);
|
||||
if (retVal) {
|
||||
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!global) {
|
||||
global = FastGetGlobalJSObject();
|
||||
}
|
||||
aError = nsContentUtils::XPConnect()->VariantToJS(aCx,
|
||||
FastGetGlobalJSObject(),
|
||||
global,
|
||||
retVal, aRetval);
|
||||
} else {
|
||||
aRetval.setNull();
|
||||
|
|
|
@ -87,7 +87,6 @@
|
|||
|
||||
#include "nsCycleCollectionNoteRootCallback.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/IdleTaskRunner.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -121,7 +120,7 @@ const size_t gStackSize = 8192;
|
|||
#define NS_CC_SKIPPABLE_DELAY 250 // ms
|
||||
|
||||
// ForgetSkippable is usually fast, so we can use small budgets.
|
||||
// This isn't a real budget but a hint to IdleTaskRunner whether there
|
||||
// This isn't a real budget but a hint to CollectorRunner whether there
|
||||
// is enough time to call ForgetSkippable.
|
||||
static const int64_t kForgetSkippableSliceDuration = 2;
|
||||
|
||||
|
@ -150,14 +149,16 @@ static const uint32_t kMaxICCDuration = 2000; // ms
|
|||
// Large value used to specify that a script should run essentially forever
|
||||
#define NS_UNLIMITED_SCRIPT_RUNTIME (0x40000000LL << 32)
|
||||
|
||||
class CollectorRunner;
|
||||
|
||||
// if you add statics here, add them to the list in StartupJSEnvironment
|
||||
|
||||
static nsITimer *sGCTimer;
|
||||
static nsITimer *sShrinkingGCTimer;
|
||||
static StaticRefPtr<IdleTaskRunner> sCCRunner;
|
||||
static StaticRefPtr<IdleTaskRunner> sICCRunner;
|
||||
static StaticRefPtr<CollectorRunner> sCCRunner;
|
||||
static StaticRefPtr<CollectorRunner> sICCRunner;
|
||||
static nsITimer *sFullGCTimer;
|
||||
static StaticRefPtr<IdleTaskRunner> sInterSliceGCRunner;
|
||||
static StaticRefPtr<CollectorRunner> sInterSliceGCRunner;
|
||||
|
||||
static TimeStamp sLastCCEndTime;
|
||||
|
||||
|
@ -227,6 +228,183 @@ static int32_t sExpensiveCollectorPokes = 0;
|
|||
static const int32_t kPokesBetweenExpensiveCollectorTriggers = 5;
|
||||
|
||||
static TimeDuration sGCUnnotifiedTotalTime;
|
||||
|
||||
// Return true if some meaningful work was done.
|
||||
typedef bool (*CollectorRunnerCallback) (TimeStamp aDeadline, void* aData);
|
||||
|
||||
// Repeating callback runner for CC and GC.
|
||||
class CollectorRunner final : public IdleRunnable
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<CollectorRunner>
|
||||
Create(CollectorRunnerCallback aCallback, uint32_t aDelay,
|
||||
int64_t aBudget, bool aRepeating, void* aData = nullptr)
|
||||
{
|
||||
if (sShuttingDown) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CollectorRunner> runner =
|
||||
new CollectorRunner(aCallback, aDelay, aBudget, aRepeating, aData);
|
||||
runner->Schedule(false); // Initial scheduling shouldn't use idle dispatch.
|
||||
return runner.forget();
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
if (!mCallback) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Deadline is null when called from timer.
|
||||
bool deadLineWasNull = mDeadline.IsNull();
|
||||
bool didRun = false;
|
||||
if (deadLineWasNull || ((TimeStamp::Now() + mBudget) < mDeadline)) {
|
||||
CancelTimer();
|
||||
didRun = mCallback(mDeadline, mData);
|
||||
}
|
||||
|
||||
if (mCallback && (mRepeating || !didRun)) {
|
||||
// If we didn't do meaningful work, don't schedule using immediate
|
||||
// idle dispatch, since that could lead to a loop until the idle
|
||||
// period ends.
|
||||
Schedule(didRun);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
TimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<CollectorRunner> runnable = static_cast<CollectorRunner*>(aClosure);
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) override
|
||||
{
|
||||
mDeadline = aDeadline;
|
||||
};
|
||||
|
||||
void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override
|
||||
{
|
||||
if (mTimerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
mTarget = aTarget;
|
||||
if (!mTimer) {
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
} else {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
if (mTimer) {
|
||||
mTimer->SetTarget(mTarget);
|
||||
mTimer->InitWithFuncCallback(TimedOut, this, aDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mTimerActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Cancel() override
|
||||
{
|
||||
CancelTimer();
|
||||
mTimer = nullptr;
|
||||
mScheduleTimer = nullptr;
|
||||
mCallback = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ScheduleTimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<CollectorRunner> runnable = static_cast<CollectorRunner*>(aClosure);
|
||||
runnable->Schedule(true);
|
||||
}
|
||||
|
||||
void Schedule(bool aAllowIdleDispatch)
|
||||
{
|
||||
if (!mCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sShuttingDown) {
|
||||
Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
mDeadline = TimeStamp();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
TimeStamp hint = nsRefreshDriver::GetIdleDeadlineHint(now);
|
||||
if (hint != now) {
|
||||
// RefreshDriver is ticking, let it schedule the idle dispatch.
|
||||
nsRefreshDriver::DispatchIdleRunnableAfterTick(this, mDelay);
|
||||
// Ensure we get called at some point, even if RefreshDriver is stopped.
|
||||
SetTimer(mDelay, mTarget);
|
||||
} else {
|
||||
// RefreshDriver doesn't seem to be running.
|
||||
if (aAllowIdleDispatch) {
|
||||
nsCOMPtr<nsIRunnable> runnable = this;
|
||||
NS_IdleDispatchToCurrentThread(runnable.forget(), mDelay);
|
||||
SetTimer(mDelay, mTarget);
|
||||
} else {
|
||||
if (!mScheduleTimer) {
|
||||
mScheduleTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (!mScheduleTimer) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mScheduleTimer->Cancel();
|
||||
}
|
||||
|
||||
// We weren't allowed to do idle dispatch immediately, do it after a
|
||||
// short timeout.
|
||||
mScheduleTimer->InitWithFuncCallback(ScheduleTimedOut, this, 16,
|
||||
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
explicit CollectorRunner(CollectorRunnerCallback aCallback,
|
||||
uint32_t aDelay, int64_t aBudget,
|
||||
bool aRepeating, void* aData)
|
||||
: mCallback(aCallback), mDelay(aDelay)
|
||||
, mBudget(TimeDuration::FromMilliseconds(aBudget))
|
||||
, mRepeating(aRepeating), mTimerActive(false), mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
~CollectorRunner()
|
||||
{
|
||||
CancelTimer();
|
||||
}
|
||||
|
||||
void CancelTimer()
|
||||
{
|
||||
nsRefreshDriver::CancelIdleRunnable(this);
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
if (mScheduleTimer) {
|
||||
mScheduleTimer->Cancel();
|
||||
}
|
||||
mTimerActive = false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsITimer> mScheduleTimer;
|
||||
nsCOMPtr<nsIEventTarget> mTarget;
|
||||
CollectorRunnerCallback mCallback;
|
||||
uint32_t mDelay;
|
||||
TimeStamp mDeadline;
|
||||
TimeDuration mBudget;
|
||||
bool mRepeating;
|
||||
bool mTimerActive;
|
||||
void* mData;
|
||||
};
|
||||
|
||||
static const char*
|
||||
ProcessNameForCollectorLog()
|
||||
{
|
||||
|
@ -1602,7 +1780,7 @@ nsJSContext::GetMaxCCSliceTimeSinceClear()
|
|||
}
|
||||
|
||||
static bool
|
||||
ICCRunnerFired(TimeStamp aDeadline)
|
||||
ICCRunnerFired(TimeStamp aDeadline, void* aData)
|
||||
{
|
||||
if (sDidShutdown) {
|
||||
return false;
|
||||
|
@ -1643,8 +1821,8 @@ nsJSContext::BeginCycleCollectionCallback()
|
|||
|
||||
// Create an ICC timer even if ICC is globally disabled, because we could be manually triggering
|
||||
// an incremental collection, and we want to be sure to finish it.
|
||||
sICCRunner = IdleTaskRunner::Create(ICCRunnerFired, kICCIntersliceDelay,
|
||||
kIdleICCSliceBudget, true, []{ return sShuttingDown; });
|
||||
sICCRunner = CollectorRunner::Create(ICCRunnerFired, kICCIntersliceDelay,
|
||||
kIdleICCSliceBudget, true);
|
||||
}
|
||||
|
||||
static_assert(NS_GC_DELAY > kMaxICCDuration, "A max duration ICC shouldn't reduce GC delay to 0");
|
||||
|
@ -1856,9 +2034,11 @@ GCTimerFired(nsITimer *aTimer, void *aClosure)
|
|||
{
|
||||
nsJSContext::KillGCTimer();
|
||||
// Now start the actual GC after initial timer has fired.
|
||||
sInterSliceGCRunner = IdleTaskRunner::Create([aClosure](TimeStamp aDeadline) {
|
||||
return InterSliceGCRunnerFired(aDeadline, aClosure);
|
||||
}, NS_INTERSLICE_GC_DELAY, sActiveIntersliceGCBudget, false, []{ return sShuttingDown; });
|
||||
sInterSliceGCRunner = CollectorRunner::Create(InterSliceGCRunnerFired,
|
||||
NS_INTERSLICE_GC_DELAY,
|
||||
sActiveIntersliceGCBudget,
|
||||
false,
|
||||
aClosure);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -1882,7 +2062,7 @@ ShouldTriggerCC(uint32_t aSuspected)
|
|||
}
|
||||
|
||||
static bool
|
||||
CCRunnerFired(TimeStamp aDeadline)
|
||||
CCRunnerFired(TimeStamp aDeadline, void* aData)
|
||||
{
|
||||
if (sDidShutdown) {
|
||||
return false;
|
||||
|
@ -2034,13 +2214,13 @@ nsJSContext::RunNextCollectorTimer()
|
|||
|
||||
if (sCCRunner) {
|
||||
if (ReadyToTriggerExpensiveCollectorTimer()) {
|
||||
CCRunnerFired(TimeStamp());
|
||||
CCRunnerFired(TimeStamp(), nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sICCRunner) {
|
||||
ICCRunnerFired(TimeStamp());
|
||||
ICCRunnerFired(TimeStamp(), nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2147,9 +2327,8 @@ nsJSContext::MaybePokeCC()
|
|||
nsCycleCollector_dispatchDeferredDeletion();
|
||||
|
||||
sCCRunner =
|
||||
IdleTaskRunner::Create(CCRunnerFired, NS_CC_SKIPPABLE_DELAY,
|
||||
kForgetSkippableSliceDuration, true,
|
||||
[]{ return sShuttingDown; });
|
||||
CollectorRunner::Create(CCRunnerFired, NS_CC_SKIPPABLE_DELAY,
|
||||
kForgetSkippableSliceDuration, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2329,9 +2508,8 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip
|
|||
nsJSContext::KillInterSliceGCRunner();
|
||||
if (!sShuttingDown && !aDesc.isComplete_) {
|
||||
sInterSliceGCRunner =
|
||||
IdleTaskRunner::Create([](TimeStamp aDeadline) {
|
||||
return InterSliceGCRunnerFired(aDeadline, nullptr);
|
||||
}, NS_INTERSLICE_GC_DELAY, sActiveIntersliceGCBudget, false, []{ return sShuttingDown; });
|
||||
CollectorRunner::Create(InterSliceGCRunnerFired, NS_INTERSLICE_GC_DELAY,
|
||||
sActiveIntersliceGCBudget, false);
|
||||
}
|
||||
|
||||
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
|
||||
|
|
|
@ -16,8 +16,16 @@
|
|||
*/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function openModal() {
|
||||
showModalDialog("javascript:opener.winRef = window; \
|
||||
async function openModal() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [[
|
||||
"dom.disable_window_showModalDialog", false ]] });
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener("load", resolve);
|
||||
});
|
||||
iframe.contentWindow.showModalDialog("javascript:opener.winRef = window; \
|
||||
window.opener.setTimeout(\'winRef.dialogArguments;\', 0);\
|
||||
window.close();");
|
||||
|
||||
|
|
|
@ -487,7 +487,14 @@ function testSyncXHR2() {
|
|||
then(testModalDialog);
|
||||
}
|
||||
|
||||
function testModalDialog() {
|
||||
async function testModalDialog() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [[ "dom.disable_window_showModalDialog", false ]] });
|
||||
let iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener("load", resolve);
|
||||
});
|
||||
window.showModalDialog = iframe.contentWindow.showModalDialog;
|
||||
var didHandleCallback = false;
|
||||
div.innerHTML = "<span>1</span><span>2</span>";
|
||||
m = new M(function(records, observer) {
|
||||
|
|
|
@ -100,11 +100,11 @@ skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests
|
|||
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
|
||||
[test_fuzzing_bugs.html]
|
||||
[test_video_fastpath_mp4.html]
|
||||
fail-if = (os == 'mac') || (os == 'win' && !(e10s && os_version == '6.1'))
|
||||
fail-if = (os == 'mac') || (os == 'win' && !(e10s && os_version == '6.1')) # no fast path on windows yet (bug 1373165 or 1373770), and mac (bug 1373669)
|
||||
[test_video_fastpath_theora.html]
|
||||
fail-if = (os == 'mac')
|
||||
fail-if = (os == 'mac') || (os == 'win' && os_version != '6.1') # no fast path on windows yet (bug 1373192), and mac (bug 1373702)
|
||||
[test_video_fastpath_vp8.html]
|
||||
fail-if = (os == 'mac')
|
||||
fail-if = (os == 'mac') || (os == 'win' && os_version != '6.1') # no fast path on windows yet (bug 1373192), and mac (bug 1373702)
|
||||
[test_video_fastpath_vp9.html]
|
||||
fail-if = (os == 'mac')
|
||||
fail-if = (os == 'mac') || (os == 'win' && os_version != '6.1') # no fast path on windows yet (bug 1373192), and mac (bug 1373702)
|
||||
[test_webglcontextcreationerror.html]
|
||||
|
|
|
@ -14,11 +14,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391777
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 391777 **/
|
||||
var arg = {};
|
||||
arg.testVal = "foo";
|
||||
var result = window.showModalDialog("javascript:window.returnValue = window.dialogArguments.testVal; window.close(); 'This window should close on its own.';", arg);
|
||||
ok(true, "We should get here without user interaction");
|
||||
is(result, "foo", "Unexpected result from showModalDialog");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [[ "dom.disable_window_showModalDialog", false ]] }, doTest);
|
||||
async function doTest() {
|
||||
let iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener("load", resolve);
|
||||
});
|
||||
window.showModalDialog = iframe.contentWindow.showModalDialog;
|
||||
var arg = {};
|
||||
arg.testVal = "foo";
|
||||
var result = window.showModalDialog("javascript:window.returnValue = window.dialogArguments.testVal; window.close(); 'This window should close on its own.';", arg);
|
||||
ok(true, "We should get here without user interaction");
|
||||
is(result, "foo", "Unexpected result from showModalDialog");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -109,7 +109,9 @@ function doTest() {
|
|||
// file_iframe_j_if3.html has an ok() function that calls window.parent.ok_wrapper.
|
||||
}
|
||||
|
||||
addLoadEvent(doTest);
|
||||
let loaded = new Promise(resolve => { addLoadEvent(resolve) });
|
||||
let prefSet = SpecialPowers.pushPrefEnv({ set: [[ "dom.disable_window_showModalDialog", false ]] });
|
||||
Promise.all([ loaded, prefSet ]).then(doTest);
|
||||
</script>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -5198,6 +5198,15 @@ ContentParent::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvRecordDiscardedData(
|
||||
const mozilla::Telemetry::DiscardedData& aDiscardedData)
|
||||
{
|
||||
TelemetryIPC::RecordDiscardedData(GetTelemetryProcessID(mRemoteType),
|
||||
aDiscardedData);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// PURLClassifierParent
|
||||
|
||||
|
|
|
@ -1177,6 +1177,8 @@ private:
|
|||
InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
|
||||
virtual mozilla::ipc::IPCResult RecvRecordChildEvents(
|
||||
nsTArray<ChildEventData>&& events) override;
|
||||
virtual mozilla::ipc::IPCResult RecvRecordDiscardedData(
|
||||
const DiscardedData& aDiscardedData) override;
|
||||
public:
|
||||
void SendGetFilesResponseAndForget(const nsID& aID,
|
||||
const GetFilesResponseResult& aResult);
|
||||
|
|
|
@ -95,6 +95,7 @@ using mozilla::Telemetry::KeyedAccumulation from "mozilla/TelemetryComms.h";
|
|||
using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
|
||||
using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
|
||||
using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
|
||||
using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
|
||||
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
|
||||
|
||||
union ChromeRegistryItem
|
||||
|
@ -1091,6 +1092,7 @@ parent:
|
|||
async UpdateChildScalars(ScalarAction[] updates);
|
||||
async UpdateChildKeyedScalars(KeyedScalarAction[] updates);
|
||||
async RecordChildEvents(ChildEventData[] events);
|
||||
async RecordDiscardedData(DiscardedData data);
|
||||
|
||||
sync GetA11yContentId() returns (uint32_t aContentId);
|
||||
async A11yHandlerControl(uint32_t aPid,
|
||||
|
|
|
@ -102,7 +102,6 @@ PEExpectedNumberOrAngle=Expected a number or an angle but found ‘%1$S’.
|
|||
PEExpectedNumberOrPercent=Expected a number or a percentage but found ‘%1$S’.
|
||||
PEColorBadRGBContents=Expected number or percentage in rgb() but found ‘%1$S’.
|
||||
PEColorComponentBadTerm=Expected ‘%2$S’ but found ‘%1$S’.
|
||||
PEColorHueEOF=hue
|
||||
PEExpectedComma=Expected ‘,’ but found ‘%1$S’.
|
||||
PEColorSaturationEOF=saturation
|
||||
PEColorLightnessEOF=lightness
|
||||
|
|
|
@ -5,14 +5,18 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Benchmark.h"
|
||||
|
||||
#include "BufferMediaResource.h"
|
||||
#include "MediaData.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "PDMFactory.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "WebMDemuxer.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
|
@ -21,6 +25,8 @@
|
|||
#include "WebMSample.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Update this version number to force re-running the benchmark. Such as when
|
||||
|
|
|
@ -8,11 +8,10 @@
|
|||
#define MOZILLA_BENCHMARK_H
|
||||
|
||||
#include "MediaDataDemuxer.h"
|
||||
#include "QueueObject.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "QueueObject.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CanvasCaptureMediaStream.h"
|
||||
|
||||
#include "DOMMediaStream.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "MediaStreamListener.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/dom/CanvasCaptureMediaStreamBinding.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
|
|
@ -4,20 +4,23 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsString.h"
|
||||
#include "CubebUtils.h"
|
||||
|
||||
#include "MediaInfo.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "CubebUtils.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prdtoa.h"
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PREF_VOLUME_SCALE "media.volume_scale"
|
||||
#define PREF_CUBEB_BACKEND "media.cubeb.backend"
|
||||
|
|
|
@ -4,28 +4,31 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DOMMediaStream.h"
|
||||
|
||||
#include "AudioCaptureStream.h"
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "AudioStreamTrack.h"
|
||||
#include "Layers.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "MediaStreamListener.h"
|
||||
#include "VideoStreamTrack.h"
|
||||
#include "mozilla/dom/AudioNode.h"
|
||||
#include "mozilla/dom/AudioTrack.h"
|
||||
#include "mozilla/dom/AudioTrackList.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/dom/LocalMediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackEvent.h"
|
||||
#include "mozilla/dom/VideoTrack.h"
|
||||
#include "mozilla/dom/VideoTrackList.h"
|
||||
#include "mozilla/media/MediaUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsRFPService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackEvent.h"
|
||||
#include "mozilla/dom/LocalMediaStreamBinding.h"
|
||||
#include "mozilla/dom/AudioNode.h"
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "mozilla/dom/AudioTrack.h"
|
||||
#include "mozilla/dom/AudioTrackList.h"
|
||||
#include "mozilla/dom/VideoTrack.h"
|
||||
#include "mozilla/dom/VideoTrackList.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/media/MediaUtils.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "AudioStreamTrack.h"
|
||||
#include "VideoStreamTrack.h"
|
||||
#include "Layers.h"
|
||||
#include "nsRFPService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing
|
||||
|
|
|
@ -67,12 +67,14 @@ IsAndroidMediaType(const MediaContainerType& aType)
|
|||
/* static */ bool
|
||||
DecoderTraits::IsHttpLiveStreamingType(const MediaContainerType& aType)
|
||||
{
|
||||
const auto& mimeType = aType.Type();
|
||||
return // For m3u8.
|
||||
// https://tools.ietf.org/html/draft-pantos-http-live-streaming-19#section-10
|
||||
aType.Type() == MEDIAMIMETYPE("application/vnd.apple.mpegurl")
|
||||
mimeType == MEDIAMIMETYPE("application/vnd.apple.mpegurl")
|
||||
// Some sites serve these as the informal m3u type.
|
||||
|| aType.Type() == MEDIAMIMETYPE("application/x-mpegurl")
|
||||
|| aType.Type() == MEDIAMIMETYPE("audio/x-mpegurl");
|
||||
|| mimeType == MEDIAMIMETYPE("application/x-mpegurl")
|
||||
|| mimeType == MEDIAMIMETYPE("audio/mpegurl")
|
||||
|| mimeType == MEDIAMIMETYPE("audio/x-mpegurl");
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
|
|
@ -4,25 +4,25 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
|
||||
#include "MediaCache.h"
|
||||
#include "prio.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MediaResource.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "FileBlockCache.h"
|
||||
#include "MediaBlockCacheBase.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MemoryBlockCache.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prio.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
#ifndef MediaCache_h_
|
||||
#define MediaCache_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "Intervals.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
|
|
|
@ -5,17 +5,24 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaData.h"
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/layers/SharedRGBImage.h"
|
||||
#include "YCbCrUtils.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/KnowsCompositor.h"
|
||||
#include "mozilla/layers/SharedRGBImage.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include <cutils/properties.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "mozilla/layers/D3D11YCbCrImage.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -241,19 +248,14 @@ VideoData::UpdateTimestamp(const TimeUnit& aTimestamp)
|
|||
mDuration = updatedDuration;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
const VideoInfo& aInfo,
|
||||
const YCbCrBuffer &aBuffer,
|
||||
const IntRect& aPicture,
|
||||
bool aCopyData)
|
||||
PlanarYCbCrData
|
||||
ConstructPlanarYCbCrData(const VideoInfo& aInfo,
|
||||
const VideoData::YCbCrBuffer& aBuffer,
|
||||
const IntRect& aPicture)
|
||||
{
|
||||
if (!aVideoImage) {
|
||||
return false;
|
||||
}
|
||||
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
||||
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
||||
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
|
||||
const VideoData::YCbCrBuffer::Plane& Y = aBuffer.mPlanes[0];
|
||||
const VideoData::YCbCrBuffer::Plane& Cb = aBuffer.mPlanes[1];
|
||||
const VideoData::YCbCrBuffer::Plane& Cr = aBuffer.mPlanes[2];
|
||||
|
||||
PlanarYCbCrData data;
|
||||
data.mYChannel = Y.mData + Y.mOffset;
|
||||
|
@ -271,6 +273,21 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
|||
data.mPicSize = aPicture.Size();
|
||||
data.mStereoMode = aInfo.mStereoMode;
|
||||
data.mYUVColorSpace = aBuffer.mYUVColorSpace;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
const VideoInfo& aInfo,
|
||||
const YCbCrBuffer &aBuffer,
|
||||
const IntRect& aPicture,
|
||||
bool aCopyData)
|
||||
{
|
||||
if (!aVideoImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PlanarYCbCrData data = ConstructPlanarYCbCrData(aInfo, aBuffer, aPicture);
|
||||
|
||||
aVideoImage->SetDelayedConversion(true);
|
||||
if (aCopyData) {
|
||||
|
@ -290,7 +307,8 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
|
|||
const YCbCrBuffer& aBuffer,
|
||||
bool aKeyframe,
|
||||
const TimeUnit& aTimecode,
|
||||
const IntRect& aPicture)
|
||||
const IntRect& aPicture,
|
||||
layers::KnowsCompositor* aAllocator)
|
||||
{
|
||||
if (!aContainer) {
|
||||
// Create a dummy VideoData with no image. This gives us something to
|
||||
|
@ -328,6 +346,19 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
|
|||
if (IsYV12Format(Y, Cb, Cr) && !IsInEmulator()) {
|
||||
v->mImage = new layers::GrallocImage();
|
||||
}
|
||||
#elif XP_WIN
|
||||
if (aAllocator && aAllocator->GetCompositorBackendType()
|
||||
== layers::LayersBackend::LAYERS_D3D11) {
|
||||
RefPtr<layers::D3D11YCbCrImage> d3d11Image = new layers::D3D11YCbCrImage();
|
||||
PlanarYCbCrData data = ConstructPlanarYCbCrData(aInfo, aBuffer, aPicture);
|
||||
if (d3d11Image->SetData(layers::ImageBridgeChild::GetSingleton()
|
||||
? layers::ImageBridgeChild::GetSingleton().get()
|
||||
: aAllocator,
|
||||
aContainer, data)) {
|
||||
v->mImage = d3d11Image;
|
||||
return v.forget();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!v->mImage) {
|
||||
v->mImage = aContainer->CreatePlanarYCbCrImage();
|
||||
|
|
|
@ -8,25 +8,26 @@
|
|||
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "nsSize.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "SharedBuffer.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "TimeUnits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
class Image;
|
||||
class ImageContainer;
|
||||
class KnowsCompositor;
|
||||
} // namespace layers
|
||||
|
||||
class MediaByteBuffer;
|
||||
|
@ -497,7 +498,8 @@ public:
|
|||
const YCbCrBuffer& aBuffer,
|
||||
bool aKeyframe,
|
||||
const media::TimeUnit& aTimecode,
|
||||
const IntRect& aPicture);
|
||||
const IntRect& aPicture,
|
||||
layers::KnowsCompositor* aAllocator = nullptr);
|
||||
|
||||
static already_AddRefed<VideoData> CreateAndCopyData(
|
||||
const VideoInfo& aInfo,
|
||||
|
|
|
@ -5,34 +5,35 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaDecoder.h"
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "Layers.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MediaShutdownManager.h"
|
||||
#include "VideoFrameContainer.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include <limits>
|
||||
#include "nsIObserver.h"
|
||||
#include "nsTArray.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "MediaResource.h"
|
||||
#include "VideoFrameContainer.h"
|
||||
#include "nsError.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include <algorithm>
|
||||
#include "MediaShutdownManager.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/AudioTrack.h"
|
||||
#include "mozilla/dom/AudioTrackList.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/VideoTrack.h"
|
||||
#include "mozilla/dom/VideoTrackList.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "Layers.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsTArray.h"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#ifdef MOZ_ANDROID_OMX
|
||||
#include "AndroidBridge.h"
|
||||
|
@ -44,6 +45,12 @@ using namespace mozilla::media;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
|
||||
#ifdef GetCurrentTime
|
||||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
// avoid redefined macro in unified build
|
||||
#undef LOG
|
||||
#undef DUMP
|
||||
|
|
|
@ -7,22 +7,6 @@
|
|||
#if !defined(MediaDecoder_h_)
|
||||
#define MediaDecoder_h_
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/StateMirroring.h"
|
||||
#include "mozilla/StateWatching.h"
|
||||
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
|
||||
#include "necko-config.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "DecoderDoctorDiagnostics.h"
|
||||
#include "MediaDecoderOwner.h"
|
||||
|
@ -32,8 +16,21 @@
|
|||
#include "MediaResourceCallback.h"
|
||||
#include "MediaStatistics.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "SeekTarget.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/StateMirroring.h"
|
||||
#include "mozilla/StateWatching.h"
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
#include "necko-config.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
class nsIPrincipal;
|
||||
|
|
|
@ -5,17 +5,19 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaDecoderReader.h"
|
||||
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "MediaResource.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "MediaPrefs.h"
|
||||
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "MediaResource.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include <stdint.h>
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace mozilla::media;
|
||||
|
||||
|
|
|
@ -6,26 +6,26 @@
|
|||
#if !defined(MediaDecoderReader_h_)
|
||||
#define MediaDecoderReader_h_
|
||||
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "AudioCompactor.h"
|
||||
#include "Intervals.h"
|
||||
#include "MediaData.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
#include "MediaQueue.h"
|
||||
#include "MediaResult.h"
|
||||
#include "MediaTimer.h"
|
||||
#include "SeekTarget.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "MediaData.h"
|
||||
#include "MediaResult.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
#include "MediaQueue.h"
|
||||
#include "MediaTimer.h"
|
||||
#include "AudioCompactor.h"
|
||||
#include "Intervals.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "SeekTarget.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CDMProxy;
|
||||
class MediaDecoderReader;
|
||||
class TaskQueue;
|
||||
|
||||
struct WaitForDataRejectValue
|
||||
{
|
||||
|
|
|
@ -4,25 +4,26 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaFormatReader.h"
|
||||
|
||||
#include "AutoTaskQueue.h"
|
||||
#include "mozilla/SizePrintfMacros.h"
|
||||
#include "Layers.h"
|
||||
#include "MediaData.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "MediaFormatReader.h"
|
||||
#include "MediaResource.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "VideoFrameContainer.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "mozilla/SizePrintfMacros.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsSize.h"
|
||||
|
@ -2281,6 +2282,15 @@ MediaFormatReader::Update(TrackType aTrack)
|
|||
nsCString error;
|
||||
mVideo.mIsHardwareAccelerated =
|
||||
mVideo.mDecoder && mVideo.mDecoder->IsHardwareAccelerated(error);
|
||||
#ifdef XP_WIN
|
||||
// D3D11_YCBCR_IMAGE images are GPU based, we try to limit the amount
|
||||
// of GPU RAM used.
|
||||
VideoData* videoData = static_cast<VideoData*>(output.get());
|
||||
mVideo.mIsHardwareAccelerated =
|
||||
mVideo.mIsHardwareAccelerated ||
|
||||
(videoData->mImage &&
|
||||
videoData->mImage->GetFormat() == ImageFormat::D3D11_YCBCR_IMAGE);
|
||||
#endif
|
||||
}
|
||||
} else if (decoder.HasFatalError()) {
|
||||
LOG("Rejecting %s promise: DECODE_ERROR", TrackTypeToStr(aTrack));
|
||||
|
|
|
@ -6,21 +6,19 @@
|
|||
#ifndef MOZILLA_MEDIASTREAMGRAPH_H_
|
||||
#define MOZILLA_MEDIASTREAMGRAPH_H_
|
||||
|
||||
#include "AudioStream.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "MediaStreamTypes.h"
|
||||
#include "StreamTracks.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
|
||||
#include "AudioStream.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "StreamTracks.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "StreamTracks.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsTArray.h"
|
||||
#include <speex/speex_resampler.h>
|
||||
|
||||
class nsIRunnable;
|
||||
|
@ -170,9 +168,6 @@ class ProcessedMediaStream;
|
|||
class SourceMediaStream;
|
||||
class TrackUnionStream;
|
||||
|
||||
enum MediaStreamGraphEvent : uint32_t;
|
||||
enum TrackEventCommand : uint32_t;
|
||||
|
||||
/**
|
||||
* Helper struct for binding a track listener to a specific TrackID.
|
||||
*/
|
||||
|
@ -183,24 +178,6 @@ struct TrackBound
|
|||
TrackID mTrackID;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes how a track should be disabled.
|
||||
*
|
||||
* ENABLED Not disabled.
|
||||
* SILENCE_BLACK Audio data is turned into silence, video frames are made black.
|
||||
* SILENCE_FREEZE Audio data is turned into silence, video freezes at last frame.
|
||||
*/
|
||||
enum class DisabledTrackMode
|
||||
{
|
||||
ENABLED, SILENCE_BLACK, SILENCE_FREEZE
|
||||
};
|
||||
struct DisabledTrack {
|
||||
DisabledTrack(TrackID aTrackID, DisabledTrackMode aMode)
|
||||
: mTrackID(aTrackID), mMode(aMode) {}
|
||||
TrackID mTrackID;
|
||||
DisabledTrackMode mMode;
|
||||
};
|
||||
|
||||
/**
|
||||
* A stream of synchronized audio and video data. All (not blocked) streams
|
||||
* progress at the same rate --- "real time". Streams cannot seek. The only
|
||||
|
|
|
@ -19,21 +19,6 @@ class MediaStreamGraph;
|
|||
class MediaStreamVideoSink;
|
||||
class VideoSegment;
|
||||
|
||||
enum MediaStreamGraphEvent : uint32_t {
|
||||
EVENT_FINISHED,
|
||||
EVENT_REMOVED,
|
||||
EVENT_HAS_DIRECT_LISTENERS, // transition from no direct listeners
|
||||
EVENT_HAS_NO_DIRECT_LISTENERS, // transition to no direct listeners
|
||||
};
|
||||
|
||||
// maskable flags, not a simple enumerated value
|
||||
enum TrackEventCommand : uint32_t {
|
||||
TRACK_EVENT_NONE = 0x00,
|
||||
TRACK_EVENT_CREATED = 0x01,
|
||||
TRACK_EVENT_ENDED = 0x02,
|
||||
TRACK_EVENT_UNUSED = ~(TRACK_EVENT_ENDED | TRACK_EVENT_CREATED),
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a base class for media graph thread listener callbacks.
|
||||
* Override methods to be notified of audio or video data or changes in stream
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
#include "MediaStreamTrack.h"
|
||||
|
||||
#include "DOMMediaStream.h"
|
||||
#include "MediaStreamError.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "MediaStreamListener.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "MediaStreamListener.h"
|
||||
#include "systemservices/MediaUtils.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
|
@ -21,6 +22,8 @@
|
|||
static mozilla::LazyLogModule gMediaStreamTrackLog("MediaStreamTrack");
|
||||
#define LOG(type, msg) MOZ_LOG(gMediaStreamTrackLog, type, msg)
|
||||
|
||||
using namespace mozilla::media;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
#ifndef MEDIASTREAMTRACK_H_
|
||||
#define MEDIASTREAMTRACK_H_
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsError.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "StreamTracks.h"
|
||||
#include "MediaTrackConstraints.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "PrincipalChangeObserver.h"
|
||||
#include "StreamTracks.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaTrackSettingsBinding.h"
|
||||
#include "mozilla/media/MediaUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_MEDIASTREAMTYPES_h_
|
||||
#define MOZILLA_MEDIASTREAMTYPES_h_
|
||||
|
||||
#include "StreamTracks.h" // for TrackID
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum MediaStreamGraphEvent : uint32_t {
|
||||
EVENT_FINISHED,
|
||||
EVENT_REMOVED,
|
||||
EVENT_HAS_DIRECT_LISTENERS, // transition from no direct listeners
|
||||
EVENT_HAS_NO_DIRECT_LISTENERS, // transition to no direct listeners
|
||||
};
|
||||
|
||||
// maskable flags, not a simple enumerated value
|
||||
enum TrackEventCommand : uint32_t {
|
||||
TRACK_EVENT_NONE = 0x00,
|
||||
TRACK_EVENT_CREATED = 0x01,
|
||||
TRACK_EVENT_ENDED = 0x02,
|
||||
TRACK_EVENT_UNUSED = ~(TRACK_EVENT_ENDED | TRACK_EVENT_CREATED),
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes how a track should be disabled.
|
||||
*
|
||||
* ENABLED Not disabled.
|
||||
* SILENCE_BLACK Audio data is turned into silence, video frames are made black.
|
||||
* SILENCE_FREEZE Audio data is turned into silence, video freezes at last frame.
|
||||
*/
|
||||
enum class DisabledTrackMode
|
||||
{
|
||||
ENABLED, SILENCE_BLACK, SILENCE_FREEZE
|
||||
};
|
||||
struct DisabledTrack {
|
||||
DisabledTrack(TrackID aTrackID, DisabledTrackMode aMode)
|
||||
: mTrackID(aTrackID), mMode(aMode) {}
|
||||
TrackID mTrackID;
|
||||
DisabledTrackMode mMode;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_MEDIASTREAMTYPES_h_
|
|
@ -6,13 +6,12 @@
|
|||
|
||||
#include "MediaTimer.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
#if !defined(MediaTimer_h_)
|
||||
#define MediaTimer_h_
|
||||
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "nsITimer.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsITimer.h"
|
||||
#include <queue>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "MediaPrefs.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "prsystem.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -4,26 +4,25 @@
|
|||
|
||||
#include "VideoUtils.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "MediaContainerType.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "MediaResource.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsSize.h"
|
||||
#include "VorbisUtils.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "nsIRandomGenerator.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsContentTypeParser.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIRandomGenerator.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include <functional>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
#ifndef VideoUtils_h
|
||||
#define VideoUtils_h
|
||||
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "VideoLimits.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
@ -15,19 +18,14 @@
|
|||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
#include "nsSize.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prtime.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "VideoLimits.h"
|
||||
|
||||
using mozilla::CheckedInt64;
|
||||
using mozilla::CheckedUint64;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче