Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE

--HG--
rename : browser/components/nsBrowserContentHandler.js => browser/components/BrowserContentHandler.jsm
This commit is contained in:
Daniel Varga 2019-02-15 03:51:05 +02:00
Родитель dfc6aeef42 30780abeeb
Коммит 1e9aa9e1fc
445 изменённых файлов: 4735 добавлений и 3694 удалений

Просмотреть файл

@ -272,22 +272,15 @@ update-packaging:
package-generated-sources:
$(call py_action,package_generated_sources,'$(DIST)/$(PKG_PATH)$(GENERATED_SOURCE_FILE_PACKAGE)')
#XXX: this is a hack, since we don't want to clobber for MSVC
# PGO support, but we can't do this test in client.mk
# No point in clobbering if PGO has been explicitly disabled.
ifdef NO_PROFILE_GUIDED_OPTIMIZE
maybe_clobber_profiledbuild:
else
ifneq ($(CC_TYPE),msvc)
maybe_clobber_profiledbuild: clean
ifneq (,$(findstring clang,$(CC_TYPE)))
$(LLVM_PROFDATA) merge -o $(DEPTH)/merged.profdata $(DEPTH)/*.profraw
endif
else
maybe_clobber_profiledbuild:
$(RM) $(DIST)/bin/*.pgc
find $(DIST)/$(MOZ_APP_NAME) -name '*.pgc' -exec mv {} $(DIST)/bin \;
endif # msvc
endif # NO_PROFILE_GUIDED_OPTIMIZE
.PHONY: maybe_clobber_profiledbuild

Просмотреть файл

@ -262,6 +262,14 @@ already_AddRefed<nsIAccessibleEvent> a11y::MakeXPCEvent(AccEvent* aEvent) {
return xpEvent.forget();
}
if (eventGroup & (1 << AccEvent::eAnnouncementEvent)) {
AccAnnouncementEvent* aa = downcast_accEvent(aEvent);
xpEvent = new xpcAccAnnouncementEvent(type, ToXPC(acc), ToXPCDocument(doc),
node, fromUser, aa->Announcement(),
aa->Priority());
return xpEvent.forget();
}
xpEvent =
new xpcAccEvent(type, ToXPC(acc), ToXPCDocument(doc), node, fromUser);
return xpEvent.forget();

Просмотреть файл

@ -104,6 +104,7 @@ class AccEvent {
eVirtualCursorChangeEvent,
eObjectAttrChangedEvent,
eScrollingEvent,
eAnnouncementEvent,
};
static const EventGroup kEventGroup = eGenericEvent;
@ -544,6 +545,34 @@ class AccScrollingEvent : public AccEvent {
uint32_t mMaxScrollY;
};
/**
* Accessible announcement event.
*/
class AccAnnouncementEvent : public AccEvent {
public:
AccAnnouncementEvent(Accessible* aAccessible, const nsAString& aAnnouncement,
uint16_t aPriority)
: AccEvent(nsIAccessibleEvent::EVENT_ANNOUNCEMENT, aAccessible),
mAnnouncement(aAnnouncement),
mPriority(aPriority) {}
virtual ~AccAnnouncementEvent() {}
// AccEvent
static const EventGroup kEventGroup = eAnnouncementEvent;
virtual unsigned int GetEventGroups() const override {
return AccEvent::GetEventGroups() | (1U << eAnnouncementEvent);
}
const nsString& Announcement() const { return mAnnouncement; }
uint16_t Priority() { return mPriority; }
private:
nsString mAnnouncement;
uint16_t mPriority;
};
/**
* Downcast the generic accessible event object to derived type.
*/

Просмотреть файл

@ -465,6 +465,7 @@ static const char kEventTypeNames[][40] = {
"virtual cursor changed", // EVENT_VIRTUALCURSOR_CHANGED
"text value change", // EVENT_TEXT_VALUE_CHANGE
"scrolling", // EVENT_SCROLLING
"announcement", // EVENT_ANNOUNCEMENT
};
#endif

Просмотреть файл

@ -914,6 +914,14 @@ nsresult Accessible::HandleAccEvent(AccEvent* aEvent) {
scrollingEvent->MaxScrollY());
break;
}
#if !defined(XP_WIN)
case nsIAccessibleEvent::EVENT_ANNOUNCEMENT: {
AccAnnouncementEvent* announcementEvent = downcast_accEvent(aEvent);
ipcDoc->SendAnnouncementEvent(id, announcementEvent->Announcement(),
announcementEvent->Priority());
break;
}
#endif
default:
ipcDoc->SendEvent(id, aEvent->GetEventType());
}
@ -2441,6 +2449,12 @@ Accessible* Accessible::ContainerWidget() const {
return nullptr;
}
void Accessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) {
RefPtr<AccAnnouncementEvent> event =
new AccAnnouncementEvent(this, aAnnouncement, aPriority);
nsEventShell::FireEvent(event);
}
////////////////////////////////////////////////////////////////////////////////
// Accessible protected methods

Просмотреть файл

