This commit is contained in:
Wes Kocher 2015-04-08 17:25:12 -07:00
Родитель 4e17cd5e14 ec1ec1e487
Коммит 6ec4b5852a
32 изменённых файлов: 381 добавлений и 112 удалений

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

@ -164,6 +164,9 @@ let handleContentContextMenu = function (event) {
let baseURI = doc.baseURI;
let referrer = doc.referrer;
let referrerPolicy = doc.referrerPolicy;
let frameOuterWindowID = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.outerWindowID;
// Media related cache info parent needs for saving
let contentType = null;
@ -199,7 +202,8 @@ let handleContentContextMenu = function (event) {
sendSyncMessage("contextmenu",
{ editFlags, spellInfo, customMenuItems, addonInfo,
principal, docLocation, charSet, baseURI, referrer,
referrerPolicy, contentType, contentDisposition },
referrerPolicy, contentType, contentDisposition,
frameOuterWindowID },
{ event, popupNode: event.target });
}
else {

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

@ -599,24 +599,31 @@ nsContextMenu.prototype = {
this.focusedWindow = win;
this.focusedElement = elt;
let ownerDoc = this.target.ownerDocument;
// If this is a remote context menu event, use the information from
// gContextMenuContentData instead.
if (this.isRemote) {
this.browser = gContextMenuContentData.browser;
this.principal = gContextMenuContentData.principal;
this.frameOuterWindowID = gContextMenuContentData.frameOuterWindowID;
} else {
editFlags = SpellCheckHelper.isEditable(this.target, window);
this.browser = this.target.ownerDocument.defaultView
this.browser = ownerDoc.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
this.principal = this.target.ownerDocument.nodePrincipal;
this.principal = ownerDoc.nodePrincipal;
this.frameOuterWindowID = ownerDoc.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.outerWindowID;
}
this.onSocial = !!this.browser.getAttribute("origin");
// Check if we are in a synthetic document (stand alone image, video, etc.).
this.inSyntheticDoc = this.target.ownerDocument.mozSyntheticDocument;
this.inSyntheticDoc = ownerDoc.mozSyntheticDocument;
// First, do checks for nodes that never have children.
if (this.target.nodeType == Node.ELEMENT_NODE) {
// See if the user clicked on an image.
@ -635,7 +642,7 @@ nsContextMenu.prototype = {
var descURL = this.target.getAttribute("longdesc");
if (descURL) {
this.imageDescURL = makeURLAbsolute(this.target.ownerDocument.body.baseURI, descURL);
this.imageDescURL = makeURLAbsolute(ownerDoc.body.baseURI, descURL);
}
}
else if (this.target instanceof HTMLCanvasElement) {
@ -685,7 +692,7 @@ nsContextMenu.prototype = {
this.onKeywordField = (editFlags & SpellCheckHelper.KEYWORD);
}
else if (this.target instanceof HTMLHtmlElement) {
var bodyElt = this.target.ownerDocument.body;
var bodyElt = ownerDoc.body;
if (bodyElt) {
let computedURL;
try {
@ -776,11 +783,11 @@ nsContextMenu.prototype = {
this.onMathML = true;
// See if the user clicked in a frame.
var docDefaultView = this.target.ownerDocument.defaultView;
var docDefaultView = ownerDoc.defaultView;
if (docDefaultView != docDefaultView.top) {
this.inFrame = true;
if (this.target.ownerDocument.isSrcdocDocument) {
if (ownerDoc.isSrcdocDocument) {
this.inSrcdocFrame = true;
}
}
@ -805,7 +812,7 @@ nsContextMenu.prototype = {
InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
}
else {
var targetWin = this.target.ownerDocument.defaultView;
var targetWin = ownerDoc.defaultView;
var editingSession = targetWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIInterfaceRequestor)

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

@ -3776,6 +3776,7 @@
referrerPolicy: aMessage.data.referrerPolicy,
contentType: aMessage.data.contentType,
contentDisposition: aMessage.data.contentDisposition,
frameOuterWindowID: aMessage.data.frameOuterWindowID,
};
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
let event = gContextMenuContentData.event;

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

@ -5,6 +5,7 @@
const TESTROOT = "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
const TESTROOT2 = "http://example.org/browser/toolkit/mozapps/extensions/test/xpinstall/";
const SECUREROOT = "https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
const PROGRESS_NOTIFICATION = "addon-progress";
@ -86,6 +87,52 @@ function wait_for_notification_close(aCallback) {
}, false);
}
function wait_for_install_dialog(aCallback) {
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
wait_for_notification("addon-install-confirmation", function(aPanel) {
aCallback();
});
return;
}
info("Waiting for install dialog");
Services.wm.addListener({
onOpenWindow: function(aXULWindow) {
info("Install dialog opened, waiting for focus");
Services.wm.removeListener(this);
var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
waitForFocus(function() {
info("Saw install dialog");
is(domwindow.document.location.href, XPINSTALL_URL, "Should have seen the right window open");
// Override the countdown timer on the accept button
var button = domwindow.document.documentElement.getButton("accept");
button.disabled = false;
aCallback();
}, domwindow);
},
onCloseWindow: function(aXULWindow) {
},
onWindowTitleChange: function(aXULWindow, aNewTitle) {
}
});
}
function accept_install_dialog() {
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
document.getElementById("addon-install-confirmation-accept").click();
} else {
let win = Services.wm.getMostRecentWindow("Addons:Install");
win.document.documentElement.acceptDialog();
}
}
function wait_for_single_notification(aCallback) {
function inner_waiter() {
info("Waiting for single notification");
@ -165,7 +212,7 @@ function test_blocked_install() {
"Should have seen the right message");
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
let notification = aPanel.childNodes[0];
@ -183,7 +230,7 @@ function test_blocked_install() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
// Click on Allow
@ -208,7 +255,7 @@ function test_whitelisted_install() {
gBrowser.selectedTab = originalTab;
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
is(gBrowser.selectedTab, tab,
"tab selected in response to the addon-install-confirmation notification");
@ -230,7 +277,7 @@ function test_whitelisted_install() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -331,7 +378,7 @@ function test_restartless() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
let notification = aPanel.childNodes[0];
@ -352,7 +399,7 @@ function test_restartless() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -370,7 +417,7 @@ function test_multiple() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
let notification = aPanel.childNodes[0];
@ -393,7 +440,7 @@ function test_multiple() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -412,7 +459,7 @@ function test_url() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
let notification = aPanel.childNodes[0];
@ -430,7 +477,7 @@ function test_url() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -499,7 +546,7 @@ function test_reload() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
let notification = aPanel.childNodes[0];
@ -534,7 +581,7 @@ function test_reload() {
gBrowser.loadURI(TESTROOT2 + "enabled.html");
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -552,7 +599,7 @@ function test_theme() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
let notification = aPanel.childNodes[0];
@ -577,7 +624,7 @@ function test_theme() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -630,7 +677,7 @@ function test_renotify_installed() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
// Wait for the complete notification
wait_for_notification("addon-install-complete", function(aPanel) {
// Dismiss the notification
@ -640,7 +687,7 @@ function test_renotify_installed() {
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_notification("addon-install-confirmation", function(aPanel) {
wait_for_install_dialog(function() {
info("Timeouts after this probably mean bug 589954 regressed");
// Wait for the complete notification
@ -655,7 +702,7 @@ function test_renotify_installed() {
});
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});
@ -667,7 +714,7 @@ function test_renotify_installed() {
aPanel.hidePopup();
});
document.getElementById("addon-install-confirmation-accept").click();
accept_install_dialog();
});
});

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

@ -282,7 +282,10 @@ let LoopCallsInternal = {
*/
_startCall: function(callData) {
const openChat = () => {
this.conversationInProgress.id = MozLoopService.openChatWindow(callData);
let windowId = MozLoopService.openChatWindow(callData);
if (windowId) {
this.conversationInProgress.id = windowId;
}
};
if (callData.type == "incoming" && ("callerId" in callData) &&

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

@ -62,11 +62,7 @@ const extend = function(target, source) {
*/
const containsParticipant = function(room, participant) {
for (let user of room.participants) {
// XXX until a bug 1100318 is implemented and deployed,
// we need to check the "id" field here as well - roomConnectionId is the
// official value for the interface.
if (user.roomConnectionId == participant.roomConnectionId &&
user.id == participant.id) {
if (user.roomConnectionId == participant.roomConnectionId) {
return true;
}
}
@ -451,10 +447,7 @@ let LoopRoomsInternal = {
let origRoom = this.rooms.get(roomToken);
let patchData = {
roomName: newRoomName,
// XXX We have to supply the max size and room owner due to bug 1099063.
maxSize: origRoom.maxSize,
roomOwner: origRoom.roomOwner
roomName: newRoomName
};
MozLoopService.hawkRequest(this.sessionType, url, "PATCH", patchData)
.then(response => {

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

@ -827,7 +827,8 @@ let MozLoopServiceInternal = {
*
* @param {Object} conversationWindowData The data to be obtained by the
* window when it opens.
* @returns {Number} The id of the window.
* @returns {Number} The id of the window, null if a window could not
* be opened.
*/
openChatWindow: function(conversationWindowData) {
// So I guess the origin is the loop server!?
@ -913,7 +914,9 @@ let MozLoopServiceInternal = {
}.bind(this), true);
};
Chat.open(null, origin, "", url, undefined, undefined, callback);
if (!Chat.open(null, origin, "", url, undefined, undefined, callback)) {
return null;
}
return windowId;
},

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

@ -33,7 +33,6 @@
<script type="text/javascript" src="loop/shared/js/dispatcher.js"></script>
<script type="text/javascript" src="loop/shared/js/otSdkDriver.js"></script>
<script type="text/javascript" src="loop/shared/js/store.js"></script>
<script type="text/javascript" src="loop/shared/js/roomStore.js"></script>
<script type="text/javascript" src="loop/shared/js/conversationStore.js"></script>
<script type="text/javascript" src="loop/shared/js/roomStates.js"></script>
<script type="text/javascript" src="loop/shared/js/fxOSActiveRoomStore.js"></script>
@ -46,6 +45,7 @@
<script type="text/javascript" src="loop/js/conversationAppStore.js"></script>
<script type="text/javascript" src="loop/js/client.js"></script>
<script type="text/javascript" src="loop/js/conversationViews.js"></script>
<script type="text/javascript" src="loop/js/roomStore.js"></script>
<script type="text/javascript" src="loop/js/roomViews.js"></script>
<script type="text/javascript" src="loop/js/conversation.js"></script>
</body>

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

@ -28,11 +28,11 @@
<script type="text/javascript" src="loop/shared/js/actions.js"></script>
<script type="text/javascript" src="loop/shared/js/dispatcher.js"></script>
<script type="text/javascript" src="loop/shared/js/store.js"></script>
<script type="text/javascript" src="loop/shared/js/roomStore.js"></script>
<script type="text/javascript" src="loop/shared/js/roomStates.js"></script>
<script type="text/javascript" src="loop/shared/js/fxOSActiveRoomStore.js"></script>
<script type="text/javascript" src="loop/shared/js/activeRoomStore.js"></script>
<script type="text/javascript;version=1.8" src="loop/js/contacts.js"></script>
<script type="text/javascript" src="loop/js/roomStore.js"></script>
<script type="text/javascript" src="loop/js/panel.js"></script>
</body>
</html>

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

@ -18,6 +18,7 @@ browser.jar:
content/browser/loop/js/panel.js (content/js/panel.js)
content/browser/loop/js/contacts.js (content/js/contacts.js)
content/browser/loop/js/conversationViews.js (content/js/conversationViews.js)
content/browser/loop/js/roomStore.js (content/js/roomStore.js)
content/browser/loop/js/roomViews.js (content/js/roomViews.js)
# Desktop styles
@ -71,7 +72,6 @@ browser.jar:
content/browser/loop/shared/js/actions.js (content/shared/js/actions.js)
content/browser/loop/shared/js/conversationStore.js (content/shared/js/conversationStore.js)
content/browser/loop/shared/js/store.js (content/shared/js/store.js)
content/browser/loop/shared/js/roomStore.js (content/shared/js/roomStore.js)
content/browser/loop/shared/js/roomStates.js (content/shared/js/roomStates.js)
content/browser/loop/shared/js/fxOSActiveRoomStore.js (content/shared/js/fxOSActiveRoomStore.js)
content/browser/loop/shared/js/activeRoomStore.js (content/shared/js/activeRoomStore.js)

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

@ -50,7 +50,6 @@
<script src="../../content/shared/js/otSdkDriver.js"></script>
<script src="../../content/shared/js/store.js"></script>
<script src="../../content/shared/js/conversationStore.js"></script>
<script src="../../content/shared/js/roomStore.js"></script>
<script src="../../content/shared/js/roomStates.js"></script>
<script src="../../content/shared/js/fxOSActiveRoomStore.js"></script>
<script src="../../content/shared/js/activeRoomStore.js"></script>
@ -59,6 +58,7 @@
<script src="../../content/shared/js/feedbackViews.js"></script>
<script src="../../content/js/client.js"></script>
<script src="../../content/js/conversationAppStore.js"></script>
<script src="../../content/js/roomStore.js"></script>
<script src="../../content/js/roomViews.js"></script>
<script src="../../content/js/conversationViews.js"></script>
<script src="../../content/js/conversation.js"></script>
@ -74,6 +74,7 @@
<script src="conversationViews_test.js"></script>
<script src="contacts_test.js"></script>
<script src="l10n_test.js"></script>
<script src="roomStore_test.js"></script>
<script>
// Stop the default init functions running to avoid conflicts in tests
document.removeEventListener('DOMContentLoaded', loop.panel.init);

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

@ -54,7 +54,6 @@
<script src="../../content/shared/js/roomStates.js"></script>
<script src="../../content/shared/js/fxOSActiveRoomStore.js"></script>
<script src="../../content/shared/js/activeRoomStore.js"></script>
<script src="../../content/shared/js/roomStore.js"></script>
<script src="../../content/shared/js/conversationStore.js"></script>
<script src="../../content/shared/js/feedbackStore.js"></script>
<script src="../../content/shared/js/views.js"></script>
@ -77,7 +76,6 @@
<script src="feedbackStore_test.js"></script>
<script src="otSdkDriver_test.js"></script>
<script src="store_test.js"></script>
<script src="roomStore_test.js"></script>
<script>
describe("Uncaught Error Check", function() {
it("should load the tests without errors", function() {

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

@ -33,6 +33,7 @@ add_task(function* test_busy_2fxa_calls() {
Chat.open = function(contentWindow, origin, title, url) {
opened++;
windowId = url.match(/about:loopconversation\#(\d+)$/)[1];
return windowId;
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);

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

@ -19,6 +19,7 @@ add_task(function test_startDirectCall_opens_window() {
let openedUrl;
Chat.open = function(contentWindow, origin, title, url) {
openedUrl = url;
return 1;
};
LoopCalls.startDirectCall(contact, "audio-video");
@ -34,6 +35,7 @@ add_task(function test_startDirectCall_getConversationWindowData() {
let openedUrl;
Chat.open = function(contentWindow, origin, title, url) {
openedUrl = url;
return 2;
};
LoopCalls.startDirectCall(contact, "audio-video");
@ -49,6 +51,36 @@ add_task(function test_startDirectCall_getConversationWindowData() {
LoopCalls.clearCallInProgress(windowId);
});
add_task(function test_startDirectCall_not_busy_if_window_fails_to_open() {
let openedUrl;
// Simulate no window available to open.
Chat.open = function(contentWindow, origin, title, url) {
openedUrl = url;
return null;
};
LoopCalls.startDirectCall(contact, "audio-video");
do_check_true(!!openedUrl, "should have attempted to open chat window");
openedUrl = null;
// Window opens successfully this time.
Chat.open = function(contentWindow, origin, title, url) {
openedUrl = url;
return 3;
};
LoopCalls.startDirectCall(contact, "audio-video");
do_check_true(!!openedUrl, "should open a chat window");
// Stop the busy kicking in for following tests.
let windowId = openedUrl.match(/about:loopconversation\#(\d+)$/)[1];
LoopCalls.clearCallInProgress(windowId);
});
function run_test() {
do_register_cleanup(function() {
// Revert original Chat.open implementation

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

@ -49,7 +49,6 @@
<script src="../content/shared/js/validate.js"></script>
<script src="../content/shared/js/dispatcher.js"></script>
<script src="../content/shared/js/store.js"></script>
<script src="../content/shared/js/roomStore.js"></script>
<script src="../content/shared/js/conversationStore.js"></script>
<script src="../content/shared/js/roomStates.js"></script>
<script src="../content/shared/js/fxOSActiveRoomStore.js"></script>
@ -57,6 +56,7 @@
<script src="../content/shared/js/feedbackStore.js"></script>
<script src="../content/shared/js/views.js"></script>
<script src="../content/shared/js/feedbackViews.js"></script>
<script src="../content/js/roomStore.js"></script>
<script src="../content/js/roomViews.js"></script>
<script src="../content/js/conversationViews.js"></script>
<script src="../content/js/client.js"></script>

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

@ -3,6 +3,7 @@ tags = devtools
skip-if = e10s # Handle in Bug 1077464 for profiler
subsuite = devtools
support-files =
doc_innerHTML.html
doc_simple-test.html
head.js
@ -10,6 +11,9 @@ support-files =
# that need to be moved over to performance tool
[browser_perf-aaa-run-first-leaktest.js]
[browser_markers-parse-html.js]
[browser_perf-allocations-to-samples.js]
[browser_perf-compatibility-01.js]
[browser_perf-compatibility-02.js]

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

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we get a "Parse HTML" marker when a page sets innerHTML.
*/
const TEST_URL = EXAMPLE_URL + "doc_innerHTML.html"
function* getMarkers(front) {
const { promise, resolve } = Promise.defer();
const handler = (_, markers) => {
resolve(markers);
};
front.on("markers", handler);
yield front.startRecording({ withTicks: true });
const markers = yield promise;
front.off("markers", handler);
yield front.stopRecording();
return markers;
}
function* spawnTest () {
let { target, front } = yield initBackend(TEST_URL);
const markers = yield getMarkers(front);
info("markers = " + JSON.stringify(markers, null, 2));
ok(markers.some(m => m.name === "Parse HTML" && m.stack != undefined),
"Should get some Parse HTML markers");
yield removeTab(target.tab);
finish();
}

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

@ -0,0 +1,20 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Performance tool + innerHTML test page</title>
</head>
<body>
<script type="text/javascript">
window.test = function () {
document.body.innerHTML = "<h1>LOL</h1>";
};
setInterval(window.test, 100);
</script>
</body>
</html>

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

@ -53,6 +53,16 @@ const TIMELINE_BLUEPRINT = {
colorName: "highlight-lightorange",
label: L10N.getStr("timeline.label.javascript2")
},
"Parse HTML": {
group: 1,
colorName: "highlight-lightorange",
label: L10N.getStr("timeline.label.parseHTML")
},
"Parse XML": {
group: 1,
colorName: "highlight-lightorange",
label: L10N.getStr("timeline.label.parseXML")
},
"ConsoleTime": {
group: 2,
colorName: "highlight-bluegrey",

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

@ -40,6 +40,8 @@ timeline.label.styles2=Recalculate Style
timeline.label.reflow2=Layout
timeline.label.paint=Paint
timeline.label.javascript2=Function Call
timeline.label.parseHTML=Parse HTML
timeline.label.parseXML=Parse XML
timeline.label.domevent=DOM Event
timeline.label.consoleTime=Console

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

@ -27,8 +27,8 @@
}
/* Square back and forward buttons */
#back-button:not(:-moz-lwtheme) > .toolbarbutton-icon,
#forward-button:not(:-moz-lwtheme) > .toolbarbutton-icon {
#back-button > .toolbarbutton-icon,
#forward-button > .toolbarbutton-icon {
margin: 0;
border: none;
padding: 2px 6px;

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

@ -218,7 +218,7 @@ toolbar[brighttext] #downloads-indicator-counter {
:root[devtoolstheme="dark"] .browserContainer > findbar .findbar-textbox {
background-color: var(--url-and-searchbar-background-color) !important;
background-image: none !important;
color: var(--url-and-searchbar-color);
color: var(--url-and-searchbar-color) !important;
border: none !important;
box-shadow: none !important;
}

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AutoTimelineMarker_h__
#define AutoTimelineMarker_h__
#include "mozilla/GuardObjects.h"
#include "mozilla/Move.h"
#include "nsDocShell.h"
#include "nsRefPtr.h"
namespace mozilla {
// # AutoTimelineMarker
//
// An RAII class to trace some task in the platform by adding a start and end
// timeline marker pair. These markers are then rendered in the devtools'
// performance tool's waterfall graph.
//
// Example usage:
//
// {
// AutoTimelineMarker marker(mDocShell, "Parse CSS");
// nsresult rv = ParseTheCSSFile(mFile);
// ...
// }
class MOZ_STACK_CLASS AutoTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
nsRefPtr<nsDocShell> mDocShell;
const char* mName;
bool
DocShellIsRecording(nsDocShell& aDocShell)
{
bool isRecording = false;
if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
}
return isRecording;
}
public:
explicit AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mDocShell(nullptr)
, mName(aName)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
if (docShell && DocShellIsRecording(*docShell)) {
mDocShell = docShell;
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
}
~AutoTimelineMarker()
{
if (mDocShell) {
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
}
};
} // namespace mozilla
#endif /* AutoTimelineMarker_h__ */

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

@ -42,6 +42,7 @@ EXPORTS += [
]
EXPORTS.mozilla += [
'AutoTimelineMarker.h',
'IHistory.h',
'LoadContext.h',
]

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

@ -30,6 +30,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/AutoTimelineMarker.h"
#include "mozilla/Base64.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
@ -4246,6 +4247,8 @@ nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
bool aQuirks,
bool aPreventScriptExecution)
{
AutoTimelineMarker m(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");
if (nsContentUtils::sFragmentParsingActive) {
NS_NOTREACHED("Re-entrant fragment parsing attempted.");
return NS_ERROR_DOM_INVALID_STATE_ERR;
@ -4272,6 +4275,8 @@ nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
nsIDocument* aTargetDocument,
bool aScriptingEnabledForNoscriptParsing)
{
AutoTimelineMarker m(aTargetDocument->GetDocShell(), "Parse HTML");
if (nsContentUtils::sFragmentParsingActive) {
NS_NOTREACHED("Re-entrant fragment parsing attempted.");
return NS_ERROR_DOM_INVALID_STATE_ERR;
@ -4297,6 +4302,8 @@ nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
bool aPreventScriptExecution,
nsIDOMDocumentFragment** aReturn)
{
AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
if (nsContentUtils::sFragmentParsingActive) {
NS_NOTREACHED("Re-entrant fragment parsing attempted.");
return NS_ERROR_DOM_INVALID_STATE_ERR;

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

@ -297,14 +297,16 @@ final class GeckoEditable
}
}
/**
* Remove the head of the queue. Throw if queue is empty.
*/
void poll() {
if (DEBUG) {
ThreadUtils.assertOnGeckoThread();
}
if (mActions.isEmpty()) {
if (mActions.poll() == null) {
throw new IllegalStateException("empty actions queue");
}
mActions.poll();
synchronized(this) {
if (mActions.isEmpty()) {
@ -313,13 +315,15 @@ final class GeckoEditable
}
}
/**
* Return, but don't remove, the head of the queue, or null if queue is empty.
*
* @return head of the queue or null if empty.
*/
Action peek() {
if (DEBUG) {
ThreadUtils.assertOnGeckoThread();
}
if (mActions.isEmpty()) {
throw new IllegalStateException("empty actions queue");
}
return mActions.peek();
}
@ -669,7 +673,11 @@ final class GeckoEditable
// GeckoEditableListener methods should all be called from the Gecko thread
ThreadUtils.assertOnGeckoThread();
}
final Action action = mActionQueue.peek();
if (action == null) {
throw new IllegalStateException("empty actions queue");
}
if (DEBUG) {
Log.d(LOGTAG, "reply: Action(" +
@ -834,8 +842,8 @@ final class GeckoEditable
/* An event (keypress, etc.) has potentially changed the selection,
synchronize the selection here. There is not a race with the IC thread
because the IC thread should be blocked on the event action */
if (!mActionQueue.isEmpty() &&
mActionQueue.peek().mType == Action.TYPE_EVENT) {
final Action action = mActionQueue.peek();
if (action != null && action.mType == Action.TYPE_EVENT) {
Selection.setSelection(mText, start, end);
return;
}
@ -868,6 +876,11 @@ final class GeckoEditable
mText.insert(start, newText);
}
private boolean isSameText(int start, int oldEnd, CharSequence newText) {
return oldEnd - start == newText.length() &&
TextUtils.regionMatches(mText, start, newText, 0, oldEnd - start);
}
@Override
public void onTextChange(final CharSequence text, final int start,
final int unboundedOldEnd, final int unboundedNewEnd) {
@ -909,9 +922,9 @@ final class GeckoEditable
TextUtils.copySpansFrom(mText, start, Math.min(oldEnd, newEnd),
Object.class, mChangedText, 0);
if (!mActionQueue.isEmpty()) {
final Action action = mActionQueue.peek();
if ((action.mType == Action.TYPE_REPLACE_TEXT ||
if (action != null &&
(action.mType == Action.TYPE_REPLACE_TEXT ||
action.mType == Action.TYPE_COMPOSE_TEXT) &&
start <= action.mStart &&
action.mStart + action.mSequence.length() <= newEnd) {
@ -943,12 +956,17 @@ final class GeckoEditable
mText.setSpan(Selection.SELECTION_END, selEnd, selEnd,
Spanned.SPAN_POINT_POINT);
}
} else {
// Gecko side initiated the text change.
if (isSameText(start, oldEnd, mChangedText)) {
// Nothing to do because the text is the same.
// This could happen when the composition is updated for example.
return;
}
geckoReplaceText(start, oldEnd, mChangedText);
}
} else {
geckoReplaceText(start, oldEnd, mChangedText);
}
geckoPostToIc(new Runnable() {
@Override
public void run() {

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

@ -385,6 +385,12 @@ var SelectionHandler = {
return this.START_ERROR_NONTEXT_INPUT;
}
const focus = Services.focus.focusedWindow;
if (focus) {
// Make sure any previous focus is cleared.
Services.focus.clearFocus(focus);
}
this._initTargetInfo(aElement, this.TYPE_SELECTION);
// Perform the appropriate selection method, if we can't determine method, or it fails, return

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

@ -184,7 +184,7 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
let markers = [];
for (let docShell of this.docShells) {
markers = [...markers, ...docShell.popProfileTimelineMarkers()];
markers.push(...docShell.popProfileTimelineMarkers());
}
// The docshell may return markers with stack traces attached.

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

@ -32,6 +32,7 @@ using mozilla::unused;
#include "nsFocusManager.h"
#include "nsIWidgetListener.h"
#include "nsViewManager.h"
#include "nsISelection.h"
#include "nsIDOMSimpleGestureEvent.h"
@ -178,7 +179,6 @@ nsWindow::nsWindow() :
mParent(nullptr),
mFocus(nullptr),
mIMEMaskSelectionUpdate(false),
mIMEMaskTextUpdate(false),
mIMEMaskEventsCount(1), // Mask IME events since there's no focus yet
mIMERanges(new TextRangeArray()),
mIMEUpdatingContext(false),
@ -1692,7 +1692,6 @@ nsWindow::RemoveIMEComposition()
nsRefPtr<nsWindow> kungFuDeathGrip(this);
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
AutoIMEMask textMask(mIMEMaskTextUpdate);
WidgetCompositionEvent compositionCommitEvent(true,
NS_COMPOSITION_COMMIT_AS_IS,
@ -1704,7 +1703,6 @@ nsWindow::RemoveIMEComposition()
void
nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
{
MOZ_ASSERT(!mIMEMaskTextUpdate);
MOZ_ASSERT(!mIMEMaskSelectionUpdate);
/*
Rules for managing IME between Gecko and Java:
@ -1781,9 +1779,6 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
Selection updates are masked so the result of our temporary
selection event is not passed on to Java
Text updates are passed on, so the Java text can shadow the
Gecko text
*/
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
const auto composition(GetIMEComposition());
@ -1932,11 +1927,10 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
to eliminate the possibility of this event altering the
text content unintentionally.
Selection and text updates are masked so the result of
Selection updates are masked so the result of
temporary events are not passed on to Java
*/
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
AutoIMEMask textMask(mIMEMaskTextUpdate);
const auto composition(GetIMEComposition());
MOZ_ASSERT(!composition || !composition->IsEditorHandlingEvent());
@ -2006,11 +2000,10 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
* Remove any previous composition. This is only used for
* visual indication and does not affect the text content.
*
* Selection and text updates are masked so the result of
* Selection updates are masked so the result of
* temporary events are not passed on to Java
*/
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
AutoIMEMask textMask(mIMEMaskTextUpdate);
RemoveIMEComposition();
mIMERanges->Clear();
}
@ -2197,7 +2190,19 @@ nsWindow::PostFlushIMEChanges()
void
nsWindow::FlushIMEChanges()
{
// Only send change notifications if we are *not* masking events,
// i.e. if we have a focused editor,
NS_ENSURE_TRUE_VOID(!mIMEMaskEventsCount);
nsCOMPtr<nsISelection> imeSelection;
nsCOMPtr<nsIContent> imeRoot;
// If we are receiving notifications, we must have selection/root content.
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(IMEStateManager::GetFocusSelectionAndRoot(
getter_AddRefs(imeSelection), getter_AddRefs(imeRoot))));
nsRefPtr<nsWindow> kungFuDeathGrip(this);
for (uint32_t i = 0; i < mIMETextChanges.Length(); i++) {
IMEChange &change = mIMETextChanges[i];
@ -2213,8 +2218,8 @@ nsWindow::FlushIMEChanges()
event.InitForQueryTextContent(change.mStart,
change.mNewEnd - change.mStart);
DispatchEvent(&event);
if (!event.mSucceeded)
return;
NS_ENSURE_TRUE_VOID(event.mSucceeded);
NS_ENSURE_TRUE_VOID(event.mReply.mContentsRoot == imeRoot.get());
}
GeckoAppShell::NotifyIMEChange(event.mReply.mString, change.mStart,
@ -2227,8 +2232,8 @@ nsWindow::FlushIMEChanges()
InitEvent(event, nullptr);
DispatchEvent(&event);
if (!event.mSucceeded)
return;
NS_ENSURE_TRUE_VOID(event.mSucceeded);
NS_ENSURE_TRUE_VOID(event.mReply.mContentsRoot == imeRoot.get());
GeckoAppShell::NotifyIMEChange(EmptyString(),
int32_t(event.GetSelectionStart()),
@ -2243,9 +2248,6 @@ nsWindow::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
"NotifyIMEOfTextChange() is called with invaild notification");
if (mIMEMaskTextUpdate)
return NS_OK;
ALOGIME("IME: NotifyIMEOfTextChange: s=%d, oe=%d, ne=%d",
aIMENotification.mTextChangeData.mStartOffset,
aIMENotification.mTextChangeData.mOldEndOffset,

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

@ -217,7 +217,7 @@ protected:
nsCOMPtr<nsIIdleServiceInternal> mIdleService;
bool mIMEMaskSelectionUpdate, mIMEMaskTextUpdate;
bool mIMEMaskSelectionUpdate;
int32_t mIMEMaskEventsCount; // Mask events when > 0
nsRefPtr<mozilla::TextRangeArray> mIMERanges;
bool mIMEUpdatingContext;