Bug 1648157 - Move DisplayMode to BrowsingContext. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D92484
This commit is contained in:
Agi Sferro 2020-10-09 17:31:59 +00:00
Родитель b1029e4f28
Коммит deddd22ef0
11 изменённых файлов: 180 добавлений и 65 удалений

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

@ -40,6 +40,7 @@
#include "mozilla/Components.h"
#include "mozilla/HashTable.h"
#include "mozilla/Logging.h"
#include "mozilla/MediaFeatureChange.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs_fission.h"
@ -73,10 +74,16 @@ namespace IPC {
// Allow serialization and deserialization of OrientationType over IPC
template <>
struct ParamTraits<mozilla::dom::OrientationType>
: public ContiguousEnumSerializerInclusive<
: public ContiguousEnumSerializer<
mozilla::dom::OrientationType,
mozilla::dom::OrientationType::Portrait_primary,
mozilla::dom::OrientationType::Landscape_secondary> {};
mozilla::dom::OrientationType::EndGuard_> {};
template <>
struct ParamTraits<mozilla::dom::DisplayMode>
: public ContiguousEnumSerializer<mozilla::dom::DisplayMode,
mozilla::dom::DisplayMode::Browser,
mozilla::dom::DisplayMode::EndGuard_> {};
} // namespace IPC
@ -2170,6 +2177,33 @@ void BrowsingContext::DidSet(FieldIndex<IDX_IsActive>, bool aOldValue) {
}
}
bool BrowsingContext::CanSet(FieldIndex<IDX_DisplayMode>,
const enum DisplayMode& aDisplayMOde,
ContentParent* aSource) {
return IsTop();
}
void BrowsingContext::DidSet(FieldIndex<IDX_DisplayMode>,
enum DisplayMode aOldValue) {
MOZ_ASSERT(IsTop());
if (GetDisplayMode() == aOldValue) {
return;
}
PreOrderWalk([&](BrowsingContext* aContext) {
if (nsIDocShell* shell = aContext->GetDocShell()) {
if (nsPresContext* pc = shell->GetPresContext()) {
pc->MediaFeatureValuesChangedAllDocuments(
{MediaFeatureChangeReason::DisplayModeChange},
// We're already iterating through sub documents
// so no need to do it again.
nsPresContext::RecurseIntoInProcessSubDocuments::No);
}
}
});
}
void BrowsingContext::DidSet(FieldIndex<IDX_Muted>) {
MOZ_ASSERT(!GetParent(), "Set muted flag on non top-level context!");
USER_ACTIVATION_LOG("Set audio muted %d for %s browsing context 0x%08" PRIx64,

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

@ -20,6 +20,7 @@
#include "mozilla/dom/LocationBase.h"
#include "mozilla/dom/MaybeDiscarded.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/dom/BrowsingContextBinding.h"
#include "mozilla/dom/ScreenOrientationBinding.h"
#include "mozilla/dom/SyncedContext.h"
#include "nsCOMPtr.h"
@ -172,7 +173,8 @@ class WindowProxyHolder;
/* Default value for nsIContentViewer::authorStyleDisabled in any new \
* browsing contexts created as a descendant of this one. Valid only for \
* top BCs. */ \
FIELD(AuthorStyleDisabledDefault, bool)
FIELD(AuthorStyleDisabledDefault, bool) \
FIELD(DisplayMode, mozilla::dom::DisplayMode)
// BrowsingContext, in this context, is the cross process replicated
// environment in which information about documents is stored. In
@ -721,6 +723,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void ResetLocationChangeRateLimit();
mozilla::dom::DisplayMode DisplayMode() { return Top()->GetDisplayMode(); }
protected:
virtual ~BrowsingContext();
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
@ -809,6 +813,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return true;
}
bool CanSet(FieldIndex<IDX_DisplayMode>, const enum DisplayMode& aDisplayMode,
ContentParent* aSource);
void DidSet(FieldIndex<IDX_DisplayMode>, enum DisplayMode aOldValue);
void DidSet(FieldIndex<IDX_IsActive>, bool aOldValue);
// Ensure that we only set the flag on the top level browsingContext.

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

@ -375,7 +375,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
mLoadType(0),
mFailedLoadType(0),
mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER),
mJSRunToCompletionDepth(0),
mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE),
mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
@ -13125,34 +13124,6 @@ nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
return docShell->SetHTMLEditorInternal(aHTMLEditor);
}
NS_IMETHODIMP
nsDocShell::GetDisplayMode(DisplayMode* aDisplayMode) {
*aDisplayMode = mDisplayMode;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetDisplayMode(DisplayMode aDisplayMode) {
// We don't have a way to verify this coming from Javascript, so this check
// is still needed.
if (!(aDisplayMode == nsIDocShell::DISPLAY_MODE_BROWSER ||
aDisplayMode == nsIDocShell::DISPLAY_MODE_STANDALONE ||
aDisplayMode == nsIDocShell::DISPLAY_MODE_FULLSCREEN ||
aDisplayMode == nsIDocShell::DISPLAY_MODE_MINIMAL_UI)) {
return NS_ERROR_INVALID_ARG;
}
if (aDisplayMode != mDisplayMode) {
mDisplayMode = aDisplayMode;
RefPtr<nsPresContext> presContext = GetPresContext();
presContext->MediaFeatureValuesChangedAllDocuments(
{MediaFeatureChangeReason::DisplayModeChange});
}
return NS_OK;
}
#define MATRIX_LENGTH 20
NS_IMETHODIMP

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

@ -1236,10 +1236,6 @@ class nsDocShell final : public nsDocLoader,
uint32_t mLoadType;
uint32_t mFailedLoadType;
// This represents the CSS display-mode we are currently using. This is mostly
// used for media queries.
DisplayMode mDisplayMode;
// A depth count of how many times NotifyRunToCompletionStart
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;

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

@ -886,23 +886,6 @@ interface nsIDocShell : nsIDocShellTreeItem
nsresult SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor);
%}
/**
* Allowed CSS display modes. This needs to be kept in
* sync with similar values in ServoStyleConsts.h
*/
cenum DisplayMode: 8 {
DISPLAY_MODE_BROWSER = 0,
DISPLAY_MODE_MINIMAL_UI = 1,
DISPLAY_MODE_STANDALONE = 2,
DISPLAY_MODE_FULLSCREEN = 3,
};
/**
* Display mode for this docshell. Defaults to DISPLAY_MODE_BROWSER.
* Media queries only look at the value in the top-most docshell.
*/
[infallible] attribute nsIDocShell_DisplayMode displayMode;
/**
* The message manager for this docshell. This does not throw, but
* can return null if the docshell has no message manager.

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

@ -30,6 +30,17 @@ interface mixin LoadContextMixin {
readonly attribute any originAttributes;
};
/**
* Allowed CSS display modes. This needs to be kept in
* sync with similar values in ServoStyleConsts.h
*/
enum DisplayMode {
"browser",
"minimal-ui",
"standalone",
"fullscreen",
};
[Exposed=Window, ChromeOnly]
interface BrowsingContext {
static BrowsingContext? get(unsigned long long aId);
@ -131,6 +142,8 @@ interface BrowsingContext {
*/
[SetterThrows] attribute unsigned long long browserId;
[SetterThrows] attribute DisplayMode displayMode;
readonly attribute ChildSHistory? childSessionHistory;
// Resets the location change rate limit. Used for testing.

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

@ -19,6 +19,7 @@
#include "nsIPrintSettings.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/BrowsingContextBinding.h"
#include "nsIWidget.h"
#include "nsContentUtils.h"
#include "mozilla/RelativeLuminanceUtils.h"
@ -198,21 +199,21 @@ StyleDisplayMode Gecko_MediaFeatures_GetDisplayMode(const Document* aDocument) {
}
}
static_assert(nsIDocShell::DISPLAY_MODE_BROWSER ==
static_assert(static_cast<int32_t>(DisplayMode::Browser) ==
static_cast<int32_t>(StyleDisplayMode::Browser) &&
nsIDocShell::DISPLAY_MODE_MINIMAL_UI ==
static_cast<int32_t>(DisplayMode::Minimal_ui) ==
static_cast<int32_t>(StyleDisplayMode::MinimalUi) &&
nsIDocShell::DISPLAY_MODE_STANDALONE ==
static_cast<int32_t>(DisplayMode::Standalone) ==
static_cast<int32_t>(StyleDisplayMode::Standalone) &&
nsIDocShell::DISPLAY_MODE_FULLSCREEN ==
static_cast<int32_t>(DisplayMode::Fullscreen) ==
static_cast<int32_t>(StyleDisplayMode::Fullscreen),
"nsIDocShell display modes must mach nsStyleConsts.h");
"DisplayMode must mach nsStyleConsts.h");
nsIDocShell* docShell = rootDocument->GetDocShell();
if (!docShell) {
BrowsingContext* browsingContext = aDocument->GetBrowsingContext();
if (!browsingContext) {
return StyleDisplayMode::Browser;
}
return static_cast<StyleDisplayMode>(docShell->GetDisplayMode());
return static_cast<StyleDisplayMode>(browsingContext->DisplayMode());
}
bool Gecko_MediaFeatures_HasSystemMetric(const Document* aDocument,

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

@ -52,7 +52,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1104916
}
function setDisplayMode(mode) {
win.docShell.displayMode = mode;
window.browsingContext.top.displayMode = mode;
}
shouldApply("all and (display-mode: browser)");
@ -91,19 +91,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1104916
shouldApply("all and (display-mode: browser)");
// Test entering display mode mode through docshell
setDisplayMode(Ci.nsIDocShell.DISPLAY_MODE_STANDALONE);
setDisplayMode("standalone");
shouldApply("all and (display-mode: standalone)");
shouldNotApply("all and (display-mode: fullscreen)");
shouldNotApply("all and (display-mode: browser)");
shouldNotApply("all and (display-mode: minimal-ui)");
// Test that changes in the display mode are reflected
setDisplayMode(Ci.nsIDocShell.DISPLAY_MODE_MINIMAL_UI);
setDisplayMode("minimal-ui");
shouldApply("all and (display-mode: minimal-ui)");
shouldNotApply("all and (display-mode: standalone)");
// Set the display mode back.
setDisplayMode(Ci.nsIDocShell.DISPLAY_MODE_BROWSER);
setDisplayMode("browser");
window.close();
window.SimpleTest.finish();

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

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Media Queries Test inner frame</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<style type="text/css" id="style" media="all and (display-mode: browser)">
body { background: yellow; }
</style>
<style type="text/css" id="style" media="all and (display-mode: standalone)">
body { background: green; }
</style>
<style type="text/css" id="style" media="all and (display-mode: minimal-ui)">
body { background: red; }
</style>
<style type="text/css" id="style" media="all and (display-mode: fullscreen)">
body { background: blue; }
</style>
</head>
<body>
<script>
window.addEventListener("message", e => {
if (e.data == "get-background-color") {
let { backgroundColor } = document.defaultView.getComputedStyle(document.body);
e.source.postMessage({ backgroundColor }, e.origin);
}
});
</script>
</body>
</html>

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

@ -33,6 +33,7 @@ support-files =
file_computed_style_bfcache_display_none.html
file_computed_style_bfcache_display_none2.html
media_queries_iframe.html
media_queries_iframe2.html
neverending_font_load.sjs
neverending_stylesheet_load.sjs
post-redirect-1.css
@ -221,6 +222,7 @@ support-files = file_bug1381233.html
[test_default_computed_style.html]
[test_descriptor_storage.html]
[test_descriptor_syntax_errors.html]
[test_display_mode.html]
[test_dont_use_document_colors.html]
[test_dont_use_document_fonts.html]
[test_dynamic_change_causing_reflow.html]

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

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1648157
-->
<head>
<title>Test for displayMode</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="property_database.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display">
<iframe id="iframe" src="http://example.org/tests/layout/style/test/media_queries_iframe2.html"></iframe>
</p>
<pre id="test">
<script class="testbody">
let iframe = document.getElementById("iframe");
// Keep in sync with media_queries_iframe2.html
const DISPLAY_MODES_BACKGROUND_COLOR = {
'minimal-ui': 'rgb(255, 0, 0)',
'standalone': 'rgb(0, 128, 0)',
'fullscreen': 'rgb(0, 0, 255)',
'browser': 'rgb(255, 255, 0)'
};
const DISPLAY_MODES = Object.keys(DISPLAY_MODES_BACKGROUND_COLOR);
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", async (event) => {
const wrappedWindow = SpecialPowers.wrap(window);
function setDisplayMode(mode) {
wrappedWindow.browsingContext.top.displayMode = mode;
}
async function displayModeApplies(mode) {
let responsePromise = new Promise(resolve => {
window.addEventListener("message", e => {
resolve(e.data.backgroundColor);
}, { once: true });
});
iframe.contentWindow.postMessage('get-background-color', '*');
let response = await responsePromise;
let expected = DISPLAY_MODES_BACKGROUND_COLOR[mode];
info(`displayModeApplies: ${response} === ${expected}`);
return response === expected;
}
async function checkIfApplies(q, shouldApply) {
let message = shouldApply ? "should apply" : "should not apply";
is((await displayModeApplies(q)), shouldApply, `${q} ${message}`);
}
for (let currentMode of DISPLAY_MODES) {
setDisplayMode(currentMode);
for (let mode of DISPLAY_MODES) {
await checkIfApplies(mode, currentMode === mode);
}
}
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>