@ -980,6 +980,8 @@ class Accessible : public nsISupports {
*/
void SetHideEventTarget(bool aTarget) { mHideEventTarget = aTarget; }
void Announce(const nsAString& aAnnouncement, uint16_t aPriority);
protected:
virtual ~Accessible();

Просмотреть файл

@ -10,6 +10,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows' and CONFIG['COMPILE_ENVIRONMENT']:
XPIDL_SOURCES += [
'nsIAccessibilityService.idl',
'nsIAccessible.idl',
'nsIAccessibleAnnouncementEvent.idl',
'nsIAccessibleApplication.idl',
'nsIAccessibleCaretMoveEvent.idl',
'nsIAccessibleDocument.idl',

Просмотреть файл

@ -298,6 +298,16 @@ interface nsIAccessible : nsISupports
*/
void scrollToPoint(in unsigned long coordinateType, in long x, in long y);
/**
* Dispatches an ANNOUNCEMENT event with this accessible as target.
*
* @param announcement [in] - string to use in announcement.
* @param priority [in] - priority for announcement, could be
* nsIAccessibleAnnouncementEvent.POLITE or
* nsIAccessibleAnnouncementEvent.ASSERTIVE.
*/
void announce(in AString announcement, in unsigned short priority);
%{C++
virtual mozilla::a11y::Accessible* ToInternalAccessible() const = 0;
%}

Просмотреть файл

@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIAccessibleEvent.idl"
/**
* Fired when announce() is called on the target accessible.
*/
[scriptable, builtinclass, uuid(8818e49c-1286-4fe6-ae82-4d1b795ec88d)]
interface nsIAccessibleAnnouncementEvent : nsIAccessibleEvent
{
const unsigned short POLITE = 0;
const unsigned short ASSERTIVE = 1;
// String of actual announcement
readonly attribute AString announcement;
// Priority for announcement, could be POLITE or ASSERTIVE, ATs
// will decide how to appropriately present it.
readonly attribute unsigned short priority;
};

Просмотреть файл

@ -423,10 +423,15 @@ interface nsIAccessibleEvent : nsISupports
*/
const unsigned long EVENT_SCROLLING = 0x0058;
/**
* An accessible is making an explicit announcement.
*/
const unsigned long EVENT_ANNOUNCEMENT = 0x0059;
/**
* Help make sure event map does not get out-of-line.
*/
const unsigned long EVENT_LAST_ENTRY = 0x0059;
const unsigned long EVENT_LAST_ENTRY = 0x005A;
/**
* The type of event, based on the enumerated event values

Просмотреть файл

@ -431,6 +431,35 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvScrollingEvent(
return IPC_OK();
}
#if !defined(XP_WIN)
mozilla::ipc::IPCResult DocAccessibleParent::RecvAnnouncementEvent(
const uint64_t& aID, const nsString& aAnnouncement,
const uint16_t& aPriority) {
ProxyAccessible* target = GetAccessible(aID);
if (!target) {
NS_ERROR("no proxy for event!");
return IPC_OK();
}
// XXX: A future patch will add platform support for this event type.
// Right now, we just need to support XPC for testing.
if (!nsCoreUtils::AccEventObserversExist()) {
return IPC_OK();
}
xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
RefPtr<xpcAccAnnouncementEvent> event = new xpcAccAnnouncementEvent(
nsIAccessibleEvent::EVENT_ANNOUNCEMENT, xpcAcc, doc, nullptr, false,
aAnnouncement, aPriority);
nsCoreUtils::DispatchAccEvent(std::move(event));
return IPC_OK();
}
#endif
mozilla::ipc::IPCResult DocAccessibleParent::RecvRoleChangedEvent(
const a11y::role& aRole) {
if (mShutdown) {

Просмотреть файл

@ -117,6 +117,12 @@ class DocAccessibleParent : public ProxyAccessible,
const uint32_t& aScrollY, const uint32_t& aMaxScrollX,
const uint32_t& aMaxScrollY) override;
#if !defined(XP_WIN)
virtual mozilla::ipc::IPCResult RecvAnnouncementEvent(
const uint64_t& aID, const nsString& aAnnouncement,
const uint16_t& aPriority) override;
#endif
mozilla::ipc::IPCResult RecvRoleChangedEvent(const a11y::role& aRole) final;
virtual mozilla::ipc::IPCResult RecvBindChildDoc(

Просмотреть файл

@ -68,6 +68,8 @@ int32_t GetLevelInternal();
void ScrollTo(uint32_t aScrollType);
void ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY);
void Announce(const nsString& aAnnouncement, uint16_t aPriority);
int32_t CaretLineNumber();
int32_t CaretOffset();
void SetCaretOffset(int32_t aOffset);

Просмотреть файл

@ -263,6 +263,17 @@ mozilla::ipc::IPCResult DocAccessibleChild::RecvScrollToPoint(
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessibleChild::RecvAnnounce(
const uint64_t& aID, const nsString& aAnnouncement,
const uint16_t& aPriority) {
Accessible* acc = IdToAccessible(aID);
if (acc) {
acc->Announce(aAnnouncement, aPriority);
}
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessibleChild::RecvCaretLineNumber(
const uint64_t& aID, int32_t* aLineNumber) {
HyperTextAccessible* acc = IdToHyperTextAccessible(aID);

Просмотреть файл

@ -93,6 +93,10 @@ class DocAccessibleChild : public DocAccessibleChildBase {
const int32_t& aX,
const int32_t& aY) override;
virtual mozilla::ipc::IPCResult RecvAnnounce(
const uint64_t& aID, const nsString& aAnnouncement,
const uint16_t& aPriority) override;
virtual mozilla::ipc::IPCResult RecvCaretLineNumber(
const uint64_t& aID, int32_t* aLineNumber) override;
virtual mozilla::ipc::IPCResult RecvCaretOffset(const uint64_t& aID,

Просмотреть файл

@ -97,6 +97,9 @@ parent:
async ScrollingEvent(uint64_t aID, uint64_t aType,
uint32_t aScrollX, uint32_t aScrollY,
uint32_t aMaxScrollX, uint32_t aMaxScrollY);
async AnnouncementEvent(uint64_t aID,
nsString aAnnouncement,
uint16_t aPriority);
/*
* Tell the parent document to bind the existing document as a new child
@ -134,6 +137,7 @@ child:
async ScrollTo(uint64_t aID, uint32_t aScrollType);
async ScrollToPoint(uint64_t aID, uint32_t aScrollType, int32_t aX,
int32_t aY);
async Announce(uint64_t aID, nsString aAnnouncement, uint16_t aPriority);
// AccessibleText

Просмотреть файл

@ -126,6 +126,11 @@ void ProxyAccessible::ScrollToPoint(uint32_t aScrollType, int32_t aX,
Unused << mDoc->SendScrollToPoint(mID, aScrollType, aX, aY);
}
void ProxyAccessible::Announce(const nsString& aAnnouncement,
uint16_t aPriority) {
Unused << mDoc->SendAnnounce(mID, aAnnouncement, aPriority);
}
int32_t ProxyAccessible::CaretLineNumber() {
int32_t line = -1;
Unused << mDoc->SendCaretOffset(mID, &line);

Просмотреть файл

@ -23,6 +23,8 @@ skip-if = (e10s && os == 'win') || (os == 'mac' && debug) # Bug 1338034, leaks #
[browser_caching_value.js]
# Events tests
[browser_events_announcement.js]
skip-if = e10s && os == 'win' # Bug 1288839
[browser_events_caretmove.js]
[browser_events_hide.js]
[browser_events_show.js]

Просмотреть файл

@ -0,0 +1,23 @@
/* 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";
addAccessibleTask(`<p id="p">abc</p>`,
async function(browser, accDoc) {
let acc = findAccessibleChildByID(accDoc, "p");
let onAnnounce = waitForEvent(EVENT_ANNOUNCEMENT, acc);
acc.announce("please", nsIAccessibleAnnouncementEvent.POLITE);
let evt = await onAnnounce;
evt.QueryInterface(nsIAccessibleAnnouncementEvent);
is(evt.announcement, "please", "announcement matches.");
is(evt.priority, nsIAccessibleAnnouncementEvent.POLITE, "priority matches");
onAnnounce = waitForEvent(EVENT_ANNOUNCEMENT, acc);
acc.announce("do it", nsIAccessibleAnnouncementEvent.ASSERTIVE);
evt = await onAnnounce;
evt.QueryInterface(nsIAccessibleAnnouncementEvent);
is(evt.announcement, "do it", "announcement matches.");
is(evt.priority, nsIAccessibleAnnouncementEvent.ASSERTIVE, "priority matches");
});

Просмотреть файл

@ -9,15 +9,16 @@
/* import-globals-from shared-head.js */
/* import-globals-from ../mochitest/common.js */
/* exported EVENT_REORDER, EVENT_SCROLLING, EVENT_SCROLLING_END, EVENT_SHOW,
EVENT_TEXT_INSERTED, EVENT_TEXT_REMOVED,
EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE, EVENT_TEXT_CARET_MOVED,
EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE,
EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS,
EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED,
/* exported EVENT_ANNOUNCEMENT, EVENT_REORDER, EVENT_SCROLLING,
EVENT_SCROLLING_END, EVENT_SHOW, EVENT_TEXT_INSERTED,
EVENT_TEXT_REMOVED, EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE,
EVENT_TEXT_CARET_MOVED, EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE,
EVENT_STATE_CHANGE, EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE,
EVENT_FOCUS, EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED,
UnexpectedEvents, contentSpawnMutation, waitForEvent, waitForEvents,
waitForOrderedEvents */
const EVENT_ANNOUNCEMENT = nsIAccessibleEvent.EVENT_ANNOUNCEMENT;
const EVENT_DOCUMENT_LOAD_COMPLETE = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE;
const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;

Просмотреть файл

@ -16,6 +16,8 @@ const nsIAccessibleVirtualCursorChangeEvent =
Ci.nsIAccessibleVirtualCursorChangeEvent;
const nsIAccessibleObjectAttributeChangedEvent =
Ci.nsIAccessibleObjectAttributeChangedEvent;
const nsIAccessibleAnnouncementEvent =
Ci.nsIAccessibleAnnouncementEvent;
const nsIAccessibleStates = Ci.nsIAccessibleStates;
const nsIAccessibleRole = Ci.nsIAccessibleRole;

Просмотреть файл

@ -5,6 +5,7 @@
// Constants
const EVENT_ALERT = nsIAccessibleEvent.EVENT_ALERT;
const EVENT_ANNOUNCEMENT = nsIAccessibleEvent.EVENT_ANNOUNCEMENT;
const EVENT_DESCRIPTION_CHANGE = nsIAccessibleEvent.EVENT_DESCRIPTION_CHANGE;
const EVENT_DOCUMENT_LOAD_COMPLETE = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE;
const EVENT_DOCUMENT_RELOAD = nsIAccessibleEvent.EVENT_DOCUMENT_RELOAD;

Просмотреть файл

@ -5,6 +5,7 @@ support-files =
!/accessible/tests/mochitest/*.js
!/accessible/tests/mochitest/letters.gif
[test_announcement.html]
[test_aria_alert.html]
[test_aria_menu.html]
[test_aria_objattr.html]

Просмотреть файл

@ -0,0 +1,62 @@
<html>
<head>
<title>Announcement event and method testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
async function doTests() {
let acc = getAccessible("display");
let onAnnounce = waitForEventPromise(EVENT_ANNOUNCEMENT, acc);
acc.announce("please", nsIAccessibleAnnouncementEvent.POLITE);
let evt = await onAnnounce;
evt.QueryInterface(nsIAccessibleAnnouncementEvent);
is(evt.announcement, "please", "announcement matches.");
is(evt.priority, nsIAccessibleAnnouncementEvent.POLITE, "priority matches");
onAnnounce = waitForEventPromise(EVENT_ANNOUNCEMENT, acc);
acc.announce("do it", nsIAccessibleAnnouncementEvent.ASSERTIVE);
evt = await onAnnounce;
evt.QueryInterface(nsIAccessibleAnnouncementEvent);
is(evt.announcement, "do it", "announcement matches.");
is(evt.priority, nsIAccessibleAnnouncementEvent.ASSERTIVE,
"priority matches");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1525980"
title="Introduce announcement event and method">
Mozilla Bug 1525980
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -11,7 +11,7 @@
#include "mozilla/a11y/Compatibility.h"
#include "mozilla/a11y/Platform.h"
#include "mozilla/Assertions.h"
#include "mozilla/mscom/MainThreadRuntime.h"
#include "mozilla/mscom/ProcessRuntime.h"
#include "mozilla/mscom/Registration.h"
#include "mozilla/UniquePtr.h"
#include "nsAccessibilityService.h"
@ -313,7 +313,7 @@ LazyInstantiator::MaybeResolveRoot() {
}
if (GetAccService() ||
ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) {
ShouldInstantiate(mscom::ProcessRuntime::GetClientThreadId())) {
mWeakRootAccWrap = ResolveRootAccWrap();
if (!mWeakRootAccWrap) {
return E_POINTER;

Просмотреть файл

@ -101,5 +101,6 @@ static const uint32_t gWinEventMap[] = {
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED
EVENT_OBJECT_VALUECHANGE, // nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_SCROLLING
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_ANNOUNCEMENT
// clang-format on
};

Просмотреть файл

@ -15,5 +15,6 @@ simple_events = [
'ObjectAttributeChangedEvent',
'TableChangeEvent',
'VirtualCursorChangeEvent',
'ScrollingEvent'
'ScrollingEvent',
'AnnouncementEvent'
]

Просмотреть файл

@ -757,3 +757,19 @@ xpcAccessible::ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) {
return NS_OK;
}
NS_IMETHODIMP
xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) {
if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
#if defined(XP_WIN)
return NS_ERROR_NOT_IMPLEMENTED;
#else
nsString announcement(aAnnouncement);
proxy->Announce(announcement, aPriority);
#endif
} else {
Intl()->Announce(aAnnouncement, aPriority);
}
return NS_OK;
}

Просмотреть файл

@ -82,6 +82,8 @@ class xpcAccessible : public nsIAccessible {
NS_IMETHOD ScrollToPoint(uint32_t aCoordinateType, int32_t aX,
int32_t aY) final;
NS_IMETHOD Announce(const nsAString& aAnnouncement, uint16_t aPriority) final;
protected:
xpcAccessible() {}
virtual ~xpcAccessible() {}

Просмотреть файл

@ -62,7 +62,7 @@ if CONFIG['LIBFUZZER']:
if CONFIG['ENABLE_GECKODRIVER']:
DEFINES['MOZ_GECKODRIVER'] = True
if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
if CONFIG['CC_TYPE'] == 'clang-cl':
# Always enter a Windows program through wmain, whether or not we're
# a console application.
WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']

Просмотреть файл

@ -483,6 +483,9 @@ pref("browser.tabs.newanimations", false);
pref("browser.tabs.remote.separatePrivilegedContentProcess", true);
#endif
// Turn on HTTP response process selection.
pref("browser.tabs.remote.useHTTPResponseProcessSelection", true);
pref("browser.ctrlTab.recentlyUsedOrder", true);
// By default, do not export HTML at shutdown.
@ -1788,16 +1791,14 @@ pref("browser.fission.simulate", false);
// On platforms that do not build libprio, do not set these prefs at all, which gives us a way to detect support.
// Curve25519 public keys for Prio servers
#ifdef MOZ_LIBPRIO
pref("prio.publicKeyA", "35AC1C7576C7C6EDD7FED6BCFC337B34D48CB4EE45C86BEEFB40BD8875707733");
pref("prio.publicKeyB", "26E6674E65425B823F1F1D5F96E3BB3EF9E406EC7FBA7DEF8B08A35DD135AF50");
#endif
// Coverage ping is disabled by default.
pref("toolkit.coverage.enabled", false);
pref("toolkit.coverage.endpoint.base", "https://coverage.mozilla.org");
// Whether or not Prio-encoded Telemetry will be sent along with the main ping.
#if defined(NIGHTLY_BUILD) && defined(MOZ_LIBPRIO)
#if defined(NIGHTLY_BUILD)
pref("prio.enabled", true);
#endif

Просмотреть файл

@ -9,7 +9,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/CmdLineAndEnvUtils.h"
#include "mozilla/LauncherResult.h"
#include "mozilla/mscom/COMApartmentRegion.h"
#include "mozilla/mscom/ApartmentRegion.h"
#include "mozilla/RefPtr.h"
#include "nsWindowsHelpers.h"

Просмотреть файл

@ -35,8 +35,8 @@
#endif
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/aboutDialog.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/aboutDialog.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/>

Просмотреть файл

@ -2174,7 +2174,7 @@ function BrowserHome(aEvent) {
aEvent.button == 2) // right-click: do nothing
return;
var homePage = HomePage.get();
var homePage = HomePage.get(window);
var where = whereToOpenLink(aEvent, false, true);
var urls;
var notifyObservers;

Просмотреть файл

@ -8,6 +8,7 @@
<?xml-stylesheet href="chrome://browser/content/safeMode.css"?>
<dialog id="safeModeDialog"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
data-l10n-id="safe-mode-window"
data-l10n-attrs="title,style"
@ -20,8 +21,8 @@
onload="onLoad()">
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/safeMode.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/safeMode.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/safeMode.js"/>

Просмотреть файл

@ -26,7 +26,7 @@
ondialogaccept="return gSanitizePromptDialog.sanitize();">
<linkset>
<link rel="localization" href="browser/sanitize.ftl"/>
<html:link rel="localization" href="browser/sanitize.ftl"/>
</linkset>
<script type="application/javascript"

Просмотреть файл

@ -47,58 +47,67 @@ add_task(async function test() {
add_task(async function testLazyTabs() {
let params = {createLazyBrowser: true};
let tabs = [];
let oldTabs = [];
let numTabs = 4;
for (let i = 0; i < numTabs; ++i) {
tabs.push(BrowserTestUtils.addTab(gBrowser, `http://example.com/?${i}`, params));
oldTabs.push(BrowserTestUtils.addTab(gBrowser, `http://example.com/?${i}`, params));
}
await BrowserTestUtils.switchTab(gBrowser, tabs[0]);
await BrowserTestUtils.switchTab(gBrowser, oldTabs[0]);
for (let i = 1; i < numTabs; ++i) {
await triggerClickOn(tabs[i], { ctrlKey: true });
await triggerClickOn(oldTabs[i], { ctrlKey: true });
}
isnot(tabs[0].linkedPanel, "", `Tab 0 shouldn't be lazy`);
isnot(oldTabs[0].linkedPanel, "", `Old tab 0 shouldn't be lazy`);
for (let i = 1; i < numTabs; ++i) {
is(tabs[i].linkedPanel, "", `Tab ${i} should be lazy`);
is(oldTabs[i].linkedPanel, "", `Old tab ${i} should be lazy`);
}
is(gBrowser.multiSelectedTabsCount, numTabs, `${numTabs} multiselected tabs`);
for (let i = 0; i < numTabs; ++i) {
ok(tabs[i].multiselected, `Tab ${i} should be multiselected`);
ok(oldTabs[i].multiselected, `Old tab ${i} should be multiselected`);
}
let tabsMoved = new Promise(resolve => {
// Tab tabs in the new window will be about:blank before swapping the docshells.
// The "EndSwapDocShells" event is not dispatched for lazy tabs, so listen for
// "TabClose" instead and await a tick.
let i = 0;
window.addEventListener("TabClose", async function listener() {
let numTabsMoved = 0;
window.addEventListener("TabClose", async function listener(event) {
let tab = event.target;
let i = oldTabs.indexOf(tab);
if (i == 0) {
isnot(tab.linkedPanel, "", `Old tab ${i} should continue not being lazy`);
} else if (i > 0) {
is(tab.linkedPanel, "", `Old tab ${i} should continue being lazy`);
} else {
return;
}
await Promise.resolve();
if (++i == numTabs) {
if (++numTabsMoved == numTabs) {
window.removeEventListener("TabClose", listener);
resolve();
}
});
});
let newWindow = gBrowser.replaceTabsWithWindow(tabs[0]);
let newWindow = gBrowser.replaceTabsWithWindow(oldTabs[0]);
await tabsMoved;
tabs = newWindow.gBrowser.tabs;
let newTabs = newWindow.gBrowser.tabs;
isnot(tabs[0].linkedPanel, "", `Tab 0 should continue not being lazy`);
isnot(newTabs[0].linkedPanel, "", `New tab 0 should continue not being lazy`);
// FIXME: bug 1521923 - First inactive tab to be moved into another window loses laziness
todo_is(tabs[1].linkedPanel, "", `Tab 1 should continue being lazy`);
todo_is(newTabs[1].linkedPanel, "", `New tab 1 should continue being lazy`);
for (let i = 2; i < numTabs; ++i) {
is(tabs[i].linkedPanel, "", `Tab ${i} should continue being lazy`);
is(newTabs[i].linkedPanel, "", `New tab ${i} should continue being lazy`);
}
is(tabs[0].linkedBrowser.currentURI.spec, `http://example.com/?0`,
`Tab 0 should have the right URL`);
todo_is(SessionStore.getLazyTabValue(tabs[1], "url"), `http://example.com/?1`,
`Tab 1 should have the right lazy URL`);
is(newTabs[0].linkedBrowser.currentURI.spec, `http://example.com/?0`,
`New tab 0 should have the right URL`);
todo_is(SessionStore.getLazyTabValue(newTabs[1], "url"), `http://example.com/?1`,
`New tab 1 should have the right lazy URL`);
for (let i = 2; i < numTabs; ++i) {
is(SessionStore.getLazyTabValue(tabs[i], "url"), `http://example.com/?${i}`,
`Tab ${i} should have the right lazy URL`);
is(SessionStore.getLazyTabValue(newTabs[i], "url"), `http://example.com/?${i}`,
`New tab ${i} should have the right lazy URL`);
}
BrowserTestUtils.closeWindow(newWindow);

Просмотреть файл

@ -24,6 +24,7 @@ add_task(async function() {
await SpecialPowers.pushPrefEnv(
{set: [["browser.tabs.remote.separateFileUriProcess", true],
["browser.tabs.remote.allowLinkedWebInFileUriProcess", true],
["browser.tabs.remote.useHTTPResponseProcessSelection", false],
["dom.ipc.processCount.file", 2]]});
// Open file:// page.

Просмотреть файл

@ -24,10 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
Object.defineProperty(this, "BROWSER_NEW_TAB_URL", {
enumerable: true,
get() {
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
!aboutNewTabService.overridden) {
return "about:privatebrowsing";
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
if (!PrivateBrowsingUtils.permanentPrivateBrowsing &&
!aboutNewTabService.overridden) {
return "about:privatebrowsing";
}
// If the extension does not have private browsing permission,
// use about:privatebrowsing.
if (aboutNewTabService.newTabURL.startsWith("moz-extension")) {
let url = new URL(aboutNewTabService.newTabURL);
if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) {
return "about:privatebrowsing";
}
}
}
return aboutNewTabService.newTabURL;
},

Просмотреть файл

@ -209,7 +209,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData
let args;
if (!urlOrUrlList) {
// Just pass in the defaultArgs directly. We'll use system principal on the other end.
args = [gBrowserContentHandler.defaultArgs];
args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)];
} else {
let pService = Cc["@mozilla.org/toolkit/profile-service;1"].
getService(Ci.nsIToolkitProfileService);
@ -518,7 +518,7 @@ nsBrowserContentHandler.prototype = {
/* nsIBrowserHandler */
get defaultArgs() {
getDefaultArgs(forcePrivate = false) {
var prefb = Services.prefs;
if (!gFirstWindow) {
@ -603,7 +603,7 @@ nsBrowserContentHandler.prototype = {
try {
var choice = prefb.getIntPref("browser.startup.page");
if (choice == 1 || choice == 3)
startPage = HomePage.get();
startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get();
} catch (e) {
Cu.reportError(e);
}
@ -621,6 +621,10 @@ nsBrowserContentHandler.prototype = {
return overridePage || startPage || "about:blank";
},
get defaultArgs() {
return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing);
},
mFeatures: null,
getFeatures: function bch_features(cmdLine) {

Просмотреть файл

@ -31,6 +31,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
let {
makeWidgetId,
@ -195,6 +197,12 @@ class ExtensionControlledPopup {
extensionId = item && item.id;
}
let win = targetWindow || this.topWindow;
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win);
if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) {
return;
}
// The item should have an extension and the user shouldn't have confirmed
// the change here, but just to be sure check that it is still controlled
// and the user hasn't already confirmed the change.
@ -203,7 +211,6 @@ class ExtensionControlledPopup {
return;
}
let win = targetWindow || this.topWindow;
// If the window closes while waiting for focus, this might reject/throw,
// and we should stop trying to show the popup.
try {

Просмотреть файл

@ -454,10 +454,11 @@ class TabTracker extends TabTrackerBase {
// This tab is being created to adopt a tab from a different window.
// Handle the adoption.
this.adopt(nativeTab, adoptedTab);
adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetFrameData", {
windowId: windowTracker.getId(nativeTab.ownerGlobal),
});
if (adoptedTab.linkedPanel) {
adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetFrameData", {
windowId: windowTracker.getId(nativeTab.ownerGlobal),
});
}
} else {
// Save the size of the current tab, since the newly-created tab will
// likely be active by the time the promise below resolves and the

Просмотреть файл

@ -191,8 +191,13 @@ this.windows = class extends ExtensionAPI {
args.appendElement(mkstr(createData.url));
}
} else {
let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ?
"about:privatebrowsing" : HomePage.get().split("|", 1)[0];
let url;
if (createData.incognito) {
url = PrivateBrowsingUtils.permanentPrivateBrowsing ?
HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing";
} else {
url = HomePage.get().split("|", 1)[0];
}
args.appendElement(mkstr(url));
if (url.startsWith("about:") &&

Просмотреть файл

@ -422,3 +422,119 @@ add_task(async function test_doorhanger_new_window() {
ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall");
});
add_task(async function test_overriding_home_page_incognito_not_allowed() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_settings_overrides: {"homepage": "home.html"},
name: "extension",
},
background() {
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
},
files: {"home.html": "<h1>1</h1>"},
useAddonManager: "temporary",
});
await extension.startup();
let url = await extension.awaitMessage("url");
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url});
let win = OpenBrowserWindow();
await windowOpenedPromise;
let doc = win.document;
let description = doc.getElementById("extension-homepage-notification-description");
let panel = doc.getElementById("extension-notification-panel");
await promisePopupShown(panel);
let popupnotification = description.closest("popupnotification");
is(description.textContent,
"An extension, extension, changed what you see when you open your homepage and new windows.Learn more",
"The extension name is in the popup");
is(popupnotification.hidden, false, "The expected popup notification is visible");
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control");
await BrowserTestUtils.closeWindow(win);
// Verify a private window does not open the extension page.
windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
win.BrowserHome();
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
is(win.gURLBar.value, "", "home page not used in private window");
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
name: "extension",
},
background() {
browser.test.sendMessage("url", browser.runtime.getURL("home.html"));
},
files: {"home.html": "<h1>1</h1>"},
useAddonManager: "temporary",
});
await extension.startup();
let url = await extension.awaitMessage("url");
// Verify manually setting the pref to the extension page does not work.
let changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url);
await changed;
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
win.BrowserHome();
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
is(win.gURLBar.value, "", "home page not used in private window");
changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF);
Services.prefs.clearUserPref(HOMEPAGE_URL_PREF);
await changed;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_home_page_incognito_spanning() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_settings_overrides: {"homepage": "home.html"},
name: "private extension",
applications: {
gecko: {id: "@spanning-home"},
},
},
files: {"home.html": "<h1>1</h1>"},
useAddonManager: "permanent",
incognitoOverride: "spanning",
});
await extension.startup();
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let doc = win.document;
let panel = doc.getElementById("extension-notification-panel");
win.BrowserHome();
await promisePopupShown(panel);
ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window");
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});

