зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. r=merge a=merge CLOSED TREE
This commit is contained in:
Коммит
0fcc1a37e6
|
@ -220,6 +220,7 @@ dom/fetch/**
|
|||
dom/file/**
|
||||
dom/filehandle/**
|
||||
dom/filesystem/**
|
||||
dom/flex/**
|
||||
dom/flyweb/**
|
||||
dom/gamepad/**
|
||||
dom/geolocation/**
|
||||
|
|
|
@ -54,7 +54,7 @@ if CONFIG['MOZ_ENABLE_DBUS']:
|
|||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
if CONFIG['CLANG_CXX'] or CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
# Used in G_DEFINE_TYPE_EXTENDED macro, probably fixed in newer glib /
|
||||
# gobject headers. See bug 1243331 comment 3.
|
||||
CXXFLAGS += [
|
||||
|
|
|
@ -112,5 +112,5 @@ FINAL_LIBRARY = 'xul'
|
|||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
#include "nsIEditingSession.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
|
|
@ -66,5 +66,5 @@ FINAL_LIBRARY = 'xul'
|
|||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -46,5 +46,5 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
|||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -25,5 +25,5 @@ FINAL_LIBRARY = 'xul'
|
|||
# #endif !_MIDL_USE_GUIDDEF_
|
||||
#
|
||||
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
CFLAGS += ['-Wno-extra-tokens']
|
||||
|
|
|
@ -91,5 +91,5 @@ RCINCLUDE = 'IA2Marshal.rc'
|
|||
# #endif !_MIDL_USE_GUIDDEF_
|
||||
#
|
||||
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
CXXFLAGS += ['-Wno-extra-tokens']
|
||||
|
|
|
@ -41,5 +41,5 @@ RCINCLUDE = 'AccessibleMarshal.rc'
|
|||
# #endif !_MIDL_USE_GUIDDEF_
|
||||
#
|
||||
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
CFLAGS += ['-Wno-extra-tokens']
|
||||
|
|
|
@ -33,7 +33,7 @@ EXPORTS.mozilla.a11y += [
|
|||
'IPCTypes.h',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
if CONFIG['ACCESSIBILITY']:
|
||||
|
|
|
@ -40,7 +40,7 @@ if CONFIG['ACCESSIBILITY']:
|
|||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -23,5 +23,5 @@ LOCAL_INCLUDES += [
|
|||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -5,3 +5,4 @@ support-files =
|
|||
!/accessible/tests/mochitest/*.js
|
||||
|
||||
[browser_test_doc_creation.js]
|
||||
[browser_test_urlbar.js]
|
||||
|
|
|
@ -4,18 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const nsIAccessibleRole = Ci.nsIAccessibleRole; // eslint-disable-line no-unused-vars
|
||||
|
||||
/* import-globals-from ../../mochitest/role.js */
|
||||
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
|
||||
|
||||
async function openNewTab(url) {
|
||||
const forceNewProcess = true;
|
||||
|
||||
return BrowserTestUtils.openNewForegroundTab(
|
||||
{ gBrowser, url, forceNewProcess });
|
||||
}
|
||||
|
||||
const tab1URL = `data:text/html,
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* 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";
|
||||
|
||||
// Checking that the awesomebar popup gets COMBOBOX_LIST role instead of
|
||||
// LISTBOX, since its parent is a <panel> (see Bug 1422465)
|
||||
add_task(async function testAutocompleteRichResult() {
|
||||
let tab = await openNewTab("data:text/html;charset=utf-8,");
|
||||
let accService = await initAccessibilityService();
|
||||
|
||||
info("Opening the URL bar and entering a key to show the PopupAutoCompleteRichResult panel");
|
||||
let urlbar = document.getElementById("urlbar");
|
||||
urlbar.focus();
|
||||
let urlbarPopup = document.getElementById("PopupAutoCompleteRichResult");
|
||||
let shown = BrowserTestUtils.waitForEvent(urlbarPopup, "popupshown");
|
||||
EventUtils.synthesizeKey("a", {});
|
||||
await shown;
|
||||
|
||||
info("Waiting for accessibility to be created for the richlistbox");
|
||||
let richlistbox = document.getAnonymousElementByAttribute(urlbarPopup, "anonid", "richlistbox");
|
||||
await BrowserTestUtils.waitForCondition(() => accService.getAccessibleFor(richlistbox));
|
||||
|
||||
info("Confirming that the special case is handled in XULListboxAccessible");
|
||||
let accessible = accService.getAccessibleFor(richlistbox);
|
||||
is(accessible.role, ROLE_COMBOBOX_LIST, "Right role");
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await shutdownAccessibilityService();
|
||||
});
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* exported initAccessibilityService, shutdownAccessibilityService */
|
||||
/* exported initAccessibilityService, openNewTab, shutdownAccessibilityService */
|
||||
|
||||
// Load the shared-head file first.
|
||||
/* import-globals-from ../shared-head.js */
|
||||
|
@ -12,6 +12,18 @@ Services.scriptloader.loadSubScript(
|
|||
"chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js",
|
||||
this);
|
||||
|
||||
const nsIAccessibleRole = Ci.nsIAccessibleRole; // eslint-disable-line no-unused-vars
|
||||
|
||||
/* import-globals-from ../../mochitest/role.js */
|
||||
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
|
||||
|
||||
async function openNewTab(url) {
|
||||
const forceNewProcess = true;
|
||||
|
||||
return BrowserTestUtils.openNewForegroundTab(
|
||||
{ gBrowser, url, forceNewProcess });
|
||||
}
|
||||
|
||||
async function initAccessibilityService() {
|
||||
info("Create accessibility service.");
|
||||
let accService = Cc["@mozilla.org/accessibilityService;1"].getService(
|
||||
|
|
|
@ -52,7 +52,7 @@ FINAL_LIBRARY = 'xul'
|
|||
# #endif !_MIDL_USE_GUIDDEF_
|
||||
#
|
||||
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
CXXFLAGS += ['-Wno-extra-tokens']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -74,7 +74,7 @@ LOCAL_INCLUDES += [
|
|||
# #endif !_MIDL_USE_GUIDDEF_
|
||||
#
|
||||
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
CXXFLAGS += ['-Wno-extra-tokens']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -62,5 +62,5 @@ FINAL_LIBRARY = 'xul'
|
|||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "nsIDOMXULMenuListElement.h"
|
||||
#include "nsIDOMXULMultSelectCntrlEl.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
#include "nsIDOMXULSelectCntrlItemEl.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
@ -157,9 +156,7 @@ XULListboxAccessible::NativeRole()
|
|||
{
|
||||
// A richlistbox is used with the new autocomplete URL bar, and has a parent
|
||||
// popup <panel>.
|
||||
nsCOMPtr<nsIDOMXULPopupElement> xulPopup =
|
||||
do_QueryInterface(mContent->GetParent());
|
||||
if (xulPopup)
|
||||
if (mContent->GetParent()->IsXULElement(nsGkAtoms::panel))
|
||||
return roles::COMBOBOX_LIST;
|
||||
|
||||
return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
|
||||
|
|
|
@ -53,5 +53,5 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
|||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -62,7 +62,7 @@ if CONFIG['LIBFUZZER']:
|
|||
if CONFIG['ENABLE_GECKODRIVER']:
|
||||
DEFINES['MOZ_GECKODRIVER'] = True
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
|
||||
# Always enter a Windows program through wmain, whether or not we're
|
||||
# a console application.
|
||||
WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
|
||||
|
@ -95,7 +95,7 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
|||
# The heap will grow if need be.
|
||||
#
|
||||
# Set it to 256k. See bug 127069.
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['CC_TYPE'] not in ('clang', 'gcc'):
|
||||
LDFLAGS += ['/HEAP:0x40000']
|
||||
|
||||
DisableStlWrapping()
|
||||
|
|
|
@ -43,13 +43,10 @@ pref("extensions.webextOptionalPermissionPrompts", true);
|
|||
|
||||
// Preferences for AMO integration
|
||||
pref("extensions.getAddons.cache.enabled", true);
|
||||
pref("extensions.getAddons.maxResults", 15);
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%");
|
||||
pref("extensions.getAddons.getWithPerformance.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
|
||||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%&platform=%OS%&appver=%VERSION%");
|
||||
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%/%COMPATIBILITY_MODE%?src=firefox");
|
||||
pref("extensions.webservice.discoverURL", "https://discovery.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%/%COMPATIBILITY_MODE%");
|
||||
pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/list/recommended/all/%MAX_RESULTS%/%OS%/%VERSION%?src=firefox");
|
||||
pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/");
|
||||
pref("extensions.getAddons.themes.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes/?src=firefox");
|
||||
|
||||
|
@ -396,9 +393,9 @@ pref("browser.search.geoSpecificDefaults", false);
|
|||
pref("browser.search.geoSpecificDefaults.url", "https://search.services.mozilla.com/1/%APP%/%VERSION%/%CHANNEL%/%LOCALE%/%REGION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%");
|
||||
|
||||
// US specific default (used as a fallback if the geoSpecificDefaults request fails).
|
||||
pref("browser.search.defaultenginename.US", "data:text/plain,browser.search.defaultenginename.US=Yahoo");
|
||||
pref("browser.search.order.US.1", "data:text/plain,browser.search.order.US.1=Yahoo");
|
||||
pref("browser.search.order.US.2", "data:text/plain,browser.search.order.US.2=Google");
|
||||
pref("browser.search.defaultenginename.US", "data:text/plain,browser.search.defaultenginename.US=Google");
|
||||
pref("browser.search.order.US.1", "data:text/plain,browser.search.order.US.1=Google");
|
||||
pref("browser.search.order.US.2", "data:text/plain,browser.search.order.US.2=Yahoo");
|
||||
pref("browser.search.order.US.3", "data:text/plain,browser.search.order.US.3=Bing");
|
||||
|
||||
// search bar results always open in a new tab
|
||||
|
|
|
@ -16,12 +16,10 @@ support-files =
|
|||
browser_webext_update_origins1.xpi
|
||||
browser_webext_update_origins2.xpi
|
||||
browser_webext_update.json
|
||||
browser_webext_search.xml
|
||||
|
||||
[browser_extension_sideloading.js]
|
||||
[browser_extension_update_background.js]
|
||||
[browser_extension_update_background_noprompt.js]
|
||||
[browser_permissions_addons_search.js]
|
||||
[browser_permissions_installTrigger.js]
|
||||
[browser_permissions_local_file.js]
|
||||
[browser_permissions_mozAddonManager.js]
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
async function installSearch(filename) {
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
["extensions.getAddons.maxResults", 10],
|
||||
["extensions.getAddons.search.url", `${BASE}/browser_webext_search.xml`],
|
||||
]});
|
||||
|
||||
let win = await BrowserOpenAddonsMgr("addons://list/extension");
|
||||
|
||||
let searchResultsPromise = new Promise(resolve => {
|
||||
win.document.addEventListener("ViewChanged", resolve, {once: true});
|
||||
});
|
||||
let search = win.document.getElementById("header-search");
|
||||
search.focus();
|
||||
search.value = "search text";
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, win);
|
||||
|
||||
await searchResultsPromise;
|
||||
ok(win.gViewController.currentViewId.startsWith("addons://search"),
|
||||
"about:addons is displaying search results");
|
||||
|
||||
let list = win.document.getElementById("search-list");
|
||||
let item = null;
|
||||
for (let child of list.childNodes) {
|
||||
if (child.nodeName == "richlistitem" &&
|
||||
child.mAddon.install.sourceURI.pathQueryRef.endsWith(filename)) {
|
||||
item = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(item, `Found ${filename} in search results`);
|
||||
|
||||
// abracadabara XBL
|
||||
item.clientTop;
|
||||
|
||||
let install = win.document.getAnonymousElementByAttribute(item, "anonid", "install-status");
|
||||
let button = win.document.getAnonymousElementByAttribute(install, "anonid", "install-remote-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {}, win);
|
||||
}
|
||||
|
||||
add_task(() => testInstallMethod(installSearch, "installAmo"));
|
|
@ -1,51 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<searchresults total_results="2">
|
||||
<addon>
|
||||
<name>permissions test</name>
|
||||
<type id='1'>Extension</type>
|
||||
<guid>permissions@tests.mozilla.org</guid>
|
||||
<version>1.1</version>
|
||||
<authors>
|
||||
<author>
|
||||
<name>Test Creator</name>
|
||||
<link>http://example.com/creator.html</link>
|
||||
</author>
|
||||
</authors>
|
||||
<status id='4'>Public</status>
|
||||
<compatible_applications>
|
||||
<application>
|
||||
<name>Firefox</name>
|
||||
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
|
||||
<min_version>0</min_version>
|
||||
<max_version>*</max_version>
|
||||
</application>
|
||||
</compatible_applications>
|
||||
<compatible_os>ALL</compatible_os>
|
||||
<install size="1">https://example.com/browser/browser/base/content/test/webextensions/browser_webext_permissions.xpi</install>
|
||||
</addon>
|
||||
|
||||
<addon>
|
||||
<name>no permissions</name>
|
||||
<type id='1'>Extension</type>
|
||||
<guid>nopermissions@tests.mozilla.org</guid>
|
||||
<version>1.0</version>
|
||||
<authors>
|
||||
<author>
|
||||
<name>Test Creator</name>
|
||||
<link>http://example.com/creator.html</link>
|
||||
</author>
|
||||
</authors>
|
||||
<status id='4'>Public</status>
|
||||
<compatible_applications>
|
||||
<application>
|
||||
<name>Firefox</name>
|
||||
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
|
||||
<min_version>0</min_version>
|
||||
<max_version>*</max_version>
|
||||
</application>
|
||||
</compatible_applications>
|
||||
<compatible_os>ALL</compatible_os>
|
||||
<install size="1">https://example.com/browser/browser/base/content/test/webextensions/browser_webext_nopermissions.xpi</install>
|
||||
</addon>
|
||||
</searchresults>
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'test/browser.ini',
|
||||
'test/google_codes/browser.ini',
|
||||
'test/google_nocodes/browser.ini',
|
||||
]
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
|
|
@ -27,10 +27,6 @@ skip-if = os == "mac" # bug 967013
|
|||
skip-if = artifact # bug 1315953
|
||||
[browser_google.js]
|
||||
skip-if = artifact # bug 1315953
|
||||
[browser_google_codes.js]
|
||||
skip-if = artifact # bug 1315953
|
||||
[browser_google_nocodes.js]
|
||||
skip-if = artifact # bug 1315953
|
||||
[browser_google_behavior.js]
|
||||
skip-if = artifact # bug 1315953
|
||||
[browser_healthreport.js]
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -9,7 +9,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const SEARCH_ENGINE_DETAILS = [{
|
||||
let searchEngineDetails = [{
|
||||
alias: "g",
|
||||
baseURL: "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8",
|
||||
codes: {
|
||||
|
@ -21,6 +21,29 @@ const SEARCH_ENGINE_DETAILS = [{
|
|||
name: "Google",
|
||||
}];
|
||||
|
||||
let countryCode = Services.prefs.getCharPref("browser.search.countryCode");
|
||||
let code = "";
|
||||
switch (countryCode) {
|
||||
case "US":
|
||||
code = "firefox-b-1";
|
||||
break;
|
||||
case "DE":
|
||||
code = "firefox-b";
|
||||
break;
|
||||
case "RU":
|
||||
// Covered by test but doesn't use a code
|
||||
break;
|
||||
}
|
||||
|
||||
if (code) {
|
||||
let codes = searchEngineDetails[0].codes;
|
||||
let suffix = `&client=${code}`;
|
||||
codes.context = suffix;
|
||||
codes.newTab = suffix;
|
||||
codes.submission = suffix;
|
||||
codes.keyword = `${suffix}-ab`;
|
||||
}
|
||||
|
||||
function promiseStateChangeURI() {
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
|
@ -74,7 +97,7 @@ function promiseContentSearchReady(browser) {
|
|||
});
|
||||
}
|
||||
|
||||
for (let engine of SEARCH_ENGINE_DETAILS) {
|
||||
for (let engine of searchEngineDetails) {
|
||||
add_task(async function() {
|
||||
let previouslySelectedEngine = Services.search.currentEngine;
|
||||
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const kUrlPref = "geoSpecificDefaults.url";
|
||||
const BROWSER_SEARCH_PREF = "browser.search.";
|
||||
|
||||
var originalGeoURL;
|
||||
var originalCountryCode;
|
||||
var originalRegion;
|
||||
|
||||
/**
|
||||
* Clean the profile of any cache file left from a previous run.
|
||||
* Returns a boolean indicating if the cache file existed.
|
||||
*/
|
||||
function removeCacheFile() {
|
||||
const CACHE_FILENAME = "search.json.mozlz4";
|
||||
|
||||
let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file.append(CACHE_FILENAME);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that is resolved when an observer notification from the
|
||||
* search service fires with the specified data.
|
||||
*
|
||||
* @param aExpectedData
|
||||
* The value the observer notification sends that causes us to resolve
|
||||
* the promise.
|
||||
*/
|
||||
function waitForSearchNotification(aExpectedData, aCallback) {
|
||||
const SEARCH_SERVICE_TOPIC = "browser-search-service";
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
|
||||
if (aData != aExpectedData)
|
||||
return;
|
||||
|
||||
Services.obs.removeObserver(observer, SEARCH_SERVICE_TOPIC);
|
||||
aCallback();
|
||||
}, SEARCH_SERVICE_TOPIC);
|
||||
}
|
||||
|
||||
function asyncInit() {
|
||||
return new Promise(resolve => {
|
||||
Services.search.init(function() {
|
||||
ok(Services.search.isInitialized, "search service should be initialized");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function asyncReInit() {
|
||||
let promise = new Promise(resolve => {
|
||||
waitForSearchNotification("reinit-complete", resolve);
|
||||
});
|
||||
|
||||
Services.search.QueryInterface(Ci.nsIObserver)
|
||||
.observe(null, "intl:requested-locales-changed", null);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
let gEngineCount;
|
||||
|
||||
add_task(async function preparation() {
|
||||
// ContentSearch is interferring with our async re-initializations of the
|
||||
// search service: once _initServicePromise has resolved, it will access
|
||||
// the search service, thus causing unpredictable behavior due to
|
||||
// synchronous initializations of the service.
|
||||
let originalContentSearchPromise = ContentSearch._initServicePromise;
|
||||
ContentSearch._initServicePromise = new Promise(resolve => {
|
||||
registerCleanupFunction(() => {
|
||||
ContentSearch._initServicePromise = originalContentSearchPromise;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await asyncInit();
|
||||
gEngineCount = Services.search.getVisibleEngines().length;
|
||||
|
||||
waitForSearchNotification("uninit-complete", () => {
|
||||
// Verify search service is not initialized
|
||||
is(Services.search.isInitialized, false, "Search service should NOT be initialized");
|
||||
|
||||
removeCacheFile();
|
||||
|
||||
// Make sure we get the new country/region values, but save the old
|
||||
originalCountryCode = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "countryCode");
|
||||
originalRegion = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "region");
|
||||
Services.prefs.clearUserPref(BROWSER_SEARCH_PREF + "countryCode");
|
||||
Services.prefs.clearUserPref(BROWSER_SEARCH_PREF + "region");
|
||||
|
||||
// Geo specific defaults won't be fetched if there's no country code.
|
||||
Services.prefs.setCharPref("browser.search.geoip.url",
|
||||
'data:application/json,{"country_code": "DE"}');
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
|
||||
// Avoid going to the server for the geo lookup. We take the defaults
|
||||
originalGeoURL = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + kUrlPref);
|
||||
let geoUrl = "data:application/json,{}";
|
||||
Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).setCharPref(kUrlPref, geoUrl);
|
||||
});
|
||||
|
||||
await asyncReInit();
|
||||
|
||||
await new Promise(resolve => {
|
||||
waitForSearchNotification("write-cache-to-disk-complete", resolve);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function tests() {
|
||||
let engine = Services.search.getEngineByName("Google");
|
||||
ok(engine, "Google");
|
||||
|
||||
let base = "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8&client=firefox-b";
|
||||
|
||||
// Keyword uses a slightly different code
|
||||
let keywordBase = base + "-ab";
|
||||
|
||||
let url;
|
||||
|
||||
// Test search URLs (including purposes).
|
||||
url = engine.getSubmission("foo", null, "contextmenu").uri.spec;
|
||||
is(url, base, "Check context menu search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "keyword").uri.spec;
|
||||
is(url, keywordBase, "Check keyword search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "searchbar").uri.spec;
|
||||
is(url, base, "Check search bar search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "homepage").uri.spec;
|
||||
is(url, base, "Check homepage search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "newtab").uri.spec;
|
||||
is(url, base, "Check newtab search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "system").uri.spec;
|
||||
is(url, base, "Check system search URL for 'foo'");
|
||||
});
|
||||
|
||||
|
||||
add_task(async function cleanup() {
|
||||
waitForSearchNotification("uninit-complete", () => {
|
||||
// Verify search service is not initialized
|
||||
is(Services.search.isInitialized, false,
|
||||
"Search service should NOT be initialized");
|
||||
removeCacheFile();
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.geoip.url");
|
||||
|
||||
Services.prefs.setCharPref(BROWSER_SEARCH_PREF + "countryCode", originalCountryCode);
|
||||
Services.prefs.setCharPref(BROWSER_SEARCH_PREF + "region", originalRegion);
|
||||
|
||||
// We can't clear the pref because it's set to false by testing/profiles/prefs_general.js
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", false);
|
||||
|
||||
Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).setCharPref(kUrlPref, originalGeoURL);
|
||||
});
|
||||
|
||||
await asyncReInit();
|
||||
is(gEngineCount, Services.search.getVisibleEngines().length,
|
||||
"correct engine count after cleanup");
|
||||
});
|
|
@ -1,162 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const kUrlPref = "geoSpecificDefaults.url";
|
||||
const BROWSER_SEARCH_PREF = "browser.search.";
|
||||
|
||||
var originalGeoURL;
|
||||
var originalCountryCode;
|
||||
var originalRegion;
|
||||
|
||||
/**
|
||||
* Clean the profile of any cache file left from a previous run.
|
||||
* Returns a boolean indicating if the cache file existed.
|
||||
*/
|
||||
function removeCacheFile() {
|
||||
const CACHE_FILENAME = "search.json.mozlz4";
|
||||
|
||||
let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file.append(CACHE_FILENAME);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that is resolved when an observer notification from the
|
||||
* search service fires with the specified data.
|
||||
*
|
||||
* @param aExpectedData
|
||||
* The value the observer notification sends that causes us to resolve
|
||||
* the promise.
|
||||
*/
|
||||
function waitForSearchNotification(aExpectedData, aCallback) {
|
||||
const SEARCH_SERVICE_TOPIC = "browser-search-service";
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
|
||||
if (aData != aExpectedData)
|
||||
return;
|
||||
|
||||
Services.obs.removeObserver(observer, SEARCH_SERVICE_TOPIC);
|
||||
aCallback();
|
||||
}, SEARCH_SERVICE_TOPIC);
|
||||
}
|
||||
|
||||
function asyncInit() {
|
||||
return new Promise(resolve => {
|
||||
Services.search.init(function() {
|
||||
ok(Services.search.isInitialized, "search service should be initialized");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function asyncReInit() {
|
||||
let promise = new Promise(resolve => {
|
||||
waitForSearchNotification("reinit-complete", resolve);
|
||||
});
|
||||
|
||||
Services.search.QueryInterface(Ci.nsIObserver)
|
||||
.observe(null, "intl:requested-locales-changed", null);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
let gEngineCount;
|
||||
|
||||
add_task(async function preparation() {
|
||||
// ContentSearch is interferring with our async re-initializations of the
|
||||
// search service: once _initServicePromise has resolved, it will access
|
||||
// the search service, thus causing unpredictable behavior due to
|
||||
// synchronous initializations of the service.
|
||||
let originalContentSearchPromise = ContentSearch._initServicePromise;
|
||||
ContentSearch._initServicePromise = new Promise(resolve => {
|
||||
registerCleanupFunction(() => {
|
||||
ContentSearch._initServicePromise = originalContentSearchPromise;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await asyncInit();
|
||||
gEngineCount = Services.search.getVisibleEngines().length;
|
||||
|
||||
waitForSearchNotification("uninit-complete", () => {
|
||||
// Verify search service is not initialized
|
||||
is(Services.search.isInitialized, false, "Search service should NOT be initialized");
|
||||
|
||||
removeCacheFile();
|
||||
|
||||
// Make sure we get the new country/region values, but save the old
|
||||
originalCountryCode = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "countryCode");
|
||||
originalRegion = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "region");
|
||||
Services.prefs.clearUserPref(BROWSER_SEARCH_PREF + "countryCode");
|
||||
Services.prefs.clearUserPref(BROWSER_SEARCH_PREF + "region");
|
||||
|
||||
// Geo specific defaults won't be fetched if there's no country code.
|
||||
Services.prefs.setCharPref("browser.search.geoip.url",
|
||||
'data:application/json,{"country_code": "US"}');
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", true);
|
||||
|
||||
// Avoid going to the server for the geo lookup. We take the defaults
|
||||
originalGeoURL = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + kUrlPref);
|
||||
let geoUrl = "data:application/json,{}";
|
||||
Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).setCharPref(kUrlPref, geoUrl);
|
||||
});
|
||||
|
||||
await asyncReInit();
|
||||
|
||||
await new Promise(resolve => {
|
||||
waitForSearchNotification("write-cache-to-disk-complete", resolve);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function tests() {
|
||||
let engine = Services.search.getEngineByName("Google");
|
||||
ok(engine, "Google");
|
||||
|
||||
let base = "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8";
|
||||
|
||||
let url;
|
||||
|
||||
// Test search URLs (including purposes).
|
||||
url = engine.getSubmission("foo", null, "contextmenu").uri.spec;
|
||||
is(url, base, "Check context menu search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "keyword").uri.spec;
|
||||
is(url, base, "Check keyword search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "searchbar").uri.spec;
|
||||
is(url, base, "Check search bar search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "homepage").uri.spec;
|
||||
is(url, base, "Check homepage search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "newtab").uri.spec;
|
||||
is(url, base, "Check newtab search URL for 'foo'");
|
||||
url = engine.getSubmission("foo", null, "system").uri.spec;
|
||||
is(url, base, "Check system search URL for 'foo'");
|
||||
});
|
||||
|
||||
|
||||
add_task(async function cleanup() {
|
||||
waitForSearchNotification("uninit-complete", () => {
|
||||
// Verify search service is not initialized
|
||||
is(Services.search.isInitialized, false,
|
||||
"Search service should NOT be initialized");
|
||||
removeCacheFile();
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.geoip.url");
|
||||
|
||||
Services.prefs.setCharPref(BROWSER_SEARCH_PREF + "countryCode", originalCountryCode);
|
||||
Services.prefs.setCharPref(BROWSER_SEARCH_PREF + "region", originalRegion);
|
||||
|
||||
// We can't clear the pref because it's set to false by testing/profiles/prefs_general.js
|
||||
Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", false);
|
||||
|
||||
Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).setCharPref(kUrlPref, originalGeoURL);
|
||||
});
|
||||
|
||||
await asyncReInit();
|
||||
is(gEngineCount, Services.search.getVisibleEngines().length,
|
||||
"correct engine count after cleanup");
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
prefs =
|
||||
browser.search.countryCode='DE'
|
||||
|
||||
[../browser_google.js]
|
||||
skip-if = artifact # bug 1315953
|
||||
[../browser_google_behavior.js]
|
||||
skip-if = artifact # bug 1315953
|
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
prefs =
|
||||
browser.search.countryCode='RU'
|
||||
|
||||
[../browser_google.js]
|
||||
skip-if = artifact # bug 1315953
|
||||
[../browser_google_behavior.js]
|
||||
skip-if = artifact # bug 1315953
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# safeguard below
|
||||
|
||||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# safeguard below
|
||||
|
||||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# safeguard below
|
||||
|
||||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ for platform in all_platforms:
|
|||
'ac_add_options --enable-official-branding',
|
||||
'export BUILDING_RELEASE=1',
|
||||
'if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then',
|
||||
'MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}',
|
||||
'MOZ_AUTOMATION_UPDATE_PACKAGING=1',
|
||||
'fi',
|
||||
]
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
# MinGW does not have (or need) makecab
|
||||
unset MAKECAB
|
||||
|
||||
# These aren't supported on mingw at this time
|
||||
# Bug 1393817
|
||||
MOZ_AUTOMATION_L10N_CHECK=0
|
||||
|
||||
# Sets:
|
||||
# build/mozconfig.common
|
||||
# AUTOCLOBBER=1
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# safeguard below
|
||||
|
||||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# safeguard below
|
||||
|
||||
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=1
|
||||
fi
|
||||
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
},
|
||||
"regionOverrides": {
|
||||
"US": {
|
||||
"google": "google-nocodes"
|
||||
"google": "google-2018"
|
||||
},
|
||||
"CA": {
|
||||
"google": "google-nocodes",
|
||||
"ebay": "ebay-ca",
|
||||
"ebay-fr": "ebay-ca"
|
||||
},
|
||||
|
@ -28,12 +27,6 @@
|
|||
"CN": {
|
||||
"google": "google-nocodes"
|
||||
},
|
||||
"TW": {
|
||||
"google": "google-nocodes"
|
||||
},
|
||||
"HK": {
|
||||
"google": "google-nocodes"
|
||||
},
|
||||
"AT": {
|
||||
"ebay-de": "ebay-at"
|
||||
},
|
||||
|
|
|
@ -41,7 +41,7 @@ def GeckoBinary(linkage='dependent', mozglue=None):
|
|||
if mozglue == 'program':
|
||||
USE_LIBS += ['mozglue']
|
||||
DEFINES['MOZ_HAS_MOZGLUE'] = True
|
||||
if CONFIG['MOZ_GLUE_IN_PROGRAM'] and CONFIG['GNU_CC']:
|
||||
if CONFIG['MOZ_GLUE_IN_PROGRAM'] and CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
LDFLAGS += ['-rdynamic']
|
||||
elif mozglue == 'library':
|
||||
LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True
|
||||
|
|
|
@ -24,7 +24,7 @@ gyp_vars.update({
|
|||
'include_pulse_audio': 1 if CONFIG['MOZ_PULSEAUDIO'] else 0,
|
||||
# basic stuff for everything
|
||||
'include_internal_video_render': 0,
|
||||
'clang': 1 if CONFIG['CLANG_CXX'] else 0,
|
||||
'clang': 1 if CONFIG['CC_TYPE'] == 'clang' else 0,
|
||||
'clang_use_chrome_plugins': 0,
|
||||
'enable_protobuf': 0,
|
||||
'include_tests': 0,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
if [ "x$IS_NIGHTLY" = "xyes" ]; then
|
||||
# Some nightlies (eg: Mulet) don't want these set.
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
|
||||
fi
|
||||
. "$topsrcdir/build/mozconfig.common"
|
||||
|
|
|
@ -46,7 +46,7 @@ FINAL_TARGET_PP_FILES += ['.gdbinit_python.in']
|
|||
OBJDIR_FILES += ['!/dist/bin/.gdbinit_python']
|
||||
|
||||
# Install the clang-cl runtime library for ASAN next to the binaries we produce.
|
||||
if CONFIG['MOZ_ASAN'] and CONFIG['CLANG_CL']:
|
||||
if CONFIG['MOZ_ASAN'] and CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
FINAL_TARGET_FILES += ['%' + CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']]
|
||||
|
||||
if CONFIG['LLVM_SYMBOLIZER']:
|
||||
|
|
|
@ -66,7 +66,7 @@ def rust_compiler(rustc_info, cargo_info):
|
|||
You can install rust by running './mach bootstrap'
|
||||
or by directly running the installer from https://rustup.rs/
|
||||
'''))
|
||||
rustc_min_version = Version('1.21.0')
|
||||
rustc_min_version = Version('1.22.1')
|
||||
cargo_min_version = Version('0.{}'.format(rustc_min_version.minor + 1))
|
||||
|
||||
version = rustc_info.version
|
||||
|
|
|
@ -17,6 +17,5 @@ mk_add_options "export MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-0}"
|
|||
mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}"
|
||||
mk_add_options "export MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES=${MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES-1}"
|
||||
mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}"
|
||||
mk_add_options "export MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-0}"
|
||||
|
||||
export MOZ_AUTOMATION_MOZCONFIG=1
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
if [ "x$IS_NIGHTLY" = "xyes" ]; then
|
||||
# Some nightlies (eg: Mulet) don't want these set.
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
|
||||
fi
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
%include build/sparse-profiles/mach
|
||||
|
||||
[include]
|
||||
path:toolkit/crashreporter/tools/upload_symbols.py
|
|
@ -1,6 +1,5 @@
|
|||
if [ "x$IS_NIGHTLY" = "xyes" ]; then
|
||||
# Some nightlies (eg: Mulet) don't want these set.
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
|
||||
fi
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ const URLs = new Map([
|
|||
["http://www.example2.com", true, true, true],
|
||||
["feed:http://www.example2.com", false, false, true],
|
||||
["https://www.example2.com", true, true, true],
|
||||
["moz-icon:file:///foo/bar/baz.exe", false, false, true],
|
||||
["moz-icon://.exe", false, false, true],
|
||||
["chrome://foo/content/bar.xul", false, false, true],
|
||||
["feed:chrome://foo/content/bar.xul", false, false, false],
|
||||
["view-source:http://www.example2.com", false, false, true],
|
||||
|
@ -70,6 +72,8 @@ const URLs = new Map([
|
|||
["http://www.example2.com", true, true, true],
|
||||
["feed:http://www.example2.com", true, true, true],
|
||||
["https://www.example2.com", true, true, true],
|
||||
["moz-icon:file:///foo/bar/baz.exe", false, false, true],
|
||||
["moz-icon://.exe", false, false, true],
|
||||
["feed:https://www.example2.com", true, true, true],
|
||||
["chrome://foo/content/bar.xul", false, false, true],
|
||||
["feed:chrome://foo/content/bar.xul", false, false, false],
|
||||
|
@ -92,6 +96,8 @@ const URLs = new Map([
|
|||
["http://www.example2.com", true, true, true],
|
||||
["feed:http://www.example2.com", false, false, true],
|
||||
["https://www.example2.com", true, true, true],
|
||||
["moz-icon:file:///foo/bar/baz.exe", false, false, true],
|
||||
["moz-icon://.exe", false, false, true],
|
||||
["feed:https://www.example2.com", false, false, true],
|
||||
["chrome://foo/content/bar.xul", false, false, true],
|
||||
["feed:chrome://foo/content/bar.xul", false, false, false],
|
||||
|
@ -128,6 +134,8 @@ const URLs = new Map([
|
|||
["about:test-content-linkable", true, true, true],
|
||||
|
||||
["about:test-unknown-linkable", true, true, true],
|
||||
["moz-icon:file:///foo/bar/baz.exe", true, true, true],
|
||||
["moz-icon://.exe", true, true, true],
|
||||
]],
|
||||
["about:test-unknown-unlinkable", [
|
||||
["about:test-chrome-privs", false, false, true],
|
||||
|
|
|
@ -60,7 +60,7 @@ else:
|
|||
else:
|
||||
DEFINES['EH_FRAME_FLAGS'] = '"a"'
|
||||
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
ASFLAGS += ['-clang-cl']
|
||||
|
||||
# Common source files.
|
||||
|
@ -76,7 +76,7 @@ else:
|
|||
ffi_srcs = ()
|
||||
if CONFIG['FFI_TARGET'] == 'ARM':
|
||||
ffi_srcs = ('sysv.S', 'ffi.c')
|
||||
if CONFIG['CLANG_CXX']:
|
||||
if CONFIG['CC_TYPE'] == 'clang':
|
||||
ASFLAGS += ['-no-integrated-as']
|
||||
elif CONFIG['FFI_TARGET'] == 'AARCH64':
|
||||
ffi_srcs = ('sysv.S', 'ffi.c')
|
||||
|
|
|
@ -11,7 +11,7 @@ DEFINES['U_COMMON_IMPLEMENTATION'] = True
|
|||
|
||||
LOCAL_INCLUDES += ['/intl/icu/source/i18n']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += [
|
||||
'-Wno-deprecated-declarations',
|
||||
'-Wno-type-limits',
|
||||
|
|
|
@ -27,7 +27,7 @@ if CONFIG['MOZ_DEBUG']:
|
|||
DEFINES['U_DEBUG'] = 1
|
||||
|
||||
# ICU requires RTTI
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-frtti']
|
||||
elif CONFIG['OS_TARGET'] == 'WINNT':
|
||||
CXXFLAGS += ['-GR']
|
||||
|
@ -37,7 +37,7 @@ AllowCompilerWarnings()
|
|||
|
||||
# We allow compiler warnings, but we can at least cut down on spammy
|
||||
# warnings that get triggered for every file.
|
||||
if CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'clang-cl':
|
||||
CFLAGS += [
|
||||
'-Wno-macro-redefined',
|
||||
'-Wno-microsoft-include',
|
||||
|
@ -47,7 +47,7 @@ if CONFIG['CLANG_CL']:
|
|||
'-Wno-microsoft-include',
|
||||
]
|
||||
|
||||
if CONFIG['_MSC_VER'] and not CONFIG['CLANG_CL']:
|
||||
if CONFIG['CC_TYPE'] == 'msvc':
|
||||
CFLAGS += [
|
||||
'-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition
|
||||
'-wd4996', # The compiler encountered a deprecated declaration.
|
||||
|
|
|
@ -35,7 +35,7 @@ PYTHON_UNITTEST_MANIFESTS += [
|
|||
'tests/python.ini',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CC'] and CONFIG['MOZ_OPTIMIZE']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc') and CONFIG['MOZ_OPTIMIZE']:
|
||||
CFLAGS += ['-O3']
|
||||
|
||||
HOST_DEFINES = {
|
||||
|
@ -46,9 +46,9 @@ HOST_DEFINES = {
|
|||
include('stl-headers.mozbuild')
|
||||
if CONFIG['WRAP_STL_INCLUDES']:
|
||||
stl_compiler = None
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
stl_compiler = 'gcc'
|
||||
elif CONFIG['_MSC_VER']:
|
||||
elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
|
||||
stl_compiler = 'msvc'
|
||||
|
||||
if stl_compiler:
|
||||
|
|
|
@ -94,7 +94,7 @@ elif CONFIG['HAVE_64BIT_BUILD']:
|
|||
DEFINES['SQLITE_TEMP_STORE'] = 2
|
||||
|
||||
# Suppress warnings in third-party code.
|
||||
if CONFIG['GNU_CC']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CFLAGS += [
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-type-limits',
|
||||
|
|
|
@ -1,345 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* global content, APP_SHUTDOWN */
|
||||
/* exported startup, shutdown, install, uninstall */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
|
||||
// MultiWindowKeyListener instance for Ctrl+Alt+R key
|
||||
let listener;
|
||||
// nsIURI to the addon root folder
|
||||
let resourceURI;
|
||||
|
||||
function actionOccurred(id) {
|
||||
let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
let Telemetry = require("devtools/client/shared/telemetry");
|
||||
let telemetry = new Telemetry();
|
||||
telemetry.actionOccurred(id);
|
||||
}
|
||||
|
||||
// Synchronously fetch the content of a given URL
|
||||
function readURI(uri) {
|
||||
let stream = NetUtil.newChannel({
|
||||
uri: NetUtil.newURI(uri, "UTF-8"),
|
||||
loadUsingSystemPrincipal: true}
|
||||
).open2();
|
||||
let count = stream.available();
|
||||
let data = NetUtil.readInputStreamToString(stream, count, {
|
||||
charset: "UTF-8"
|
||||
});
|
||||
|
||||
stream.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret the processing instructions contained in a preferences file, based on a
|
||||
* limited set of supported #if statements. After we ship as an addon, we don't want to
|
||||
* introduce anymore processing instructions, so all unrecognized preprocessing
|
||||
* instructions will be treated as an error.
|
||||
*
|
||||
* This function is mostly copied from devtools/client/inspector/webpack/prefs-loader.js
|
||||
*
|
||||
* @param {String} content
|
||||
* The string content of a preferences file.
|
||||
* @return {String} the content stripped of preprocessing instructions.
|
||||
*/
|
||||
function interpretPreprocessingInstructions(content) {
|
||||
const ifMap = {
|
||||
"#if MOZ_UPDATE_CHANNEL == beta": AppConstants.MOZ_UPDATE_CHANNEL === "beta",
|
||||
"#if defined(NIGHTLY_BUILD)": AppConstants.NIGHTLY_BUILD,
|
||||
"#ifdef MOZ_DEV_EDITION": AppConstants.MOZ_DEV_EDITION,
|
||||
"#ifdef RELEASE_OR_BETA": AppConstants.RELEASE_OR_BETA,
|
||||
};
|
||||
|
||||
let lines = content.split("\n");
|
||||
let ignoring = false;
|
||||
let newLines = [];
|
||||
let continuation = false;
|
||||
for (let line of lines) {
|
||||
if (line.startsWith("#if")) {
|
||||
if (!(line in ifMap)) {
|
||||
throw new Error("missing line in ifMap: " + line);
|
||||
}
|
||||
ignoring = !ifMap[line];
|
||||
} else if (line.startsWith("#else")) {
|
||||
ignoring = !ignoring;
|
||||
} else if (line.startsWith("#endif")) {
|
||||
ignoring = false;
|
||||
}
|
||||
|
||||
let isPrefLine = /^ *(sticky_)?pref\("([^"]+)"/.test(line);
|
||||
if (continuation || (!ignoring && isPrefLine)) {
|
||||
newLines.push(line);
|
||||
|
||||
// The call to pref(...); might span more than one line.
|
||||
continuation = !/\);/.test(line);
|
||||
}
|
||||
}
|
||||
return newLines.join("\n");
|
||||
}
|
||||
|
||||
// Read a preference file and set all of its defined pref as default values
|
||||
// (This replicates the behavior of preferences files from mozilla-central)
|
||||
function processPrefFile(url) {
|
||||
let content = readURI(url);
|
||||
content = interpretPreprocessingInstructions(content);
|
||||
content.match(/pref\("[^"]+",\s*.+\s*\)/g).forEach(item => {
|
||||
let m = item.match(/pref\("([^"]+)",\s*(.+)\s*\)/);
|
||||
let name = m[1];
|
||||
let val = m[2].trim();
|
||||
|
||||
// Prevent overriding prefs that have been changed by the user
|
||||
if (Services.prefs.prefHasUserValue(name)) {
|
||||
return;
|
||||
}
|
||||
let defaultBranch = Services.prefs.getDefaultBranch("");
|
||||
if ((val.startsWith("\"") && val.endsWith("\"")) ||
|
||||
(val.startsWith("'") && val.endsWith("'"))) {
|
||||
val = val.substr(1, val.length - 2);
|
||||
val = val.replace(/\\"/g, '"');
|
||||
defaultBranch.setCharPref(name, val);
|
||||
} else if (val.match(/[0-9]+/)) {
|
||||
defaultBranch.setIntPref(name, parseInt(val, 10));
|
||||
} else if (val == "true" || val == "false") {
|
||||
defaultBranch.setBoolPref(name, val == "true");
|
||||
} else {
|
||||
console.log("Unable to match preference type for value:", val);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setPrefs() {
|
||||
processPrefFile(resourceURI.spec + "./client/preferences/devtools.js");
|
||||
processPrefFile(resourceURI.spec + "./client/preferences/debugger.js");
|
||||
processPrefFile(resourceURI.spec + "./client/webide/webide-prefs.js");
|
||||
}
|
||||
|
||||
// Helper to listen to a key on all windows
|
||||
function MultiWindowKeyListener({ keyCode, ctrlKey, altKey, callback }) {
|
||||
let keyListener = function (event) {
|
||||
if (event.ctrlKey == !!ctrlKey &&
|
||||
event.altKey == !!altKey &&
|
||||
event.keyCode === keyCode) {
|
||||
callback(event);
|
||||
|
||||
// Call preventDefault to avoid duplicated events when
|
||||
// doing the key stroke within a tab.
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
let observer = function (window, topic, data) {
|
||||
// Listen on keyup to call keyListener only once per stroke
|
||||
if (topic === "domwindowopened") {
|
||||
window.addEventListener("keyup", keyListener);
|
||||
} else {
|
||||
window.removeEventListener("keyup", keyListener);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
start: function () {
|
||||
// Automatically process already opened windows
|
||||
let e = Services.ww.getWindowEnumerator();
|
||||
while (e.hasMoreElements()) {
|
||||
let window = e.getNext();
|
||||
observer(window, "domwindowopened", null);
|
||||
}
|
||||
// And listen for new ones to come
|
||||
Services.ww.registerNotification(observer);
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
let e = Services.ww.getWindowEnumerator();
|
||||
while (e.hasMoreElements()) {
|
||||
let window = e.getNext();
|
||||
observer(window, "domwindowclosed", null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let getTopLevelWindow = function (window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
};
|
||||
|
||||
function unload(reason) {
|
||||
// This frame script is going to be executed in all processes:
|
||||
// parent and child
|
||||
Services.ppmm.loadProcessScript("data:,(" + function (scriptReason) {
|
||||
/* Flush message manager cached frame scripts as well as chrome locales */
|
||||
let obs = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
obs.notifyObservers(null, "message-manager-flush-caches");
|
||||
|
||||
/* Also purge cached modules in child processes, we do it a few lines after
|
||||
in the parent process */
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
Services.obs.notifyObservers(null, "devtools-unload", scriptReason);
|
||||
}
|
||||
} + ")(\"" + reason.replace(/"/g, '\\"') + "\")", false);
|
||||
|
||||
// As we can't get a reference to existing Loader.jsm instances, we send them
|
||||
// an observer service notification to unload them.
|
||||
Services.obs.notifyObservers(null, "devtools-unload", reason);
|
||||
|
||||
// Then spawn a brand new Loader.jsm instance and start the main module
|
||||
Cu.unload("resource://devtools/shared/Loader.jsm");
|
||||
// Also unload all resources loaded as jsm, hopefully all of them are going
|
||||
// to be converted into regular modules
|
||||
Cu.unload("resource://devtools/client/shared/browser-loader.js");
|
||||
Cu.unload("resource://devtools/client/framework/ToolboxProcess.jsm");
|
||||
Cu.unload("resource://devtools/shared/apps/Devices.jsm");
|
||||
Cu.unload("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
|
||||
Cu.unload("resource://devtools/shared/Parser.jsm");
|
||||
Cu.unload("resource://devtools/client/shared/DOMHelpers.jsm");
|
||||
Cu.unload("resource://devtools/client/shared/widgets/VariablesView.jsm");
|
||||
Cu.unload("resource://devtools/client/shared/widgets/AbstractTreeItem.jsm");
|
||||
Cu.unload("resource://devtools/shared/deprecated-sync-thenables.js");
|
||||
}
|
||||
|
||||
function reload(event) {
|
||||
// We automatically reload the toolbox if we are on a browser tab
|
||||
// with a toolbox already opened
|
||||
let reloadToolbox = false;
|
||||
if (event) {
|
||||
let top = getTopLevelWindow(event.view);
|
||||
let isBrowser = top.location.href.includes("/browser.xul");
|
||||
if (isBrowser && top.gBrowser) {
|
||||
// We do not use any devtools code before the call to Loader.jsm reload as
|
||||
// any attempt to use Loader.jsm to load a module will instanciate a new
|
||||
// Loader.
|
||||
let nbox = top.gBrowser.getNotificationBox();
|
||||
reloadToolbox =
|
||||
top.document.getAnonymousElementByAttribute(nbox, "class",
|
||||
"devtools-toolbox-bottom-iframe") ||
|
||||
top.document.getAnonymousElementByAttribute(nbox, "class",
|
||||
"devtools-toolbox-side-iframe") ||
|
||||
Services.wm.getMostRecentWindow("devtools:toolbox");
|
||||
}
|
||||
}
|
||||
let browserConsole = Services.wm.getMostRecentWindow("devtools:webconsole");
|
||||
let reopenBrowserConsole = false;
|
||||
if (browserConsole) {
|
||||
browserConsole.close();
|
||||
reopenBrowserConsole = true;
|
||||
}
|
||||
|
||||
dump("Reload DevTools. (reload-toolbox:" + reloadToolbox + ")\n");
|
||||
|
||||
// Invalidate xul cache in order to see changes made to chrome:// files
|
||||
Services.obs.notifyObservers(null, "startupcache-invalidate");
|
||||
|
||||
unload("reload");
|
||||
|
||||
// Update the preferences before starting new code
|
||||
setPrefs();
|
||||
|
||||
const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
devtools.require("devtools/client/framework/devtools-browser");
|
||||
|
||||
// Go over all top level windows to reload all devtools related things
|
||||
let windowsEnum = Services.wm.getEnumerator(null);
|
||||
while (windowsEnum.hasMoreElements()) {
|
||||
let window = windowsEnum.getNext();
|
||||
let windowtype = window.document.documentElement.getAttribute("windowtype");
|
||||
if (windowtype == "navigator:browser" && window.gBrowser) {
|
||||
// Enumerate tabs on firefox windows
|
||||
for (let tab of window.gBrowser.tabs) {
|
||||
let browser = tab.linkedBrowser;
|
||||
let location = browser.documentURI.spec;
|
||||
let mm = browser.messageManager;
|
||||
// To reload JSON-View tabs and any devtools document
|
||||
if (location.startsWith("about:debugging") ||
|
||||
location.startsWith("chrome://devtools/")) {
|
||||
browser.reload();
|
||||
}
|
||||
// We have to use a frame script to query "baseURI"
|
||||
mm.loadFrameScript("data:text/javascript,new " + function () {
|
||||
let isJSONView =
|
||||
content.document.baseURI.startsWith("resource://devtools/");
|
||||
if (isJSONView) {
|
||||
content.location.reload();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
} else if (windowtype === "devtools:webide") {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
if (reloadToolbox) {
|
||||
// Reopen the toolbox automatically if we are reloading from toolbox
|
||||
// shortcut and are on a browser window.
|
||||
// Wait for a second before opening the toolbox to avoid races
|
||||
// between the old and the new one.
|
||||
let {setTimeout} = Cu.import("resource://gre/modules/Timer.jsm", {});
|
||||
setTimeout(() => {
|
||||
let { TargetFactory } = devtools.require("devtools/client/framework/target");
|
||||
let { gDevTools } = devtools.require("devtools/client/framework/devtools");
|
||||
let top = getTopLevelWindow(event.view);
|
||||
let target = TargetFactory.forTab(top.gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Browser console document can't just be reloaded.
|
||||
// HUDService is going to close it on unload.
|
||||
// Instead we have to manually toggle it.
|
||||
if (reopenBrowserConsole) {
|
||||
let {HUDService} = devtools.require("devtools/client/webconsole/hudservice");
|
||||
HUDService.toggleBrowserConsole();
|
||||
}
|
||||
|
||||
actionOccurred("reloadAddonReload");
|
||||
}
|
||||
|
||||
function startup(data) {
|
||||
dump("DevTools addon started.\n");
|
||||
|
||||
resourceURI = data.resourceURI;
|
||||
|
||||
listener = new MultiWindowKeyListener({
|
||||
keyCode: Ci.nsIDOMKeyEvent.DOM_VK_R, ctrlKey: true, altKey: true,
|
||||
callback: reload
|
||||
});
|
||||
listener.start();
|
||||
|
||||
reload();
|
||||
}
|
||||
function shutdown(data, reason) {
|
||||
// On browser shutdown, do not try to cleanup anything
|
||||
if (reason == APP_SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener.stop();
|
||||
listener = null;
|
||||
|
||||
unload("disable");
|
||||
}
|
||||
function install() {
|
||||
try {
|
||||
actionOccurred("reloadAddonInstalled");
|
||||
} catch (e) {
|
||||
// When installing on Firefox builds without devtools, telemetry doesn't
|
||||
// work yet and throws.
|
||||
}
|
||||
}
|
||||
function uninstall() {}
|
|
@ -1,9 +0,0 @@
|
|||
content devtools client/
|
||||
skin devtools classic/1.0 client/themes/
|
||||
resource devtools .
|
||||
locale devtools en-US client/locales/en-US/
|
||||
locale devtools-shared en-US shared/locales/en-US/
|
||||
locale devtools-shim en-US shim/locales/en-US/
|
||||
|
||||
content webide client/webide/content/
|
||||
skin webide classic/1.0 client/webide/themes/
|
|
@ -49,10 +49,6 @@ Object.defineProperty(this, "browser", {
|
|||
* same lifetime as the browser.
|
||||
*/
|
||||
let gDevToolsMethods = [
|
||||
// Used by the reload addon.
|
||||
// Force reloading dependencies if the loader happens to have reloaded.
|
||||
"reload",
|
||||
|
||||
// Used by: - b2g desktop.js
|
||||
// - nsContextMenu
|
||||
// - /devtools code
|
||||
|
@ -139,7 +135,7 @@ let gDevToolsBrowserMethods = [
|
|||
// Used by browser.js
|
||||
"registerBrowserWindow",
|
||||
|
||||
// Used by reload addon
|
||||
// Used by devtools-browser.js for the Toggle Toolbox status
|
||||
"hasToolboxOpened",
|
||||
|
||||
// Used by browser.js
|
||||
|
|
|
@ -173,12 +173,6 @@ Telemetry.prototype = {
|
|||
histogram: "DEVTOOLS_CUSTOM_OPENED_COUNT",
|
||||
timerHistogram: "DEVTOOLS_CUSTOM_TIME_ACTIVE_SECONDS"
|
||||
},
|
||||
reloadAddonInstalled: {
|
||||
histogram: "DEVTOOLS_RELOAD_ADDON_INSTALLED_COUNT",
|
||||
},
|
||||
reloadAddonReload: {
|
||||
histogram: "DEVTOOLS_RELOAD_ADDON_RELOAD_COUNT",
|
||||
},
|
||||
gridInspectorShowGridAreasOverlayChecked: {
|
||||
scalar: "devtools.grid.showGridAreasOverlay.checked",
|
||||
},
|
||||
|
|
|
@ -227,12 +227,23 @@ function enableNetProvider(hud) {
|
|||
}
|
||||
}
|
||||
|
||||
// Process all incoming HTTP details packets.
|
||||
// Process all incoming HTTP details packets. Note that
|
||||
// Network event update packets are sent in batches from:
|
||||
// `NewConsoleOutputWrapper.dispatchMessageUpdate` using
|
||||
// NETWORK_MESSAGE_UPDATE action.
|
||||
// Make sure to call `dataProvider.onNetworkEventUpdate`
|
||||
// to fetch data from the backend.
|
||||
if (type == NETWORK_MESSAGE_UPDATE) {
|
||||
let actor = action.response.networkInfo.actor;
|
||||
let open = getAllMessagesUiById(state).includes(actor);
|
||||
if (open) {
|
||||
dataProvider.onNetworkEventUpdate(null, action.response);
|
||||
let message = getMessage(state, actor);
|
||||
message.updates.forEach(updateType => {
|
||||
dataProvider.onNetworkEventUpdate(null, {
|
||||
packet: { updateType },
|
||||
networkInfo: message,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ support-files =
|
|||
code_bundle_nosource.js
|
||||
code_bundle_nosource.js.map
|
||||
head.js
|
||||
sjs_slow-response-test-server.sjs
|
||||
source-mapped.css
|
||||
source-mapped.css.map
|
||||
source-mapped.scss
|
||||
|
@ -212,6 +213,8 @@ skip-if = true # Bug 1403188
|
|||
[browser_jsterm_autocomplete-properties-with-non-alphanumeric-names.js]
|
||||
[browser_jsterm_completion.js]
|
||||
[browser_jsterm_copy_command.js]
|
||||
[browser_jsterm_ctrl_key_nav.js]
|
||||
skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
|
||||
[browser_jsterm_dollar.js]
|
||||
[browser_jsterm_history.js]
|
||||
[browser_jsterm_history_persist.js]
|
||||
|
@ -264,9 +267,6 @@ skip-if = (e10s && debug) || (e10s && os == 'win') # Bug 1221499 enabled these o
|
|||
[browser_webconsole_cspro.js]
|
||||
skip-if = true # Bug 1408932
|
||||
# old console skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243967
|
||||
[browser_webconsole_ctrl_key_nav.js]
|
||||
skip-if = true # Bug 1408933
|
||||
# old console skip-if = os != "mac"
|
||||
[browser_webconsole_document_focus.js]
|
||||
skip-if = true # Bug 1404368
|
||||
[browser_webconsole_duplicate_errors.js]
|
||||
|
|
|
@ -5,46 +5,39 @@
|
|||
|
||||
// Test navigation of webconsole contents via ctrl-a, ctrl-e, ctrl-p, ctrl-n
|
||||
// see https://bugzilla.mozilla.org/show_bug.cgi?id=804845
|
||||
//
|
||||
// The shortcuts tested here have platform limitations:
|
||||
// - ctrl-e does not work on windows,
|
||||
// - ctrl-a, ctrl-p and ctrl-n only work on OSX
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
|
||||
"bug 804845 and bug 619598";
|
||||
|
||||
var jsterm, inputNode;
|
||||
add_task(async function () {
|
||||
const {jsterm} = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
add_task(function* () {
|
||||
yield loadTab(TEST_URI);
|
||||
|
||||
let hud = yield openConsole();
|
||||
|
||||
doTests(hud);
|
||||
|
||||
jsterm = inputNode = null;
|
||||
});
|
||||
|
||||
function doTests(HUD) {
|
||||
jsterm = HUD.jsterm;
|
||||
inputNode = jsterm.inputNode;
|
||||
ok(!jsterm.getInputValue(), "jsterm.getInputValue() is empty");
|
||||
is(jsterm.inputNode.selectionStart, 0);
|
||||
is(jsterm.inputNode.selectionEnd, 0);
|
||||
|
||||
testSingleLineInputNavNoHistory();
|
||||
testMultiLineInputNavNoHistory();
|
||||
testNavWithHistory();
|
||||
}
|
||||
testSingleLineInputNavNoHistory(jsterm);
|
||||
testMultiLineInputNavNoHistory(jsterm);
|
||||
testNavWithHistory(jsterm);
|
||||
});
|
||||
|
||||
function testSingleLineInputNavNoHistory() {
|
||||
function testSingleLineInputNavNoHistory(jsterm) {
|
||||
let inputNode = jsterm.inputNode;
|
||||
// Single char input
|
||||
EventUtils.synthesizeKey("1", {});
|
||||
is(inputNode.selectionStart, 1, "caret location after single char input");
|
||||
|
||||
// nav to start/end with ctrl-a and ctrl-e;
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
synthesizeLineStartKey();
|
||||
is(inputNode.selectionStart, 0,
|
||||
"caret location after single char input and ctrl-a");
|
||||
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
synthesizeLineEndKey();
|
||||
is(inputNode.selectionStart, 1,
|
||||
"caret location after single char input and ctrl-e");
|
||||
|
||||
|
@ -58,34 +51,35 @@ function testSingleLineInputNavNoHistory() {
|
|||
is(inputNode.selectionStart, 2,
|
||||
"caret location after two char input and VK_DOWN");
|
||||
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
synthesizeLineStartKey();
|
||||
is(inputNode.selectionStart, 0,
|
||||
"move caret to beginning of 2 char input with ctrl-a");
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
synthesizeLineStartKey();
|
||||
is(inputNode.selectionStart, 0,
|
||||
"no change of caret location on repeat ctrl-a");
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(inputNode.selectionStart, 0,
|
||||
"no change of caret location on ctrl-p from beginning of line");
|
||||
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
synthesizeLineEndKey();
|
||||
is(inputNode.selectionStart, 2,
|
||||
"move caret to end of 2 char input with ctrl-e");
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
synthesizeLineEndKey();
|
||||
is(inputNode.selectionStart, 2,
|
||||
"no change of caret location on repeat ctrl-e");
|
||||
EventUtils.synthesizeKey("n", { ctrlKey: true });
|
||||
synthesizeLineDownKey();
|
||||
is(inputNode.selectionStart, 2,
|
||||
"no change of caret location on ctrl-n from end of line");
|
||||
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(inputNode.selectionStart, 0, "ctrl-p moves to start of line");
|
||||
|
||||
EventUtils.synthesizeKey("n", { ctrlKey: true });
|
||||
synthesizeLineDownKey();
|
||||
is(inputNode.selectionStart, 2, "ctrl-n moves to end of line");
|
||||
}
|
||||
|
||||
function testMultiLineInputNavNoHistory() {
|
||||
function testMultiLineInputNavNoHistory(jsterm) {
|
||||
let inputNode = jsterm.inputNode;
|
||||
let lineValues = ["one", "2", "something longer", "", "", "three!"];
|
||||
jsterm.setInputValue("");
|
||||
// simulate shift-return
|
||||
|
@ -113,43 +107,43 @@ function testMultiLineInputNavNoHistory() {
|
|||
"down arrow from within multiline");
|
||||
|
||||
// navigate up through input lines
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(jsterm.getInputValue().slice(inputNode.selectionStart), expectedStringAfterCarat,
|
||||
"ctrl-p from end of multiline");
|
||||
|
||||
for (let i = 4; i >= 0; i--) {
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
expectedStringAfterCarat = lineValues[i] + newlineString +
|
||||
expectedStringAfterCarat;
|
||||
is(jsterm.getInputValue().slice(inputNode.selectionStart),
|
||||
expectedStringAfterCarat, "ctrl-p from within line " + i +
|
||||
" of multiline input");
|
||||
}
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(inputNode.selectionStart, 0, "reached start of input");
|
||||
is(jsterm.getInputValue(), inputValue,
|
||||
"no change to multiline input on ctrl-p from beginning of multiline");
|
||||
|
||||
// navigate to end of first line
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
synthesizeLineEndKey();
|
||||
let caretPos = inputNode.selectionStart;
|
||||
let expectedStringBeforeCarat = lineValues[0];
|
||||
is(jsterm.getInputValue().slice(0, caretPos), expectedStringBeforeCarat,
|
||||
"ctrl-e into multiline input");
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
synthesizeLineEndKey();
|
||||
is(inputNode.selectionStart, caretPos,
|
||||
"repeat ctrl-e doesn't change caret position in multiline input");
|
||||
|
||||
// navigate down one line; ctrl-a to the beginning; ctrl-e to end
|
||||
for (let i = 1; i < lineValues.length; i++) {
|
||||
EventUtils.synthesizeKey("n", { ctrlKey: true });
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
synthesizeLineDownKey();
|
||||
synthesizeLineStartKey();
|
||||
caretPos = inputNode.selectionStart;
|
||||
expectedStringBeforeCarat += newlineString;
|
||||
is(jsterm.getInputValue().slice(0, caretPos), expectedStringBeforeCarat,
|
||||
"ctrl-a to beginning of line " + (i + 1) + " in multiline input");
|
||||
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
synthesizeLineEndKey();
|
||||
caretPos = inputNode.selectionStart;
|
||||
expectedStringBeforeCarat += lineValues[i];
|
||||
is(jsterm.getInputValue().slice(0, caretPos), expectedStringBeforeCarat,
|
||||
|
@ -157,13 +151,17 @@ function testMultiLineInputNavNoHistory() {
|
|||
}
|
||||
}
|
||||
|
||||
function testNavWithHistory() {
|
||||
function testNavWithHistory(jsterm) {
|
||||
let inputNode = jsterm.inputNode;
|
||||
|
||||
// NOTE: Tests does NOT currently define behaviour for ctrl-p/ctrl-n with
|
||||
// caret placed _within_ single line input
|
||||
let values = ['"single line input"',
|
||||
'"a longer single-line input to check caret repositioning"',
|
||||
['"multi-line"', '"input"', '"here!"'].join("\n"),
|
||||
];
|
||||
let values = [
|
||||
'"single line input"',
|
||||
'"a longer single-line input to check caret repositioning"',
|
||||
'"multi-line"\n"input"\n"here!"',
|
||||
];
|
||||
|
||||
// submit to history
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
jsterm.setInputValue(values[i]);
|
||||
|
@ -171,7 +169,7 @@ function testNavWithHistory() {
|
|||
}
|
||||
is(inputNode.selectionStart, 0, "caret location at start of empty line");
|
||||
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(inputNode.selectionStart, values[values.length - 1].length,
|
||||
"caret location correct at end of last history input");
|
||||
|
||||
|
@ -180,20 +178,21 @@ function testNavWithHistory() {
|
|||
let match = values[i].match(/(\n)/g);
|
||||
if (match) {
|
||||
// multi-line inputs won't update from history unless caret at beginning
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
synthesizeLineStartKey();
|
||||
for (let j = 0; j < match.length; j++) {
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
}
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
} else {
|
||||
// single-line inputs will update from history from end of line
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
}
|
||||
is(jsterm.getInputValue(), values[i - 1],
|
||||
"ctrl-p updates inputNode from backwards history values[" + i - 1 + "]");
|
||||
}
|
||||
|
||||
let inputValue = jsterm.getInputValue();
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(inputNode.selectionStart, 0,
|
||||
"ctrl-p at beginning of history moves caret location to beginning " +
|
||||
"of line");
|
||||
|
@ -202,13 +201,13 @@ function testNavWithHistory() {
|
|||
|
||||
// Navigate forwards history with ctrl-n
|
||||
for (let i = 1; i < values.length; i++) {
|
||||
EventUtils.synthesizeKey("n", { ctrlKey: true });
|
||||
synthesizeLineDownKey();
|
||||
is(jsterm.getInputValue(), values[i],
|
||||
"ctrl-n updates inputNode from forwards history values[" + i + "]");
|
||||
is(inputNode.selectionStart, values[i].length,
|
||||
"caret location correct at end of history input for values[" + i + "]");
|
||||
}
|
||||
EventUtils.synthesizeKey("n", { ctrlKey: true });
|
||||
synthesizeLineDownKey();
|
||||
ok(!jsterm.getInputValue(), "ctrl-n at end of history updates to empty input");
|
||||
|
||||
// Simulate editing multi-line
|
||||
|
@ -216,12 +215,28 @@ function testNavWithHistory() {
|
|||
jsterm.setInputValue(inputValue);
|
||||
|
||||
// Attempt nav within input
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineUpKey();
|
||||
is(jsterm.getInputValue(), inputValue,
|
||||
"ctrl-p from end of multi-line does not trigger history");
|
||||
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
synthesizeLineStartKey();
|
||||
synthesizeLineUpKey();
|
||||
is(jsterm.getInputValue(), values[values.length - 1],
|
||||
"ctrl-p from start of multi-line triggers history");
|
||||
}
|
||||
|
||||
function synthesizeLineStartKey() {
|
||||
EventUtils.synthesizeKey("a", { ctrlKey: true });
|
||||
}
|
||||
|
||||
function synthesizeLineEndKey() {
|
||||
EventUtils.synthesizeKey("e", { ctrlKey: true });
|
||||
}
|
||||
|
||||
function synthesizeLineUpKey() {
|
||||
EventUtils.synthesizeKey("p", { ctrlKey: true });
|
||||
}
|
||||
|
||||
function synthesizeLineDownKey() {
|
||||
EventUtils.synthesizeKey("n", { ctrlKey: true });
|
||||
}
|
|
@ -17,53 +17,189 @@ registerCleanupFunction(() => {
|
|||
Services.prefs.clearUserPref(XHR_PREF);
|
||||
});
|
||||
|
||||
let tabs = [{
|
||||
id: "headers",
|
||||
testEmpty: testEmptyHeaders,
|
||||
testContent: testHeaders,
|
||||
}, {
|
||||
id: "cookies",
|
||||
testEmpty: testEmptyCookies,
|
||||
testContent: testCookies,
|
||||
}, {
|
||||
id: "params",
|
||||
testEmpty: testEmptyParams,
|
||||
testContent: testParams,
|
||||
}, {
|
||||
id: "response",
|
||||
testEmpty: testEmptyResponse,
|
||||
testContent: testResponse,
|
||||
}, {
|
||||
id: "timings",
|
||||
testEmpty: testEmptyTimings,
|
||||
testContent: testTimings,
|
||||
}, {
|
||||
id: "stack-trace",
|
||||
testEmpty: testEmptyStackTrace,
|
||||
testContent: testStackTrace,
|
||||
}];
|
||||
|
||||
/**
|
||||
* Main test for checking HTTP logs in the Console panel.
|
||||
*/
|
||||
add_task(async function task() {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
const currentTab = gBrowser.selectedTab;
|
||||
let target = TargetFactory.forTab(currentTab);
|
||||
|
||||
// Execute XHR and expand it after all network
|
||||
// update events are received. Consequently,
|
||||
// check out content of all (HTTP details) tabs.
|
||||
await openRequestAfterUpdates(target, hud);
|
||||
|
||||
// Test proper UI update when request is opened.
|
||||
// For every tab (with HTTP details):
|
||||
// 1. Execute long-time request
|
||||
// 2. Expand the net log before the request finishes (set default tab)
|
||||
// 3. Check the default tab empty content
|
||||
// 4. Wait till the request finishes
|
||||
// 5. Check content of all tabs
|
||||
for (let tab of tabs) {
|
||||
await openRequestBeforeUpdates(target, hud, tab);
|
||||
}
|
||||
});
|
||||
|
||||
async function openRequestAfterUpdates(target, hud) {
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
let xhrUrl = TEST_PATH + "sjs_slow-response-test-server.sjs";
|
||||
let message = waitForMessage(hud, xhrUrl);
|
||||
|
||||
// Fire an XHR POST request.
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
|
||||
content.wrappedJSObject.testXhrPost();
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
|
||||
content.wrappedJSObject.testXhrPostSlowResponse();
|
||||
});
|
||||
|
||||
info("XHR executed");
|
||||
let { node: messageNode } = await message;
|
||||
|
||||
info("Network message found.");
|
||||
|
||||
await waitForRequestUpdates(toolbox);
|
||||
|
||||
let xhrUrl = TEST_PATH + "test-data.json";
|
||||
let messageNode = await waitFor(() => findMessage(hud, xhrUrl));
|
||||
let urlNode = messageNode.querySelector(".url");
|
||||
info("Network message found.");
|
||||
|
||||
let updates = waitForPayloadReady(toolbox);
|
||||
let payload = waitForPayloadReady(toolbox);
|
||||
|
||||
// Expand network log
|
||||
let urlNode = messageNode.querySelector(".url");
|
||||
urlNode.click();
|
||||
|
||||
await payload;
|
||||
await testNetworkMessage(toolbox, messageNode);
|
||||
}
|
||||
|
||||
async function openRequestBeforeUpdates(target, hud, tab) {
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
hud.jsterm.clearOutput(true);
|
||||
|
||||
let xhrUrl = TEST_PATH + "sjs_slow-response-test-server.sjs";
|
||||
let message = waitForMessage(hud, xhrUrl);
|
||||
|
||||
// Fire an XHR POST request.
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
|
||||
content.wrappedJSObject.testXhrPostSlowResponse();
|
||||
});
|
||||
|
||||
let { node: messageNode } = await message;
|
||||
|
||||
info("Network message found.");
|
||||
|
||||
let updates = waitForRequestUpdates(toolbox);
|
||||
let payload = waitForPayloadReady(toolbox);
|
||||
|
||||
// Set the default panel.
|
||||
const state = hud.ui.newConsoleOutput.getStore().getState();
|
||||
state.ui.networkMessageActiveTabId = tab.id;
|
||||
|
||||
// Expand network log
|
||||
let urlNode = messageNode.querySelector(".url");
|
||||
urlNode.click();
|
||||
|
||||
// Make sure the current tab is the expected one.
|
||||
let currentTab = messageNode.querySelector(`#${tab.id}-tab`);
|
||||
is(currentTab.getAttribute("aria-selected"), "true",
|
||||
"The correct tab is selected");
|
||||
|
||||
// The tab should be empty now.
|
||||
tab.testEmpty(messageNode);
|
||||
|
||||
// Wait till all updates and payload are received.
|
||||
await updates;
|
||||
await testNetworkMessage(messageNode);
|
||||
});
|
||||
await payload;
|
||||
|
||||
async function testNetworkMessage(messageNode) {
|
||||
// Test content of the default tab.
|
||||
await tab.testContent(messageNode);
|
||||
|
||||
// Test all tabs in the network log.
|
||||
await testNetworkMessage(toolbox, messageNode);
|
||||
}
|
||||
|
||||
// Panel testing helpers
|
||||
|
||||
async function testNetworkMessage(toolbox, messageNode) {
|
||||
await testHeaders(messageNode);
|
||||
await testCookies(messageNode);
|
||||
await testParams(messageNode);
|
||||
await testResponse(messageNode);
|
||||
await testTimings(messageNode);
|
||||
await testStackTrace(messageNode);
|
||||
await waitForLazyRequests(toolbox);
|
||||
}
|
||||
|
||||
// Headers
|
||||
|
||||
function testEmptyHeaders(messageNode) {
|
||||
let emptyNotice = messageNode.querySelector("#headers-panel .empty-notice");
|
||||
ok(emptyNotice, "Headers tab is empty");
|
||||
}
|
||||
|
||||
async function testHeaders(messageNode) {
|
||||
let headersTab = messageNode.querySelector("#headers-tab");
|
||||
let cookiesTab = messageNode.querySelector("#cookies-tab");
|
||||
let paramsTab = messageNode.querySelector("#params-tab");
|
||||
let responseTab = messageNode.querySelector("#response-tab");
|
||||
let timingsTab = messageNode.querySelector("#timings-tab");
|
||||
|
||||
ok(headersTab, "Headers tab is available");
|
||||
ok(cookiesTab, "Cookies tab is available");
|
||||
ok(paramsTab, "Params tab is available");
|
||||
ok(responseTab, "Response tab is available");
|
||||
ok(timingsTab, "Timings tab is available");
|
||||
|
||||
// Headers tab should be selected by default, so just check its content.
|
||||
let headersContent = messageNode.querySelector(
|
||||
"#headers-panel .headers-overview");
|
||||
ok(headersContent, "Headers content is available");
|
||||
// Select Headers tab and check the content.
|
||||
headersTab.click();
|
||||
await waitUntil(() => {
|
||||
return !!messageNode.querySelector("#headers-panel .headers-overview");
|
||||
});
|
||||
}
|
||||
|
||||
// Cookies
|
||||
|
||||
function testEmptyCookies(messageNode) {
|
||||
let emptyNotice = messageNode.querySelector("#cookies-panel .empty-notice");
|
||||
ok(emptyNotice, "Cookies tab is empty");
|
||||
}
|
||||
|
||||
async function testCookies(messageNode) {
|
||||
let cookiesTab = messageNode.querySelector("#cookies-tab");
|
||||
ok(cookiesTab, "Cookies tab is available");
|
||||
|
||||
// Select tab and check the content.
|
||||
cookiesTab.click();
|
||||
await waitUntil(() => {
|
||||
return !!messageNode.querySelector("#cookies-panel .treeValueCell");
|
||||
});
|
||||
}
|
||||
|
||||
// Params
|
||||
|
||||
function testEmptyParams(messageNode) {
|
||||
let emptyNotice = messageNode.querySelector("#params-panel .empty-notice");
|
||||
ok(emptyNotice, "Params tab is empty");
|
||||
}
|
||||
|
||||
async function testParams(messageNode) {
|
||||
let paramsTab = messageNode.querySelector("#params-tab");
|
||||
ok(paramsTab, "Params tab is available");
|
||||
|
||||
// Select Params tab and check the content. CodeMirror initialization
|
||||
// is delayed to prevent UI freeze, so wait for a little while.
|
||||
|
@ -74,6 +210,18 @@ async function testNetworkMessage(messageNode) {
|
|||
"#params-panel .panel-container .CodeMirror");
|
||||
ok(paramsContent, "Params content is available");
|
||||
ok(paramsContent.textContent.includes("Hello world!"), "Post body is correct");
|
||||
}
|
||||
|
||||
// Response
|
||||
|
||||
function testEmptyResponse(messageNode) {
|
||||
let panel = messageNode.querySelector("#response-panel .tab-panel");
|
||||
is(panel.textContent, "", "Cookies tab is empty");
|
||||
}
|
||||
|
||||
async function testResponse(messageNode) {
|
||||
let responseTab = messageNode.querySelector("#response-tab");
|
||||
ok(responseTab, "Response tab is available");
|
||||
|
||||
// Select Response tab and check the content. CodeMirror initialization
|
||||
// is delayed, so again wait for a little while.
|
||||
|
@ -84,6 +232,18 @@ async function testNetworkMessage(messageNode) {
|
|||
"#response-panel .editor-row-container .CodeMirror");
|
||||
ok(responseContent, "Response content is available");
|
||||
ok(responseContent.textContent, "Response text is available");
|
||||
}
|
||||
|
||||
// Timings
|
||||
|
||||
function testEmptyTimings(messageNode) {
|
||||
let panel = messageNode.querySelector("#timings-panel .tab-panel");
|
||||
is(panel.textContent, "", "Timings tab is empty");
|
||||
}
|
||||
|
||||
async function testTimings(messageNode) {
|
||||
let timingsTab = messageNode.querySelector("#timings-tab");
|
||||
ok(timingsTab, "Timings tab is available");
|
||||
|
||||
// Select Timings tab and check the content.
|
||||
timingsTab.click();
|
||||
|
@ -93,6 +253,26 @@ async function testNetworkMessage(messageNode) {
|
|||
ok(timingsContent.textContent, "Timings text is available");
|
||||
}
|
||||
|
||||
// Stack Trace
|
||||
|
||||
function testEmptyStackTrace(messageNode) {
|
||||
let panel = messageNode.querySelector("#stack-trace-panel .stack-trace");
|
||||
is(panel.textContent, "", "StackTrace tab is empty");
|
||||
}
|
||||
|
||||
async function testStackTrace(messageNode) {
|
||||
let stackTraceTab = messageNode.querySelector("#stack-trace-tab");
|
||||
ok(stackTraceTab, "StackTrace tab is available");
|
||||
|
||||
// Select Timings tab and check the content.
|
||||
stackTraceTab.click();
|
||||
await waitUntil(() => {
|
||||
return !!messageNode.querySelector("#stack-trace-panel .frame-link");
|
||||
});
|
||||
}
|
||||
|
||||
// Waiting helpers
|
||||
|
||||
async function waitForPayloadReady(toolbox) {
|
||||
let {ui} = toolbox.getCurrentPanel().hud;
|
||||
return new Promise(resolve => {
|
||||
|
@ -118,3 +298,11 @@ async function waitForRequestUpdates(toolbox) {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function waitForLazyRequests(toolbox) {
|
||||
let {ui} = toolbox.getCurrentPanel().hud;
|
||||
let proxy = ui.jsterm.hud.proxy;
|
||||
return waitUntil(() => {
|
||||
return !proxy.networkDataProvider.lazyRequestData.size;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { classes: Cc, interfaces: Ci } = Components;
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.processAsync();
|
||||
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(() => {
|
||||
// to avoid garbage collection
|
||||
timer = null;
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.setHeader("Set-Cookie", "foo=bar; Max-Age=10; HttpOnly", true);
|
||||
response.write("Some response data");
|
||||
response.finish();
|
||||
}, 300, Ci.nsITimer.TYPE_ONE_SHOT); // Make sure this request takes a few hundred ms.
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
<meta charset="utf-8">
|
||||
<title>Console HTTP test page</title>
|
||||
<script type="text/javascript">
|
||||
/* exported testXhrGet, testXhrWarn, testXhrPost */
|
||||
/* exported testXhrGet, testXhrWarn, testXhrPost, testXhrPostSlowResponse */
|
||||
"use strict";
|
||||
|
||||
function makeXhr(method, url, requestBody, callback) {
|
||||
|
@ -32,6 +32,10 @@
|
|||
function testXhrPost(callback) {
|
||||
makeXhr("post", "test-data.json", "Hello world!", callback);
|
||||
}
|
||||
|
||||
function testXhrPostSlowResponse(callback) {
|
||||
makeXhr("post", "sjs_slow-response-test-server.sjs", "Hello world!", callback);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest"
|
||||
em:id="devtools@mozilla.org"
|
||||
em:name="Developer Tools"
|
||||
em:description="System-addon for Firefox DevTools"
|
||||
em:version="44.0a1"
|
||||
em:type="2"
|
||||
em:creator="Mozilla">
|
||||
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
<!-- Valid for all toolkit applications -->
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>toolkit@mozilla.org</em:id>
|
||||
<em:minVersion>57.0a1</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
|
@ -58,5 +58,5 @@ DevToolsModules(
|
|||
'shortest-paths.js',
|
||||
)
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -23,12 +23,12 @@ UNIFIED_SOURCES = [
|
|||
'SerializesTypeNames.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
# THE MOCK_METHOD2 macro from gtest triggers this clang warning and it's hard
|
||||
# to work around, so we just ignore it.
|
||||
if CONFIG['CLANG_CXX']:
|
||||
if CONFIG['CC_TYPE'] == 'clang':
|
||||
CXXFLAGS += ['-Wno-inconsistent-missing-override']
|
||||
# Workaround bug 1142396. Suppress the warning from gmock library for clang.
|
||||
CXXFLAGS += ['-Wno-null-dereference']
|
||||
|
|
|
@ -122,5 +122,5 @@ LOCAL_INCLUDES += [
|
|||
if CONFIG['MOZ_TOOLKIT_SEARCH']:
|
||||
DEFINES['MOZ_TOOLKIT_SEARCH'] = True
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -36,5 +36,5 @@ LOCAL_INCLUDES += [
|
|||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -13,10 +13,10 @@ Test chrome-only MutationObserver animation notifications (async tests)
|
|||
in test_animation_observers_sync.html.
|
||||
|
||||
-->
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="../testharness.js"></script>
|
||||
<script type="application/javascript" src="../testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<div id="log"></div>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
to { transform: translate(100px); }
|
||||
|
@ -39,72 +39,13 @@ var gObserver = new MutationObserver(newRecords => {
|
|||
gRecords.push(...newRecords);
|
||||
});
|
||||
|
||||
// Asynchronous testing framework based on layout/style/test/animation_utils.js.
|
||||
|
||||
var gTests = [];
|
||||
var gCurrentTestName;
|
||||
|
||||
function addAsyncAnimTest(aName, aOptions, aTestGenerator) {
|
||||
aTestGenerator.testName = aName;
|
||||
aTestGenerator.options = aOptions || {};
|
||||
gTests.push(aTestGenerator);
|
||||
}
|
||||
|
||||
function runAsyncTest(aTestGenerator) {
|
||||
return waitForFrame().then(() => {
|
||||
var generator;
|
||||
|
||||
function step(arg) {
|
||||
var next;
|
||||
try {
|
||||
next = generator.next(arg);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
if (next.done) {
|
||||
return Promise.resolve(next.value);
|
||||
} else {
|
||||
return Promise.resolve(next.value).then(step);
|
||||
}
|
||||
}
|
||||
|
||||
var subtree = aTestGenerator.options.subtree;
|
||||
|
||||
gCurrentTestName = aTestGenerator.testName;
|
||||
if (subtree) {
|
||||
gCurrentTestName += ":subtree";
|
||||
}
|
||||
|
||||
gRecords = [];
|
||||
function setupAsynchronousObserver(t, options) {
|
||||
gRecords = [];
|
||||
t.add_cleanup(() => {
|
||||
gObserver.disconnect();
|
||||
gObserver.observe(aTestGenerator.options.observe,
|
||||
{ animations: true, subtree: subtree});
|
||||
|
||||
generator = aTestGenerator();
|
||||
return step();
|
||||
});
|
||||
};
|
||||
|
||||
function runAllAsyncTests() {
|
||||
return gTests.reduce((sequence, test) => {
|
||||
return sequence.then(() => runAsyncTest(test));
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
// Wrap is and ok with versions that prepend the current sub-test name
|
||||
// to the assertion description.
|
||||
var old_is = is, old_ok = ok;
|
||||
is = function(a, b, message) {
|
||||
if (gCurrentTestName && message) {
|
||||
message = `[${gCurrentTestName}] ${message}`;
|
||||
}
|
||||
old_is(a, b, message);
|
||||
}
|
||||
ok = function(a, message) {
|
||||
if (gCurrentTestName && message) {
|
||||
message = `[${gCurrentTestName}] ${message}`;
|
||||
}
|
||||
old_ok(a, message);
|
||||
gObserver.observe(options.subtree ? div.parentNode : div,
|
||||
{ animations: true, subtree: options.subtree });
|
||||
}
|
||||
|
||||
// Adds an event listener and returns a Promise that is resolved when the
|
||||
|
@ -120,20 +61,21 @@ function await_event(aElement, aEventName) {
|
|||
}
|
||||
|
||||
function assert_record_list(actual, expected, desc, index, listName) {
|
||||
is(actual.length, expected.length, `${desc} - record[${index}].${listName} length`);
|
||||
assert_equals(actual.length, expected.length,
|
||||
`${desc} - record[${index}].${listName} length`);
|
||||
if (actual.length != expected.length) {
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < actual.length; i++) {
|
||||
ok(actual.indexOf(expected[i]) != -1,
|
||||
`${desc} - record[${index}].${listName} contains expected Animation`);
|
||||
assert_not_equals(actual.indexOf(expected[i]), -1,
|
||||
`${desc} - record[${index}].${listName} contains expected Animation`);
|
||||
}
|
||||
}
|
||||
|
||||
function assert_records(expected, desc) {
|
||||
var records = gRecords;
|
||||
gRecords = [];
|
||||
is(records.length, expected.length, `${desc} - number of records`);
|
||||
assert_equals(records.length, expected.length, `${desc} - number of records`);
|
||||
if (records.length != expected.length) {
|
||||
return;
|
||||
}
|
||||
|
@ -190,267 +132,327 @@ function assert_records_any_order(expected, desc) {
|
|||
// targeting the div and observing its parent while using the subtree:true
|
||||
// MutationObserver option.
|
||||
|
||||
[
|
||||
{ observe: div, target: div, subtree: false },
|
||||
{ observe: div.parentNode, target: div, subtree: true },
|
||||
].forEach(aOptions => {
|
||||
function runTest() {
|
||||
[
|
||||
{ observe: div, target: div, subtree: false },
|
||||
{ observe: div.parentNode, target: div, subtree: true },
|
||||
].forEach(aOptions => {
|
||||
|
||||
var e = aOptions.target;
|
||||
var e = aOptions.target;
|
||||
|
||||
// Test that starting a single transition that completes normally
|
||||
// dispatches an added notification and then a removed notification.
|
||||
addAsyncAnimTest("single_transition", aOptions, function*() {
|
||||
// Start a transition.
|
||||
e.style = "transition: background-color 100s; background-color: lime;";
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, aOptions);
|
||||
// Clear all styles once test finished since we re-use the same element
|
||||
// in all test cases.
|
||||
t.add_cleanup(() => {
|
||||
e.style = "";
|
||||
flushComputedStyle(e);
|
||||
});
|
||||
|
||||
// Register for the end of the transition.
|
||||
var transitionEnd = await_event(e, "transitionend");
|
||||
// Start a transition.
|
||||
e.style = "transition: background-color 100s; background-color: lime;";
|
||||
|
||||
// The transition should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
is(animations.length, 1, "getAnimations().length after transition start");
|
||||
// Register for the end of the transition.
|
||||
var transitionEnd = await_event(e, "transitionend");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after transition start");
|
||||
// The transition should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
assert_equals(animations.length, 1,
|
||||
"getAnimations().length after transition start");
|
||||
|
||||
// Advance until near the end of the transition, then wait for it to finish.
|
||||
animations[0].currentTime = 99900;
|
||||
yield transitionEnd;
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
return waitForFrame().then(() => {
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after transition start");
|
||||
|
||||
// After the transition has finished, the Animation should disappear.
|
||||
is(e.getAnimations().length, 0,
|
||||
"getAnimations().length after transition end");
|
||||
// Advance until near the end of the transition, then wait for it to
|
||||
// finish.
|
||||
animations[0].currentTime = 99900;
|
||||
}).then(() => {
|
||||
return transitionEnd;
|
||||
}).then(() => {
|
||||
// After the transition has finished, the Animation should disappear.
|
||||
assert_equals(e.getAnimations().length, 0,
|
||||
"getAnimations().length after transition end");
|
||||
|
||||
// Wait for the change MutationRecord for seeking the Animation to be
|
||||
// delivered, followed by the the removal MutationRecord.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: animations, removed: [] },
|
||||
{ added: [], changed: [], removed: animations }],
|
||||
"records after transition end");
|
||||
// Wait for the change MutationRecord for seeking the Animation to be
|
||||
// delivered, followed by the the removal MutationRecord.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: animations, removed: [] },
|
||||
{ added: [], changed: [], removed: animations }],
|
||||
"records after transition end");
|
||||
});
|
||||
}, `single_transition ${aOptions.subtree ? ': subtree' : ''}`);
|
||||
|
||||
e.style = "";
|
||||
// Test that starting a single animation that completes normally
|
||||
// dispatches an added notification and then a removed notification.
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, aOptions);
|
||||
t.add_cleanup(() => {
|
||||
e.style = "";
|
||||
flushComputedStyle(e);
|
||||
});
|
||||
|
||||
// Start an animation.
|
||||
e.style = "animation: anim 100s;";
|
||||
|
||||
// Register for the end of the animation.
|
||||
var animationEnd = await_event(e, "animationend");
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
assert_equals(animations.length, 1,
|
||||
"getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
return waitForFrame().then(() => {
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Advance until near the end of the animation, then wait for it to finish.
|
||||
animations[0].currentTime = 99900;
|
||||
return animationEnd;
|
||||
}).then(() => {
|
||||
// After the animation has finished, the Animation should disappear.
|
||||
assert_equals(e.getAnimations().length, 0,
|
||||
"getAnimations().length after animation end");
|
||||
|
||||
// Wait for the change MutationRecord from seeking the Animation to
|
||||
// be delivered, followed by a further MutationRecord for the Animation
|
||||
// removal.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: animations, removed: [] },
|
||||
{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
}, `single_animation ${aOptions.subtree ? ': subtree' : ''}`);
|
||||
|
||||
// Test that starting a single animation that is cancelled by updating
|
||||
// the animation-fill-mode property dispatches an added notification and
|
||||
// then a removed notification.
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, aOptions);
|
||||
t.add_cleanup(() => {
|
||||
e.style = "";
|
||||
flushComputedStyle(e);
|
||||
});
|
||||
|
||||
// Start a short, filled animation.
|
||||
e.style = "animation: anim 100s forwards;";
|
||||
|
||||
// Register for the end of the animation.
|
||||
var animationEnd = await_event(e, "animationend");
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
assert_equals(animations.length, 1,
|
||||
"getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
return waitForFrame().then(() => {
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Advance until near the end of the animation, then wait for it to finish.
|
||||
animations[0].currentTime = 99900;
|
||||
return animationEnd;
|
||||
}).then(() => {
|
||||
// The only MutationRecord at this point should be the change from
|
||||
// seeking the Animation.
|
||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
||||
"records after animation starts filling");
|
||||
|
||||
// Cancel the animation by setting animation-fill-mode.
|
||||
e.style.animationFillMode = "none";
|
||||
// Explicitly flush style to make sure the above style change happens.
|
||||
// Normally we don't need explicit style flush if there is a waitForFrame()
|
||||
// call but in this particular case we are in the middle of animation events'
|
||||
// callback handling and requestAnimationFrame handling so that we have no
|
||||
// chance to process styling even after the requestAnimationFrame handling.
|
||||
flushComputedStyle(e);
|
||||
|
||||
// Wait for the single MutationRecord for the Animation removal to
|
||||
// be delivered.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
}, `single_animation_cancelled_fill ${aOptions.subtree ? ': subtree' : ''}`);
|
||||
|
||||
// Test that calling finish() on a paused (but otherwise finished) animation
|
||||
// dispatches a changed notification.
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, aOptions);
|
||||
t.add_cleanup(() => {
|
||||
e.style = "";
|
||||
flushComputedStyle(e);
|
||||
});
|
||||
|
||||
// Start a long animation
|
||||
e.style = "animation: anim 100s forwards";
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
assert_equals(animations.length, 1,
|
||||
"getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
return waitForFrame().then(() => {
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Wait until the animation is playing.
|
||||
return animations[0].ready;
|
||||
}).then(() => {
|
||||
// Finish and pause.
|
||||
animations[0].finish();
|
||||
animations[0].pause();
|
||||
|
||||
// Wait for the pause to complete.
|
||||
return animations[0].ready;
|
||||
}).then(() => {
|
||||
assert_equals(animations[0].playState, "paused",
|
||||
"playState after finishing and pausing");
|
||||
|
||||
// We should have two MutationRecords for the Animation changes:
|
||||
// one for the finish, one for the pause.
|
||||
assert_records([{ added: [], changed: animations, removed: [] },
|
||||
{ added: [], changed: animations, removed: [] }],
|
||||
"records after finish() and pause()");
|
||||
|
||||
// Call finish() again.
|
||||
animations[0].finish();
|
||||
assert_equals(animations[0].playState, "finished",
|
||||
"playState after finishing from paused state");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation change to
|
||||
// be delivered. Even though the currentTime does not change, the
|
||||
// playState will change.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
||||
"records after finish() and pause()");
|
||||
|
||||
// Cancel the animation.
|
||||
e.style = "";
|
||||
|
||||
// Wait for the single removal notification.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
}, `finish_from_pause ${aOptions.subtree ? ': subtree' : ''}`);
|
||||
|
||||
// Test that calling play() on a paused Animation dispatches a changed
|
||||
// notification.
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, aOptions);
|
||||
t.add_cleanup(() => {
|
||||
e.style = "";
|
||||
flushComputedStyle(e);
|
||||
});
|
||||
|
||||
// Start a long, paused animation
|
||||
e.style = "animation: anim 100s paused";
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
assert_equals(animations.length, 1,
|
||||
"getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
return waitForFrame().then(() => {
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Wait until the animation is ready
|
||||
return animations[0].ready;
|
||||
}).then(() => {
|
||||
// Play
|
||||
animations[0].play();
|
||||
|
||||
// Wait for the single MutationRecord for the Animation change to
|
||||
// be delivered.
|
||||
return animations[0].ready;
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
||||
"records after play()");
|
||||
|
||||
// Redundant play
|
||||
animations[0].play();
|
||||
|
||||
// Wait to ensure no change is dispatched
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([], "records after redundant play()");
|
||||
|
||||
// Cancel the animation.
|
||||
e.style = "";
|
||||
|
||||
// Wait for the single removal notification.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
}, `play ${aOptions.subtree ? ': subtree' : ''}`);
|
||||
|
||||
// Test that a non-cancelling change to an animation followed immediately by a
|
||||
// cancelling change will only send an animation removal notification.
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, aOptions);
|
||||
t.add_cleanup(() => {
|
||||
e.style = "";
|
||||
flushComputedStyle(e);
|
||||
});
|
||||
|
||||
// Start a long animation.
|
||||
e.style = "animation: anim 100s;";
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
assert_equals(animations.length, 1,
|
||||
"getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
return waitForFrame().then(() => {;
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Update the animation's delay such that it is still running.
|
||||
e.style.animationDelay = "-1s";
|
||||
|
||||
// Then cancel the animation by updating its duration.
|
||||
e.style.animationDuration = "0.5s";
|
||||
|
||||
// We should get a single removal notification.
|
||||
return waitForFrame();
|
||||
}).then(() => {
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
}, `coalesce_change_cancel ${aOptions.subtree ? ': subtree' : ''}`);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
promise_test(t => {
|
||||
setupAsynchronousObserver(t, { observe: div, subtree: true });
|
||||
t.add_cleanup(() => {
|
||||
div.style = "";
|
||||
flushComputedStyle(div);
|
||||
});
|
||||
|
||||
// Test that starting a single animation that completes normally
|
||||
// dispatches an added notification and then a removed notification.
|
||||
addAsyncAnimTest("single_animation", aOptions, function*() {
|
||||
// Start an animation.
|
||||
e.style = "animation: anim 100s;";
|
||||
|
||||
// Register for the end of the animation.
|
||||
var animationEnd = await_event(e, "animationend");
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
is(animations.length, 1, "getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Advance until near the end of the animation, then wait for it to finish.
|
||||
animations[0].currentTime = 99900;
|
||||
yield animationEnd;
|
||||
|
||||
// After the animation has finished, the Animation should disappear.
|
||||
is(e.getAnimations().length, 0,
|
||||
"getAnimations().length after animation end");
|
||||
|
||||
// Wait for the change MutationRecord from seeking the Animation to
|
||||
// be delivered, followed by a further MutationRecord for the Animation
|
||||
// removal.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: animations, removed: [] },
|
||||
{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
|
||||
e.style = "";
|
||||
});
|
||||
|
||||
// Test that starting a single animation that is cancelled by updating
|
||||
// the animation-fill-mode property dispatches an added notification and
|
||||
// then a removed notification.
|
||||
addAsyncAnimTest("single_animation_cancelled_fill", aOptions, function*() {
|
||||
// Start a short, filled animation.
|
||||
e.style = "animation: anim 100s forwards;";
|
||||
|
||||
// Register for the end of the animation.
|
||||
var animationEnd = await_event(e, "animationend");
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
is(animations.length, 1, "getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Advance until near the end of the animation, then wait for it to finish.
|
||||
animations[0].currentTime = 99900;
|
||||
yield animationEnd;
|
||||
|
||||
// The only MutationRecord at this point should be the change from
|
||||
// seeking the Animation.
|
||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
||||
"records after animation starts filling");
|
||||
|
||||
// Cancel the animation by setting animation-fill-mode.
|
||||
e.style.animationFillMode = "none";
|
||||
// Explicitly flush style to make sure the above style change happens.
|
||||
// Normally we don't need explicit style flush if there is a waitForFrame()
|
||||
// call but in this particular case we are in the middle of animation events'
|
||||
// callback handling and requestAnimationFrame handling so that we have no
|
||||
// chance to process styling even after the requestAnimationFrame handling.
|
||||
flushComputedStyle(e);
|
||||
|
||||
// Wait for the single MutationRecord for the Animation removal to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
|
||||
e.style = "";
|
||||
});
|
||||
|
||||
// Test that calling finish() on a paused (but otherwise finished) animation
|
||||
// dispatches a changed notification.
|
||||
addAsyncAnimTest("finish_from_pause", aOptions, function*() {
|
||||
// Start a long animation
|
||||
e.style = "animation: anim 100s forwards";
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
is(animations.length, 1, "getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Wait until the animation is playing.
|
||||
yield animations[0].ready;
|
||||
|
||||
// Finish and pause.
|
||||
animations[0].finish();
|
||||
animations[0].pause();
|
||||
|
||||
// Wait for the pause to complete.
|
||||
yield animations[0].ready;
|
||||
is(animations[0].playState, "paused",
|
||||
"playState after finishing and pausing");
|
||||
|
||||
// We should have two MutationRecords for the Animation changes:
|
||||
// one for the finish, one for the pause.
|
||||
assert_records([{ added: [], changed: animations, removed: [] },
|
||||
{ added: [], changed: animations, removed: [] }],
|
||||
"records after finish() and pause()");
|
||||
|
||||
// Call finish() again.
|
||||
animations[0].finish();
|
||||
is(animations[0].playState, "finished",
|
||||
"playState after finishing from paused state");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation change to
|
||||
// be delivered. Even though the currentTime does not change, the
|
||||
// playState will change.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
||||
"records after finish() and pause()");
|
||||
|
||||
// Cancel the animation.
|
||||
e.style = "";
|
||||
|
||||
// Wait for the single removal notification.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
|
||||
// Test that calling play() on a paused Animation dispatches a changed
|
||||
// notification.
|
||||
addAsyncAnimTest("play", aOptions, function*() {
|
||||
// Start a long, paused animation
|
||||
e.style = "animation: anim 100s paused";
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
is(animations.length, 1, "getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Wait until the animation is ready
|
||||
yield animations[0].ready;
|
||||
|
||||
// Play
|
||||
animations[0].play();
|
||||
|
||||
// Wait for the single MutationRecord for the Animation change to
|
||||
// be delivered.
|
||||
yield animations[0].ready;
|
||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
||||
"records after play()");
|
||||
|
||||
// Redundant play
|
||||
animations[0].play();
|
||||
|
||||
// Wait to ensure no change is dispatched
|
||||
yield waitForFrame();
|
||||
assert_records([], "records after redundant play()");
|
||||
|
||||
// Cancel the animation.
|
||||
e.style = "";
|
||||
|
||||
// Wait for the single removal notification.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
});
|
||||
|
||||
// Test that a non-cancelling change to an animation followed immediately by a
|
||||
// cancelling change will only send an animation removal notification.
|
||||
addAsyncAnimTest("coalesce_change_cancel", aOptions, function*() {
|
||||
// Start a long animation.
|
||||
e.style = "animation: anim 100s;";
|
||||
|
||||
// The animation should cause the creation of a single Animation.
|
||||
var animations = e.getAnimations();
|
||||
is(animations.length, 1, "getAnimations().length after animation start");
|
||||
|
||||
// Wait for the single MutationRecord for the Animation addition to
|
||||
// be delivered.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
||||
"records after animation start");
|
||||
|
||||
// Update the animation's delay such that it is still running.
|
||||
e.style.animationDelay = "-1s";
|
||||
|
||||
// Then cancel the animation by updating its duration.
|
||||
e.style.animationDuration = "0.5s";
|
||||
|
||||
// We should get a single removal notification.
|
||||
yield waitForFrame();
|
||||
assert_records([{ added: [], changed: [], removed: animations }],
|
||||
"records after animation end");
|
||||
|
||||
e.style = "";
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
||||
// Add style for pseudo elements
|
||||
var extraStyle = document.createElement('style');
|
||||
document.head.appendChild(extraStyle);
|
||||
|
@ -491,7 +493,7 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
|||
|
||||
// Check all animations we have in this document
|
||||
var docAnims = document.getAnimations();
|
||||
is(docAnims.length, 10, "total animations");
|
||||
assert_equals(docAnims.length, 10, "total animations");
|
||||
|
||||
var divAnimations = div.getAnimations();
|
||||
var childAAnimations = childA.getAnimations();
|
||||
|
@ -506,6 +508,7 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
|||
var childBPseudoAnimations =
|
||||
docAnims.filter(x => x.effect.target.parentElement == childB);
|
||||
|
||||
var seekRecords;
|
||||
// The order in which we get the corresponding records is currently
|
||||
// based on the order we visit these nodes when updating styles.
|
||||
//
|
||||
|
@ -513,75 +516,73 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
|||
// mutation records when we flush styles. We may introduce that in the
|
||||
// future but for now all we are interested in testing here is that the
|
||||
// right records are generated, but we allow them to occur in any order.
|
||||
yield waitForFrame();
|
||||
assert_records_any_order(
|
||||
[{ added: divAfterAnimations, changed: [], removed: [] },
|
||||
{ added: childAAnimations, changed: [], removed: [] },
|
||||
{ added: childBAnimations, changed: [], removed: [] },
|
||||
{ added: childBPseudoAnimations, changed: [], removed: [] },
|
||||
{ added: divAnimations, changed: [], removed: [] },
|
||||
{ added: divBeforeAnimations, changed: [], removed: [] }],
|
||||
"records after simultaneous animation start");
|
||||
return waitForFrame().then(() => {
|
||||
assert_records_any_order(
|
||||
[{ added: divAfterAnimations, changed: [], removed: [] },
|
||||
{ added: childAAnimations, changed: [], removed: [] },
|
||||
{ added: childBAnimations, changed: [], removed: [] },
|
||||
{ added: childBPseudoAnimations, changed: [], removed: [] },
|
||||
{ added: divAnimations, changed: [], removed: [] },
|
||||
{ added: divBeforeAnimations, changed: [], removed: [] }],
|
||||
"records after simultaneous animation start");
|
||||
|
||||
// The one case where we *do* currently perform document-level (or actually
|
||||
// timeline-level) batching is when animations are updated from a refresh
|
||||
// driver tick. In particular, this means that when animations finish
|
||||
// naturally the removed records should be dispatched according to the
|
||||
// position of the elements in the tree.
|
||||
// The one case where we *do* currently perform document-level (or actually
|
||||
// timeline-level) batching is when animations are updated from a refresh
|
||||
// driver tick. In particular, this means that when animations finish
|
||||
// naturally the removed records should be dispatched according to the
|
||||
// position of the elements in the tree.
|
||||
|
||||
// First, flatten the set of animations. we put the animations targeting to
|
||||
// pseudo elements last. (Actually, we don't care the order in the list.)
|
||||
var animations = [ ...divAnimations,
|
||||
...childAAnimations,
|
||||
...childBAnimations,
|
||||
...divBeforeAnimations,
|
||||
...divAfterAnimations,
|
||||
...childBPseudoAnimations ];
|
||||
// First, flatten the set of animations. we put the animations targeting to
|
||||
// pseudo elements last. (Actually, we don't care the order in the list.)
|
||||
var animations = [ ...divAnimations,
|
||||
...childAAnimations,
|
||||
...childBAnimations,
|
||||
...divBeforeAnimations,
|
||||
...divAfterAnimations,
|
||||
...childBPseudoAnimations ];
|
||||
|
||||
// Fast-forward to *just* before the end of the animation.
|
||||
animations.forEach(animation => animation.currentTime = 99999);
|
||||
// Fast-forward to *just* before the end of the animation.
|
||||
animations.forEach(animation => animation.currentTime = 99999);
|
||||
|
||||
// Prepare the set of expected change MutationRecords, one for each
|
||||
// animation that was seeked.
|
||||
var seekRecords = animations.map(
|
||||
p => ({ added: [], changed: [p], removed: [] })
|
||||
);
|
||||
// Prepare the set of expected change MutationRecords, one for each
|
||||
// animation that was seeked.
|
||||
seekRecords = animations.map(
|
||||
p => ({ added: [], changed: [p], removed: [] })
|
||||
);
|
||||
|
||||
yield await_event(div, "animationend");
|
||||
return await_event(div, "animationend");
|
||||
}).then(() => {
|
||||
// After the changed notifications, which will be dispatched in the order that
|
||||
// the animations were seeked, we should get removal MutationRecords in order
|
||||
// (div, div::before, div::after), childA, (childB, childB::before).
|
||||
// Note: The animations targeting to the pseudo element are appended after
|
||||
// the animations of its parent element.
|
||||
divAnimations = [ ...divAnimations,
|
||||
...divBeforeAnimations,
|
||||
...divAfterAnimations ];
|
||||
childBAnimations = [ ...childBAnimations, ...childBPseudoAnimations ];
|
||||
assert_records(seekRecords.concat(
|
||||
{ added: [], changed: [], removed: divAnimations },
|
||||
{ added: [], changed: [], removed: childAAnimations },
|
||||
{ added: [], changed: [], removed: childBAnimations }),
|
||||
"records after finishing");
|
||||
|
||||
// After the changed notifications, which will be dispatched in the order that
|
||||
// the animations were seeked, we should get removal MutationRecords in order
|
||||
// (div, div::before, div::after), childA, (childB, childB::before).
|
||||
// Note: The animations targeting to the pseudo element are appended after
|
||||
// the animations of its parent element.
|
||||
divAnimations = [ ...divAnimations,
|
||||
...divBeforeAnimations,
|
||||
...divAfterAnimations ];
|
||||
childBAnimations = [ ...childBAnimations, ...childBPseudoAnimations ];
|
||||
assert_records(seekRecords.concat(
|
||||
{ added: [], changed: [], removed: divAnimations },
|
||||
{ added: [], changed: [], removed: childAAnimations },
|
||||
{ added: [], changed: [], removed: childBAnimations }),
|
||||
"records after finishing");
|
||||
|
||||
// Clean up
|
||||
div.classList.remove("before");
|
||||
div.classList.remove("after");
|
||||
div.style = "";
|
||||
childA.remove();
|
||||
childB.remove();
|
||||
extraStyle.remove();
|
||||
});
|
||||
// Clean up
|
||||
div.classList.remove("before");
|
||||
div.classList.remove("after");
|
||||
div.style = "";
|
||||
childA.remove();
|
||||
childB.remove();
|
||||
extraStyle.remove();
|
||||
});
|
||||
}, "tree_ordering: subtree");
|
||||
|
||||
// Run the tests.
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setup({explicit_done: true});
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ set: [["dom.animations-api.pending-member.enabled", true]] }
|
||||
).then(runAllAsyncTests).then(() => {
|
||||
SimpleTest.finish();
|
||||
}, aError => {
|
||||
ok(false, "Something failed: " + aError);
|
||||
).then(runTest).then(() => {
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -36,10 +36,10 @@ Test chrome-only MutationObserver animation notifications (sync tests)
|
|||
* it will raise an assertion.
|
||||
*/
|
||||
function setupSynchronousObserver(t, target, subtree) {
|
||||
var observer = new MutationObserver(records => {
|
||||
assert_unreached("Any MutationRecords should not be observed in this " +
|
||||
"callback");
|
||||
});
|
||||
var observer = new MutationObserver(records => {
|
||||
assert_unreached("Any MutationRecords should not be observed in this " +
|
||||
"callback");
|
||||
});
|
||||
t.add_cleanup(() => {
|
||||
observer.disconnect();
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Attr.h"
|
||||
#include "mozilla/dom/Flex.h"
|
||||
#include "mozilla/dom/Grid.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "nsDOMAttributeMap.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIContentIterator.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsILinkHandler.h"
|
||||
|
@ -3707,6 +3709,23 @@ Element::RequestPointerLock(CallerType aCallerType)
|
|||
OwnerDoc()->RequestPointerLock(this, aCallerType);
|
||||
}
|
||||
|
||||
already_AddRefed<Flex>
|
||||
Element::GetAsFlexContainer()
|
||||
{
|
||||
nsIFrame* frame = GetPrimaryFrame();
|
||||
|
||||
// We need the flex frame to compute additional info, and use
|
||||
// that annotated version of the frame.
|
||||
nsFlexContainerFrame* flexFrame =
|
||||
nsFlexContainerFrame::GetFlexFrameWithComputedInfo(frame);
|
||||
|
||||
if (flexFrame) {
|
||||
RefPtr<Flex> flex = new Flex(this, flexFrame);
|
||||
return flex.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Element::GetGridFragments(nsTArray<RefPtr<Grid>>& aResult)
|
||||
{
|
||||
|
|
|
@ -189,6 +189,7 @@ class Link;
|
|||
class DOMRect;
|
||||
class DOMRectList;
|
||||
class DestinationInsertionPointList;
|
||||
class Flex;
|
||||
class Grid;
|
||||
|
||||
// IID for the dom::Element interface
|
||||
|
@ -1308,6 +1309,7 @@ public:
|
|||
0;
|
||||
}
|
||||
|
||||
already_AddRefed<Flex> GetAsFlexContainer();
|
||||
void GetGridFragments(nsTArray<RefPtr<Grid>>& aResult);
|
||||
|
||||
already_AddRefed<DOMMatrixReadOnly> GetTransformToAncestor(Element& aAncestor);
|
||||
|
|
|
@ -485,5 +485,5 @@ counterlist = GENERATED_FILES['UseCounterList.h']
|
|||
counterlist.script = 'gen-usecounters.py:use_counter_list'
|
||||
counterlist.inputs = ['UseCounters.conf']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
#include "nsError.h"
|
||||
#include "nsIDOMXULButtonElement.h"
|
||||
#include "nsIDOMXULCheckboxElement.h"
|
||||
#include "nsIDOMXULPopupElement.h"
|
||||
|
||||
// Event related includes
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
@ -194,8 +193,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCheckboxElement, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULPopupElement, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
};
|
||||
|
||||
nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
|
||||
|
@ -475,10 +472,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCheckboxElement)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULPopupElement, nsIDOMXULPopupElement)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULPopupElement)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(sClassInfoData) == eDOMClassInfoIDCount,
|
||||
"The number of items in sClassInfoData doesn't match the "
|
||||
"number of nsIDOMClassInfo ID's, this is bad! Fix it!");
|
||||
|
|
|
@ -28,7 +28,6 @@ enum nsDOMClassInfoID
|
|||
eDOMClassInfo_XULLabeledControlElement_id,
|
||||
eDOMClassInfo_XULButtonElement_id,
|
||||
eDOMClassInfo_XULCheckboxElement_id,
|
||||
eDOMClassInfo_XULPopupElement_id,
|
||||
|
||||
// This one better be the last one in this list
|
||||
eDOMClassInfoIDCount
|
||||
|
|
|
@ -52,14 +52,10 @@ using mozilla::AutoJSContext;
|
|||
} \
|
||||
nsINode* node = content_; \
|
||||
NS_ASSERTION(node->OwnerDoc() == doc, "Bogus document"); \
|
||||
if (doc) { \
|
||||
doc->BindingManager()->func_ params_; \
|
||||
} \
|
||||
doc->BindingManager()->func_ params_; \
|
||||
do { \
|
||||
nsINode::nsSlots* slots = node->GetExistingSlots(); \
|
||||
if (slots && !slots->mMutationObservers.IsEmpty()) { \
|
||||
/* No need to explicitly notify the first observer first \
|
||||
since that'll happen anyway. */ \
|
||||
NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS( \
|
||||
slots->mMutationObservers, nsIMutationObserver, 1, \
|
||||
func_, params_); \
|
||||
|
@ -86,8 +82,6 @@ using mozilla::AutoJSContext;
|
|||
do { \
|
||||
nsINode::nsSlots* slots = node->GetExistingSlots(); \
|
||||
if (slots && !slots->mMutationObservers.IsEmpty()) { \
|
||||
/* No need to explicitly notify the first observer first \
|
||||
since that'll happen anyway. */ \
|
||||
NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS_WITH_QI( \
|
||||
slots->mMutationObservers, nsIMutationObserver, 1, \
|
||||
nsIAnimationObserver, func_, params_); \
|
||||
|
|
|
@ -160,7 +160,7 @@ PYTHON_UNITTEST_MANIFESTS += [
|
|||
'mozwebidlcodegen/test/python.ini',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
# Suppress warnings in third-party code.
|
||||
CXXFLAGS += [
|
||||
|
|
|
@ -54,5 +54,5 @@ LOCAL_INCLUDES += [
|
|||
'/js/xpconnect/wrappers',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -100,5 +100,5 @@ XPCSHELL_TESTS_MANIFESTS += [
|
|||
'test/xpcshell/xpcshell.ini',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -189,7 +189,7 @@ SOURCES += [
|
|||
]
|
||||
|
||||
# Suppress warnings from third-party code.
|
||||
if CONFIG['CLANG_CXX'] or CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
SOURCES['MurmurHash3.cpp'].flags += ['-Wno-implicit-fallthrough']
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
@ -220,5 +220,5 @@ CXXFLAGS += CONFIG['TK_CFLAGS']
|
|||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -157,5 +157,5 @@ LOCAL_INCLUDES += [
|
|||
'/layout/xul/tree/',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
|
|
@ -53,7 +53,7 @@ FINAL_LIBRARY = 'xul'
|
|||
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Flex.h"
|
||||
|
||||
#include "FlexLine.h"
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Flex, mParent, mLines)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Flex)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Flex)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Flex)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
Flex::Flex(Element* aParent,
|
||||
nsFlexContainerFrame* aFrame)
|
||||
: mParent(aParent)
|
||||
{
|
||||
MOZ_ASSERT(aFrame,
|
||||
"Should never be instantiated with a null nsFlexContainerFrame");
|
||||
|
||||
// Eagerly create property values from aFrame, because we're not
|
||||
// going to keep it around.
|
||||
const ComputedFlexContainerInfo* containerInfo =
|
||||
aFrame->GetFlexContainerInfo();
|
||||
MOZ_ASSERT(containerInfo, "Should only be passed a frame with info.");
|
||||
|
||||
mLines.SetLength(containerInfo->mLines.Length());
|
||||
uint32_t index = 0;
|
||||
for (auto&& l : containerInfo->mLines) {
|
||||
FlexLine* line = new FlexLine(this, &l);
|
||||
mLines.ElementAt(index) = line;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Flex::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return FlexBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
Flex::GetLines(nsTArray<RefPtr<FlexLine>>& aResult)
|
||||
{
|
||||
aResult.AppendElements(mLines);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_Flex_h
|
||||
#define mozilla_dom_Flex_h
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsFlexContainerFrame;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FlexLine;
|
||||
|
||||
class Flex : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit Flex(Element* aParent, nsFlexContainerFrame* aFrame);
|
||||
|
||||
protected:
|
||||
virtual ~Flex() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Flex)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
Element* GetParentObject()
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
void GetLines(nsTArray<RefPtr<FlexLine>>& aResult);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<Element> mParent;
|
||||
nsTArray<RefPtr<FlexLine>> mLines;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_Flex_h */
|
|
@ -0,0 +1,98 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FlexItem.h"
|
||||
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexItem, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexItem)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexItem)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexItem)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
FlexItem::FlexItem(FlexLine* aParent,
|
||||
const ComputedFlexItemInfo* aItem)
|
||||
: mParent(aParent)
|
||||
{
|
||||
MOZ_ASSERT(aItem,
|
||||
"Should never be instantiated with a null ComputedFlexLineInfo.");
|
||||
|
||||
// Eagerly copy values from aItem, because we're not
|
||||
// going to keep it around.
|
||||
mNode = aItem->mNode;
|
||||
|
||||
// Convert app unit sizes to css pixel sizes.
|
||||
mMainBaseSize = nsPresContext::AppUnitsToDoubleCSSPixels(
|
||||
aItem->mMainBaseSize);
|
||||
mMainDeltaSize = nsPresContext::AppUnitsToDoubleCSSPixels(
|
||||
aItem->mMainDeltaSize);
|
||||
mMainMinSize = nsPresContext::AppUnitsToDoubleCSSPixels(
|
||||
aItem->mMainMinSize);
|
||||
mMainMaxSize = nsPresContext::AppUnitsToDoubleCSSPixels(
|
||||
aItem->mMainMaxSize);
|
||||
mCrossMinSize = nsPresContext::AppUnitsToDoubleCSSPixels(
|
||||
aItem->mCrossMinSize);
|
||||
mCrossMaxSize = nsPresContext::AppUnitsToDoubleCSSPixels(
|
||||
aItem->mCrossMaxSize);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
FlexItem::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return FlexItemBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsINode*
|
||||
FlexItem::GetNode() const
|
||||
{
|
||||
return mNode;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainBaseSize() const
|
||||
{
|
||||
return mMainBaseSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainDeltaSize() const
|
||||
{
|
||||
return mMainDeltaSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainMinSize() const
|
||||
{
|
||||
return mMainMinSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::MainMaxSize() const
|
||||
{
|
||||
return mMainMaxSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::CrossMinSize() const
|
||||
{
|
||||
return mCrossMinSize;
|
||||
}
|
||||
|
||||
double
|
||||
FlexItem::CrossMaxSize() const
|
||||
{
|
||||
return mCrossMaxSize;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_FlexItem_h
|
||||
#define mozilla_dom_FlexItem_h
|
||||
|
||||
#include "mozilla/dom/FlexBinding.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
struct ComputedFlexItemInfo;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FlexLine;
|
||||
|
||||
class FlexItem : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit FlexItem(FlexLine* aParent,
|
||||
const ComputedFlexItemInfo* aItem);
|
||||
|
||||
protected:
|
||||
virtual ~FlexItem() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FlexItem)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
FlexLine* GetParentObject()
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
nsINode* GetNode() const;
|
||||
double MainBaseSize() const;
|
||||
double MainDeltaSize() const;
|
||||
double MainMinSize() const;
|
||||
double MainMaxSize() const;
|
||||
double CrossMinSize() const;
|
||||
double CrossMaxSize() const;
|
||||
|
||||
protected:
|
||||
RefPtr<FlexLine> mParent;
|
||||
RefPtr<nsINode> mNode;
|
||||
|
||||
// These sizes are all CSS pixel units.
|
||||
double mMainBaseSize;
|
||||
double mMainDeltaSize;
|
||||
double mMainMinSize;
|
||||
double mMainMaxSize;
|
||||
double mCrossMinSize;
|
||||
double mCrossMaxSize;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_FlexItem_h */
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче