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

This commit is contained in:
Margareta Eliza Balazs 2018-05-14 19:49:50 +03:00
Родитель 35690640f2 2b9779c593
Коммит 17675612bf
39 изменённых файлов: 865 добавлений и 496 удалений

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

@ -126,7 +126,7 @@ if (AppConstants.NIGHTLY_BUILD) {
// lazy service getters
XPCOMUtils.defineLazyServiceGetters(this, {
Favicons: ["@mozilla.org/browser/favicon-service;1", "mozIAsyncFavicons"],
Favicons: ["@mozilla.org/browser/favicon-service;1", "nsIFaviconService"],
gAboutNewTabService: ["@mozilla.org/browser/aboutnewtab-service;1", "nsIAboutNewTabService"],
gDNSService: ["@mozilla.org/network/dns-service;1", "nsIDNSService"],
gSerializationHelper: ["@mozilla.org/network/serialization-helper;1", "nsISerializationHelper"],

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

@ -8,6 +8,7 @@ support-files =
[browser_devices_get_user_media.js]
skip-if = (os == "linux" && debug) # linux: bug 976544
[browser_devices_get_user_media_anim.js]
[browser_devices_get_user_media_default_permissions.js]
[browser_devices_get_user_media_in_frame.js]
skip-if = debug # bug 1369731
[browser_devices_get_user_media_multi_process.js]

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

@ -0,0 +1,164 @@
/* 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/. */
const permissionError = "error: NotAllowedError: The request is not allowed " +
"by the user agent or the platform in the current context.";
const CAMERA_PREF = "permissions.default.camera";
const MICROPHONE_PREF = "permissions.default.microphone";
var gTests = [
{
desc: "getUserMedia audio+video: globally blocking camera",
run: async function checkAudioVideo() {
Services.prefs.setIntPref(CAMERA_PREF, SitePermissions.BLOCK);
// Requesting audio+video shouldn't work.
let promise = promiseMessage(permissionError);
await promiseRequestDevice(true, true);
await promise;
await expectObserverCalled("recording-window-ended");
await checkNotSharing();
// Requesting only video shouldn't work.
promise = promiseMessage(permissionError);
await promiseRequestDevice(false, true);
await promise;
await expectObserverCalled("recording-window-ended");
await checkNotSharing();
// Requesting audio should work.
promise = promisePopupNotificationShown("webRTC-shareDevices");
await promiseRequestDevice(true);
await promise;
await expectObserverCalled("getUserMedia:request");
is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID,
"webRTC-shareMicrophone-notification-icon", "anchored to mic icon");
checkDeviceSelectors(true);
let iconclass =
PopupNotifications.panel.firstChild.getAttribute("iconclass");
ok(iconclass.includes("microphone-icon"), "panel using microphone icon");
let indicator = promiseIndicatorWindow();
await promiseMessage("ok", () => {
PopupNotifications.panel.firstChild.button.click();
});
await expectObserverCalled("getUserMedia:response:allow");
await expectObserverCalled("recording-device-events");
Assert.deepEqual((await getMediaCaptureState()), {audio: true},
"expected microphone to be shared");
await indicator;
await checkSharingUI({audio: true});
await closeStream();
Services.prefs.clearUserPref(CAMERA_PREF);
}
},
{
desc: "getUserMedia video: globally blocking camera + local exception",
run: async function checkAudioVideo() {
let browser = gBrowser.selectedBrowser;
Services.prefs.setIntPref(CAMERA_PREF, SitePermissions.BLOCK);
// Overwrite the permission for that URI, requesting video should work again.
SitePermissions.set(browser.currentURI, "camera", SitePermissions.ALLOW);
// Requesting video should work.
let indicator = promiseIndicatorWindow();
let promise = promiseMessage("ok");
await promiseRequestDevice(false, true);
await promise;
await expectObserverCalled("getUserMedia:request");
await expectObserverCalled("getUserMedia:response:allow");
await expectObserverCalled("recording-device-events");
await indicator;
await checkSharingUI({video: true});
await closeStream();
SitePermissions.remove(browser.currentURI, "camera");
Services.prefs.clearUserPref(CAMERA_PREF);
}
},
{
desc: "getUserMedia audio+video: globally blocking microphone",
run: async function checkAudioVideo() {
Services.prefs.setIntPref(MICROPHONE_PREF, SitePermissions.BLOCK);
// Requesting audio+video shouldn't work.
let promise = promiseMessage(permissionError);
await promiseRequestDevice(true, true);
await promise;
await expectObserverCalled("recording-window-ended");
await checkNotSharing();
// Requesting only audio shouldn't work.
promise = promiseMessage(permissionError);
await promiseRequestDevice(true);
await promise;
await expectObserverCalled("recording-window-ended");
await checkNotSharing();
// Requesting video should work.
promise = promisePopupNotificationShown("webRTC-shareDevices");
await promiseRequestDevice(false, true);
await promise;
await expectObserverCalled("getUserMedia:request");
is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID,
"webRTC-shareDevices-notification-icon", "anchored to device icon");
checkDeviceSelectors(false, true);
let iconclass =
PopupNotifications.panel.firstChild.getAttribute("iconclass");
ok(iconclass.includes("camera-icon"), "panel using devices icon");
let indicator = promiseIndicatorWindow();
await promiseMessage("ok", () => {
PopupNotifications.panel.firstChild.button.click();
});
await expectObserverCalled("getUserMedia:response:allow");
await expectObserverCalled("recording-device-events");
Assert.deepEqual((await getMediaCaptureState()), {video: true},
"expected camera to be shared");
await indicator;
await checkSharingUI({video: true});
await closeStream();
Services.prefs.clearUserPref(MICROPHONE_PREF);
}
},
{
desc: "getUserMedia audio: globally blocking microphone + local exception",
run: async function checkAudioVideo() {
let browser = gBrowser.selectedBrowser;
Services.prefs.setIntPref(MICROPHONE_PREF, SitePermissions.BLOCK);
// Overwrite the permission for that URI, requesting video should work again.
SitePermissions.set(browser.currentURI, "microphone", SitePermissions.ALLOW);
// Requesting audio should work.
let indicator = promiseIndicatorWindow();
let promise = promiseMessage("ok");
await promiseRequestDevice(true);
await promise;
await expectObserverCalled("getUserMedia:request");
await expectObserverCalled("getUserMedia:response:allow");
await expectObserverCalled("recording-device-events");
await indicator;
await checkSharingUI({audio: true});
await closeStream();
SitePermissions.remove(browser.currentURI, "microphone");
Services.prefs.clearUserPref(MICROPHONE_PREF);
}
},
];
add_task(async function test() {
await runTests(gTests);
});

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

@ -114,7 +114,7 @@ async function assertWebRTCIndicatorStatus(expected) {
while (windows.hasMoreElements()) {
let win = windows.getNext();
let menu = win.document.getElementById("tabSharingMenu");
is(menu && !menu.hidden, !!expected, "WebRTC menu should be " + expectedState);
is(!!menu && !menu.hidden, !!expected, "WebRTC menu should be " + expectedState);
}
if (!("nsISystemStatusBar" in Ci)) {

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

@ -85,7 +85,7 @@
value="custom"
search-l10n-ids="
history-private-browsing-permanent.label,
history-remember-option.label,
history-remember-browser-option.label,
history-remember-search-option.label,
history-clear-on-close-option.label,
history-clear-on-close-settings.label"/>
@ -120,7 +120,7 @@
preference="browser.privatebrowsing.autostart"/>
<vbox class="indent">
<checkbox id="rememberHistory"
data-l10n-id="history-remember-option"
data-l10n-id="history-remember-browser-option"
preference="places.history.enabled"/>
<checkbox id="rememberForms"
data-l10n-id="history-remember-search-option"
@ -146,7 +146,7 @@
<button id="clearDataSettings"
class="accessory-button"
data-l10n-id="history-clear-on-close-settings"
searchkeywords="&clearDataSettings3.label;
searchkeywords="&clearDataSettings4.label;
&historySection.label;
&itemHistoryAndDownloads.label;
&itemCookies.label;

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

@ -39,7 +39,7 @@
<script type="application/javascript" src="chrome://browser/content/preferences/sanitize.js"/>
<description>&clearDataSettings3.label;</description>
<description>&clearDataSettings4.label;</description>
<groupbox orient="horizontal">
<caption><label>&historySection.label;</label></caption>

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

@ -696,8 +696,8 @@ history-private-browsing-permanent =
.label = Always use private browsing mode
.accesskey = p
history-remember-option =
.label = Remember my browsing and download history
history-remember-browser-option =
.label = Remember browsing and download history
.accesskey = b
history-remember-search-option =

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

@ -13,7 +13,7 @@
<!-- LOCALIZATION NOTE (sanitizeDialog2.width): width of the Clear Recent History dialog -->
<!ENTITY sanitizeDialog2.width "34em">
<!ENTITY clearDataSettings3.label "When I quit &brandShortName;, it should automatically clear all">
<!ENTITY clearDataSettings4.label "When closed, &brandShortName; should automatically clear all">
<!-- XXX rearrange entities to match physical layout when l10n isn't an issue -->
<!-- LOCALIZATION NOTE (clearTimeDuration.*): "Time range to clear" dropdown.

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

@ -341,12 +341,20 @@ function prompt(aBrowser, aRequest) {
let { audioDevices, videoDevices, sharingScreen, sharingAudio,
requestTypes } = aRequest;
let uri;
try {
// This fails for principals that serialize to "null", e.g. file URIs.
uri = Services.io.newURI(aRequest.origin);
} catch (e) {
uri = Services.io.newURI(aRequest.documentURI);
}
// If the user has already denied access once in this tab,
// deny again without even showing the notification icon.
if ((audioDevices.length && SitePermissions
.get(null, "microphone", aBrowser).state == SitePermissions.BLOCK) ||
.get(uri, "microphone", aBrowser).state == SitePermissions.BLOCK) ||
(videoDevices.length && SitePermissions
.get(null, sharingScreen ? "screen" : "camera", aBrowser).state == SitePermissions.BLOCK)) {
.get(uri, sharingScreen ? "screen" : "camera", aBrowser).state == SitePermissions.BLOCK)) {
denyRequest(aBrowser, aRequest);
return;
}
@ -356,14 +364,6 @@ function prompt(aBrowser, aRequest) {
aBrowser.dispatchEvent(new aBrowser.ownerGlobal
.CustomEvent("PermissionStateChange"));
let uri;
try {
// This fails for principals that serialize to "null", e.g. file URIs.
uri = Services.io.newURI(aRequest.origin);
} catch (e) {
uri = Services.io.newURI(aRequest.documentURI);
}
let chromeDoc = aBrowser.ownerDocument;
let stringBundle = chromeDoc.defaultView.gNavigatorBundle;

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

@ -104,16 +104,19 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
_SAVE_CXXFLAGS="$CXXFLAGS"
_SAVE_CPPFLAGS="$CPPFLAGS"
_SAVE_CXX="$CXX"
_SAVE_MACOSX_DEPLOYMENT_TARGET="$MACOSX_DEPLOYMENT_TARGET"
unset MACOSX_DEPLOYMENT_TARGET
CXXFLAGS="${LLVM_CXXFLAGS}"
CPPFLAGS=""
CXX="${HOST_CXX}"
AC_TRY_COMPILE([#include "clang/ASTMatchers/ASTMatchers.h"],
[clang::ast_matchers::cxxConstructExpr();],
ac_cv_have_new_ASTMatcher_names="yes",
ac_cv_have_new_ASTMatcher_names="no")
CXX="$_SAVE_CXX"
CPPFLAGS="$_SAVE_CPPFLAGS"
CXXFLAGS="$_SAVE_CXXFLAGS"
export MACOSX_DEPLOYMENT_TARGET="$_SAVE_MACOSX_DEPLOYMENT_TARGET"
AC_LANG_RESTORE
@ -131,10 +134,12 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
_SAVE_CXXFLAGS="$CXXFLAGS"
_SAVE_CPPFLAGS="$CPPFLAGS"
_SAVE_CXX="$CXX"
_SAVE_MACOSX_DEPLOYMENT_TARGET="$MACOSX_DEPLOYMENT_TARGET"
unset MACOSX_DEPLOYMENT_TARGET
CXXFLAGS="${LLVM_CXXFLAGS}"
CPPFLAGS=""
CXX="${HOST_CXX}"
AC_TRY_COMPILE([#include "clang/ASTMatchers/ASTMatchers.h"],
[using namespace clang::ast_matchers;
@ -143,6 +148,7 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
ac_cv_has_accepts_ignoringParenImpCasts="yes",
ac_cv_has_accepts_ignoringParenImpCasts="no")
CXX="$_SAVE_CXX"
CPPFLAGS="$_SAVE_CPPFLAGS"
CXXFLAGS="$_SAVE_CXXFLAGS"
export MACOSX_DEPLOYMENT_TARGET="$_SAVE_MACOSX_DEPLOYMENT_TARGET"
AC_LANG_RESTORE

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

@ -39,6 +39,7 @@ function TabboxPanel({
activeTabId,
cloneSelectedRequest = () => {},
connector,
hideToggleButton,
openLink,
request,
selectTab,
@ -56,7 +57,8 @@ function TabboxPanel({
onSelect: selectTab,
renderOnlySelected: true,
showAllTabsMenu: true,
sidebarToggleButton: {
sidebarToggleButton: hideToggleButton ? null :
{
collapsed: false,
collapsePaneTitle: COLLAPSE_DETAILS_PANE,
expandPaneTitle: "",
@ -144,6 +146,7 @@ TabboxPanel.propTypes = {
request: PropTypes.object,
selectTab: PropTypes.func.isRequired,
sourceMapService: PropTypes.object,
hideToggleButton: PropTypes.boolean,
};
module.exports = TabboxPanel;

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

@ -148,6 +148,7 @@ function NetworkEventMessage({
selectTab: (tabId) => {
dispatch(actions.selectNetworkMessageTab(tabId));
},
hideToggleButton: true,
})
);

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

@ -94,6 +94,9 @@ async function openRequestAfterUpdates(target, hud) {
let urlNode = messageNode.querySelector(".url");
urlNode.click();
let toggleButtonNode = messageNode.querySelector(".sidebar-toggle");
ok(!toggleButtonNode, "Sidebar toggle button shouldn't be shown");
await payload;
await testNetworkMessage(toolbox, messageNode);
}

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

@ -214,7 +214,6 @@
#ifdef MOZ_PLACES
#include "nsIFaviconService.h"
#include "mozIPlacesPendingOperation.h"
#include "mozIAsyncFavicons.h"
#endif
#if NS_PRINT_PREVIEW
@ -9121,7 +9120,7 @@ nsDocShell::CopyFavicon(nsIURI* aOldURI,
}
#ifdef MOZ_PLACES
nsCOMPtr<mozIAsyncFavicons> favSvc =
nsCOMPtr<nsIFaviconService> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
if (favSvc) {
favSvc->CopyFavicons(aOldURI, aNewURI,

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

@ -32,7 +32,7 @@ SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) {
if (aMsg.message == "SENTINEL") {
is(consoleCount, 0);
SimpleTest.executeSoon(finish);
} else {
} else if (aMsg.message.includes("Content Security Policy")) {
++consoleCount;
ok(false, "Must never see a console warning here");
}

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

@ -570,6 +570,12 @@ WebRenderLayerManager::SetTransactionIdAllocator(TransactionIdAllocator* aAlloca
mTransactionIdAllocator = aAllocator;
}
TransactionId
WebRenderLayerManager::GetLastTransactionId()
{
return mLatestTransactionId;
}
void
WebRenderLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
{

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

@ -102,6 +102,7 @@ public:
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override;
virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override;
virtual TransactionId GetLastTransactionId() override;
virtual void AddDidCompositeObserver(DidCompositeObserver* aObserver) override;
virtual void RemoveDidCompositeObserver(DidCompositeObserver* aObserver) override;

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

@ -36,11 +36,14 @@ function StartListener(event) {
}
function IterationListener(event) {
setTimeout(RemoveReftestWait, 0);
window.addEventListener("MozAfterPaint", () => {
requestAnimationFrame(RemoveReftestWait);
}, { once: true });
}
function RemoveReftestWait() {
document.documentElement.classList.remove("reftest-wait");
document.documentElement.classList.add("reftest-ignore-pending-paints");
}
</script>

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

@ -1,5 +1,5 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<html class="reftest-wait reftest-no-flush">
<title>Testcase, bug 1176969</title>
<style>
@ -46,11 +46,14 @@ body { padding: 50px }
document.getElementById("parent").addEventListener("animationiteration", IterationListener);
function IterationListener(event) {
setTimeout(RemoveReftestWait, 0);
window.addEventListener("MozAfterPaint", () => {
requestAnimationFrame(RemoveReftestWait);
}, { once: true });
}
function RemoveReftestWait() {
document.documentElement.classList.remove("reftest-wait");
document.documentElement.classList.add("reftest-ignore-pending-paints");
}
</script>

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

@ -1,5 +1,5 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<html class="reftest-wait reftest-no-flush">
<title>Testcase, bug 1176969</title>
<style>
@ -48,11 +48,14 @@ function StartListener(event) {
}
function IterationListener(event) {
setTimeout(RemoveReftestWait, 0);
window.addEventListener("MozAfterPaint", () => {
requestAnimationFrame(RemoveReftestWait);
}, { once: true });
}
function RemoveReftestWait() {
document.documentElement.classList.remove("reftest-wait");
document.documentElement.classList.add("reftest-ignore-pending-paints");
}
</script>

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

@ -71,7 +71,7 @@ fuzzy(3,99) == animate-cube-degrees.html animate-cube-degrees-ref.html # subpixe
!= animate-cube-degrees-ref.html animate-cube-degrees-zoom-ref.html
fuzzy-if(gtkWidget,128,100) fuzzy-if(Android||OSX==1010||(gtkWidget&&layersGPUAccelerated),143,100) fuzzy-if(winWidget||OSX<1010,141,100) == preserves3d-nested.html preserves3d-nested-ref.html
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
fuzzy-if(cocoaWidget,128,9) skip-if(Android) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac, bug 1461311 for Android
== animate-backface-hidden.html about:blank
== 1245450-1.html green-rect.html
fuzzy(1,2000) == opacity-preserve3d-1.html opacity-preserve3d-1-ref.html

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

@ -665,3 +665,20 @@ to push a layer-tree update to the compositor before taking the snapshot.
Setting the "reftest-no-sync-layers" attribute on the root element skips this
step, enabling testing that layer-tree updates are being correctly generated.
However the test must manually wait for a MozAfterPaint event before ending.
Avoid hanging on long/infinite animation tests: reftest-ignore-pending-paints
=============================================================================
If a test contains a long animation, and the desired behaviour is to take a
snapshot partway through the animation, the usual procedure is to have a part
of the animation that is visually unchanging, and when the test page reaches that
part, it removes the reftest-wait to allow the harness to finish. However, this
relies on an optimization inside Gecko that stops repaints if it detects that
nothing will visually change (by detecting an empty invalidation area, for
example). In some cases, this optimization may not trigger (e.g. with WebRender
enabled). For such cases, the reftest-wait class attribute can be replaced by
reftest-ignore-pending-paints on the root html element, and this will make the
harness ignore any pending repaints (i.e. stop listening for MozAfterPaint) and
just go ahead and finish the test.
Note that any reftest that attempts to use this feature without animations will
fail with an error.

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

@ -422,10 +422,26 @@ function shouldWaitForExplicitPaintWaiters() {
return gExplicitPendingPaintCount > 0;
}
function shouldWaitForPendingPaints() {
function shouldWaitForPendingPaints(contentRootElement) {
// if gHaveCanvasSnapshot is false, we're not taking snapshots so
// there is no need to wait for pending paints to be flushed.
return gHaveCanvasSnapshot && windowUtils().isMozAfterPaintPending;
return gHaveCanvasSnapshot &&
!shouldIgnorePendingMozAfterPaints(contentRootElement) &&
windowUtils().isMozAfterPaintPending;
}
function shouldIgnorePendingMozAfterPaints(contentRootElement) {
// use getAttribute because className works differently in HTML and SVG
var ignore = contentRootElement &&
contentRootElement.hasAttribute('class') &&
contentRootElement.getAttribute('class').split(/\s+/)
.includes("reftest-ignore-pending-paints");
// getAnimations is nightly-only, so check it exists before calling it
if (ignore && contentRootElement.ownerDocument.getAnimations
&& contentRootElement.ownerDocument.getAnimations().length == 0) {
LogError("reftest-ignore-pending-paints should only be used on documents with animations!");
}
return ignore;
}
function shouldWaitForReftestWaitRemoval(contentRootElement) {
@ -611,13 +627,13 @@ function WaitForTestEnd(contentRootElement, inPrintMode, spellCheckedElements) {
switch (state) {
case STATE_WAITING_TO_FIRE_INVALIDATE_EVENT: {
LogInfo("MakeProgress: STATE_WAITING_TO_FIRE_INVALIDATE_EVENT");
if (shouldWaitForExplicitPaintWaiters() || shouldWaitForPendingPaints()) {
if (shouldWaitForExplicitPaintWaiters() || shouldWaitForPendingPaints(contentRootElement)) {
gFailureReason = "timed out waiting for pending paint count to reach zero";
if (shouldWaitForExplicitPaintWaiters()) {
gFailureReason += " (waiting for MozPaintWaitFinished)";
LogInfo("MakeProgress: waiting for MozPaintWaitFinished");
}
if (shouldWaitForPendingPaints()) {
if (shouldWaitForPendingPaints(contentRootElement)) {
gFailureReason += " (waiting for MozAfterPaint)";
LogInfo("MakeProgress: waiting for MozAfterPaint");
}
@ -655,7 +671,7 @@ function WaitForTestEnd(contentRootElement, inPrintMode, spellCheckedElements) {
// MozReftestInvalidate handler removed reftest-wait.
// We expect something to have been invalidated...
FlushRendering(FlushMode.ALL);
if (!shouldWaitForPendingPaints() && !shouldWaitForExplicitPaintWaiters()) {
if (!shouldWaitForPendingPaints(contentRootElement) && !shouldWaitForExplicitPaintWaiters()) {
LogWarning("MozInvalidateEvent didn't invalidate");
}
}
@ -720,14 +736,14 @@ function WaitForTestEnd(contentRootElement, inPrintMode, spellCheckedElements) {
case STATE_WAITING_TO_FINISH:
LogInfo("MakeProgress: STATE_WAITING_TO_FINISH");
if (shouldWaitForExplicitPaintWaiters() || shouldWaitForPendingPaints()) {
if (shouldWaitForExplicitPaintWaiters() || shouldWaitForPendingPaints(contentRootElement)) {
gFailureReason = "timed out waiting for pending paint count to " +
"reach zero (after reftest-wait removed and switch to print mode)";
if (shouldWaitForExplicitPaintWaiters()) {
gFailureReason += " (waiting for MozPaintWaitFinished)";
LogInfo("MakeProgress: waiting for MozPaintWaitFinished");
}
if (shouldWaitForPendingPaints()) {
if (shouldWaitForPendingPaints(contentRootElement)) {
gFailureReason += " (waiting for MozAfterPaint)";
LogInfo("MakeProgress: waiting for MozAfterPaint");
}
@ -1080,6 +1096,15 @@ function LoadURI(uri)
webNavigation().loadURI(uri, flags, null, null, null);
}
function LogError(str)
{
if (gVerbose) {
sendSyncMessage("reftest:Log", { type: "error", msg: str });
} else {
sendAsyncMessage("reftest:Log", { type: "error", msg: str });
}
}
function LogWarning(str)
{
if (gVerbose) {

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

@ -1512,6 +1512,9 @@ function RecvLog(type, msg)
TestBuffer(msg);
} else if (type == "warning") {
logger.warning(msg);
} else if (type == "error") {
logger.error("REFTEST TEST-UNEXPECTED-FAIL | " + g.currentURL + " | " + msg + "\n");
++g.testResults.Exception;
} else {
logger.error("REFTEST TEST-UNEXPECTED-FAIL | " + g.currentURL + " | unknown log type " + type + "\n");
++g.testResults.Exception;

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

@ -106,19 +106,10 @@ pref("browser.cache.compression_level", 0);
pref("browser.download.forbid_open_with", false);
// Remove navigator.registerContentHandler
#ifdef EARLY_BETA_OR_EARLIER
pref("dom.registerContentHandler.enabled", false);
#else
pref("dom.registerContentHandler.enabled", true);
#endif
// Nightly will have insecure registerProtocolHandler disabled by default
// Beta and Stable will remain enabled until Firefox 62 providing deprecation stats.
#ifdef NIGHTLY_BUILD
// Insecure registerProtocolHandler is disabled by default
pref("dom.registerProtocolHandler.insecure.enabled", false);
#else
pref("dom.registerProtocolHandler.insecure.enabled", true);
#endif
// Whether or not testing features are enabled.
pref("dom.quotaManager.testing", false);

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

@ -893,6 +893,9 @@ class BaseMarionetteTestRunner(object):
version_info=self.version_info,
device_info=device_info)
if self.shuffle:
self.logger.info("Using shuffle seed: %d" % self.shuffle_seed)
self._log_skipped_tests()
interrupted = None
@ -925,8 +928,6 @@ class BaseMarionetteTestRunner(object):
for run_tests in self.mixin_run_tests:
run_tests(tests)
if self.shuffle:
self.logger.info("Using shuffle seed: %d" % self.shuffle_seed)
self.logger.suite_end()
except Exception:

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

@ -18,7 +18,6 @@
#include "nsToolkitCompsCID.h"
#ifdef MOZ_PLACES
#include "mozIAsyncFavicons.h"
#include "nsIFaviconService.h"
#endif // MOZ_PLACES
@ -104,7 +103,7 @@ ShowWithIconBackend(nsIAlertsService* aBackend, nsIAlertNotification* aAlert,
return NS_ERROR_NOT_IMPLEMENTED;
}
nsCOMPtr<mozIAsyncFavicons> favicons(do_GetService(
nsCOMPtr<nsIFaviconService> favicons(do_GetService(
"@mozilla.org/browser/favicon-service;1"));
NS_ENSURE_TRUE(favicons, NS_ERROR_FAILURE);

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

@ -1872,7 +1872,7 @@ XPCOMUtils.defineLazyGetter(PlacesUtils, "history", function() {
XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "favicons",
"@mozilla.org/browser/favicon-service;1",
"mozIAsyncFavicons");
"nsIFaviconService");
XPCOMUtils.defineLazyServiceGetter(this, "bmsvc",
"@mozilla.org/browser/nav-bookmarks-service;1",

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

@ -15,7 +15,6 @@ XPIDL_MODULE = 'places'
if CONFIG['MOZ_PLACES']:
XPIDL_SOURCES += [
'mozIAsyncFavicons.idl',
'mozIAsyncHistory.idl',
'mozIAsyncLivemarks.idl',
'mozIColorAnalyzer.idl',

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

@ -1,211 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsIURI;
interface nsIFaviconDataCallback;
interface nsIPrincipal;
interface mozIPlacesPendingOperation;
[scriptable, uuid(a9c81797-9133-4823-b55f-3646e67cfd41)]
interface mozIAsyncFavicons : nsISupports
{
/**
* Declares that a given page uses a favicon with the given URI and
* attempts to fetch and save the icon data by loading the favicon URI
* through an async network request.
*
* If the icon data already exists, we won't try to reload the icon unless
* aForceReload is true. Similarly, if the icon is in the failed favicon
* cache we won't do anything unless aForceReload is true, in which case
* we'll try to reload the favicon.
*
* This function will only save favicons for pages that are already stored in
* the database, like visited pages or bookmarks. For any other URIs, it
* will succeed but do nothing. This function will also ignore the error
* page favicon URI (see FAVICON_ERRORPAGE_URL below).
*
* Icons that fail to load will automatically be added to the failed favicon
* cache, and this function will not save favicons for non-bookmarked URIs
* when history is disabled.
*
* @note This function is identical to
* nsIFaviconService::setAndLoadFaviconForPage.
*
* @param aPageURI
* URI of the page whose favicon is being set.
* @param aFaviconURI
* URI of the favicon to associate with the page.
* @param aForceReload
* If aForceReload is false, we try to reload the favicon only if we
* don't have it or it has expired from the cache. Setting
* aForceReload to true causes us to reload the favicon even if we
* have a usable copy.
* @param aFaviconLoadType
* Set to FAVICON_LOAD_PRIVATE if the favicon is loaded from a private
* browsing window. Set to FAVICON_LOAD_NON_PRIVATE otherwise.
* @param [optional] aCallback
* Once we're done setting and/or fetching the favicon, we invoke this
* callback.
* @param [optional] aLoadingPrincipal
* Principal of the page whose favicon is being set. If this argument
* is omitted, the loadingPrincipal defaults to the nullPrincipal.
* @param [optional] aRequestContextID
* used to inform Necko of how to link the
* favicon request with other requests in the same tab.
*
* @see nsIFaviconDataCallback in nsIFaviconService.idl.
*/
mozIPlacesPendingOperation setAndFetchFaviconForPage(
in nsIURI aPageURI,
in nsIURI aFaviconURI,
in boolean aForceReload,
in unsigned long aFaviconLoadType,
[optional] in nsIFaviconDataCallback aCallback,
[optional] in nsIPrincipal aLoadingPrincipal,
[optional] in unsigned long long aRequestContextID);
/**
* Sets the data for a given favicon URI either by replacing existing data in
* the database or taking the place of otherwise fetched icon data when
* calling setAndFetchFaviconForPage later.
*
* Favicon data for favicon URIs that are not associated with a page URI via
* setAndFetchFaviconForPage will be stored in memory, but may be expired at
* any time, so you should make an effort to associate favicon URIs with page
* URIs as soon as possible.
*
* It's better to not use this function for chrome: icon URIs since you can
* reference the chrome image yourself. getFaviconLinkForIcon/Page will ignore
* any associated data if the favicon URI is "chrome:" and just return the
* same chrome URI.
*
* This function does NOT send out notifications that the data has changed.
* Pages using this favicons that are visible in history or bookmarks views
* will keep the old icon until they have been refreshed by other means.
*
* This function tries to optimize the favicon size, if it is bigger
* than a defined limit we will try to convert it to a 16x16 png image.
* If the conversion fails and favicon is still bigger than our max accepted
* size it won't be saved.
*
* @param aFaviconURI
* URI of the favicon whose data is being set.
* @param aData
* Binary contents of the favicon to save
* @param aDataLength
* Length of binary data
* @param aMimeType
* MIME type of the data to store. This is important so that we know
* what to report when the favicon is used. You should always set this
* param unless you are clearing an icon.
* @param [optional] aExpiration
* Time in microseconds since the epoch when this favicon expires.
* Until this time, we won't try to load it again.
* @throws NS_ERROR_FAILURE
* Thrown if the favicon is overbloated and won't be saved to the db.
*/
void replaceFaviconData(in nsIURI aFaviconURI,
[const,array,size_is(aDataLen)] in octet aData,
in unsigned long aDataLen,
in AUTF8String aMimeType,
[optional] in PRTime aExpiration);
/**
* Same as replaceFaviconData but the data is provided by a string
* containing a data URL.
*
* @see replaceFaviconData
*
* @param aFaviconURI
* URI of the favicon whose data is being set.
* @param aDataURL
* string containing a data URL that represents the contents of
* the favicon to save
* @param [optional] aExpiration
* Time in microseconds since the epoch when this favicon expires.
* Until this time, we won't try to load it again.
* @param [optional] aLoadingPrincipal
* Principal of the page whose favicon is being set. If this argument
* is omitted, the loadingPrincipal defaults to the nullPrincipal.
* @throws NS_ERROR_FAILURE
* Thrown if the favicon is overbloated and won't be saved to the db.
*/
void replaceFaviconDataFromDataURL(in nsIURI aFaviconURI,
in AString aDataURL,
[optional] in PRTime aExpiration,
[optional] in nsIPrincipal aLoadingPrincipal);
/**
* Retrieves the favicon URI associated to the given page, if any.
*
* @param aPageURI
* URI of the page whose favicon URI we're looking up.
* @param aCallback
* This callback is always invoked to notify the result of the lookup.
* The aURI parameter will be the favicon URI, or null when no favicon
* is associated with the page or an error occurred while fetching it.
* aDataLen will be always 0, aData will be an empty array, and
* aMimeType will be an empty string, regardless of whether a favicon
* was found.
* @param [optional] aPreferredWidth
* The preferred icon width, 0 for the biggest available.
*
* @note If a favicon specific to this page cannot be found, this will try to
* fallback to the /favicon.ico for the root domain.
*
* @see nsIFaviconDataCallback in nsIFaviconService.idl.
*/
void getFaviconURLForPage(in nsIURI aPageURI,
in nsIFaviconDataCallback aCallback,
[optional] in unsigned short aPreferredWidth);
/**
* Retrieves the favicon URI and data associated to the given page, if any.
* If the page icon is not available, it will try to return the root domain
* icon data, when it's known.
*
* @param aPageURI
* URI of the page whose favicon URI and data we're looking up.
* @param aCallback
* This callback is always invoked to notify the result of the lookup. The aURI
* parameter will be the favicon URI, or null when no favicon is
* associated with the page or an error occurred while fetching it. If
* aURI is not null, the other parameters may contain the favicon data.
* However, if no favicon data is currently associated with the favicon
* URI, aDataLen will be 0, aData will be an empty array, and aMimeType
* will be an empty string.
* @param [optional] aPreferredWidth
* The preferred icon width, 0 for the biggest available.
* @note If a favicon specific to this page cannot be found, this will try to
* fallback to the /favicon.ico for the root domain.
*
* @see nsIFaviconDataCallback in nsIFaviconService.idl.
*/
void getFaviconDataForPage(in nsIURI aPageURI,
in nsIFaviconDataCallback aCallback,
[optional] in unsigned short aPreferredWidth);
/**
* Copies cached favicons from a page to another one.
*
* @param aFromPageURI
* URI of the originating page.
* @param aToPageURI
* URI of the destination page.
* @param aFaviconLoadType
* Set to FAVICON_LOAD_PRIVATE if the copy is started from a private
* browsing window. Set to FAVICON_LOAD_NON_PRIVATE otherwise.
* @param [optional] aCallback
* Once we're done copying the favicon, we invoke this callback.
* If a copy has been done, the callback will report one of the
* favicons uri as aFaviconURI, otherwise all the params will be null.
*/
void copyFavicons(in nsIURI aFromPageURI,
in nsIURI aToPageURI,
in unsigned long aFaviconLoadType,
[optional] in nsIFaviconDataCallback aCallback);
};

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

@ -127,7 +127,6 @@ NS_IMPL_CLASSINFO(nsFaviconService, nullptr, 0, NS_FAVICONSERVICE_CID)
NS_IMPL_ISUPPORTS_CI(
nsFaviconService
, nsIFaviconService
, mozIAsyncFavicons
, nsITimerCallback
, nsINamed
)

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

@ -7,7 +7,6 @@
#define nsFaviconService_h_
#include "nsIFaviconService.h"
#include "mozIAsyncFavicons.h"
#include "nsCOMPtr.h"
#include "nsString.h"
@ -50,7 +49,6 @@ public:
};
class nsFaviconService final : public nsIFaviconService
, public mozIAsyncFavicons
, public nsITimerCallback
, public nsINamed
{
@ -124,7 +122,6 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFAVICONSERVICE
NS_DECL_MOZIASYNCFAVICONS
NS_DECL_NSITIMERCALLBACK
NS_DECL_NSINAMED

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

@ -6,6 +6,9 @@
#include "nsISupports.idl"
interface nsIURI;
interface nsIPrincipal;
interface mozIPlacesPendingOperation;
interface nsIFaviconDataCallback;
[scriptable, uuid(e81e0b0c-b9f1-4c2e-8f3c-b809933cf73c)]
interface nsIFaviconService : nsISupports
@ -115,6 +118,202 @@ interface nsIFaviconService : nsISupports
* The default favicon mimeType
*/
readonly attribute AUTF8String defaultFaviconMimeType;
/**
* Declares that a given page uses a favicon with the given URI and
* attempts to fetch and save the icon data by loading the favicon URI
* through an async network request.
*
* If the icon data already exists, we won't try to reload the icon unless
* aForceReload is true. Similarly, if the icon is in the failed favicon
* cache we won't do anything unless aForceReload is true, in which case
* we'll try to reload the favicon.
*
* This function will only save favicons for pages that are already stored in
* the database, like visited pages or bookmarks. For any other URIs, it
* will succeed but do nothing. This function will also ignore the error
* page favicon URI (see FAVICON_ERRORPAGE_URL below).
*
* Icons that fail to load will automatically be added to the failed favicon
* cache, and this function will not save favicons for non-bookmarked URIs
* when history is disabled.
*
* @note This function is identical to
* nsIFaviconService::setAndLoadFaviconForPage.
*
* @param aPageURI
* URI of the page whose favicon is being set.
* @param aFaviconURI
* URI of the favicon to associate with the page.
* @param aForceReload
* If aForceReload is false, we try to reload the favicon only if we
* don't have it or it has expired from the cache. Setting
* aForceReload to true causes us to reload the favicon even if we
* have a usable copy.
* @param aFaviconLoadType
* Set to FAVICON_LOAD_PRIVATE if the favicon is loaded from a private
* browsing window. Set to FAVICON_LOAD_NON_PRIVATE otherwise.
* @param [optional] aCallback
* Once we're done setting and/or fetching the favicon, we invoke this
* callback.
* @param [optional] aLoadingPrincipal
* Principal of the page whose favicon is being set. If this argument
* is omitted, the loadingPrincipal defaults to the nullPrincipal.
* @param [optional] aRequestContextID
* used to inform Necko of how to link the
* favicon request with other requests in the same tab.
*
* @see nsIFaviconDataCallback in nsIFaviconService.idl.
*/
mozIPlacesPendingOperation setAndFetchFaviconForPage(
in nsIURI aPageURI,
in nsIURI aFaviconURI,
in boolean aForceReload,
in unsigned long aFaviconLoadType,
[optional] in nsIFaviconDataCallback aCallback,
[optional] in nsIPrincipal aLoadingPrincipal,
[optional] in unsigned long long aRequestContextID);
/**
* Sets the data for a given favicon URI either by replacing existing data in
* the database or taking the place of otherwise fetched icon data when
* calling setAndFetchFaviconForPage later.
*
* Favicon data for favicon URIs that are not associated with a page URI via
* setAndFetchFaviconForPage will be stored in memory, but may be expired at
* any time, so you should make an effort to associate favicon URIs with page
* URIs as soon as possible.
*
* It's better to not use this function for chrome: icon URIs since you can
* reference the chrome image yourself. getFaviconLinkForIcon/Page will ignore
* any associated data if the favicon URI is "chrome:" and just return the
* same chrome URI.
*
* This function does NOT send out notifications that the data has changed.
* Pages using this favicons that are visible in history or bookmarks views
* will keep the old icon until they have been refreshed by other means.
*
* This function tries to optimize the favicon size, if it is bigger
* than a defined limit we will try to convert it to a 16x16 png image.
* If the conversion fails and favicon is still bigger than our max accepted
* size it won't be saved.
*
* @param aFaviconURI
* URI of the favicon whose data is being set.
* @param aData
* Binary contents of the favicon to save
* @param aDataLength
* Length of binary data
* @param aMimeType
* MIME type of the data to store. This is important so that we know
* what to report when the favicon is used. You should always set this
* param unless you are clearing an icon.
* @param [optional] aExpiration
* Time in microseconds since the epoch when this favicon expires.
* Until this time, we won't try to load it again.
* @throws NS_ERROR_FAILURE
* Thrown if the favicon is overbloated and won't be saved to the db.
*/
void replaceFaviconData(in nsIURI aFaviconURI,
[const,array,size_is(aDataLen)] in octet aData,
in unsigned long aDataLen,
in AUTF8String aMimeType,
[optional] in PRTime aExpiration);
/**
* Same as replaceFaviconData but the data is provided by a string
* containing a data URL.
*
* @see replaceFaviconData
*
* @param aFaviconURI
* URI of the favicon whose data is being set.
* @param aDataURL
* string containing a data URL that represents the contents of
* the favicon to save
* @param [optional] aExpiration
* Time in microseconds since the epoch when this favicon expires.
* Until this time, we won't try to load it again.
* @param [optional] aLoadingPrincipal
* Principal of the page whose favicon is being set. If this argument
* is omitted, the loadingPrincipal defaults to the nullPrincipal.
* @throws NS_ERROR_FAILURE
* Thrown if the favicon is overbloated and won't be saved to the db.
*/
void replaceFaviconDataFromDataURL(in nsIURI aFaviconURI,
in AString aDataURL,
[optional] in PRTime aExpiration,
[optional] in nsIPrincipal aLoadingPrincipal);
/**
* Retrieves the favicon URI associated to the given page, if any.
*
* @param aPageURI
* URI of the page whose favicon URI we're looking up.
* @param aCallback
* This callback is always invoked to notify the result of the lookup.
* The aURI parameter will be the favicon URI, or null when no favicon
* is associated with the page or an error occurred while fetching it.
* aDataLen will be always 0, aData will be an empty array, and
* aMimeType will be an empty string, regardless of whether a favicon
* was found.
* @param [optional] aPreferredWidth
* The preferred icon width, 0 for the biggest available.
*
* @note If a favicon specific to this page cannot be found, this will try to
* fallback to the /favicon.ico for the root domain.
*
* @see nsIFaviconDataCallback in nsIFaviconService.idl.
*/
void getFaviconURLForPage(in nsIURI aPageURI,
in nsIFaviconDataCallback aCallback,
[optional] in unsigned short aPreferredWidth);
/**
* Retrieves the favicon URI and data associated to the given page, if any.
* If the page icon is not available, it will try to return the root domain
* icon data, when it's known.
*
* @param aPageURI
* URI of the page whose favicon URI and data we're looking up.
* @param aCallback
* This callback is always invoked to notify the result of the lookup. The aURI
* parameter will be the favicon URI, or null when no favicon is
* associated with the page or an error occurred while fetching it. If
* aURI is not null, the other parameters may contain the favicon data.
* However, if no favicon data is currently associated with the favicon
* URI, aDataLen will be 0, aData will be an empty array, and aMimeType
* will be an empty string.
* @param [optional] aPreferredWidth
* The preferred icon width, 0 for the biggest available.
* @note If a favicon specific to this page cannot be found, this will try to
* fallback to the /favicon.ico for the root domain.
*
* @see nsIFaviconDataCallback in nsIFaviconService.idl.
*/
void getFaviconDataForPage(in nsIURI aPageURI,
in nsIFaviconDataCallback aCallback,
[optional] in unsigned short aPreferredWidth);
/**
* Copies cached favicons from a page to another one.
*
* @param aFromPageURI
* URI of the originating page.
* @param aToPageURI
* URI of the destination page.
* @param aFaviconLoadType
* Set to FAVICON_LOAD_PRIVATE if the copy is started from a private
* browsing window. Set to FAVICON_LOAD_NON_PRIVATE otherwise.
* @param [optional] aCallback
* Once we're done copying the favicon, we invoke this callback.
* If a copy has been done, the callback will report one of the
* favicons uri as aFaviconURI, otherwise all the params will be null.
*/
void copyFavicons(in nsIURI aFromPageURI,
in nsIURI aToPageURI,
in unsigned long aFaviconLoadType,
[optional] in nsIFaviconDataCallback aCallback);
};
[scriptable, function, uuid(c85e5c82-b70f-4621-9528-beb2aa47fb44)]

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

@ -2,7 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* Tests for mozIAsyncFavicons::replaceFaviconData()
* Tests for replaceFaviconData()
*/
var iconsvc = PlacesUtils.favicons;

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

@ -2,7 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* Tests for mozIAsyncFavicons::replaceFaviconData()
* Tests for replaceFaviconData()
*/
var iconsvc = PlacesUtils.favicons;

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

@ -106,6 +106,14 @@ namespace TelemetryIPCAccumulator = mozilla::TelemetryIPCAccumulator;
// break that cycle, we relax that requirement. Unfortunately this
// means that this file is not guaranteed race-free.
// This is a StaticMutex rather than a plain Mutex (1) so that
// it gets initialised in a thread-safe manner the first time
// it is used, and (2) because it is never de-initialised, and
// a normal Mutex would show up as a leak in BloatView. StaticMutex
// also has the "OffTheBooks" property, so it won't show as a leak
// in BloatView.
static StaticMutex gTelemetryHistogramMutex;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@ -144,6 +152,17 @@ enum reflectStatus {
REFLECT_FAILURE
};
// Struct used to keep information about the histograms for which a
// snapshot should be created.
struct HistogramSnapshotData {
nsTArray<Histogram::Sample> mBucketRanges;
nsTArray<Histogram::Count> mBucketCounts;
int64_t mSampleSum; // Same type as Histogram::SampleSet::sum_
};
// The following is used to handle snapshot information for keyed histograms.
typedef nsDataHashtable<nsCStringHashKey, HistogramSnapshotData> KeyedHistogramSnapshotData;
class KeyedHistogram {
public:
KeyedHistogram(HistogramID id, const HistogramInfo& info);
@ -152,8 +171,11 @@ public:
Histogram* GetHistogram(const nsCString& name);
uint32_t GetHistogramType() const { return mHistogramInfo.histogramType; }
nsresult GetJSKeys(JSContext* cx, JS::CallArgs& args);
// Note: unlike other methods, GetJSSnapshot is thread safe.
nsresult GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj,
bool clearSubsession);
nsresult GetSnapshot(const StaticMutexAutoLock& aLock,
KeyedHistogramSnapshotData& aSnapshot, bool aClearSubsession);
nsresult Add(const nsCString& key, uint32_t aSample, ProcessID aProcessType);
void Clear();
@ -165,10 +187,6 @@ private:
typedef AutoHashtable<KeyedHistogramEntry> KeyedHistogramMapType;
KeyedHistogramMapType mHistogramMap;
static bool ReflectKeyedHistogram(KeyedHistogramEntry* entry,
JSContext* cx,
JS::Handle<JSObject*> obj);
const HistogramID mId;
const HistogramInfo& mHistogramInfo;
};
@ -622,68 +640,98 @@ internal_HistogramAdd(Histogram& histogram,
namespace {
bool
internal_FillRanges(JSContext *cx, JS::Handle<JSObject*> array, Histogram *h)
/**
* Copy histograms and samples to Mozilla-friendly structures.
* Please note that this version does not make use of JS contexts.
*
* @param {StaticMutexAutoLock} the proof we hold the mutex.
* @param {Histogram} the histogram to reflect.
* @return {nsresult} NS_ERROR_FAILURE if we fail to allocate memory for the snapshot.
*/
nsresult
internal_GetHistogramAndSamples(const StaticMutexAutoLock& aLock,
const Histogram *h,
HistogramSnapshotData& aSnapshot)
{
JS::Rooted<JS::Value> range(cx);
for (size_t i = 0; i < h->bucket_count(); i++) {
range.setInt32(h->ranges(i));
if (!JS_DefineElement(cx, array, i, range, JSPROP_ENUMERATE))
return false;
}
return true;
}
MOZ_ASSERT(h);
enum reflectStatus
internal_ReflectHistogramAndSamples(JSContext *cx,
JS::Handle<JSObject*> obj, Histogram *h,
const Histogram::SampleSet &ss)
{
if (!(JS_DefineProperty(cx, obj, "min",
h->declared_min(), JSPROP_ENUMERATE)
&& JS_DefineProperty(cx, obj, "max",
h->declared_max(), JSPROP_ENUMERATE)
&& JS_DefineProperty(cx, obj, "histogram_type",
h->histogram_type(), JSPROP_ENUMERATE)
&& JS_DefineProperty(cx, obj, "sum",
double(ss.sum()), JSPROP_ENUMERATE))) {
return REFLECT_FAILURE;
}
const size_t count = h->bucket_count();
JS::Rooted<JSObject*> rarray(cx, JS_NewArrayObject(cx, count));
if (!rarray) {
return REFLECT_FAILURE;
}
if (!(internal_FillRanges(cx, rarray, h)
&& JS_DefineProperty(cx, obj, "ranges", rarray, JSPROP_ENUMERATE))) {
return REFLECT_FAILURE;
}
JS::Rooted<JSObject*> counts_array(cx, JS_NewArrayObject(cx, count));
if (!counts_array) {
return REFLECT_FAILURE;
}
if (!JS_DefineProperty(cx, obj, "counts", counts_array, JSPROP_ENUMERATE)) {
return REFLECT_FAILURE;
}
for (size_t i = 0; i < count; i++) {
if (!JS_DefineElement(cx, counts_array, i,
ss.counts(i), JSPROP_ENUMERATE)) {
return REFLECT_FAILURE;
// Convert the ranges of the buckets to a nsTArray.
const size_t bucketCount = h->bucket_count();
for (size_t i = 0; i < bucketCount; i++) {
if (!aSnapshot.mBucketRanges.AppendElement(h->ranges(i))) {
return NS_ERROR_FAILURE;
}
}
return REFLECT_OK;
}
enum reflectStatus
internal_ReflectHistogramSnapshot(JSContext *cx,
JS::Handle<JSObject*> obj, Histogram *h)
{
// Get a snapshot of the samples.
Histogram::SampleSet ss;
h->SnapshotSample(&ss);
return internal_ReflectHistogramAndSamples(cx, obj, h, ss);
// Get the number of samples in each bucket.
for (size_t i = 0; i < bucketCount; i++) {
if (!aSnapshot.mBucketCounts.AppendElement(ss.counts(i))) {
return NS_ERROR_FAILURE;
}
}
// Finally, save the |sum|. We don't need to reflect declared_min, declared_max and
// histogram_type as they are in gHistogramInfo.
aSnapshot.mSampleSum = ss.sum();
return NS_OK;
}
nsresult
internal_ReflectHistogramAndSamples(JSContext *cx,
JS::Handle<JSObject*> obj,
const HistogramInfo& aHistogramInfo,
const HistogramSnapshotData& aSnapshot)
{
if (!(JS_DefineProperty(cx, obj, "min",
aHistogramInfo.min, JSPROP_ENUMERATE)
&& JS_DefineProperty(cx, obj, "max",
aHistogramInfo.max, JSPROP_ENUMERATE)
&& JS_DefineProperty(cx, obj, "histogram_type",
aHistogramInfo.histogramType, JSPROP_ENUMERATE)
&& JS_DefineProperty(cx, obj, "sum",
double(aSnapshot.mSampleSum), JSPROP_ENUMERATE))) {
return NS_ERROR_FAILURE;
}
// Don't rely on the bucket counts from "aHistogramInfo": it may
// differ from the length of aSnapshot.mBucketCounts due to expired
// histograms.
const size_t count = aSnapshot.mBucketCounts.Length();
MOZ_ASSERT(count == aSnapshot.mBucketRanges.Length(),
"The number of buckets and the number of counts must match.");
// Create the "ranges" property and add it to the final object.
JS::Rooted<JSObject*> rarray(cx, JS_NewArrayObject(cx, count));
if (!rarray
|| !JS_DefineProperty(cx, obj, "ranges", rarray, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
// Fill the "ranges" property.
for (size_t i = 0; i < count; i++) {
if (!JS_DefineElement(cx, rarray, i, aSnapshot.mBucketRanges[i], JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
JS::Rooted<JSObject*> counts_array(cx, JS_NewArrayObject(cx, count));
if (!counts_array
|| !JS_DefineProperty(cx, obj, "counts", counts_array, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
// Fill the "counts" property.
for (size_t i = 0; i < count; i++) {
if (!JS_DefineElement(cx, counts_array, i, aSnapshot.mBucketCounts[i], JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
bool
@ -706,10 +754,39 @@ internal_ShouldReflectHistogram(Histogram* h, HistogramID id)
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// PRIVATE: class KeyedHistogram
// PRIVATE: class KeyedHistogram and internal_ReflectKeyedHistogram
namespace {
nsresult
internal_ReflectKeyedHistogram(const KeyedHistogramSnapshotData& aSnapshot,
const HistogramInfo& info,
JSContext* aCx, JS::Handle<JSObject*> aObj)
{
for (auto iter = aSnapshot.ConstIter(); !iter.Done(); iter.Next()) {
HistogramSnapshotData& keyData = iter.Data();
JS::RootedObject histogramSnapshot(aCx, JS_NewPlainObject(aCx));
if (!histogramSnapshot) {
return NS_ERROR_FAILURE;
}
if (NS_FAILED(internal_ReflectHistogramAndSamples(aCx, histogramSnapshot,
info,
keyData))) {
return NS_ERROR_FAILURE;
}
const NS_ConvertUTF8toUTF16 key(iter.Key());
if (!JS_DefineUCProperty(aCx, aObj, key.Data(), key.Length(),
histogramSnapshot, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
KeyedHistogram::KeyedHistogram(HistogramID id, const HistogramInfo& info)
: mHistogramMap()
, mId(id)
@ -848,37 +925,47 @@ KeyedHistogram::GetJSKeys(JSContext* cx, JS::CallArgs& args)
return NS_OK;
}
bool
KeyedHistogram::ReflectKeyedHistogram(KeyedHistogramEntry* entry,
JSContext* cx, JS::Handle<JSObject*> obj)
{
JS::RootedObject histogramSnapshot(cx, JS_NewPlainObject(cx));
if (!histogramSnapshot) {
return false;
}
if (internal_ReflectHistogramSnapshot(cx, histogramSnapshot,
entry->mData) != REFLECT_OK) {
return false;
}
const NS_ConvertUTF8toUTF16 key(entry->GetKey());
if (!JS_DefineUCProperty(cx, obj, key.Data(), key.Length(),
histogramSnapshot, JSPROP_ENUMERATE)) {
return false;
}
return true;
}
nsresult
KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj, bool clearSubsession)
{
if (!mHistogramMap.ReflectIntoJS(&KeyedHistogram::ReflectKeyedHistogram, cx, obj)) {
return NS_ERROR_FAILURE;
// Get a snapshot of the data.
KeyedHistogramSnapshotData dataSnapshot;
{
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
MOZ_ASSERT(internal_IsHistogramEnumId(mId));
// Take a snapshot of the data here, protected by the lock, and then,
// outside of the lock protection, mirror it to a JS structure.
if (NS_FAILED(GetSnapshot(locker, dataSnapshot, clearSubsession))) {
return NS_ERROR_FAILURE;
}
}
if (clearSubsession) {
// Now that we have a copy of the data, mirror it to JS.
return internal_ReflectKeyedHistogram(dataSnapshot, gHistogramInfos[mId], cx, obj);
}
nsresult
KeyedHistogram::GetSnapshot(const StaticMutexAutoLock& aLock,
KeyedHistogramSnapshotData& aSnapshot, bool aClearSubsession)
{
// Snapshot every key.
for (auto iter = mHistogramMap.ConstIter(); !iter.Done(); iter.Next()) {
Histogram* keyData = iter.Get()->mData;
if (!keyData) {
return NS_ERROR_FAILURE;
}
HistogramSnapshotData keySnapshot;
if (NS_FAILED(internal_GetHistogramAndSamples(aLock, keyData, keySnapshot))) {
return NS_ERROR_FAILURE;
}
// Append to the final snapshot.
aSnapshot.Put(iter.Get()->GetKey(), mozilla::Move(keySnapshot));
}
if (aClearSubsession) {
Clear();
}
@ -892,14 +979,6 @@ KeyedHistogram::GetJSSnapshot(JSContext* cx, JS::Handle<JSObject*> obj, bool cle
//
// PRIVATE: thread-unsafe helpers for the external interface
// This is a StaticMutex rather than a plain Mutex (1) so that
// it gets initialised in a thread-safe manner the first time
// it is used, and (2) because it is never de-initialised, and
// a normal Mutex would show up as a leak in BloatView. StaticMutex
// also has the "OffTheBooks" property, so it won't show as a leak
// in BloatView.
static StaticMutex gTelemetryHistogramMutex;
namespace {
bool
@ -1228,8 +1307,7 @@ internal_JSHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
MOZ_ASSERT(data);
HistogramID id = data->histogramId;
Histogram* h = nullptr;
Histogram::SampleSet ss;
HistogramSnapshotData dataSnapshot;
{
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
MOZ_ASSERT(internal_IsHistogramEnumId(id));
@ -1237,11 +1315,12 @@ internal_JSHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
// This is not good standard behavior given that we have histogram instances
// covering multiple processes.
// However, changing this requires some broader changes to callers.
h = internal_GetHistogramById(id, ProcessID::Parent);
// Take a snapshot of Histogram::SampleSet here, protected by the lock,
// and then, outside of the lock protection, mirror it to a JS structure
MOZ_ASSERT(h);
h->SnapshotSample(&ss);
Histogram* h = internal_GetHistogramById(id, ProcessID::Parent);
// Take a snapshot of the data here, protected by the lock, and then,
// outside of the lock protection, mirror it to a JS structure
if (NS_FAILED(internal_GetHistogramAndSamples(locker, h, dataSnapshot))) {
return false;
}
}
JS::Rooted<JSObject*> snapshot(cx, JS_NewPlainObject(cx));
@ -1249,18 +1328,14 @@ internal_JSHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
return false;
}
reflectStatus status = internal_ReflectHistogramAndSamples(cx, snapshot, h, ss);
switch (status) {
case REFLECT_FAILURE:
if (NS_FAILED(internal_ReflectHistogramAndSamples(cx,
snapshot,
gHistogramInfos[id],
dataSnapshot))) {
return false;
case REFLECT_OK:
args.rval().setObject(*snapshot);
return true;
default:
MOZ_ASSERT_UNREACHABLE("Unhandled reflection status.");
}
args.rval().setObject(*snapshot);
return true;
}
@ -1407,6 +1482,7 @@ internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
return false;
}
// No argument was passed, so snapshot all the keys.
if (args.length() == 0) {
JS::RootedObject snapshot(cx, JS_NewPlainObject(cx));
if (!snapshot) {
@ -1423,17 +1499,30 @@ internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
return true;
}
// One argument was passed. If it's a string, use it as a key
// and just snapshot the data for that key.
nsAutoJSString key;
if (!args[0].isString() || !key.init(cx, args[0])) {
JS_ReportErrorASCII(cx, "Not a string");
return false;
}
Histogram* h = nullptr;
nsresult rv = keyed->GetHistogram(NS_ConvertUTF16toUTF8(key), &h);
if (NS_FAILED(rv)) {
JS_ReportErrorASCII(cx, "Failed to get histogram");
return false;
HistogramSnapshotData dataSnapshot;
{
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
// Get data for the key we're looking for.
Histogram* h = nullptr;
nsresult rv = keyed->GetHistogram(NS_ConvertUTF16toUTF8(key), &h);
if (NS_FAILED(rv)) {
return false;
}
// Take a snapshot of the data here, protected by the lock, and then,
// outside of the lock protection, mirror it to a JS structure
if (NS_FAILED(internal_GetHistogramAndSamples(locker, h, dataSnapshot))) {
return false;
}
}
JS::RootedObject snapshot(cx, JS_NewPlainObject(cx));
@ -1441,17 +1530,15 @@ internal_KeyedHistogram_SnapshotImpl(JSContext *cx, unsigned argc,
return false;
}
switch (internal_ReflectHistogramSnapshot(cx, snapshot, h)) {
case REFLECT_FAILURE:
if (NS_FAILED(internal_ReflectHistogramAndSamples(cx,
snapshot,
gHistogramInfos[id],
dataSnapshot))) {
JS_ReportErrorASCII(cx, "Failed to reflect histogram");
return false;
case REFLECT_OK:
args.rval().setObject(*snapshot);
return true;
default:
MOZ_CRASH("unhandled reflection status");
}
args.rval().setObject(*snapshot);
return true;
}
@ -2140,14 +2227,12 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
// Struct used to keep information about the histograms for which a
// snapshot should be created
struct MOZ_NON_MEMMOVABLE HistogramProcessInfo {
Histogram* h;
Histogram::SampleSet ss;
size_t index;
struct HistogramProcessInfo {
HistogramSnapshotData data;
HistogramID histogramID;
};
mozilla::Vector<mozilla::Vector<HistogramProcessInfo>>
processHistArray;
mozilla::Vector<mozilla::Vector<HistogramProcessInfo>> processHistArray;
{
if (!processHistArray.resize(static_cast<uint32_t>(ProcessID::Count))) {
return NS_ERROR_OUT_OF_MEMORY;
@ -2182,9 +2267,12 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
continue;
}
Histogram::SampleSet ss;
h->SnapshotSample(&ss);
if (!hArray.emplaceBack(HistogramProcessInfo{h, ss, i})) {
HistogramSnapshotData snapshotData;
if (NS_FAILED(internal_GetHistogramAndSamples(locker, h, snapshotData))) {
continue;
}
if (!hArray.emplaceBack(HistogramProcessInfo{snapshotData, id})) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -2210,26 +2298,23 @@ TelemetryHistogram::CreateHistogramSnapshots(JSContext* aCx,
const mozilla::Vector<HistogramProcessInfo>& hArray = processHistArray[process];
for (size_t i = 0; i < hArray.length(); ++i) {
const HistogramProcessInfo& hData = hArray[i];
uint32_t histogramIndex = hData.index;
HistogramID id = HistogramID(histogramIndex);
HistogramID id = hData.histogramID;
JS::Rooted<JSObject*> hobj(aCx, JS_NewPlainObject(aCx));
if (!hobj) {
return NS_ERROR_FAILURE;
}
Histogram* h = hData.h;
reflectStatus status = internal_ReflectHistogramAndSamples(aCx, hobj, h,
hData.ss);
switch (status) {
case REFLECT_FAILURE:
if (NS_FAILED(internal_ReflectHistogramAndSamples(aCx,
hobj,
gHistogramInfos[id],
hData.data))) {
return NS_ERROR_FAILURE;
case REFLECT_OK:
if (!JS_DefineProperty(aCx, processObject, gHistogramInfos[id].name(),
hobj, JSPROP_ENUMERATE)) {
}
if (!JS_DefineProperty(aCx, processObject, gHistogramInfos[id].name(),
hobj, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
}
}
@ -2256,7 +2341,63 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx,
includeGPUProcess = gpm->AttemptedGPUProcess();
}
for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
struct KeyedHistogramProcessInfo {
KeyedHistogramSnapshotData data;
HistogramID histogramId;
};
// Get a snapshot of all the data while holding the mutex.
mozilla::Vector<mozilla::Vector<KeyedHistogramProcessInfo>> dataSnapshot;
{
if (!dataSnapshot.resize(static_cast<uint32_t>(ProcessID::Count))) {
return NS_ERROR_OUT_OF_MEMORY;
}
StaticMutexAutoLock locker(gTelemetryHistogramMutex);
for (uint32_t process = 0; process < static_cast<uint32_t>(ProcessID::Count); ++process) {
mozilla::Vector<KeyedHistogramProcessInfo>& hArray = dataSnapshot[process];
for (size_t i = 0; i < HistogramCount; ++i) {
HistogramID id = HistogramID(i);
const HistogramInfo& info = gHistogramInfos[id];
if (!info.keyed) {
continue;
}
if (!CanRecordInProcess(info.record_in_processes, ProcessID(process)) ||
((ProcessID(process) == ProcessID::Gpu) && !includeGPUProcess)) {
continue;
}
if (!IsInDataset(info.dataset, aDataset)) {
continue;
}
KeyedHistogram* keyed = internal_GetKeyedHistogramById(id,
ProcessID(process),
/* instantiate = */ false);
if (!keyed) {
continue;
}
// Take a snapshot of the keyed histogram data!
KeyedHistogramSnapshotData snapshot;
if (!NS_SUCCEEDED(keyed->GetSnapshot(locker, snapshot, aClearSubsession))) {
return NS_ERROR_FAILURE;
}
if (!hArray.emplaceBack(KeyedHistogramProcessInfo{mozilla::Move(snapshot), id})) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
}
}
// Mirror the snapshot data to JS, now that we released the mutex.
for (uint32_t process = 0; process < dataSnapshot.length(); ++process) {
const mozilla::Vector<KeyedHistogramProcessInfo>& hArray = dataSnapshot[process];
JS::Rooted<JSObject*> processObject(aCx, JS_NewPlainObject(aCx));
if (!processObject) {
return NS_ERROR_FAILURE;
@ -2265,38 +2406,20 @@ TelemetryHistogram::GetKeyedHistogramSnapshots(JSContext* aCx,
processObject, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
for (size_t id = 0; id < HistogramCount; ++id) {
const HistogramInfo& info = gHistogramInfos[id];
if (!info.keyed) {
continue;
}
if (!CanRecordInProcess(info.record_in_processes, ProcessID(process)) ||
((ProcessID(process) == ProcessID::Gpu) && !includeGPUProcess)) {
continue;
}
if (!IsInDataset(info.dataset, aDataset)) {
continue;
}
KeyedHistogram* keyed = internal_GetKeyedHistogramById(HistogramID(id),
ProcessID(process),
/* instantiate = */ false);
if (!keyed) {
continue;
}
for (size_t i = 0; i < hArray.length(); ++i) {
const KeyedHistogramProcessInfo& hData = hArray[i];
const HistogramInfo& info = gHistogramInfos[hData.histogramId];
JS::RootedObject snapshot(aCx, JS_NewPlainObject(aCx));
if (!snapshot) {
return NS_ERROR_FAILURE;
}
if (!NS_SUCCEEDED(keyed->GetJSSnapshot(aCx, snapshot, aClearSubsession))) {
if (!NS_SUCCEEDED(internal_ReflectKeyedHistogram(hData.data, info, aCx, snapshot))) {
return NS_ERROR_FAILURE;
}
if (!JS_DefineProperty(aCx, processObject, gHistogramInfos[id].name(),
if (!JS_DefineProperty(aCx, processObject, info.name(),
snapshot, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}

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

@ -3890,17 +3890,7 @@ nsWindow::Create(nsIWidget* aParent,
// If the window were to get unredirected, there could be visible
// tearing because Gecko does not align its framebuffer updates with
// vblank.
if (mIsX11Display) {
gulong value = 2; // Opt out of unredirection
GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
gdk_property_change(gtk_widget_get_window(mShell),
gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE),
cardinal_atom,
32, // format
GDK_PROP_MODE_REPLACE,
(guchar*)&value,
1);
}
SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED);
#endif
}
break;
@ -4114,60 +4104,70 @@ nsWindow::Create(nsIWidget* aParent,
}
void
nsWindow::SetWindowClass(const nsAString &xulWinType)
nsWindow::RefreshWindowClass(void)
{
if (!mShell)
return;
if (mGtkWindowTypeName.IsEmpty() || mGtkWindowRoleName.IsEmpty())
return;
const char *res_class = gdk_get_program_class();
if (!res_class)
return;
char *res_name = ToNewCString(xulWinType);
if (!res_name)
return;
const char *role = nullptr;
// Parse res_name into a name and role. Characters other than
// [A-Za-z0-9_-] are converted to '_'. Anything after the first
// colon is assigned to role; if there's no colon, assign the
// whole thing to both role and res_name.
for (char *c = res_name; *c; c++) {
if (':' == *c) {
*c = 0;
role = c + 1;
}
else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
*c = '_';
}
res_name[0] = toupper(res_name[0]);
if (!role) role = res_name;
GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
gdk_window_set_role(gdkWindow, role);
GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
gdk_window_set_role(gdkWindow, mGtkWindowRoleName.get());
#ifdef MOZ_X11
if (mIsX11Display) {
XClassHint *class_hint = XAllocClassHint();
if (!class_hint) {
free(res_name);
return;
}
class_hint->res_name = res_name;
class_hint->res_class = const_cast<char*>(res_class);
if (mIsX11Display) {
XClassHint *class_hint = XAllocClassHint();
if (!class_hint) {
return;
}
const char *res_class = gdk_get_program_class();
if (!res_class)
return;
// Can't use gtk_window_set_wmclass() for this; it prints
// a warning & refuses to make the change.
GdkDisplay *display = gdk_display_get_default();
XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
gdk_x11_window_get_xid(gdkWindow),
class_hint);
XFree(class_hint);
}
class_hint->res_name = const_cast<char*>(mGtkWindowTypeName.get());
class_hint->res_class = const_cast<char*>(res_class);
// Can't use gtk_window_set_wmclass() for this; it prints
// a warning & refuses to make the change.
GdkDisplay *display = gdk_display_get_default();
XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
gdk_x11_window_get_xid(gdkWindow),
class_hint);
XFree(class_hint);
}
#endif /* MOZ_X11 */
}
free(res_name);
void
nsWindow::SetWindowClass(const nsAString &xulWinType)
{
if (!mShell)
return;
char *res_name = ToNewCString(xulWinType);
if (!res_name)
return;
const char *role = nullptr;
// Parse res_name into a name and role. Characters other than
// [A-Za-z0-9_-] are converted to '_'. Anything after the first
// colon is assigned to role; if there's no colon, assign the
// whole thing to both role and res_name.
for (char *c = res_name; *c; c++) {
if (':' == *c) {
*c = 0;
role = c + 1;
}
else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
*c = '_';
}
res_name[0] = toupper(res_name[0]);
if (!role) role = res_name;
mGtkWindowTypeName = res_name;
mGtkWindowRoleName = role;
free(res_name);
RefreshWindowClass();
}
void
@ -6731,6 +6731,10 @@ nsWindow::SetDrawsInTitlebar(bool aState)
// can find its way home.
g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
"nsWindow", this);
#ifdef MOZ_X11
SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED);
#endif
RefreshWindowClass();
// When we use system titlebar setup managed by Gtk+ we also get
// _NET_FRAME_EXTENTS property for our toplevel window so we can't
@ -7212,3 +7216,21 @@ nsWindow::SetProgress(unsigned long progressPercent)
progressPercent);
#endif // MOZ_X11
}
#ifdef MOZ_X11
void
nsWindow::SetCompositorHint(WindowComposeRequest aState)
{
if (mIsX11Display) {
gulong value = aState;
GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
gdk_property_change(gtk_widget_get_window(mShell),
gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE),
cardinal_atom,
32, // format
GDK_PROP_MODE_REPLACE,
(guchar*)&value,
1);
}
}
#endif

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

@ -481,6 +481,18 @@ private:
void UpdateClientOffsetForCSDWindow();
#ifdef MOZ_X11
typedef enum { GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
GTK_WIDGET_COMPOSIDED_DISABLED = 1,
GTK_WIDGET_COMPOSIDED_ENABLED = 2
} WindowComposeRequest;
void SetCompositorHint(WindowComposeRequest aState);
#endif
nsCString mGtkWindowTypeName;
nsCString mGtkWindowRoleName;
void RefreshWindowClass();
GtkWidget *mShell;
MozContainer *mContainer;
GdkWindow *mGdkWindow;

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

@ -37,7 +37,7 @@
#include "nsNetCID.h"
#include "prtime.h"
#ifdef MOZ_PLACES
#include "mozIAsyncFavicons.h"
#include "nsIFaviconService.h"
#endif
#include "nsIIconURI.h"
#include "nsIDownloader.h"
@ -1649,7 +1649,7 @@ nsresult
{
#ifdef MOZ_PLACES
// Obtain the favicon service and get the favicon for the specified page
nsCOMPtr<mozIAsyncFavicons> favIconSvc(
nsCOMPtr<nsIFaviconService> favIconSvc(
do_GetService("@mozilla.org/browser/favicon-service;1"));
NS_ENSURE_TRUE(favIconSvc, NS_ERROR_FAILURE);