Просмотреть файл

@ -5,6 +5,9 @@
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
const NEWTAB_URI_1 = "webext-newtab-1.html";
@ -522,3 +525,189 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() {
BrowserTestUtils.removeTab(tab);
await extension.unload();
});
add_task(async function test_overriding_newtab_incognito_not_allowed() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let panel = getNewTabDoorhanger().closest("panel");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_url_overrides: {"newtab": "newtab.html"},
name: "extension",
applications: {
gecko: {id: "@not-allowed-newtab"},
},
},
files: {
"newtab.html": `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
<script src="newtab.js"></script>
</body>
</html>
`,
"newtab.js": function() {
window.onload = () => {
browser.test.sendMessage("from-newtab-page", window.location.href);
};
},
},
useAddonManager: "permanent",
});
await extension.startup();
let popupShown = promisePopupShown(panel);
BrowserOpenTab();
await popupShown;
let url = await extension.awaitMessage("from-newtab-page");
ok(url.endsWith("newtab.html"),
"Newtab url is overridden by the extension.");
// This will show a confirmation doorhanger, make sure we don't leave it open.
let popupHidden = promisePopupHidden(panel);
panel.hidePopup();
await popupHidden;
BrowserTestUtils.removeTab(gBrowser.selectedTab);
// Verify a private window does not open the extension page. We would
// get an extra notification that we don't listen for if it gets loaded.
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let newTabOpened = waitForNewTab();
win.BrowserOpenTab();
await newTabOpened;
is(win.gURLBar.value, "", "newtab not used in private window");
// Verify setting the pref directly doesn't bypass permissions.
let origUrl = aboutNewTabService.newTabURL;
aboutNewTabService.newTabURL = url;
newTabOpened = waitForNewTab();
win.BrowserOpenTab();
await newTabOpened;
is(win.gURLBar.value, "", "directly set newtab not used in private window");
aboutNewTabService.newTabURL = origUrl;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
name: "extension",
applications: {
gecko: {id: "@not-allowed-newtab"},
},
},
background() {
browser.test.sendMessage("url", browser.runtime.getURL("newtab.html"));
},
files: {
"newtab.html": `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
</body>
</html>
`,
},
useAddonManager: "permanent",
});
await extension.startup();
let url = await extension.awaitMessage("url");
// Verify setting the pref directly doesn't bypass permissions.
let origUrl = aboutNewTabService.newTabURL;
aboutNewTabService.newTabURL = url;
// Verify a private window does not open the extension page. We would
// get an extra notification that we don't listen for if it gets loaded.
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let newTabOpened = waitForNewTab();
win.BrowserOpenTab();
await newTabOpened;
is(win.gURLBar.value, "", "directly set newtab not used in private window");
aboutNewTabService.newTabURL = origUrl;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_overriding_newtab_incognito_spanning() {
await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
chrome_url_overrides: {"newtab": "newtab.html"},
name: "extension",
applications: {
gecko: {id: "@spanning-newtab"},
},
},
files: {
"newtab.html": `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
<script src="newtab.js"></script>
</body>
</html>
`,
"newtab.js": function() {
window.onload = () => {
browser.test.sendMessage("from-newtab-page", window.location.href);
};
},
},
useAddonManager: "permanent",
incognitoOverride: "spanning",
});
await extension.startup();
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
let win = OpenBrowserWindow({private: true});
await windowOpenedPromise;
let panel = win.document.getElementById("extension-new-tab-notification").closest("panel");
let popupShown = promisePopupShown(panel);
win.BrowserOpenTab();
await popupShown;
let url = await extension.awaitMessage("from-newtab-page");
ok(url.endsWith("newtab.html"),
"Newtab url is overridden by the extension.");
// This will show a confirmation doorhanger, make sure we don't leave it open.
let popupHidden = promisePopupHidden(panel);
panel.hidePopup();
await popupHidden;
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
async function testIconPaths(icon, manifest, expectedError) {
let normalized = await ExtensionTestUtils.normalizeManifest(manifest);
if (expectedError) {
ok(expectedError.test(normalized.error),
`Should have an error for ${JSON.stringify(manifest)}`);
} else {
ok(!normalized.error, `Should not have an error ${JSON.stringify(manifest)}, ${normalized.error}`);
}
}
add_task(async function test_manifest() {
let badpaths = ["", " ", "\t", "http://foo.com/icon.png"];
for (let path of badpaths) {
for (let action of ["browser_action", "page_action", "sidebar_action"]) {
let manifest = {};
manifest[action] = {default_icon: path};
let error = new RegExp(`Error processing ${action}.default_icon`);
await testIconPaths(path, manifest, error);
manifest[action] = {default_icon: {"16": path}};
await testIconPaths(path, manifest, error);
}
}
let paths = ["icon.png", "/icon.png", "./icon.png", "path to an icon.png", " icon.png"];
for (let path of paths) {
for (let action of ["browser_action", "page_action", "sidebar_action"]) {
let manifest = {};
manifest[action] = {default_icon: path};
if (action == "sidebar_action") {
// Sidebar requires panel.
manifest[action].default_panel = "foo.html";
}
await testIconPaths(path, manifest);
manifest[action] = {default_icon: {"16": path}};
if (action == "sidebar_action") {
manifest[action].default_panel = "foo.html";
}
await testIconPaths(path, manifest);
}
}
});

Просмотреть файл

@ -17,6 +17,7 @@ dupe-manifest =
# For tests which should only run with both remote extensions and remote content.
[test_ext_geckoProfiler_schema.js]
[test_ext_manifest.js]
[test_ext_manifest_commands.js]
[test_ext_manifest_omnibox.js]
[test_ext_manifest_permissions.js]

Просмотреть файл

@ -8,6 +8,7 @@
<dialog id="appManager"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
buttons="accept,cancel"
onload="gAppManagerDialog.onLoad();"
ondialogaccept="gAppManagerDialog.onOK();"
@ -17,7 +18,7 @@
persist="screenX screenY">
<linkset>
<link rel="localization" href="browser/preferences/applicationManager.ftl"/>
<html:link rel="localization" href="browser/preferences/applicationManager.ftl"/>
</linkset>
<script type="application/javascript"

Просмотреть файл

@ -19,8 +19,8 @@
onkeypress="gBlocklistManager.onWindowKeyPress(event);">
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/preferences/blocklists.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/preferences/blocklists.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/blocklists.js"/>

Просмотреть файл

@ -9,6 +9,7 @@
<dialog id="BrowserLanguagesDialog" type="child"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-id="browser-languages-window"
data-l10n-attrs="title, style"
buttons="accept,cancel,help"
@ -19,8 +20,8 @@
helpTopic="prefs-languages">
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/preferences/languages.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/preferences/languages.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>

Просмотреть файл

@ -11,13 +11,14 @@
<window id="ClearSiteDataDialog"
windowtype="Browser:ClearSiteData"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-id="clear-site-data-window"
data-l10n-attrs="title, style"
persist="screenX screenY width height">
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/preferences/clearSiteData.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/preferences/clearSiteData.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/clearSiteData.js"/>

Просмотреть файл

@ -19,7 +19,7 @@
helpTopic="prefs-fonts-and-colors">
<linkset>
<link rel="localization" href="browser/preferences/colors.ftl"/>
<html:link rel="localization" href="browser/preferences/colors.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>

Просмотреть файл

@ -21,9 +21,9 @@
<!-- Used for extension-controlled lockdown message -->
<linkset>
<link rel="localization" href="browser/preferences/connection.ftl"/>
<link rel="localization" href="browser/preferences/preferences.ftl"/>
<link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/preferences/connection.ftl"/>
<html:link rel="localization" href="browser/preferences/preferences.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>

Просмотреть файл

@ -9,6 +9,7 @@
<window id="ContainersDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-attrs="title, style"
onload="gContainersManager.onLoad();"
onunload="gContainersManager.uninit();"
@ -16,7 +17,7 @@
onkeypress="gContainersManager.onWindowKeyPress(event);">
<linkset>
<link rel="localization" href="browser/preferences/containers.ftl"/>
<html:link rel="localization" href="browser/preferences/containers.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/containers.js"/>

Просмотреть файл

@ -19,7 +19,7 @@
helpTopic="prefs-fonts-and-colors">
<linkset>
<link rel="localization" href="browser/preferences/fonts.ftl"/>
<html:link rel="localization" href="browser/preferences/fonts.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>

Просмотреть файл

@ -25,26 +25,26 @@
data-l10n-attrs="title">
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/branding/sync-brand.ftl"/>
<link rel="localization" href="browser/preferences/preferences.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/branding/sync-brand.ftl"/>
<html:link rel="localization" href="browser/preferences/preferences.ftl"/>
<!-- Used by fontbuilder.js -->
<link rel="localization" href="browser/preferences/fonts.ftl"/>
<html:link rel="localization" href="browser/preferences/fonts.ftl"/>
<!-- Links below are only used for search-l10n-ids into subdialogs -->
<link rel="localization" href="browser/preferences/blocklists.ftl"/>
<link rel="localization" href="browser/preferences/clearSiteData.ftl"/>
<link rel="localization" href="browser/preferences/colors.ftl"/>
<link rel="localization" href="browser/preferences/connection.ftl"/>
<link rel="localization" href="browser/preferences/languages.ftl"/>
<link rel="localization" href="browser/preferences/permissions.ftl"/>
<link rel="localization" href="browser/preferences/selectBookmark.ftl"/>
<link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
<link rel="localization" href="browser/aboutDialog.ftl"/>
<link rel="localization" href="browser/sanitize.ftl"/>
<link rel="localization" href="toolkit/updates/history.ftl"/>
<link rel="localization" href="security/certificates/deviceManager.ftl"/>
<link rel="localization" href="security/certificates/certManager.ftl"/>
<html:link rel="localization" href="browser/preferences/blocklists.ftl"/>
<html:link rel="localization" href="browser/preferences/clearSiteData.ftl"/>
<html:link rel="localization" href="browser/preferences/colors.ftl"/>
<html:link rel="localization" href="browser/preferences/connection.ftl"/>
<html:link rel="localization" href="browser/preferences/languages.ftl"/>
<html:link rel="localization" href="browser/preferences/permissions.ftl"/>
<html:link rel="localization" href="browser/preferences/selectBookmark.ftl"/>
<html:link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
<html:link rel="localization" href="browser/aboutDialog.ftl"/>
<html:link rel="localization" href="browser/sanitize.ftl"/>
<html:link rel="localization" href="toolkit/updates/history.ftl"/>
<html:link rel="localization" href="security/certificates/deviceManager.ftl"/>
<html:link rel="localization" href="security/certificates/certManager.ftl"/>
</linkset>
<html:link rel="shortcut icon"

Просмотреть файл

@ -10,14 +10,15 @@
<window id="syncDisconnectDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
role="dialog"
onload="gSyncDisconnectDialog.init();"
data-l10n-id="sync-disconnect-dialog"
data-l10n-attrs="title, style">
<linkset>
<link rel="localization" href="browser/branding/sync-brand.ftl"/>
<link rel="localization" href="browser/preferences/syncDisconnect.ftl"/>
<html:link rel="localization" href="browser/branding/sync-brand.ftl"/>
<html:link rel="localization" href="browser/preferences/syncDisconnect.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/in-content/syncDisconnect.js"/>

Просмотреть файл

@ -9,6 +9,7 @@
<dialog id="LanguagesDialog" type="child"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-id="webpage-languages-window"
data-l10n-attrs="title, style"
buttons="accept,cancel,help"
@ -18,7 +19,7 @@
helpTopic="prefs-languages">
<linkset>
<link rel="localization" href="browser/preferences/languages.ftl"/>
<html:link rel="localization" href="browser/preferences/languages.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>

Просмотреть файл

@ -10,6 +10,7 @@
<window id="PermissionsDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-id="permissions-window"
data-l10n-attrs="title, style"
onload="gPermissionManager.onLoad();"
@ -18,7 +19,7 @@
onkeypress="gPermissionManager.onWindowKeyPress(event);">
<linkset>
<link rel="localization" href="browser/preferences/permissions.ftl"/>
<html:link rel="localization" href="browser/preferences/permissions.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/permissions.js"/>

Просмотреть файл

@ -22,8 +22,8 @@
onload="gSanitizeDialog.init();">
<linkset>
<link rel="localization" href="browser/sanitize.ftl"/>
<link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/sanitize.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
</linkset>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>

Просмотреть файл

@ -11,6 +11,7 @@
<dialog id="selectBookmarkDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-id="select-bookmark-window"
data-l10n-attrs="title, style"
persist="screenX screenY width height" screenX="24" screenY="24"
@ -18,7 +19,7 @@
ondialogaccept="SelectBookmarkDialog.accept();">
<linkset>
<link rel="localization" href="browser/preferences/selectBookmark.ftl"/>
<html:link rel="localization" href="browser/preferences/selectBookmark.ftl"/>
</linkset>
<script type="application/javascript"

Просмотреть файл

@ -16,10 +16,11 @@
onload="gSiteDataRemoveSelected.init();"
ondialogaccept="gSiteDataRemoveSelected.ondialogaccept(); return true;"
ondialogcancel="gSiteDataRemoveSelected.ondialogcancel(); return true;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
<linkset>
<link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
<html:link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
</linkset>
<hbox>

Просмотреть файл

@ -13,14 +13,15 @@
data-l10n-id="site-data-settings-window"
data-l10n-attrs="title"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
style="width: 45em;"
onload="gSiteDataSettings.init();"
onkeypress="gSiteDataSettings.onKeyPress(event);"
persist="screenX screenY width height">
<linkset>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/siteDataSettings.js"/>

Просмотреть файл

@ -11,6 +11,7 @@
<window id="SitePermissionsDialog"
windowtype="Browser:SitePermissions"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
data-l10n-id="permissions-window"
data-l10n-attrs="title, style"
onload="gSitePermissionsManager.onLoad();"
@ -19,8 +20,8 @@
onkeypress="gSitePermissionsManager.onWindowKeyPress(event);">
<linkset>
<link rel="localization" href="browser/preferences/preferences.ftl"/>
<link rel="localization" href="browser/preferences/permissions.ftl"/>
<html:link rel="localization" href="browser/preferences/preferences.ftl"/>
<html:link rel="localization" href="browser/preferences/permissions.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/sitePermissions.js"/>

Просмотреть файл

@ -12,13 +12,14 @@
data-l10n-id="translation-window"
data-l10n-attrs="title, style"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
onload="gTranslationExceptions.onLoad();"
onunload="gTranslationExceptions.uninit();"
persist="screenX screenY width height"
onkeypress="gTranslationExceptions.onWindowKeyPress(event);">
<linkset>
<link rel="localization" href="browser/preferences/translation.ftl"/>
<html:link rel="localization" href="browser/preferences/translation.ftl"/>
</linkset>
<script src="chrome://browser/content/preferences/translation.js"/>

Просмотреть файл

@ -186,7 +186,8 @@ ContentRestoreInternal.prototype = {
// If the load was started in another process, and the in-flight channel
// was redirected into this process, resume that load within our process.
if (loadArguments.redirectLoadSwitchId) {
webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId);
webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId,
loadArguments.redirectHistoryIndex);
return true;
}

Просмотреть файл

@ -48,9 +48,7 @@ const OBSERVING = [
"quit-application", "browser:purge-session-history",
"browser:purge-session-history-for-domain",
"idle-daily", "clear-origin-attributes-data",
"http-on-examine-response",
"http-on-examine-merged-response",
"http-on-examine-cached-response",
"http-on-may-change-process",
];
// XUL Window properties to (re)store
@ -814,10 +812,8 @@ var SessionStoreInternal = {
this._forgetTabsWithUserContextId(userContextId);
}
break;
case "http-on-examine-response":
case "http-on-examine-cached-response":
case "http-on-examine-merged-response":
this.onExamineResponse(aSubject);
case "http-on-may-change-process":
this.onMayChangeProcess(aSubject);
break;
}
},
@ -2286,6 +2282,8 @@ var SessionStoreInternal = {
* processes.
*/
async _doProcessSwitch(aBrowser, aRemoteType, aChannel, aSwitchId) {
debug(`[process-switch]: performing switch from ${aBrowser.remoteType} to ${aRemoteType}`);
// Don't try to switch tabs before delayed startup is completed.
await aBrowser.ownerGlobal.delayedStartupPromise;
@ -2309,12 +2307,14 @@ var SessionStoreInternal = {
}
// Tell our caller to redirect the load into this newly created process.
return aBrowser.frameLoader.tabParent;
let tabParent = aBrowser.frameLoader.tabParent;
debug(`[process-switch]: new tabID: ${tabParent.tabId}`);
return tabParent;
},
// Examine the channel response to see if we should change the process
// performing the given load.
onExamineResponse(aChannel) {
onMayChangeProcess(aChannel) {
if (!E10SUtils.useHttpResponseProcessSelection()) {
return;
}
@ -2323,13 +2323,21 @@ var SessionStoreInternal = {
return; // Not a document load.
}
let browsingContext = aChannel.loadInfo.browsingContext;
if (!browsingContext) {
return; // Not loading in a browsing context.
// Check that this is a toplevel document load.
let cpType = aChannel.loadInfo.externalContentPolicyType;
let toplevel = cpType == Ci.nsIContentPolicy.TYPE_DOCUMENT;
if (!toplevel) {
debug(`[process-switch]: non-toplevel - ignoring`);
return;
}
if (browsingContext.parent) {
return; // Not a toplevel load, can't flip procs.
// Check that the document has a corresponding BrowsingContext.
let browsingContext = toplevel
? aChannel.loadInfo.browsingContext
: aChannel.loadInfo.frameBrowsingContext;
if (!browsingContext) {
debug(`[process-switch]: no BrowsingContext - ignoring`);
return;
}
// Get principal for a document already loaded in the BrowsingContext.
@ -2338,34 +2346,60 @@ var SessionStoreInternal = {
currentPrincipal = browsingContext.currentWindowGlobal.documentPrincipal;
}
let parentChannel = aChannel.notificationCallbacks
.getInterface(Ci.nsIParentChannel);
if (!parentChannel) {
return; // Not an actor channel
// Ensure we have an nsIParentChannel listener for a remote load.
let parentChannel;
try {
parentChannel = aChannel.notificationCallbacks
.getInterface(Ci.nsIParentChannel);
} catch (e) {
debug(`[process-switch]: No nsIParentChannel callback - ignoring`);
return;
}
let tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsITabParent);
if (!tabParent || !tabParent.ownerElement) {
console.warn("warning: Missing tabParent");
return; // Not an embedded browsing context
// Ensure we have a nsITabParent for our remote load.
let tabParent;
try {
tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsITabParent);
} catch (e) {
debug(`[process-switch]: No nsITabParent for channel - ignoring`);
return;
}
// Ensure we're loaded in a regular tabbrowser environment, and can swap processes.
let browser = tabParent.ownerElement;
if (browser.tagName !== "browser") {
console.warn("warning: Not a xul:browser element:", browser.tagName);
return; // Not a vanilla xul:browser element performing embedding.
if (!browser) {
debug(`[process-switch]: TabParent has no ownerElement - ignoring`);
}
let tabbrowser = browser.ownerGlobal.gBrowser;
if (!tabbrowser) {
debug(`[process-switch]: cannot find tabbrowser for loading tab - ignoring`);
return;
}
let tab = tabbrowser.getTabForBrowser(browser);
if (!tab) {
debug(`[process-switch]: not a normal tab, so cannot swap processes - ignoring`);
return;
}
// Determine the process type the load should be performed in.
let resultPrincipal =
Services.scriptSecurityManager.getChannelResultPrincipal(aChannel);
let useRemoteTabs = browser.ownerGlobal.gMultiProcessBrowser;
let remoteType = E10SUtils.getRemoteTypeForPrincipal(resultPrincipal,
useRemoteTabs,
true,
browser.remoteType,
currentPrincipal);
if (browser.remoteType == remoteType) {
return; // Already in compatible process.
debug(`[process-switch]: type (${remoteType}) is compatible - ignoring`);
return;
}
if (remoteType == E10SUtils.NOT_REMOTE ||
browser.remoteType == E10SUtils.NOT_REMOTE) {
debug(`[process-switch]: non-remote source/target - ignoring`);
return;
}
// ------------------------------------------------------------------------
@ -3231,6 +3265,14 @@ var SessionStoreInternal = {
tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
} else {
options.loadArguments = loadArguments;
// If we're resuming a load which has been redirected from another
// process, record the history index which is currently being requested.
// It has to be offset by 1 to get back to native history indices from
// SessionStore history indicies.
if (loadArguments.redirectLoadSwitchId) {
loadArguments.redirectHistoryIndex = tabState.requestedIndex - 1;
}
}
// Need to reset restoring tabs.
@ -3299,7 +3341,7 @@ var SessionStoreInternal = {
let tabbrowser = aWindow.gBrowser;
let startupPref = this._prefBranch.getIntPref("startup.page");
if (startupPref == 1)
homePages = homePages.concat(HomePage.get().split("|"));
homePages = homePages.concat(HomePage.get(aWindow).split("|"));
for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) {
let tab = tabbrowser.tabs[i];

Просмотреть файл

@ -184,6 +184,10 @@ var TabStateInternal = {
if (value.hasOwnProperty("index")) {
tabData.index = value.index;
}
if (value.hasOwnProperty("requestedIndex")) {
tabData.requestedIndex = value.requestedIndex;
}
} else {
tabData[key] = value;
}

Просмотреть файл

@ -217,43 +217,54 @@ class UrlbarInput {
return;
}
// TODO: Hook up one-off button handling.
// Determine whether to use the selected one-off search button. In
// one-off search buttons parlance, "selected" means that the button
// has been navigated to via the keyboard. So we want to use it if
// the triggering event is not a mouse click -- i.e., it's a Return
// key -- or if the one-off was mouse-clicked.
// let selectedOneOff = this.popup.oneOffSearchButtons.selectedButton;
// if (selectedOneOff &&
// isMouseEvent &&
// event.originalTarget != selectedOneOff) {
// selectedOneOff = null;
// }
//
// // Do the command of the selected one-off if it's not an engine.
// if (selectedOneOff && !selectedOneOff.engine) {
// selectedOneOff.doCommand();
// return;
// }
let selectedOneOff;
if (this.view.isOpen) {
selectedOneOff = this.view.oneOffSearchButtons.selectedButton;
if (selectedOneOff &&
isMouseEvent &&
event.target != selectedOneOff) {
selectedOneOff = null;
}
// Do the command of the selected one-off if it's not an engine.
if (selectedOneOff && !selectedOneOff.engine) {
selectedOneOff.doCommand();
return;
}
}
// Use the selected result if we have one; this should always be the case
// Use the selected result if we have one; this is usually the case
// when the view is open.
let result = this.view.selectedResult;
let result = !selectedOneOff && this.view.selectedResult;
if (result) {
this.pickResult(event, result);
return;
}
// Use the current value if we don't have a UrlbarResult e.g. because the
// view is closed.
let url = this.value;
let url;
if (selectedOneOff) {
// If there's a selected one-off button then load a search using
// the button's engine.
[url, openParams.postData] = UrlbarUtils.getSearchQueryUrl(
selectedOneOff.engine, this._lastSearchString);
this._recordSearch(selectedOneOff.engine, event);
} else {
// Use the current value if we don't have a UrlbarResult e.g. because the
// view is closed.
url = this.value;
openParams.postData = null;
}
if (!url) {
return;
}
let where = openWhere || this._whereToOpen(event);
openParams.postData = null;
openParams.allowInheritPrincipal = false;
// TODO: Work out how we get the user selection behavior, probably via passing

Просмотреть файл

@ -256,7 +256,7 @@ var UrlbarUtils = {
};
case UrlbarUtils.RESULT_TYPE.SEARCH: {
const engine = Services.search.getEngineByName(result.payload.engine);
let [url, postData] = getSearchQueryUrl(
let [url, postData] = this.getSearchQueryUrl(
engine, result.payload.suggestion || result.payload.query);
return {url, postData};
}
@ -264,6 +264,22 @@ var UrlbarUtils = {
return {url: null, postData: null};
},
/**
* Get the url to load for the search query.
*
* @param {nsISearchEngine} engine
* The engine to generate the query for.
* @param {string} query
* The query string to search for.
* @returns {array}
* Returns an array containing the query url (string) and the
* post data (object).
*/
getSearchQueryUrl(engine, query) {
let submission = engine.getSubmission(query, null, "keyword");
return [submission.uri.spec, submission.postData];
},
/**
* Tries to initiate a speculative connection to a given url.
* @param {nsISearchEngine|nsIURI|URL|string} urlOrEngine entity to initiate
@ -325,23 +341,6 @@ var UrlbarUtils = {
},
};
/**
* Get the url to load for the search query and records in telemetry that it
* is being loaded.
*
* @param {nsISearchEngine} engine
* The engine to generate the query for.
* @param {string} query
* The query string to search for.
* @returns {array}
* Returns an array containing the query url (string) and the
* post data (object).
*/
function getSearchQueryUrl(engine, query) {
let submission = engine.getSubmission(query, null, "keyword");
return [submission.uri.spec, submission.postData];
}
/**
* UrlbarQueryContext defines a user's autocomplete input from within the urlbar.
* It supplements it with details of how the search results should be obtained

Просмотреть файл

@ -162,7 +162,7 @@ class UrlbarView {
if (queryContext.lastResultCount == 0) {
if (queryContext.preselected) {
this._selectItem(fragment.firstElementChild);
this._selectItem(fragment.firstElementChild, false);
} else {
// Clear the selection when we get a new set of results.
this._selectItem(null);
@ -172,7 +172,7 @@ class UrlbarView {
// TODO bug 1523602: the selection should stay on the node that had it, if
// it's still in the current result set.
let resultIndex = this._selected.getAttribute("resultIndex");
this._selectItem(fragment.children[resultIndex]);
this._selectItem(fragment.children[resultIndex], false);
}
// TODO bug 1523602: For now, clear the results for each set received.

Просмотреть файл

@ -31,6 +31,10 @@ add_task(async function() {
await PlacesUtils.history.clear();
});
await promiseAutocompleteResultPopup("moz");
Assert.equal(gURLBar.textValue, "moz",
"Preselected search keyword result shouldn't automatically add a space");
await promiseAutocompleteResultPopup("moz open a search");
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
if (UrlbarPrefs.get("quantumbar")) {

Просмотреть файл

@ -1,9 +0,0 @@
. "$topsrcdir/browser/config/mozconfigs/win32/debug"
export CC="cl.exe"
export CXX="cl.exe"
export LINKER="link.exe"
export HOST_CC=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
export HOST_CXX=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
unset ENABLE_CLANG_PLUGIN

Просмотреть файл

@ -1,9 +0,0 @@
. "$topsrcdir/browser/config/mozconfigs/win32/nightly"
export CC="cl.exe"
export CXX="cl.exe"
export LINKER="link.exe"
export HOST_CC=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
export HOST_CXX=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
unset ENABLE_CLANG_PLUGIN

Просмотреть файл

@ -1,6 +0,0 @@
. "$topsrcdir/browser/config/mozconfigs/win64/debug"
export CC="cl.exe"
export CXX="cl.exe"
export LINKER="link.exe"
unset ENABLE_CLANG_PLUGIN

Просмотреть файл

@ -1,6 +0,0 @@
. "$topsrcdir/browser/config/mozconfigs/win64/nightly"
export CC="cl.exe"
export CXX="cl.exe"
export LINKER="link.exe"
unset ENABLE_CLANG_PLUGIN

Просмотреть файл

@ -10,6 +10,8 @@
var EXPORTED_SYMBOLS = ["HomePage"];
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
const kPrefName = "browser.startup.homepage";
@ -43,7 +45,11 @@ function getHomepagePref(useDefault) {
}
let HomePage = {
get() {
get(aWindow) {
if (PrivateBrowsingUtils.permanentPrivateBrowsing ||
(aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) {
return this.getPrivate();
}
return getHomepagePref();
},
@ -51,6 +57,24 @@ let HomePage = {
return getHomepagePref(true);
},
getPrivate() {
let homePages = getHomepagePref();
if (!homePages.includes("moz-extension")) {
return homePages;
}
// Verify private access and build a new list.
let privateHomePages = homePages.split("|").filter(page => {
let url = new URL(page);
if (url.protocol !== "moz-extension:") {
return true;
}
let policy = WebExtensionPolicy.getByHostname(url.hostname);
return policy && policy.privateBrowsingAllowed;
});
// Extensions may not be ready on startup, fallback to defaults.
return privateHomePages.join("|") || this.getDefault();
},
get overridden() {
return Services.prefs.prefHasUserValue(kPrefName);
},

Просмотреть файл

@ -45,9 +45,6 @@ for cdm in CONFIG['MOZ_EME_MODULES']:
if CONFIG['MOZ_GPSD']:
DEFINES['MOZ_GPSD'] = True
if CONFIG['MOZ_LIBPRIO']:
DEFINES['MOZ_LIBPRIO'] = True
# These files are specified in this moz.build to pick up DIST_SUBDIR as set in
# this directory, which is un-set in browser/app.
JS_PREFERENCE_PP_FILES += [

Просмотреть файл

@ -20,7 +20,7 @@ AC_CACHE_CHECK(what kind of list files are supported by the linker,
dnl https://sourceware.org/bugzilla/show_bug.cgi?id=23600
if AC_TRY_COMMAND(${CC-cc} -o conftest.${OBJ_SUFFIX} -c $MOZ_LTO_CFLAGS $CFLAGS $CPPFLAGS conftest.${ac_ext} 1>&5) && test -s conftest.${OBJ_SUFFIX}; then
echo "INPUT(conftest.${OBJ_SUFFIX})" > conftest.list
if test "$CC_TYPE" = "msvc" -o "$CC_TYPE" = "clang-cl"; then
if test "$CC_TYPE" = "clang-cl"; then
link="$LINKER -OUT:conftest${ac_exeext}"
else
link="${CC-cc} -o conftest${ac_exeext}"

Просмотреть файл

@ -273,7 +273,7 @@ def basic_bindgen_cflags(target, is_unix, compiler_info, android_cflags, clang_p
],
}.get(target.os, [])
if compiler_info.type in ('msvc', 'clang-cl'):
if compiler_info.type == 'clang-cl':
args += [
# To enable the builtin __builtin_offsetof so that CRT wouldn't
# use reinterpret_cast in offsetof() which is not allowed inside

Просмотреть файл

@ -27,7 +27,6 @@ check_headers(
'unistd.h',
'nl_types.h',
'cpuid.h',
when=non_msvc_compiler,
)
# These are all the places some variant of statfs can be hiding.
@ -36,7 +35,6 @@ check_headers(
'sys/statfs.h',
'sys/vfs.h',
'sys/mount.h',
when=non_msvc_compiler,
)
# Quota support
@ -45,7 +43,6 @@ check_headers(
set_define('HAVE_SYS_QUOTA_H',
try_compile(includes=['sys/quota.h'],
body='quotactl(0, nullptr, 0, (caddr_t)nullptr);',
when=non_msvc_compiler,
check_msg='for sys/quota.h'))
check_header('linux/quota.h',
includes=['sys/socket.h'],
@ -59,14 +56,12 @@ check_headers(
when=building_linux,
)
check_header('sys/queue.h',
when=non_msvc_compiler)
check_header('sys/queue.h')
check_headers(
'sys/types.h',
'netinet/in.h',
'byteswap.h',
when=non_msvc_compiler,
)
# TODO: Move these checks to file specific to --enable-project=js.

Просмотреть файл

@ -325,7 +325,7 @@ set_config('WIN64_CARGO_LINKER_CONFIG', win64_cargo_linker_config)
@depends(target, c_compiler, rustc)
@imports('os')
def rustc_natvis_ldflags(target, compiler_info, rustc):
if target.kernel == 'WINNT' and compiler_info.type in ('msvc', 'clang-cl'):
if target.kernel == 'WINNT' and compiler_info.type == 'clang-cl':
sysroot = check_cmd_output(rustc, '--print', 'sysroot').strip()
etc = os.path.join(sysroot, 'lib/rustlib/etc')
ldflags = []

Просмотреть файл

@ -448,14 +448,11 @@ def get_compiler_info(compiler, language):
form of a list or tuple), in the given `language`.
The returned information includes:
- the compiler type (msvc, clang-cl, clang or gcc)
- the compiler type (clang-cl, clang or gcc)
- the compiler version
- the compiler supported language
- the compiler supported language version
'''
# Note: MSVC doesn't expose __STDC_VERSION__. It does expose __STDC__,
# but only when given the -Za option, which disables compiler
# extensions.
# Note: We'd normally do a version check for clang, but versions of clang
# in Xcode have a completely different versioning scheme despite exposing
# the version with the same defines.
@ -469,9 +466,6 @@ def get_compiler_info(compiler, language):
#if defined(__clang__)
%COMPILER "clang-cl"
%VERSION __clang_major__.__clang_minor__.__clang_patchlevel__
#else
%COMPILER "msvc"
%VERSION _MSC_FULL_VER
#endif
#elif defined(__clang__)
%COMPILER "clang"
@ -487,8 +481,6 @@ def get_compiler_info(compiler, language):
%cplusplus __cplusplus
#elif __STDC_VERSION__
%STDC_VERSION __STDC_VERSION__
#elif __STDC__
%STDC_VERSION 198900L
#endif
''')
@ -514,9 +506,9 @@ def get_compiler_info(compiler, language):
# Also check for endianness. The advantage of living in modern times is
# that all the modern compilers we support now have __BYTE_ORDER__ defined
# by the preprocessor, except MSVC, which only supports little endian.
# by the preprocessor.
check += dedent('''\
#if _MSC_VER || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
%ENDIANNESS "little"
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
%ENDIANNESS "big"
@ -549,14 +541,6 @@ def get_compiler_info(compiler, language):
stdc_version = int(data.get('STDC_VERSION', '0L').rstrip('L'))
version = data.get('VERSION')
if version and type == 'msvc':
msc_ver = version
version = msc_ver[0:2]
if len(msc_ver) > 2:
version += '.' + msc_ver[2:4]
if len(msc_ver) > 4:
version += '.' + msc_ver[4:]
if version:
version = Version(version)
@ -604,7 +588,6 @@ def check_compiler(compiler, language, target):
flags.append('-Xclang')
flags.append('-std=gnu99')
# Note: MSVC, while supporting C++14, still reports 199711L for __cplusplus.
# Note: this is a strict version check because we used to always add
# -std=gnu++14.
cxx14_version = 201402
@ -634,7 +617,7 @@ def check_compiler(compiler, language, target):
flags.append('--target=%s' % target.toolchain)
has_target = True
if not has_target and (not info.cpu or info.cpu != target.cpu and info.type != 'msvc'):
if not has_target and (not info.cpu or info.cpu != target.cpu):
same_arch = same_arch_different_bits()
if (target.cpu, info.cpu) in same_arch:
flags.append('-m32')
@ -853,7 +836,7 @@ def default_c_compilers(host_or_target, other_c_compiler=None):
def default_c_compilers(host_or_target, target, toolchain_prefix,
android_clang_compiler, *other_c_compiler):
if host_or_target.kernel == 'WINNT':
supported = types = ('clang-cl', 'msvc', 'gcc', 'clang')
supported = types = ('clang-cl', 'gcc', 'clang')
elif host_or_target.kernel == 'Darwin':
types = ('clang',)
supported = ('clang', 'gcc')
@ -878,10 +861,6 @@ def default_c_compilers(host_or_target, other_c_compiler=None):
# Android NDK clangs do not function as host compiler, so
# prioritize a raw 'clang' instead.
prioritized = info.type
elif info.type == 'msvc' and target.cpu != host_or_target.cpu:
# MSVC compilers only support one architecture, so we'll
# want a cl in another (detected) path.
prioritized = 'cl'
types = [prioritized] + [t for t in types if t != info.type]
@ -898,8 +877,6 @@ def default_c_compilers(host_or_target, other_c_compiler=None):
result.append(android_clang_compiler)
elif type == 'gcc':
result.extend(gcc)
elif type == 'msvc':
result.append('cl')
else:
result.append(type)
@ -1119,16 +1096,6 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
raise FatalCheckError(
'Only clang/llvm 3.9 or newer is supported.')
if info.type == 'msvc':
if info.version < '19.15.26726':
raise FatalCheckError(
'This version (%s) of the MSVC compiler is not '
'supported.\n'
'You must install Visual C++ 2017 Update 8 or '
'later in order to build.\n'
'See https://developer.mozilla.org/en/'
'Windows_Build_Prerequisites' % info.version)
if info.flags:
raise FatalCheckError(
'Unknown compiler or compiler not supported.')
@ -1234,19 +1201,12 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
if value:
return value[0]
@depends(valid_compiler, linker)
def unused_linker(compiler, linker):
if linker and compiler.type != 'msvc':
@depends(linker)
def unused_linker(linker):
if linker:
log.warning('The value of %s is not used by this build system.'
% linker_var)
if host_or_target is target:
@depends(valid_compiler)
def is_msvc(compiler):
return compiler.type == 'msvc'
imply_option('LINKER', linker, reason='LD', when=is_msvc)
return valid_compiler
@ -1258,7 +1218,6 @@ host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler,
other_c_compiler=c_compiler)
# Generic compiler-based conditions.
non_msvc_compiler = depends(c_compiler)(lambda info: info.type != 'msvc')
building_with_gcc = depends(c_compiler)(lambda info: info.type == 'gcc')
@ -1266,7 +1225,7 @@ building_with_gcc = depends(c_compiler)(lambda info: info.type == 'gcc')
def msvs_version(info):
# clang-cl emulates the same version scheme as cl. And MSVS_VERSION needs to
# be set for GYP on Windows.
if info.type in ('clang-cl', 'msvc'):
if info.type == 'clang-cl':
return '2017'
return ''
@ -1289,7 +1248,7 @@ def check_have_64_bit(have_64_bit, compiler_have_64_bit):
@depends(c_compiler, target)
def default_debug_flags(compiler_info, target):
# Debug info is ON by default.
if compiler_info.type in ('msvc', 'clang-cl'):
if compiler_info.type == 'clang-cl':
return '-Z7'
elif target.kernel == 'WINNT' and compiler_info.type == 'clang':
return '-g -gcodeview'
@ -1427,11 +1386,11 @@ set_config('WRAP_SYSTEM_INCLUDES', wrap_system_includes)
set_config('VISIBILITY_FLAGS', visibility_flags)
@depends(c_compiler, using_sccache)
def depend_cflags(info, using_sccache):
if info.type not in ('clang-cl', 'msvc'):
@depends(c_compiler)
def depend_cflags(info):
if info.type != 'clang-cl':
return ['-MD', '-MP', '-MF $(MDDEPDIR)/$(@F).pp']
elif info.type == 'clang-cl':
else:
# clang-cl doesn't accept the normal -MD -MP -MF options that clang
# does, but the underlying cc1 binary understands how to generate
# dependency files. These options are based on analyzing what the
@ -1444,10 +1403,6 @@ def depend_cflags(info, using_sccache):
'-Xclang', '-MT',
'-Xclang', '$@'
]
elif using_sccache:
# sccache supports a special flag to create depfiles
# by parsing MSVC's -showIncludes output.
return ['-deps$(MDDEPDIR)/$(@F).pp']
set_config('_DEPEND_CFLAGS', depend_cflags)
@ -1492,29 +1447,6 @@ def pgo_flags(compiler, build_env, target):
use_ldflags=[],
)
if compiler.type == 'msvc':
num_cores = min(8, multiprocessing.cpu_count())
cgthreads = '-CGTHREADS:%s' % num_cores
return namespace(
gen_cflags=['-GL'],
gen_ldflags=['-LTCG:PGINSTRUMENT', '-PogoSafeMode', cgthreads],
# XXX: PGO builds can fail with warnings treated as errors,
# specifically "no profile data available" appears to be
# treated as an error sometimes. This might be a consequence
# of using WARNINGS_AS_ERRORS in some modules, combined
# with the linker doing most of the work in the whole-program
# optimization/PGO case. I think it's probably a compiler bug,
# but we work around it here.
use_cflags=['-GL', '-wd4624', '-wd4952'],
# XXX: should be -LTCG:PGOPTIMIZE, but that fails on libxul.
# Probably also a compiler bug, but what can you do?
# /d2:-cgsummary prints a summary of what is happening during
# code generation. How long individual functions are optimized,
# which functions are optimized, etc.
use_ldflags=['-LTCG:PGUPDATE', cgthreads, '-d2:-cgsummary'],
)
set_config('PROFILE_GEN_CFLAGS', pgo_flags.gen_cflags)
set_config('PROFILE_GEN_LDFLAGS', pgo_flags.gen_ldflags)
@ -2069,7 +2001,7 @@ js_option(env='AS', nargs=1, help='Path to the assembler')
@depends(target, c_compiler)
def as_info(target, c_compiler):
if c_compiler.type in ('msvc', 'clang-cl'):
if c_compiler.type == 'clang-cl':
ml = {
'x86': 'ml',
'x86_64': 'ml64',
@ -2079,7 +2011,7 @@ def as_info(target, c_compiler):
type='masm',
names=(ml, )
)
# When building with anything but MSVC, we just use the C compiler as the assembler.
# When building with anything but clang-cl, we just use the C compiler as the assembler.
return namespace(
type='gcc',
names=(c_compiler.compiler, )

Просмотреть файл

@ -251,16 +251,13 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env, c_compiler):
@depends(c_compiler, toolchain_search_path)
@imports('os')
def vc_path(c_compiler, toolchain_search_path):
if c_compiler.type not in ('msvc', 'clang-cl'):
if c_compiler.type != 'clang-cl':
return
vc_program = c_compiler.compiler
# In clang-cl builds, we use the headers and libraries from an MSVC installation.
if c_compiler.type == 'clang-cl':
vc_program = find_program('cl.exe', paths=toolchain_search_path)
if not vc_program:
die('Cannot find a Visual C++ install for e.g. ATL headers.')
# In clang-cl builds, we need the headers and libraries from an MSVC installation.
vc_program = find_program('cl.exe', paths=toolchain_search_path)
if not vc_program:
die('Cannot find a Visual C++ install for e.g. ATL headers.')
result = os.path.dirname(vc_program)
while True:
@ -487,65 +484,17 @@ def valid_mt(path):
set_config('MSMANIFEST_TOOL', depends(valid_mt)(lambda x: bool(x)))
@template
def linker_progs_for(host_or_target):
compiler = {
host: host_c_compiler,
target: c_compiler,
}[host_or_target]
@depends(compiler)
def linker_progs(compiler):
if compiler.type == 'msvc':
return ('link', 'lld-link')
if compiler.type == 'clang-cl':
return ('lld-link', 'link')
return linker_progs
js_option(env='LINKER', nargs=1, help='Path to the linker')
link = check_prog('LINKER', linker_progs_for(target), input='LINKER',
link = check_prog('LINKER', ('lld-link',), input='LINKER',
paths=toolchain_search_path)
js_option(env='HOST_LINKER', nargs=1, help='Path to the host linker')
host_link = check_prog('HOST_LINKER', linker_progs_for(host),
input='HOST_LINKER',
host_link = check_prog('HOST_LINKER', ('lld-link',), input='HOST_LINKER',
paths=host_toolchain_search_path)
add_old_configure_assignment('LINKER', link)
check_prog('MAKECAB', ('makecab.exe',))
@depends(c_compiler, using_sccache)
def need_showincludes_prefix(info, using_sccache):
# sccache does its own -showIncludes prefix checking.
# clang-cl uses a gcc-style dependency scheme, see toolchain.configure.
if info.type == 'msvc' and not using_sccache:
return True
@depends(c_compiler, when=need_showincludes_prefix)
@imports(_from='re', _import='compile', _as='re_compile')
def msvc_showincludes_prefix(c_compiler):
pattern = re_compile(br'^([^:]*:.*[ :] )(.*\\stdio.h)$')
output = try_invoke_compiler([c_compiler.compiler], 'C', '#include <stdio.h>\n',
['-nologo', '-c', '-Fonul', '-showIncludes'])
for line in output.splitlines():
if line.endswith(b'\\stdio.h'):
m = pattern.match(line)
if m:
return m.group(1)
# We should have found the prefix and returned earlier
die('Cannot find cl -showIncludes prefix.')
set_config('CL_INCLUDES_PREFIX', msvc_showincludes_prefix)
# Make sure that the build system can handle non-ASCII characters in
# environment variables to prevent silent breakage on non-English systems.
set_config('NONASCII', b'\241\241')

Просмотреть файл

@ -19,6 +19,7 @@ MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0}
ac_add_options --enable-js-shell
. "$topsrcdir/build/mozconfig.nasm"
. "$topsrcdir/build/mozconfig.node"
. "$topsrcdir/build/mozconfig.automation"
. "$topsrcdir/build/mozconfig.rust"

11
build/mozconfig.nasm Normal file
Просмотреть файл

@ -0,0 +1,11 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
case "$(uname -s)" in
MINGW*)
export NASM=$topsrcdir/nasm/nasm.exe
;;
*)
;;
esac

Просмотреть файл

@ -159,7 +159,7 @@ def NoVisibilityFlags():
@template
def ForceInclude(*headers):
"""Force includes a set of header files in C++ compilations"""
if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
if CONFIG['CC_TYPE'] == 'clang-cl':
include_flag = '-FI'
else:
include_flag = '-include'

Просмотреть файл

@ -106,14 +106,6 @@ VERSION_NUMBER = 50
CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config
AUTOCONF_TOOLS = $(MOZILLA_DIR)/build/autoconf
ifeq (msvc,$(CC_TYPE))
# clang-cl is smart enough to generate dependencies directly.
ifeq (,$(MOZ_USING_SCCACHE))
CC_WRAPPER ?= $(call py_action,cl)
CXX_WRAPPER ?= $(call py_action,cl)
endif # MOZ_USING_SCCACHE
endif # CC_TYPE
CC := $(CC_WRAPPER) $(CC)
CXX := $(CXX_WRAPPER) $(CXX)
MKDIR ?= mkdir
@ -441,9 +433,3 @@ endif
endif
PLY_INCLUDE = -I$(MOZILLA_DIR)/other-licenses/ply
export CL_INCLUDES_PREFIX
# Make sure that the build system can handle non-ASCII characters
# in environment variables to prevent it from breking silently on
# non-English systems.
export NONASCII

11
config/external/icu/defs.mozbuild поставляемый
Просмотреть файл

@ -49,14 +49,3 @@ if CONFIG['CC_TYPE'] == 'clang-cl':
'-Wno-macro-redefined',
'-Wno-microsoft-include',
]
if CONFIG['CC_TYPE'] == 'msvc':
CFLAGS += [
'-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition
'-wd4996', # The compiler encountered a deprecated declaration.
]
CXXFLAGS += [
'-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition
'-wd4333', # '>>' : right shift by too large amount, data loss
'-wd4996', # The compiler encountered a deprecated declaration.
]

7
config/external/moz.build поставляемый
Просмотреть файл

@ -13,10 +13,9 @@ DIRS += [
if not CONFIG['MOZ_SYSTEM_JPEG']:
external_dirs += ['media/libjpeg']
if CONFIG['MOZ_LIBPRIO']:
DIRS += [
'prio',
]
DIRS += [
'prio',
]
# There's no "native" brotli or woff2 yet, but probably in the future...
external_dirs += ['modules/brotli']

4
config/external/msgpack/moz.build поставляемый
Просмотреть файл

@ -4,6 +4,4 @@
# 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/.
if CONFIG['MOZ_LIBPRIO']:
DIRS += ['/third_party/msgpack']
DIRS += ['/third_party/msgpack']

Просмотреть файл

@ -43,7 +43,7 @@ if CONFIG['WRAP_STL_INCLUDES']:
stl_compiler = None
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
stl_compiler = 'gcc'
elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
elif CONFIG['CC_TYPE'] == 'clang-cl':
stl_compiler = 'msvc'
if stl_compiler:

Просмотреть файл

@ -359,7 +359,7 @@ else
# Windows-to-Windows cross compiles should always use MSVC-style options for
# host compiles.
ifeq (WINNT_WINNT,$(HOST_OS_ARCH)_$(OS_ARCH))
ifneq (,$(filter-out msvc clang-cl,$(HOST_CC_TYPE)))
ifneq (,$(filter-out clang-cl,$(HOST_CC_TYPE)))
$(error MSVC-style compilers should be used for host compilations!)
endif
HOST_OUTOPTION = -Fo# eol
@ -517,13 +517,6 @@ define EXPAND_CC_OR_CXX
$(if $(PROG_IS_C_ONLY_$(1)),$(CC),$(CCC))
endef
# Workaround a bug of MSVC 2017 Update 8 (see bug 1485224)
ifeq ($(CC_TYPE)_$(HOST_OS_ARCH)_$(MOZ_PROFILE_GENERATE),msvc_WINNT_1)
LINKER_OUT=$(subst /,\,$1)
else
LINKER_OUT=$1
endif
#
# PROGRAM = Foo
# creates OBJS, links with LIBS to create Foo
@ -532,7 +525,7 @@ $(PROGRAM): $(PROGOBJS) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(EXTRA_DEPS) $(RESFIL
$(REPORT_BUILD)
@$(RM) $@.manifest
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
$(LINKER) -NOLOGO -OUT:$(call LINKER_OUT,$@) -PDB:$(LINK_PDBFILE) -IMPLIB:$(basename $(@F)).lib $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $($(notdir $@)_$(OBJS_VAR_SUFFIX)) $(RESFILE) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(SHARED_LIBS) $(OS_LIBS)
$(LINKER) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) -IMPLIB:$(basename $(@F)).lib $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $($(notdir $@)_$(OBJS_VAR_SUFFIX)) $(RESFILE) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(SHARED_LIBS) $(OS_LIBS)
ifdef MSMANIFEST_TOOL
@if test -f $@.manifest; then \
if test -f '$(srcdir)/$(notdir $@).manifest'; then \
@ -659,7 +652,7 @@ endif
$(HOST_SHARED_LIBRARY): Makefile
$(REPORT_BUILD)
$(RM) $@
ifneq (,$(filter msvc clang-cl,$(HOST_CC_TYPE)))
ifneq (,$(filter clang-cl,$(HOST_CC_TYPE)))
$(HOST_LINKER) -NOLOGO -DLL -OUT:$@ $($(notdir $@)_OBJS) $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LINKER_LIBPATHS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
else
$(HOST_CXX) $(HOST_OUTOPTION)$@ $($(notdir $@)_OBJS) $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)

Просмотреть файл

@ -8,6 +8,7 @@ const {
FILTER_TEXT_SET,
FILTER_TOGGLE,
DEFAULT_FILTERS_RESET,
MESSAGES_ADD,
} = require("devtools/client/webconsole/constants");
/**
@ -37,6 +38,8 @@ function eventTelemetryMiddleware(telemetry, sessionId, store) {
telemetry,
sessionId,
});
} else if (action.type === MESSAGES_ADD) {
messagesAdd({ action, telemetry });
}
return res;
@ -77,4 +80,14 @@ function filterChange({action, state, oldState, telemetry, sessionId}) {
});
}
function messagesAdd({ action, telemetry }) {
const {messages} = action;
for (const message of messages) {
if (message.level === "error" && message.source === "javascript") {
telemetry.getKeyedHistogramById("DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED")
.add(message.errorMessageName || "Unknown", true);
}
}
}
module.exports = eventTelemetryMiddleware;

Просмотреть файл

@ -34,6 +34,7 @@ stubPreparedMessages.set(`console.log('foobar', 'test')`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -64,6 +65,7 @@ stubPreparedMessages.set(`console.log(undefined)`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -92,6 +94,7 @@ stubPreparedMessages.set(`console.warn('danger, will robinson!')`, new ConsoleMe
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -122,6 +125,7 @@ stubPreparedMessages.set(`console.log(NaN)`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -152,6 +156,7 @@ stubPreparedMessages.set(`console.log(null)`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -180,6 +185,7 @@ stubPreparedMessages.set(`console.log('鼬')`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -208,6 +214,7 @@ stubPreparedMessages.set(`console.clear()`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -234,6 +241,7 @@ stubPreparedMessages.set(`console.count('bar')`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -292,6 +300,7 @@ stubPreparedMessages.set(`console.assert(false, {message: 'foobar'})`, new Conso
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -320,6 +329,7 @@ stubPreparedMessages.set(`console.log('hello \nfrom \rthe \"string world!')`, ne
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -348,6 +358,7 @@ stubPreparedMessages.set(`console.log('úṇĩçödê țĕșť')`, new ConsoleMe
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -388,6 +399,7 @@ stubPreparedMessages.set(`console.dirxml(window)`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -434,6 +446,7 @@ stubPreparedMessages.set(`console.log('myarray', ['red', 'green', 'blue'])`, new
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -472,6 +485,7 @@ stubPreparedMessages.set(`console.log('myregex', /a.b.c/)`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -517,6 +531,7 @@ stubPreparedMessages.set(`console.table(['red', 'green', 'blue']);`, new Console
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -581,6 +596,7 @@ stubPreparedMessages.set(`console.log('myobject', {red: 'redValue', green: 'gree
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -609,6 +625,7 @@ stubPreparedMessages.set(`console.debug('debug message');`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -637,6 +654,7 @@ stubPreparedMessages.set(`console.info('info message');`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -672,6 +690,7 @@ stubPreparedMessages.set(`console.error('error message');`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -723,6 +742,7 @@ stubPreparedMessages.set(`console.log('mymap')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -768,6 +788,7 @@ stubPreparedMessages.set(`console.log('myset')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -813,6 +834,7 @@ stubPreparedMessages.set(`console.trace()`, new ConsoleMessage({
"column": 11
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -902,6 +924,7 @@ stubPreparedMessages.set(`console.trace('bar', {'foo': 'bar'}, [1,2,3])`, new Co
"column": 11
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -928,6 +951,7 @@ stubPreparedMessages.set(`console.time('bar')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -954,6 +978,7 @@ stubPreparedMessages.set(`timerAlreadyExists`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -982,6 +1007,7 @@ stubPreparedMessages.set(`console.timeLog('bar') - 1`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1035,6 +1061,7 @@ stubPreparedMessages.set(`console.timeLog('bar') - 2`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1061,6 +1088,7 @@ stubPreparedMessages.set(`console.timeEnd('bar')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1087,6 +1115,7 @@ stubPreparedMessages.set(`timeEnd.timerDoesntExist`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1113,6 +1142,7 @@ stubPreparedMessages.set(`timeLog.timerDoesntExist`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1141,6 +1171,7 @@ stubPreparedMessages.set(`console.table('bar')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1186,6 +1217,7 @@ stubPreparedMessages.set(`console.table(['a', 'b', 'c'])`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1214,6 +1246,7 @@ stubPreparedMessages.set(`console.group('bar')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1240,6 +1273,7 @@ stubPreparedMessages.set(`console.groupEnd('bar')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1268,6 +1302,7 @@ stubPreparedMessages.set(`console.groupCollapsed('foo')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1294,6 +1329,7 @@ stubPreparedMessages.set(`console.groupEnd('foo')`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1322,6 +1358,7 @@ stubPreparedMessages.set(`console.group()`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1348,6 +1385,7 @@ stubPreparedMessages.set(`console.groupEnd()`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1377,6 +1415,7 @@ stubPreparedMessages.set(`console.log(%cfoobar)`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [
"color:blue; font-size:1.3em; background:url('http://example.com/test'); position:absolute; top:10px; ",
@ -1410,6 +1449,7 @@ stubPreparedMessages.set(`console.log("%cHello%c|%cWorld")`, new ConsoleMessage(
"column": 11
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [
"color:red",
@ -1443,6 +1483,7 @@ stubPreparedMessages.set(`console.group(%cfoo%cbar)`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [
"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
@ -1472,6 +1513,7 @@ stubPreparedMessages.set(`console.groupEnd(%cfoo%cbar)`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1501,6 +1543,7 @@ stubPreparedMessages.set(`console.groupCollapsed(%cfoo%cbaz)`, new ConsoleMessag
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [
"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
@ -1530,6 +1573,7 @@ stubPreparedMessages.set(`console.groupEnd(%cfoo%cbaz)`, new ConsoleMessage({
"column": 9
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1599,6 +1643,7 @@ stubPreparedMessages.set(`console.dir({C, M, Y, K})`, new ConsoleMessage({
"column": 35
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1625,6 +1670,7 @@ stubPreparedMessages.set(`console.count | default: 1`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1651,6 +1697,7 @@ stubPreparedMessages.set(`console.count | default: 2`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1677,6 +1724,7 @@ stubPreparedMessages.set(`console.count | test counter: 1`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1703,6 +1751,7 @@ stubPreparedMessages.set(`console.count | test counter: 2`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1729,6 +1778,7 @@ stubPreparedMessages.set(`console.count | default: 3`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1757,6 +1807,7 @@ stubPreparedMessages.set(`console.count | clear`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1783,6 +1834,7 @@ stubPreparedMessages.set(`console.count | default: 4`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1809,6 +1861,7 @@ stubPreparedMessages.set(`console.count | test counter: 3`, new ConsoleMessage({
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1835,6 +1888,7 @@ stubPreparedMessages.set(`console.countReset | test counter: 0`, new ConsoleMess
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
@ -1861,6 +1915,7 @@ stubPreparedMessages.set(`console.countReset | counterDoesntExist`, new ConsoleM
"column": 13
},
"groupId": null,
"errorMessageName": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,

Просмотреть файл

@ -31,6 +31,7 @@ stubPreparedMessages.set(`Unknown property such-unknown-property. Declara
"column": 25
},
"groupId": null,
"errorMessageName": "",
"userProvidedStyles": null,
"notes": null,
"indent": 0,
@ -56,6 +57,7 @@ stubPreparedMessages.set(`Error in parsing value for padding-top. Declara
"column": 16
},
"groupId": null,
"errorMessageName": "",
"userProvidedStyles": null,
"notes": null,
"indent": 0,

Просмотреть файл

@ -67,6 +67,7 @@ stubPreparedMessages.set(`asdf()`, new ConsoleMessage({
"column": 1
},
"groupId": null,
"errorMessageName": "JSMSG_NOT_DEFINED",
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"userProvidedStyles": null,
"notes": null,
@ -96,6 +97,7 @@ stubPreparedMessages.set(`1 + @`, new ConsoleMessage({
"column": 4
},
"groupId": null,
"errorMessageName": "JSMSG_ILLEGAL_CHARACTER",
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"userProvidedStyles": null,
"notes": null,
@ -320,6 +322,7 @@ stubPackets.set(`asdf()`, {
},
"exceptionMessage": "ReferenceError: asdf is not defined",
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"errorMessageName": "JSMSG_NOT_DEFINED",
"frame": {
"source": "debugger eval code",
"line": 1,
@ -356,6 +359,7 @@ stubPackets.set(`1 + @`, {
},
"exceptionMessage": "SyntaxError: illegal character",
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"errorMessageName": "JSMSG_ILLEGAL_CHARACTER",
"frame": {
"source": "debugger eval code",
"line": 1,

Просмотреть файл

@ -62,6 +62,7 @@ stubPreparedMessages.set(`ReferenceError: asdf is not defined`, new ConsoleMessa
"column": 5
},
"groupId": null,
"errorMessageName": "JSMSG_NOT_DEFINED",
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"userProvidedStyles": null,
"notes": null,
@ -101,6 +102,7 @@ stubPreparedMessages.set(`SyntaxError: redeclaration of let a`, new ConsoleMessa
"column": 9
},
"groupId": null,
"errorMessageName": "JSMSG_REDECLARED_VAR",
"userProvidedStyles": null,
"notes": [
{
@ -159,6 +161,7 @@ stubPreparedMessages.set(`TypeError longString message`, new ConsoleMessage({
"column": 7
},
"groupId": null,
"errorMessageName": "",
"userProvidedStyles": null,
"notes": null,
"indent": 0,
@ -180,6 +183,7 @@ stubPreparedMessages.set(`throw ""`, new ConsoleMessage({
"stacktrace": null,
"frame": null,
"groupId": null,
"errorMessageName": "JSMSG_UNCAUGHT_EXCEPTION",
"userProvidedStyles": null,
"notes": null,
"indent": 0,
@ -201,6 +205,7 @@ stubPreparedMessages.set(`throw "tomato"`, new ConsoleMessage({
"stacktrace": null,
"frame": null,
"groupId": null,
"errorMessageName": "JSMSG_UNCAUGHT_EXCEPTION",
"userProvidedStyles": null,
"notes": null,
"indent": 0,

Просмотреть файл

@ -415,6 +415,7 @@ skip-if = verify
[browser_webconsole_stacktrace_location_scratchpad_link.js]
[browser_webconsole_strict_mode_errors.js]
[browser_webconsole_string.js]
[browser_webconsole_telemetry_js_errors.js]
[browser_webconsole_telemetry_filters_changed.js]
[browser_webconsole_telemetry_jump_to_definition.js]
[browser_webconsole_telemetry_object_expanded.js]

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests the DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED telemetry event.
"use strict";
const TEST_URI = `data:text/html,<meta charset=utf8><script>document()</script>`;
add_task(async function() {
startTelemetry();
const hud = await openNewTabAndConsole(TEST_URI);
info("Check that the error message is logged in telemetry with the expected key");
await waitFor(() => findMessage(hud, "is not a function"));
checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 1);
await refreshTab();
info("Reloading the page (and having the same error) increments the sum");
await waitFor(() => findMessage(hud, "is not a function"));
checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 2);
info("Evaluating an expression resulting in the same error increments the sum");
let onMessage = waitForMessage(hud, "window is not a function");
hud.jsterm.execute("window()");
await onMessage;
checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 3);
info("Evaluating an expression resulting in another error is logged in telemetry");
onMessage = waitForMessage(hud, "repeat count must be non-negative");
hud.jsterm.execute(`"a".repeat(-1)`);
await onMessage;
checkErrorDisplayedTelemetry("JSMSG_NEGATIVE_REPETITION_COUNT", 1);
onMessage = waitForMessage(hud, "repeat count must be non-negative");
hud.jsterm.execute(`"b".repeat(-1)`);
await onMessage;
checkErrorDisplayedTelemetry("JSMSG_NEGATIVE_REPETITION_COUNT", 2);
});
function checkErrorDisplayedTelemetry(key, count) {
checkTelemetry(
"DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED", key, {0: 0, 1: count, 2: 0}, "array");
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше