зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1624150, bug 1432749) for wpt failures at open-features-tokenization-top-left.html. CLOSED TREE
Backed out changeset ff061c8d9da9 (bug 1624150) Backed out changeset 7e96d4acf317 (bug 1432749) Backed out changeset a95f77732a1c (bug 1432749)
This commit is contained in:
Родитель
4c093d6d9b
Коммит
1783003a34
|
@ -1,233 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WindowFeatures.h"
|
||||
|
||||
#include "nsINode.h" // IsSpaceCharacter
|
||||
#include "nsContentUtils.h" // nsContentUtils
|
||||
#include "nsDependentSubstring.h" // Substring
|
||||
#include "nsReadableUtils.h" // ToLowerCase
|
||||
|
||||
#ifdef DEBUG
|
||||
/* static */
|
||||
bool WindowFeatures::IsLowerCase(const char* text) {
|
||||
nsAutoCString before(text);
|
||||
nsAutoCString after;
|
||||
ToLowerCase(before, after);
|
||||
return before == after;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool IsFeatureSeparator(char aChar) {
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#feature-separator
|
||||
// A code point is a feature separator if it is ASCII whitespace, U+003D (=),
|
||||
// or U+002C (,).
|
||||
return IsSpaceCharacter(aChar) || aChar == '=' || aChar == ',';
|
||||
}
|
||||
|
||||
template <class IterT, class CondT>
|
||||
void AdvanceWhile(IterT& aPosition, const IterT& aEnd, CondT aCondition) {
|
||||
// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
|
||||
//
|
||||
// Step 2. While `position` doesn’t point past the end of `input` and the
|
||||
// code point at `position` within `input` meets the condition condition:
|
||||
while (aCondition(*aPosition) && aPosition < aEnd) {
|
||||
// Step 2.1. Append that code point to the end of `result`.
|
||||
// (done by caller)
|
||||
|
||||
// Step 2.2. Advance `position` by 1.
|
||||
++aPosition;
|
||||
}
|
||||
}
|
||||
|
||||
template <class IterT, class CondT>
|
||||
nsTDependentSubstring<char> CollectSequence(IterT& aPosition, const IterT& aEnd,
|
||||
CondT aCondition) {
|
||||
// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
|
||||
// To collect a sequence of code points meeting a condition `condition` from
|
||||
// a string `input`, given a position variable `position` tracking the
|
||||
// position of the calling algorithm within `input`:
|
||||
|
||||
// Step 1. Let `result` be the empty string.
|
||||
auto start = aPosition;
|
||||
|
||||
// Step 2.
|
||||
AdvanceWhile(aPosition, aEnd, aCondition);
|
||||
|
||||
// Step 3. Return `result`.
|
||||
return Substring(start, aPosition);
|
||||
}
|
||||
|
||||
static void NormalizeName(nsAutoCString& aName) {
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#normalizing-the-feature-name
|
||||
if (aName == "screenx") {
|
||||
aName = "left";
|
||||
} else if (aName == "screeny") {
|
||||
aName = "top";
|
||||
} else if (aName == "innerwidth") {
|
||||
aName = "width";
|
||||
} else if (aName == "innerheight") {
|
||||
aName = "height";
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
int32_t WindowFeatures::ParseIntegerWithFallback(const nsCString& aValue) {
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#concept-window-open-features-parse-boolean
|
||||
//
|
||||
// Step 3. Let `parsed` be the result of parsing value as an integer.
|
||||
nsContentUtils::ParseHTMLIntegerResultFlags parseResult;
|
||||
int32_t parsed = nsContentUtils::ParseHTMLInteger(aValue, &parseResult);
|
||||
|
||||
// Step 4. If `parsed` is an error, then set it to 0.
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-integers
|
||||
//
|
||||
// eParseHTMLInteger_NonStandard is not tested given:
|
||||
// * Step 4 allows leading whitespaces
|
||||
// * Step 6 allows a plus sign
|
||||
// * Step 8 does not disallow leading zeros
|
||||
// * Steps 6 and 9 allow `-0`
|
||||
//
|
||||
// eParseHTMLInteger_DidNotConsumeAllInput is not tested given:
|
||||
// * Step 8 collects digits and ignores remaining part
|
||||
//
|
||||
if (parseResult & nsContentUtils::eParseHTMLInteger_Error) {
|
||||
parsed = 0;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool WindowFeatures::ParseBool(const nsCString& aValue) {
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#concept-window-open-features-parse-boolean
|
||||
// To parse a boolean feature given a string `value`:
|
||||
|
||||
// Step 1. If `value` is the empty string, then return true.
|
||||
if (aValue.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 2. If `value` is a case-sensitive match for "yes", then return true.
|
||||
if (aValue == "yes") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 3-4.
|
||||
int32_t parsed = ParseIntegerWithFallback(aValue);
|
||||
|
||||
// Step 5. Return false if `parsed` is 0, and true otherwise.
|
||||
return parsed != 0;
|
||||
}
|
||||
|
||||
bool WindowFeatures::Tokenize(const nsACString& aFeatures) {
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#concept-window-open-features-tokenize
|
||||
// To tokenize the `features` argument:
|
||||
|
||||
// Step 1. Let `tokenizedFeatures` be a new ordered map.
|
||||
// (implicit)
|
||||
|
||||
// Step 2. Let `position` point at the first code point of features.
|
||||
auto position = aFeatures.BeginReading();
|
||||
|
||||
// Step 3. While `position` is not past the end of `features`:
|
||||
auto end = aFeatures.EndReading();
|
||||
while (position < end) {
|
||||
// Step 3.1. Let `name` be the empty string.
|
||||
// (implicit)
|
||||
|
||||
// Step 3.2. Let `value` be the empty string.
|
||||
nsAutoCString value;
|
||||
|
||||
// Step 3.3. Collect a sequence of code points that are feature separators
|
||||
// from `features` given `position`. This skips past leading separators
|
||||
// before the name.
|
||||
//
|
||||
// NOTE: Do not collect given this value is unused.
|
||||
AdvanceWhile(position, end, IsFeatureSeparator);
|
||||
|
||||
// Step 3.4. Collect a sequence of code points that are not feature
|
||||
// separators from `features` given `position`. Set `name` to the collected
|
||||
// characters, converted to ASCII lowercase.
|
||||
nsAutoCString name(CollectSequence(
|
||||
position, end, [](char c) { return !IsFeatureSeparator(c); }));
|
||||
ToLowerCase(name);
|
||||
|
||||
// Step 3.5. Set `name` to the result of normalizing the feature name
|
||||
// `name`.
|
||||
NormalizeName(name);
|
||||
|
||||
// Step 3.6. While `position` is not past the end of `features` and the
|
||||
// code point at `position` in features is not U+003D (=):
|
||||
//
|
||||
// Step 3.6.1. If the code point at `position` in features is U+002C (,),
|
||||
// or if it is not a feature separator, then break.
|
||||
//
|
||||
// Step 3.6.2. Advance `position` by 1.
|
||||
//
|
||||
// NOTE: This skips to the first U+003D (=) but does not skip past a U+002C
|
||||
// (,) or a non-separator.
|
||||
//
|
||||
// The above means skip all whitespaces.
|
||||
AdvanceWhile(position, end, [](char c) { return IsSpaceCharacter(c); });
|
||||
|
||||
// Step 3.7. If the code point at `position` in `features` is a feature
|
||||
// separator:
|
||||
if (position < end && IsFeatureSeparator(*position)) {
|
||||
// Step 3.7.1. While `position` is not past the end of `features` and the
|
||||
// code point at `position` in `features` is a feature separator:
|
||||
//
|
||||
// Step 3.7.1.1. If the code point at `position` in `features` is
|
||||
// U+002C (,), then break.
|
||||
//
|
||||
// Step 3.7.1.2. Advance `position` by 1.
|
||||
//
|
||||
// NOTE: This skips to the first non-separator but does not skip past a
|
||||
// U+002C (,).
|
||||
AdvanceWhile(position, end,
|
||||
[](char c) { return IsFeatureSeparator(c) && c != ','; });
|
||||
|
||||
// Step 3.7.2. Collect a sequence of code points that are not feature
|
||||
// separators code points from `features` given `position`. Set `value` to
|
||||
// the collected code points, converted to ASCII lowercase.
|
||||
value = CollectSequence(position, end,
|
||||
[](char c) { return !IsFeatureSeparator(c); });
|
||||
ToLowerCase(value);
|
||||
}
|
||||
|
||||
// Step 3.8. If `name` is not the empty string, then set
|
||||
// `tokenizedFeatures[name]` to `value`.
|
||||
if (!name.IsEmpty()) {
|
||||
if (!tokenizedFeatures_.put(name, value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4. Return `tokenizedFeatures`.
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowFeatures::Stringify(nsAutoCString& aOutput) {
|
||||
MOZ_ASSERT(aOutput.IsEmpty());
|
||||
|
||||
for (auto r = tokenizedFeatures_.all(); !r.empty(); r.popFront()) {
|
||||
if (!aOutput.IsEmpty()) {
|
||||
aOutput.Append(',');
|
||||
}
|
||||
|
||||
const nsCString& name = r.front().key();
|
||||
const nsCString& value = r.front().value();
|
||||
|
||||
aOutput.Append(name);
|
||||
|
||||
if (!value.IsEmpty()) {
|
||||
aOutput.Append('=');
|
||||
aOutput.Append(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_WindowFeatures_h
|
||||
#define mozilla_dom_WindowFeatures_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/HashTable.h" // mozilla::HashMap
|
||||
|
||||
#include "nsStringFwd.h" // nsCString, nsACString, nsAutoCString, nsLiteralCString
|
||||
#include "nsTStringHasher.h" // mozilla::DefaultHasher<nsCString>
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Represents `tokenizedFeatures` in
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#concept-window-open-features-tokenize
|
||||
// with accessor methods for values.
|
||||
class WindowFeatures {
|
||||
public:
|
||||
WindowFeatures() = default;
|
||||
|
||||
WindowFeatures(const WindowFeatures& aOther) = delete;
|
||||
WindowFeatures& operator=(const WindowFeatures& aOther) = delete;
|
||||
|
||||
WindowFeatures(WindowFeatures&& aOther) = delete;
|
||||
WindowFeatures& operator=(WindowFeatures&& aOther) = delete;
|
||||
|
||||
// Tokenizes `aFeatures` and stores the result map in member field.
|
||||
// This should be called at the begining, only once.
|
||||
//
|
||||
// Returns true if successfully tokenized, false otherwise.
|
||||
bool Tokenize(const nsACString& aFeatures);
|
||||
|
||||
// Returns true if the `aName` feature is specified.
|
||||
template <size_t N>
|
||||
bool Exists(const char (&aName)[N]) const {
|
||||
MOZ_ASSERT(IsLowerCase(aName));
|
||||
nsLiteralCString name(aName);
|
||||
return tokenizedFeatures_.has(name);
|
||||
}
|
||||
|
||||
// Returns string value of `aName` feature.
|
||||
// The feature must exist.
|
||||
template <size_t N>
|
||||
const nsCString& Get(const char (&aName)[N]) const {
|
||||
MOZ_ASSERT(IsLowerCase(aName));
|
||||
nsLiteralCString name(aName);
|
||||
auto p = tokenizedFeatures_.lookup(name);
|
||||
MOZ_ASSERT(p.found());
|
||||
|
||||
return p->value();
|
||||
}
|
||||
|
||||
// Returns integer value of `aName` feature.
|
||||
// The feature must exist.
|
||||
template <size_t N>
|
||||
int32_t GetInt(const char (&aName)[N]) const {
|
||||
const nsCString& value = Get(aName);
|
||||
return ParseIntegerWithFallback(value);
|
||||
}
|
||||
|
||||
// Returns bool value of `aName` feature.
|
||||
// The feature must exist.
|
||||
template <size_t N>
|
||||
bool GetBool(const char (&aName)[N]) const {
|
||||
const nsCString& value = Get(aName);
|
||||
return ParseBool(value);
|
||||
}
|
||||
|
||||
// Returns bool value of `aName` feature.
|
||||
// If the feature doesn't exist, returns `aDefault`.
|
||||
//
|
||||
// If `aPresenceFlag` is provided and the feature exists, it's set to `true`.
|
||||
// (note that the value isn't overwritten if the feature doesn't exist)
|
||||
template <size_t N>
|
||||
bool GetBoolWithDefault(const char (&aName)[N], bool aDefault,
|
||||
bool* aPresenceFlag = nullptr) const {
|
||||
MOZ_ASSERT(IsLowerCase(aName));
|
||||
nsLiteralCString name(aName);
|
||||
auto p = tokenizedFeatures_.lookup(name);
|
||||
if (p.found()) {
|
||||
if (aPresenceFlag) {
|
||||
*aPresenceFlag = true;
|
||||
}
|
||||
return ParseBool(p->value());
|
||||
}
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
// Remove the feature from the map.
|
||||
template <size_t N>
|
||||
void Remove(const char (&aName)[N]) {
|
||||
MOZ_ASSERT(IsLowerCase(aName));
|
||||
nsLiteralCString name(aName);
|
||||
tokenizedFeatures_.remove(name);
|
||||
}
|
||||
|
||||
// Returns true if there was no feature specified, or all features are
|
||||
// removed by `Remove`.
|
||||
//
|
||||
// Note that this can be true even if `aFeatures` parameter of `Tokenize`
|
||||
// is not empty, in case it contains no feature with non-empty name.
|
||||
bool IsEmpty() const { return tokenizedFeatures_.empty(); }
|
||||
|
||||
// Stringify the map into `aOutput`.
|
||||
// The result can be parsed again with `Tokenize`.
|
||||
void Stringify(nsAutoCString& aOutput);
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
// Returns true if `text` does not contain any character that gets modified by
|
||||
// `ToLowerCase`.
|
||||
static bool IsLowerCase(const char* text);
|
||||
#endif
|
||||
|
||||
static int32_t ParseIntegerWithFallback(const nsCString& aValue);
|
||||
static bool ParseBool(const nsCString& aValue);
|
||||
|
||||
// A map from feature name to feature value.
|
||||
// If value is not provided, it's empty string.
|
||||
mozilla::HashMap<nsCString, nsCString> tokenizedFeatures_;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_dom_WindowFeatures_h
|
|
@ -253,7 +253,6 @@ EXPORTS.mozilla.dom += [
|
|||
'UserActivation.h',
|
||||
'ViewportMetaData.h',
|
||||
'VisualViewport.h',
|
||||
'WindowFeatures.h',
|
||||
'WindowOrientationObserver.h',
|
||||
'WindowProxyHolder.h',
|
||||
]
|
||||
|
@ -426,7 +425,6 @@ UNIFIED_SOURCES += [
|
|||
'ViewportMetaData.cpp',
|
||||
'VisualViewport.cpp',
|
||||
'WindowDestroyedEvent.cpp',
|
||||
'WindowFeatures.cpp',
|
||||
'WindowNamedPropertiesHandler.cpp',
|
||||
'WindowOrientationObserver.cpp',
|
||||
'XPathGenerator.cpp',
|
||||
|
|
|
@ -1181,14 +1181,11 @@ nsContentUtils::InternalSerializeAutocompleteAttribute(
|
|||
}
|
||||
|
||||
// Parse an integer according to HTML spec
|
||||
template <class StringT>
|
||||
int32_t nsContentUtils::ParseHTMLIntegerImpl(
|
||||
const StringT& aValue, ParseHTMLIntegerResultFlags* aResult) {
|
||||
using CharT = typename StringT::char_type;
|
||||
|
||||
int32_t nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
|
||||
ParseHTMLIntegerResultFlags* aResult) {
|
||||
int result = eParseHTMLInteger_NoFlags;
|
||||
|
||||
typename StringT::const_iterator iter, end;
|
||||
nsAString::const_iterator iter, end;
|
||||
aValue.BeginReading(iter);
|
||||
aValue.EndReading(end);
|
||||
|
||||
|
@ -1204,11 +1201,11 @@ int32_t nsContentUtils::ParseHTMLIntegerImpl(
|
|||
}
|
||||
|
||||
int sign = 1;
|
||||
if (*iter == CharT('-')) {
|
||||
if (*iter == char16_t('-')) {
|
||||
sign = -1;
|
||||
result |= eParseHTMLInteger_Negative;
|
||||
++iter;
|
||||
} else if (*iter == CharT('+')) {
|
||||
} else if (*iter == char16_t('+')) {
|
||||
result |= eParseHTMLInteger_NonStandard;
|
||||
++iter;
|
||||
}
|
||||
|
@ -1219,7 +1216,7 @@ int32_t nsContentUtils::ParseHTMLIntegerImpl(
|
|||
// Check for leading zeros first.
|
||||
uint64_t leadingZeros = 0;
|
||||
while (iter != end) {
|
||||
if (*iter != CharT('0')) {
|
||||
if (*iter != char16_t('0')) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1229,8 +1226,8 @@ int32_t nsContentUtils::ParseHTMLIntegerImpl(
|
|||
}
|
||||
|
||||
while (iter != end) {
|
||||
if (*iter >= CharT('0') && *iter <= CharT('9')) {
|
||||
value = (value * 10) + (*iter - CharT('0')) * sign;
|
||||
if (*iter >= char16_t('0') && *iter <= char16_t('9')) {
|
||||
value = (value * 10) + (*iter - char16_t('0')) * sign;
|
||||
++iter;
|
||||
if (!value.isValid()) {
|
||||
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
|
||||
|
@ -1260,17 +1257,6 @@ int32_t nsContentUtils::ParseHTMLIntegerImpl(
|
|||
return value.isValid() ? value.value() : 0;
|
||||
}
|
||||
|
||||
// Parse an integer according to HTML spec
|
||||
int32_t nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
|
||||
ParseHTMLIntegerResultFlags* aResult) {
|
||||
return ParseHTMLIntegerImpl(aValue, aResult);
|
||||
}
|
||||
|
||||
int32_t nsContentUtils::ParseHTMLInteger(const nsACString& aValue,
|
||||
ParseHTMLIntegerResultFlags* aResult) {
|
||||
return ParseHTMLIntegerImpl(aValue, aResult);
|
||||
}
|
||||
|
||||
#define SKIP_WHITESPACE(iter, end_iter, end_res) \
|
||||
while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
|
||||
++(iter); \
|
||||
|
|
|
@ -614,12 +614,7 @@ class nsContentUtils {
|
|||
enum ParseHTMLIntegerResultFlags {
|
||||
eParseHTMLInteger_NoFlags = 0,
|
||||
// eParseHTMLInteger_NonStandard is set if the string representation of the
|
||||
// integer was not the canonical one, but matches at least one of the
|
||||
// following:
|
||||
// * had leading whitespaces
|
||||
// * had '+' sign
|
||||
// * had leading '0'
|
||||
// * was '-0'
|
||||
// integer was not the canonical one (e.g. had extra leading '+' or '0').
|
||||
eParseHTMLInteger_NonStandard = 1 << 0,
|
||||
eParseHTMLInteger_DidNotConsumeAllInput = 1 << 1,
|
||||
// Set if one or more error flags were set.
|
||||
|
@ -631,15 +626,7 @@ class nsContentUtils {
|
|||
};
|
||||
static int32_t ParseHTMLInteger(const nsAString& aValue,
|
||||
ParseHTMLIntegerResultFlags* aResult);
|
||||
static int32_t ParseHTMLInteger(const nsACString& aValue,
|
||||
ParseHTMLIntegerResultFlags* aResult);
|
||||
|
||||
private:
|
||||
template <class StringT>
|
||||
static int32_t ParseHTMLIntegerImpl(const StringT& aValue,
|
||||
ParseHTMLIntegerResultFlags* aResult);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Parse a margin string of format 'top, right, bottom, left' into
|
||||
* an nsIntMargin.
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "mozilla/dom/TimeoutHandler.h"
|
||||
#include "mozilla/dom/TimeoutManager.h"
|
||||
#include "mozilla/dom/WindowContext.h"
|
||||
#include "mozilla/dom/WindowFeatures.h" // WindowFeatures
|
||||
#include "mozilla/dom/WindowProxyHolder.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
|
@ -77,6 +76,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/Wrapper.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
@ -7019,32 +7019,34 @@ nsresult nsGlobalWindowOuter::OpenInternal(
|
|||
|
||||
NS_ASSERTION(mDocShell, "Must have docshell here");
|
||||
|
||||
NS_ConvertUTF16toUTF8 optionsUtf8(aOptions);
|
||||
|
||||
WindowFeatures features;
|
||||
if (!features.Tokenize(optionsUtf8)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString options;
|
||||
bool forceNoOpener = aForceNoOpener;
|
||||
if (features.Exists("noopener")) {
|
||||
forceNoOpener = features.GetBool("noopener");
|
||||
features.Remove("noopener");
|
||||
}
|
||||
|
||||
bool forceNoReferrer = false;
|
||||
if (features.Exists("noreferrer")) {
|
||||
forceNoReferrer = features.GetBool("noreferrer");
|
||||
if (forceNoReferrer) {
|
||||
// Unlike other window flags, "noopener" comes from splitting on commas with
|
||||
// HTML whitespace trimming...
|
||||
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
|
||||
aOptions, ',');
|
||||
while (tok.hasMoreTokens()) {
|
||||
auto nextTok = tok.nextToken();
|
||||
if (nextTok.EqualsLiteral("noopener")) {
|
||||
forceNoOpener = true;
|
||||
continue;
|
||||
}
|
||||
if (StaticPrefs::dom_window_open_noreferrer_enabled() &&
|
||||
nextTok.LowerCaseEqualsLiteral("noreferrer")) {
|
||||
forceNoReferrer = true;
|
||||
// noreferrer implies noopener
|
||||
forceNoOpener = true;
|
||||
continue;
|
||||
}
|
||||
features.Remove("noreferrer");
|
||||
// Want to create a copy of the options without 'noopener' because having
|
||||
// 'noopener' in the options affects other window features.
|
||||
if (!options.IsEmpty()) {
|
||||
options.Append(',');
|
||||
}
|
||||
AppendUTF16toUTF8(nextTok, options);
|
||||
}
|
||||
|
||||
nsAutoCString options;
|
||||
features.Stringify(options);
|
||||
|
||||
// If current's top-level browsing context's active document's
|
||||
// cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
|
||||
// if currentDoc's origin is not same origin with currentDoc's top-level
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "nsClassHashtable.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTStringHasher.h" // mozilla::DefaultHasher<nsCString>
|
||||
#include "nsZipArchive.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
|
@ -122,6 +121,19 @@ struct StartupCacheEntry {
|
|||
};
|
||||
};
|
||||
|
||||
struct nsCStringHasher {
|
||||
using Key = nsCString;
|
||||
using Lookup = nsCString;
|
||||
|
||||
static HashNumber hash(const Lookup& aLookup) {
|
||||
return HashString(aLookup.get());
|
||||
}
|
||||
|
||||
static bool match(const Key& aKey, const Lookup& aLookup) {
|
||||
return aKey.Equals(aLookup);
|
||||
}
|
||||
};
|
||||
|
||||
// We don't want to refcount StartupCache, and ObserverService wants to
|
||||
// refcount its listeners, so we'll let it refcount this instead.
|
||||
class StartupCacheListener final : public nsIObserver {
|
||||
|
@ -206,7 +218,7 @@ class StartupCache : public nsIMemoryReporter {
|
|||
static void ThreadedWrite(void* aClosure);
|
||||
static void ThreadedPrefetch(void* aClosure);
|
||||
|
||||
HashMap<nsCString, StartupCacheEntry> mTable;
|
||||
HashMap<nsCString, StartupCacheEntry, nsCStringHasher> mTable;
|
||||
// owns references to the contents of tables which have been invalidated.
|
||||
// In theory grows forever if the cache is continually filled and then
|
||||
// invalidated, but this should not happen in practice.
|
||||
|
|
|
@ -3,14 +3,10 @@
|
|||
if webrender and not debug: bug 1425588
|
||||
if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
|
||||
["innerwidth==401" should set width of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
expected: FAIL
|
||||
|
||||
["innerheight==402" should set height of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
expected: FAIL
|
||||
|
||||
["INNERHEIGHT=402" should set height of opened window]
|
||||
expected:
|
||||
|
|
|
@ -1,2 +1,20 @@
|
|||
[open-features-tokenization-noopener.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1364696
|
||||
[tokenization should skip window features separators before `name`]
|
||||
expected: FAIL
|
||||
|
||||
[feature `name` should be converted to ASCII lowercase]
|
||||
expected: FAIL
|
||||
|
||||
[after `name`, tokenization should skip window features separators that are not "=" or ","]
|
||||
expected: FAIL
|
||||
|
||||
[Tokenizing should ignore window feature separators except "," after initial "=" and before value]
|
||||
expected: FAIL
|
||||
|
||||
[Tokenizing should read characters until first window feature separator as `value`]
|
||||
expected: FAIL
|
||||
|
||||
["noopener" should be based on name (key), not value]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
[open-features-tokenization-noreferrer.html]
|
||||
expected:
|
||||
if webrender and (os == "linux"): ["OK", "TIMEOUT", "CRASH"]
|
||||
|
||||
[Tokenizing "noreferrer" should ignore window feature separators except "," after initial "=" and before value]
|
||||
expected: FAIL
|
||||
|
||||
[Tokenizing "noreferrer" should read characters until first window feature separator as `value`]
|
||||
expected: FAIL
|
||||
|
||||
[After "noreferrer", tokenization should skip window features separators that are not "=" or ","]
|
||||
expected: FAIL
|
||||
|
||||
[Integer values other than 0 should activate the feature]
|
||||
expected: FAIL
|
||||
|
||||
[Tokenization of "noreferrer" should skip window features separators before feature]
|
||||
expected: FAIL
|
||||
|
||||
[Feature "noreferrer" should be converted to ASCII lowercase]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -2,5 +2,69 @@
|
|||
disabled:
|
||||
if webrender and not debug: bug 1425588
|
||||
if verify and (os == "linux") and not debug: fails in verify mode
|
||||
if os == "android": frequently hits timeout
|
||||
["screenx==141" should set left position of opened window]
|
||||
expected: FAIL
|
||||
|
||||
["screeny==142" should set top position of opened window]
|
||||
expected: FAIL
|
||||
|
||||
["screenx=141" should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["screeny=142" should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["\\nscreenx= 141" should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
[" screeny = 142" should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["screenX=141" should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
[",screenx=141,," should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
[",screeny=142,," should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["screenY=142" should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
[" screenx = 141" should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["SCREENX=141" should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["SCREENY=142" should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
["\\nscreeny= 142" should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
|
||||
|
|
|
@ -3,19 +3,13 @@
|
|||
if webrender and not debug: bug 1425588
|
||||
if verify and (os == "linux") and not debug: fails in verify mode
|
||||
["left==141" should set left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
expected: FAIL
|
||||
|
||||
["top==142" should set top position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
expected: FAIL
|
||||
|
||||
["top=152==left=152" should set top and left position of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
expected: FAIL
|
||||
|
||||
[",left=141,," should set left position of opened window]
|
||||
expected:
|
||||
|
|
|
@ -3,27 +3,16 @@
|
|||
if webrender and not debug: bug 1425588
|
||||
if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
|
||||
["width==401" should set width of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
expected: FAIL
|
||||
|
||||
["height==402" should set height of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
if devedition and os == "win" and bits == 32: FAIL # bug 1540551
|
||||
expected: FAIL
|
||||
|
||||
["height==402 width = 401" should set height and width of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
if devedition and os == "win" and bits == 32: FAIL # bug 1540551
|
||||
expected: FAIL
|
||||
|
||||
[",height=402,,width==401" should set height and width of opened window]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: FAIL
|
||||
if devedition and os == "win" and bits == 32: FAIL # bug 1540551
|
||||
expected: FAIL
|
||||
|
||||
["\\nheight= 402" should set height of opened window]
|
||||
expected:
|
||||
|
|
|
@ -14949,16 +14949,6 @@
|
|||
"bug_numbers": [1597956, 1614905],
|
||||
"description": "milliseconds to complete a TLS session resumption with external cache"
|
||||
},
|
||||
"WINDOW_OPEN_OUTER_SIZE": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"products": ["firefox"],
|
||||
"alert_emails": ["tfujisawa.birchill@mozilla.com"],
|
||||
"expires_in_version": "80",
|
||||
"kind": "boolean",
|
||||
"bug_numbers": [1624150],
|
||||
"releaseChannelCollection": "opt-out",
|
||||
"description": "Flag indicating consumer of non-standard outerWidth/outerHeight features in window.open"
|
||||
},
|
||||
"WINDOW_REMOTE_SUBFRAMES_ENABLED_STATUS": {
|
||||
"record_in_processes": ["main"],
|
||||
"products": ["firefox"],
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
#include "mozilla/ResultExtensions.h"
|
||||
#include "mozilla/StaticPrefs_fission.h"
|
||||
#include "mozilla/StaticPrefs_full_screen_api.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Storage.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
@ -318,7 +317,9 @@ struct SizeSpec {
|
|||
mOuterHeightSpecified(false),
|
||||
mInnerWidthSpecified(false),
|
||||
mInnerHeightSpecified(false),
|
||||
mLockAspectRatio(false) {}
|
||||
mLockAspectRatio(false),
|
||||
mUseDefaultWidth(false),
|
||||
mUseDefaultHeight(false) {}
|
||||
|
||||
int32_t mLeft;
|
||||
int32_t mTop;
|
||||
|
@ -335,6 +336,11 @@ struct SizeSpec {
|
|||
bool mInnerHeightSpecified;
|
||||
bool mLockAspectRatio;
|
||||
|
||||
// If these booleans are true, don't look at the corresponding width values
|
||||
// even if they're specified -- they'll be bogus
|
||||
bool mUseDefaultWidth;
|
||||
bool mUseDefaultHeight;
|
||||
|
||||
bool PositionSpecified() const { return mLeftSpecified || mTopSpecified; }
|
||||
|
||||
bool SizeSpecified() const { return WidthSpecified() || HeightSpecified(); }
|
||||
|
@ -405,7 +411,8 @@ static bool CheckUserContextCompatibility(nsIDocShell* aDocShell) {
|
|||
return subjectPrincipal->GetUserContextId() == userContextId;
|
||||
}
|
||||
|
||||
nsresult nsWindowWatcher::CreateChromeWindow(nsIWebBrowserChrome* aParentChrome,
|
||||
nsresult nsWindowWatcher::CreateChromeWindow(const nsACString& aFeatures,
|
||||
nsIWebBrowserChrome* aParentChrome,
|
||||
uint32_t aChromeFlags,
|
||||
nsIOpenWindowInfo* aOpenWindowInfo,
|
||||
nsIWebBrowserChrome** aResult) {
|
||||
|
@ -437,18 +444,21 @@ nsresult nsWindowWatcher::CreateChromeWindow(nsIWebBrowserChrome* aParentChrome,
|
|||
* the size.
|
||||
*
|
||||
* @param aFeatures
|
||||
* The features that was used to open the window.
|
||||
* The features string that was used to open the window.
|
||||
* @param aTreeOwner
|
||||
* The nsIDocShellTreeOwner of the newly opened window. If null,
|
||||
* this function is a no-op.
|
||||
*/
|
||||
void nsWindowWatcher::MaybeDisablePersistence(
|
||||
const SizeSpec& sizeSpec, nsIDocShellTreeOwner* aTreeOwner) {
|
||||
const nsACString& aFeatures, nsIDocShellTreeOwner* aTreeOwner) {
|
||||
if (!aTreeOwner) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sizeSpec.SizeSpecified()) {
|
||||
// At the moment, the strings "height=" or "width=" never happen
|
||||
// outside a size specification, so we can do this the Q&D way.
|
||||
if (PL_strcasestr(aFeatures.BeginReading(), "width=") ||
|
||||
PL_strcasestr(aFeatures.BeginReading(), "height=")) {
|
||||
aTreeOwner->SetPersistence(false, false, false);
|
||||
}
|
||||
}
|
||||
|
@ -513,13 +523,10 @@ nsWindowWatcher::OpenWindowWithRemoteTab(nsIRemoteTab* aRemoteTab,
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
WindowFeatures features;
|
||||
features.Tokenize(aFeatures);
|
||||
|
||||
SizeSpec sizeSpec;
|
||||
CalcSizeSpec(features, sizeSpec);
|
||||
CalcSizeSpec(aFeatures, sizeSpec);
|
||||
|
||||
uint32_t chromeFlags = CalculateChromeFlagsForChild(features, sizeSpec);
|
||||
uint32_t chromeFlags = CalculateChromeFlagsForChild(aFeatures, sizeSpec);
|
||||
|
||||
if (isPrivateBrowsingWindow) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
|
||||
|
@ -536,7 +543,7 @@ nsWindowWatcher::OpenWindowWithRemoteTab(nsIRemoteTab* aRemoteTab,
|
|||
nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
|
||||
nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
|
||||
|
||||
CreateChromeWindow(parentChrome, chromeFlags, aOpenWindowInfo,
|
||||
CreateChromeWindow(aFeatures, parentChrome, chromeFlags, aOpenWindowInfo,
|
||||
getter_AddRefs(newWindowChrome));
|
||||
|
||||
if (NS_WARN_IF(!newWindowChrome)) {
|
||||
|
@ -567,7 +574,7 @@ nsWindowWatcher::OpenWindowWithRemoteTab(nsIRemoteTab* aRemoteTab,
|
|||
// that will also run with out-of-process tabs.
|
||||
MOZ_ASSERT(chromeContext->UseRemoteTabs());
|
||||
|
||||
MaybeDisablePersistence(sizeSpec, chromeTreeOwner);
|
||||
MaybeDisablePersistence(aFeatures, chromeTreeOwner);
|
||||
|
||||
SizeOpenedWindow(chromeTreeOwner, parentWindowOuter, false, sizeSpec,
|
||||
Some(aOpenerFullZoom));
|
||||
|
@ -599,6 +606,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
|
||||
uint32_t chromeFlags;
|
||||
nsAutoString name; // string version of aName
|
||||
nsAutoCString features; // string version of aFeatures
|
||||
nsCOMPtr<nsIURI> uriToLoad; // from aUrl, if any
|
||||
nsCOMPtr<nsIDocShellTreeOwner>
|
||||
parentTreeOwner; // from the parent window, if any
|
||||
|
@ -636,13 +644,11 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
name.SetIsVoid(true);
|
||||
}
|
||||
|
||||
WindowFeatures features;
|
||||
nsAutoCString featuresStr;
|
||||
if (aFeatures) {
|
||||
featuresStr.Assign(aFeatures);
|
||||
features.Tokenize(featuresStr);
|
||||
features.Assign(aFeatures);
|
||||
features.StripWhitespace();
|
||||
} else {
|
||||
featuresStr.SetIsVoid(true);
|
||||
features.SetIsVoid(true);
|
||||
}
|
||||
|
||||
RefPtr<BrowsingContext> parentBC(
|
||||
|
@ -685,13 +691,6 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
|
||||
bool isCallerChrome = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
||||
|
||||
if (!hasChromeParent) {
|
||||
bool outerSizeUsed =
|
||||
features.Exists("outerwidth") || features.Exists("outerheight");
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::WINDOW_OPEN_OUTER_SIZE,
|
||||
outerSizeUsed);
|
||||
}
|
||||
|
||||
SizeSpec sizeSpec;
|
||||
CalcSizeSpec(features, sizeSpec);
|
||||
|
||||
|
@ -840,8 +839,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
if (provider) {
|
||||
rv = provider->ProvideWindow(openWindowInfo, chromeFlags, aCalledFromJS,
|
||||
sizeSpec.WidthSpecified(), uriToLoad, name,
|
||||
featuresStr, aForceNoOpener,
|
||||
aForceNoReferrer, aLoadState, &windowIsNew,
|
||||
features, aForceNoOpener, aForceNoReferrer,
|
||||
aLoadState, &windowIsNew,
|
||||
getter_AddRefs(newBC));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && newBC) {
|
||||
|
@ -937,8 +936,9 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
completely honest: we clear that indicator if the opener is chrome, so
|
||||
that the downstream consumer can treat the indicator to mean simply
|
||||
that the new window is subject to popup control. */
|
||||
rv = CreateChromeWindow(parentChrome, chromeFlags, openWindowInfo,
|
||||
getter_AddRefs(newChrome));
|
||||
rv = CreateChromeWindow(features, parentChrome, chromeFlags,
|
||||
openWindowInfo, getter_AddRefs(newChrome));
|
||||
|
||||
if (parentTopInnerWindow) {
|
||||
parentTopInnerWindow->Resume();
|
||||
}
|
||||
|
@ -1031,7 +1031,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
|
|||
if (isNewToplevelWindow) {
|
||||
nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
|
||||
newDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
|
||||
MaybeDisablePersistence(sizeSpec, newTreeOwner);
|
||||
MaybeDisablePersistence(features, newTreeOwner);
|
||||
}
|
||||
|
||||
if (aDialog && aArgv) {
|
||||
|
@ -1649,43 +1649,41 @@ nsresult nsWindowWatcher::URIfromURL(const char* aURL,
|
|||
return NS_NewURI(aURI, aURL, baseURI);
|
||||
}
|
||||
|
||||
#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \
|
||||
chromeFlags |= \
|
||||
WinHasOption(aFeatures, (feature), 0, &presenceFlag) ? (flag) : 0;
|
||||
// static
|
||||
uint32_t nsWindowWatcher::CalculateChromeFlagsHelper(
|
||||
uint32_t aInitialFlags, const WindowFeatures& aFeatures,
|
||||
const SizeSpec& aSizeSpec, bool* presenceFlag, bool aHasChromeParent) {
|
||||
uint32_t aInitialFlags, const nsACString& aFeatures,
|
||||
const SizeSpec& aSizeSpec, bool& presenceFlag, bool aHasChromeParent) {
|
||||
uint32_t chromeFlags = aInitialFlags;
|
||||
|
||||
if (aFeatures.GetBoolWithDefault("titlebar", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("close", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("toolbar", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_TOOLBAR;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("location", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_LOCATIONBAR;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("personalbar", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("status", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_STATUSBAR;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("menubar", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_MENUBAR;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("resizable", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_RESIZE;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("minimizable", false, presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_MIN;
|
||||
}
|
||||
// NS_CALCULATE_CHROME_FLAG_FOR requires aFeatures, presenceFlag, and
|
||||
// chromeFlags to be in scope.
|
||||
|
||||
if (aFeatures.GetBoolWithDefault("scrollbars", true, presenceFlag)) {
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("titlebar",
|
||||
nsIWebBrowserChrome::CHROME_TITLEBAR);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("close",
|
||||
nsIWebBrowserChrome::CHROME_WINDOW_CLOSE);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("toolbar", nsIWebBrowserChrome::CHROME_TOOLBAR);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("location",
|
||||
nsIWebBrowserChrome::CHROME_LOCATIONBAR);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("personalbar",
|
||||
nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("status", nsIWebBrowserChrome::CHROME_STATUSBAR);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("menubar", nsIWebBrowserChrome::CHROME_MENUBAR);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("resizable",
|
||||
nsIWebBrowserChrome::CHROME_WINDOW_RESIZE);
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("minimizable",
|
||||
nsIWebBrowserChrome::CHROME_WINDOW_MIN);
|
||||
|
||||
// default scrollbar to "on," unless explicitly turned off
|
||||
bool scrollbarsPresent = false;
|
||||
if (WinHasOption(aFeatures, "scrollbars", 1, &scrollbarsPresent) ||
|
||||
!scrollbarsPresent) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
|
||||
}
|
||||
presenceFlag = presenceFlag || scrollbarsPresent;
|
||||
|
||||
if (aHasChromeParent) {
|
||||
return chromeFlags;
|
||||
|
@ -1741,32 +1739,37 @@ uint32_t nsWindowWatcher::EnsureFlagsSafeForContent(uint32_t aChromeFlags,
|
|||
}
|
||||
|
||||
// static
|
||||
bool nsWindowWatcher::ShouldOpenPopup(const WindowFeatures& aFeatures,
|
||||
bool nsWindowWatcher::ShouldOpenPopup(const nsACString& aFeatures,
|
||||
const SizeSpec& aSizeSpec) {
|
||||
if (aFeatures.IsEmpty()) {
|
||||
if (aFeatures.IsVoid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Follow Google Chrome's behavior that opens a popup depending on
|
||||
// the following features.
|
||||
if (!aFeatures.GetBoolWithDefault("location", false) &&
|
||||
!aFeatures.GetBoolWithDefault("toolbar", false)) {
|
||||
bool unused;
|
||||
if (!WinHasOption(aFeatures, "location", 0, &unused) &&
|
||||
!WinHasOption(aFeatures, "toolbar", 0, &unused)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aFeatures.GetBoolWithDefault("menubar", false)) {
|
||||
if (!WinHasOption(aFeatures, "menubar", 0, &unused)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aFeatures.GetBoolWithDefault("resizable", true)) {
|
||||
// `resizable` defaults to true.
|
||||
// Should open popup only when explicitly specified to 0.
|
||||
bool resizablePresent = false;
|
||||
if (!WinHasOption(aFeatures, "resizable", 0, &resizablePresent) &&
|
||||
resizablePresent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aFeatures.GetBoolWithDefault("scrollbars", false)) {
|
||||
if (!WinHasOption(aFeatures, "scrollbars", 0, &unused)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aFeatures.GetBoolWithDefault("status", false)) {
|
||||
if (!WinHasOption(aFeatures, "status", 0, &unused)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1788,13 +1791,15 @@ bool nsWindowWatcher::ShouldOpenPopup(const WindowFeatures& aFeatures,
|
|||
*/
|
||||
// static
|
||||
uint32_t nsWindowWatcher::CalculateChromeFlagsForChild(
|
||||
const WindowFeatures& aFeatures, const SizeSpec& aSizeSpec) {
|
||||
if (aFeatures.IsEmpty()) {
|
||||
const nsACString& aFeatures, const SizeSpec& aSizeSpec) {
|
||||
if (aFeatures.IsVoid()) {
|
||||
return nsIWebBrowserChrome::CHROME_ALL;
|
||||
}
|
||||
|
||||
uint32_t chromeFlags = CalculateChromeFlagsHelper(
|
||||
nsIWebBrowserChrome::CHROME_WINDOW_BORDERS, aFeatures, aSizeSpec);
|
||||
bool presenceFlag = false;
|
||||
uint32_t chromeFlags =
|
||||
CalculateChromeFlagsHelper(nsIWebBrowserChrome::CHROME_WINDOW_BORDERS,
|
||||
aFeatures, aSizeSpec, presenceFlag);
|
||||
|
||||
return EnsureFlagsSafeForContent(chromeFlags);
|
||||
}
|
||||
|
@ -1812,7 +1817,7 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForChild(
|
|||
*/
|
||||
// static
|
||||
uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
||||
mozIDOMWindowProxy* aParent, const WindowFeatures& aFeatures,
|
||||
mozIDOMWindowProxy* aParent, const nsACString& aFeatures,
|
||||
const SizeSpec& aSizeSpec, bool aDialog, bool aChromeURL,
|
||||
bool aHasChromeParent, bool aCalledFromJS) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
@ -1822,7 +1827,7 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
|
||||
// The features string is made void by OpenWindowInternal
|
||||
// if nullptr was originally passed as the features string.
|
||||
if (aFeatures.IsEmpty()) {
|
||||
if (aFeatures.IsVoid()) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
if (aDialog) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
|
@ -1841,29 +1846,29 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
in the standards-compliant window.(normal)open. */
|
||||
|
||||
bool presenceFlag = false;
|
||||
if (aDialog && aFeatures.GetBoolWithDefault("all", false, &presenceFlag)) {
|
||||
if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
}
|
||||
|
||||
/* Next, allow explicitly named options to override the initial settings */
|
||||
chromeFlags = CalculateChromeFlagsHelper(chromeFlags, aFeatures, aSizeSpec,
|
||||
&presenceFlag, aHasChromeParent);
|
||||
presenceFlag, aHasChromeParent);
|
||||
|
||||
// Determine whether the window is a private browsing window
|
||||
if (aFeatures.GetBoolWithDefault("private", false, &presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("non-private", false, &presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW;
|
||||
}
|
||||
chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag)
|
||||
? nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag)
|
||||
? nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW
|
||||
: 0;
|
||||
|
||||
// Determine whether the window should have remote tabs.
|
||||
bool remote = BrowserTabsRemoteAutostart();
|
||||
|
||||
if (remote) {
|
||||
remote = !aFeatures.GetBoolWithDefault("non-remote", false, &presenceFlag);
|
||||
remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
|
||||
} else {
|
||||
remote = aFeatures.GetBoolWithDefault("remote", false, &presenceFlag);
|
||||
remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
|
@ -1874,19 +1879,18 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
bool fission = StaticPrefs::fission_autostart();
|
||||
|
||||
if (fission) {
|
||||
fission =
|
||||
!aFeatures.GetBoolWithDefault("non-fission", false, &presenceFlag);
|
||||
fission = !WinHasOption(aFeatures, "non-fission", 0, &presenceFlag);
|
||||
} else {
|
||||
fission = aFeatures.GetBoolWithDefault("fission", false, &presenceFlag);
|
||||
fission = WinHasOption(aFeatures, "fission", 0, &presenceFlag);
|
||||
}
|
||||
|
||||
if (fission) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
|
||||
}
|
||||
|
||||
if (aFeatures.GetBoolWithDefault("popup", false, &presenceFlag)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
|
||||
}
|
||||
chromeFlags |= WinHasOption(aFeatures, "popup", 0, &presenceFlag)
|
||||
? nsIWebBrowserChrome::CHROME_WINDOW_POPUP
|
||||
: 0;
|
||||
|
||||
/* OK.
|
||||
Normal browser windows, in spite of a stated pattern of turning off
|
||||
|
@ -1897,15 +1901,15 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
|
||||
// default titlebar and closebox to "on," if not mentioned at all
|
||||
if (!(chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_POPUP)) {
|
||||
if (!aFeatures.Exists("titlebar")) {
|
||||
if (!PL_strcasestr(aFeatures.BeginReading(), "titlebar")) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
|
||||
}
|
||||
if (!aFeatures.Exists("close")) {
|
||||
if (!PL_strcasestr(aFeatures.BeginReading(), "close")) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (aDialog && !aFeatures.IsEmpty() && !presenceFlag) {
|
||||
if (aDialog && !aFeatures.IsVoid() && !presenceFlag) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_DEFAULT;
|
||||
}
|
||||
|
||||
|
@ -1913,35 +1917,35 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
with the features that are more operating hints than appearance
|
||||
instructions. (Note modality implies dependence.) */
|
||||
|
||||
if (aFeatures.GetBoolWithDefault("alwayslowered", false) ||
|
||||
aFeatures.GetBoolWithDefault("z-lock", false)) {
|
||||
if (WinHasOption(aFeatures, "alwaysLowered", 0, nullptr) ||
|
||||
WinHasOption(aFeatures, "z-lock", 0, nullptr)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
|
||||
} else if (aFeatures.GetBoolWithDefault("alwaysraised", false)) {
|
||||
} else if (WinHasOption(aFeatures, "alwaysRaised", 0, nullptr)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
|
||||
}
|
||||
|
||||
if (aFeatures.GetBoolWithDefault("suppressanimation", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_SUPPRESS_ANIMATION;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("alwaysontop", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_ALWAYS_ON_TOP;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("chrome", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("extrachrome", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_EXTRA;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("centerscreen", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("dependent", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_DEPENDENT;
|
||||
}
|
||||
if (aFeatures.GetBoolWithDefault("modal", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_DEPENDENT;
|
||||
}
|
||||
chromeFlags |= WinHasOption(aFeatures, "suppressanimation", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_SUPPRESS_ANIMATION
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "alwaysontop", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_ALWAYS_ON_TOP
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "chrome", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_OPENAS_CHROME
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "extrachrome", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_EXTRA
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "centerscreen", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_CENTER_SCREEN
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "dependent", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_DEPENDENT
|
||||
: 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "modal", 0, nullptr)
|
||||
? (nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_DEPENDENT)
|
||||
: 0;
|
||||
|
||||
/* On mobile we want to ignore the dialog window feature, since the mobile UI
|
||||
does not provide any affordance for dialog windows. This does not interfere
|
||||
|
@ -1953,18 +1957,18 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
&disableDialogFeature);
|
||||
|
||||
if (!disableDialogFeature) {
|
||||
if (aFeatures.GetBoolWithDefault("dialog", false)) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
|
||||
}
|
||||
chromeFlags |= WinHasOption(aFeatures, "dialog", 0, nullptr)
|
||||
? nsIWebBrowserChrome::CHROME_OPENAS_DIALOG
|
||||
: 0;
|
||||
}
|
||||
|
||||
/* and dialogs need to have the last word. assume dialogs are dialogs,
|
||||
and opened as chrome, unless explicitly told otherwise. */
|
||||
if (aDialog) {
|
||||
if (!aFeatures.Exists("dialog")) {
|
||||
if (!PL_strcasestr(aFeatures.BeginReading(), "dialog")) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
|
||||
}
|
||||
if (!aFeatures.Exists("chrome")) {
|
||||
if (!PL_strcasestr(aFeatures.BeginReading(), "chrome")) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
|
||||
}
|
||||
}
|
||||
|
@ -1988,6 +1992,63 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForParent(
|
|||
return chromeFlags;
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t nsWindowWatcher::WinHasOption(const nsACString& aOptions,
|
||||
const char* aName, int32_t aDefault,
|
||||
bool* aPresenceFlag) {
|
||||
if (aOptions.IsEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* options = aOptions.BeginReading();
|
||||
char* comma;
|
||||
char* equal;
|
||||
int32_t found = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(nsAutoCString(aOptions).FindCharInSet(" \n\r\t") == kNotFound,
|
||||
"There should be no whitespace in this string!");
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
comma = PL_strchr(options, ',');
|
||||
if (comma) {
|
||||
*comma = '\0';
|
||||
}
|
||||
equal = PL_strchr(options, '=');
|
||||
if (equal) {
|
||||
*equal = '\0';
|
||||
}
|
||||
if (nsCRT::strcasecmp(options, aName) == 0) {
|
||||
if (aPresenceFlag) {
|
||||
*aPresenceFlag = true;
|
||||
}
|
||||
if (equal)
|
||||
if (*(equal + 1) == '*') {
|
||||
found = aDefault;
|
||||
} else if (nsCRT::strcasecmp(equal + 1, "yes") == 0) {
|
||||
found = 1;
|
||||
} else {
|
||||
found = atoi(equal + 1);
|
||||
}
|
||||
else {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (equal) {
|
||||
*equal = '=';
|
||||
}
|
||||
if (comma) {
|
||||
*comma = ',';
|
||||
}
|
||||
if (found || !comma) {
|
||||
break;
|
||||
}
|
||||
options = comma + 1;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
already_AddRefed<BrowsingContext> nsWindowWatcher::GetBrowsingContextByName(
|
||||
const nsAString& aName, bool aForceNoOpener,
|
||||
BrowsingContext* aCurrentContext) {
|
||||
|
@ -2019,148 +2080,70 @@ already_AddRefed<BrowsingContext> nsWindowWatcher::GetBrowsingContextByName(
|
|||
}
|
||||
|
||||
// static
|
||||
void nsWindowWatcher::CalcSizeSpec(const WindowFeatures& aFeatures,
|
||||
void nsWindowWatcher::CalcSizeSpec(const nsACString& aFeatures,
|
||||
SizeSpec& aResult) {
|
||||
// https://drafts.csswg.org/cssom-view/#set-up-browsing-context-features
|
||||
// To set up browsing context features for a browsing context `target` given
|
||||
// a map `tokenizedFeatures`:
|
||||
// Parse position spec, if any, from aFeatures
|
||||
bool present;
|
||||
int32_t temp;
|
||||
|
||||
// Step 1. Let `x` be null.
|
||||
// (implicit)
|
||||
|
||||
// Step 2. Let `y` be null.
|
||||
// (implicit)
|
||||
|
||||
// Step 3. Let `width` be null.
|
||||
// (implicit)
|
||||
|
||||
// Step 4. Let `height` be null.
|
||||
// (implicit)
|
||||
|
||||
// Step 5. If `tokenizedFeatures["left"]` exists:
|
||||
if (aFeatures.Exists("left")) {
|
||||
// Step 5.1. Set `x` to the result of invoking the rules for parsing
|
||||
// integers on `tokenizedFeatures["left"]`.
|
||||
//
|
||||
// Step 5.2. If `x` is an error, set `x` to 0.
|
||||
int32_t x = aFeatures.GetInt("left");
|
||||
|
||||
// Step 5.3. Optionally, clamp `x` in a user-agent-defined manner so that
|
||||
// the window does not move outside the Web-exposed available screen area.
|
||||
// (done later)
|
||||
|
||||
// Step 5.4. Optionally, move `target`’s window such that the window’s
|
||||
// left edge is at the horizontal coordinate `x` relative to the left edge
|
||||
// of the Web-exposed screen area, measured in CSS pixels of target.
|
||||
// The positive axis is rightward.
|
||||
aResult.mLeft = x;
|
||||
aResult.mLeftSpecified = true;
|
||||
present = false;
|
||||
if ((temp = WinHasOption(aFeatures, "left", 0, &present)) || present) {
|
||||
aResult.mLeft = temp;
|
||||
} else if ((temp = WinHasOption(aFeatures, "screenX", 0, &present)) ||
|
||||
present) {
|
||||
aResult.mLeft = temp;
|
||||
}
|
||||
aResult.mLeftSpecified = present;
|
||||
|
||||
// Step 6. If `tokenizedFeatures["top"]` exists:
|
||||
if (aFeatures.Exists("top")) {
|
||||
// Step 6.1. Set `y` to the result of invoking the rules for parsing
|
||||
// integers on `tokenizedFeatures["top"]`.
|
||||
//
|
||||
// Step 6.2. If `y` is an error, set `y` to 0.
|
||||
int32_t y = aFeatures.GetInt("top");
|
||||
|
||||
// Step 6.3. Optionally, clamp `y` in a user-agent-defined manner so that
|
||||
// the window does not move outside the Web-exposed available screen area.
|
||||
// (done later)
|
||||
|
||||
// Step 6.4. Optionally, move `target`’s window such that the window’s top
|
||||
// edge is at the vertical coordinate `y` relative to the top edge of the
|
||||
// Web-exposed screen area, measured in CSS pixels of target. The positive
|
||||
// axis is downward.
|
||||
aResult.mTop = y;
|
||||
aResult.mTopSpecified = true;
|
||||
present = false;
|
||||
if ((temp = WinHasOption(aFeatures, "top", 0, &present)) || present) {
|
||||
aResult.mTop = temp;
|
||||
} else if ((temp = WinHasOption(aFeatures, "screenY", 0, &present)) ||
|
||||
present) {
|
||||
aResult.mTop = temp;
|
||||
}
|
||||
aResult.mTopSpecified = present;
|
||||
|
||||
// Non-standard extension.
|
||||
// See bug 1623826
|
||||
if (aFeatures.Exists("outerwidth")) {
|
||||
int32_t width = aFeatures.GetInt("outerwidth");
|
||||
if (width) {
|
||||
aResult.mOuterWidth = width;
|
||||
aResult.mOuterWidthSpecified = true;
|
||||
// Parse size spec, if any. Chrome size overrides content size.
|
||||
if ((temp = WinHasOption(aFeatures, "outerWidth", INT32_MIN, nullptr))) {
|
||||
if (temp == INT32_MIN) {
|
||||
aResult.mUseDefaultWidth = true;
|
||||
} else {
|
||||
aResult.mOuterWidth = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aResult.mOuterWidthSpecified) {
|
||||
// Step 7. If `tokenizedFeatures["width"]` exists:
|
||||
if (aFeatures.Exists("width")) {
|
||||
// Step 7.1. Set `width` to the result of invoking the rules for parsing
|
||||
// integers on `tokenizedFeatures["width"]`.
|
||||
//
|
||||
// Step 7.2. If `width` is an error, set `width` to 0.
|
||||
int32_t width = aFeatures.GetInt("width");
|
||||
|
||||
// Step 7.3. If `width` is not 0:
|
||||
if (width) {
|
||||
// Step 7.3.1. Optionally, clamp `width` in a user-agent-defined manner
|
||||
// so that the window does not get too small or bigger than the
|
||||
// Web-exposed available screen area.
|
||||
// (done later)
|
||||
|
||||
// Step 7.3.2. Optionally, size `target`’s window by moving its right
|
||||
// edge such that the distance between the left and right edges of the
|
||||
// viewport are `width` CSS pixels of target.
|
||||
aResult.mInnerWidth = width;
|
||||
aResult.mInnerWidthSpecified = true;
|
||||
|
||||
// Step 7.3.3. Optionally, move target’s window in a user-agent-defined
|
||||
// manner so that it does not grow outside the Web-exposed available
|
||||
// screen area.
|
||||
// (done later)
|
||||
}
|
||||
aResult.mOuterWidthSpecified = true;
|
||||
} else if ((temp = WinHasOption(aFeatures, "width", INT32_MIN, nullptr)) ||
|
||||
(temp =
|
||||
WinHasOption(aFeatures, "innerWidth", INT32_MIN, nullptr))) {
|
||||
if (temp == INT32_MIN) {
|
||||
aResult.mUseDefaultWidth = true;
|
||||
} else {
|
||||
aResult.mInnerWidth = temp;
|
||||
}
|
||||
aResult.mInnerWidthSpecified = true;
|
||||
}
|
||||
|
||||
// Non-standard extension.
|
||||
// See bug 1623826
|
||||
if (aFeatures.Exists("outerheight")) {
|
||||
int32_t height = aFeatures.GetInt("outerheight");
|
||||
if (height) {
|
||||
aResult.mOuterHeight = height;
|
||||
aResult.mOuterHeightSpecified = true;
|
||||
if ((temp = WinHasOption(aFeatures, "outerHeight", INT32_MIN, nullptr))) {
|
||||
if (temp == INT32_MIN) {
|
||||
aResult.mUseDefaultHeight = true;
|
||||
} else {
|
||||
aResult.mOuterHeight = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aResult.mOuterHeightSpecified) {
|
||||
// Step 8. If `tokenizedFeatures["height"]` exists:
|
||||
if (aFeatures.Exists("height")) {
|
||||
// Step 8.1. Set `height` to the result of invoking the rules for parsing
|
||||
// integers on `tokenizedFeatures["height"]`.
|
||||
//
|
||||
// Step 8.2. If `height` is an error, set `height` to 0.
|
||||
int32_t height = aFeatures.GetInt("height");
|
||||
|
||||
// Step 8.3. If `height` is not 0:
|
||||
if (height) {
|
||||
// Step 8.3.1. Optionally, clamp `height` in a user-agent-defined manner
|
||||
// so that the window does not get too small or bigger than the
|
||||
// Web-exposed available screen area.
|
||||
// (done later)
|
||||
|
||||
// Step 8.3.2. Optionally, size `target`’s window by moving its bottom
|
||||
// edge such that the distance between the top and bottom edges of the
|
||||
// viewport are `height` CSS pixels of target.
|
||||
aResult.mInnerHeight = height;
|
||||
aResult.mInnerHeightSpecified = true;
|
||||
|
||||
// Step 8.3.3. Optionally, move target’s window in a user-agent-defined
|
||||
// manner so that it does not grow outside the Web-exposed available
|
||||
// screen area.
|
||||
// (done later)
|
||||
}
|
||||
aResult.mOuterHeightSpecified = true;
|
||||
} else if ((temp = WinHasOption(aFeatures, "height", INT32_MIN, nullptr)) ||
|
||||
(temp =
|
||||
WinHasOption(aFeatures, "innerHeight", INT32_MIN, nullptr))) {
|
||||
if (temp == INT32_MIN) {
|
||||
aResult.mUseDefaultHeight = true;
|
||||
} else {
|
||||
aResult.mInnerHeight = temp;
|
||||
}
|
||||
aResult.mInnerHeightSpecified = true;
|
||||
}
|
||||
|
||||
// NOTE: The value is handled only on chrome-priv code.
|
||||
// See nsWindowWatcher::SizeOpenedWindow.
|
||||
aResult.mLockAspectRatio =
|
||||
aFeatures.GetBoolWithDefault("lockaspectratio", false);
|
||||
if (WinHasOption(aFeatures, "lockaspectratio", 0, nullptr)) {
|
||||
aResult.mLockAspectRatio = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Size and position a new window according to aSizeSpec. This method
|
||||
|
@ -2250,18 +2233,30 @@ void nsWindowWatcher::SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner,
|
|||
|
||||
// Set up width
|
||||
if (aSizeSpec.mOuterWidthSpecified) {
|
||||
width = NSToIntRound(aSizeSpec.mOuterWidth * openerZoom);
|
||||
if (!aSizeSpec.mUseDefaultWidth) {
|
||||
width = NSToIntRound(aSizeSpec.mOuterWidth * openerZoom);
|
||||
} // Else specified to default; just use our existing width
|
||||
} else if (aSizeSpec.mInnerWidthSpecified) {
|
||||
sizeChromeWidth = false;
|
||||
width = NSToIntRound(aSizeSpec.mInnerWidth * openerZoom);
|
||||
if (aSizeSpec.mUseDefaultWidth) {
|
||||
width = width - chromeWidth;
|
||||
} else {
|
||||
width = NSToIntRound(aSizeSpec.mInnerWidth * openerZoom);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up height
|
||||
if (aSizeSpec.mOuterHeightSpecified) {
|
||||
height = NSToIntRound(aSizeSpec.mOuterHeight * openerZoom);
|
||||
if (!aSizeSpec.mUseDefaultHeight) {
|
||||
height = NSToIntRound(aSizeSpec.mOuterHeight * openerZoom);
|
||||
} // Else specified to default; just use our existing height
|
||||
} else if (aSizeSpec.mInnerHeightSpecified) {
|
||||
sizeChromeHeight = false;
|
||||
height = NSToIntRound(aSizeSpec.mInnerHeight * openerZoom);
|
||||
if (aSizeSpec.mUseDefaultHeight) {
|
||||
height = height - chromeHeight;
|
||||
} else {
|
||||
height = NSToIntRound(aSizeSpec.mInnerHeight * openerZoom);
|
||||
}
|
||||
}
|
||||
|
||||
bool positionSpecified = aSizeSpec.PositionSpecified();
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "nsIRemoteTab.h"
|
||||
#include "nsPIWindowWatcher.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/dom/WindowFeatures.h" // mozilla::dom::WindowFeatures
|
||||
|
||||
class nsIURI;
|
||||
class nsIDocShellTreeItem;
|
||||
|
@ -87,20 +86,23 @@ class nsWindowWatcher : public nsIWindowWatcher,
|
|||
static nsresult URIfromURL(const char* aURL, mozIDOMWindowProxy* aParent,
|
||||
nsIURI** aURI);
|
||||
|
||||
static bool ShouldOpenPopup(const mozilla::dom::WindowFeatures& aFeatures,
|
||||
static bool ShouldOpenPopup(const nsACString& aFeatures,
|
||||
const SizeSpec& aSizeSpec);
|
||||
|
||||
static uint32_t CalculateChromeFlagsForChild(
|
||||
const mozilla::dom::WindowFeatures& aFeatures, const SizeSpec& aSizeSpec);
|
||||
static uint32_t CalculateChromeFlagsForChild(const nsACString& aFeaturesStr,
|
||||
const SizeSpec& aSizeSpec);
|
||||
|
||||
static uint32_t CalculateChromeFlagsForParent(
|
||||
mozIDOMWindowProxy* aParent,
|
||||
const mozilla::dom::WindowFeatures& aFeatures, const SizeSpec& aSizeSpec,
|
||||
bool aDialog, bool aChromeURL, bool aHasChromeParent, bool aCalledFromJS);
|
||||
static uint32_t CalculateChromeFlagsForParent(mozIDOMWindowProxy* aParent,
|
||||
const nsACString& aFeaturesStr,
|
||||
const SizeSpec& aSizeSpec,
|
||||
bool aDialog, bool aChromeURL,
|
||||
bool aHasChromeParent,
|
||||
bool aCalledFromJS);
|
||||
|
||||
static int32_t WinHasOption(const nsACString& aOptions, const char* aName,
|
||||
int32_t aDefault, bool* aPresenceFlag);
|
||||
/* Compute the right SizeSpec based on aFeatures */
|
||||
static void CalcSizeSpec(const mozilla::dom::WindowFeatures& aFeatures,
|
||||
SizeSpec& aResult);
|
||||
static void CalcSizeSpec(const nsACString& aFeatures, SizeSpec& aResult);
|
||||
static void SizeOpenedWindow(
|
||||
nsIDocShellTreeOwner* aTreeOwner, mozIDOMWindowProxy* aParent,
|
||||
bool aIsCallerChrome, const SizeSpec& aSizeSpec,
|
||||
|
@ -111,18 +113,20 @@ class nsWindowWatcher : public nsIWindowWatcher,
|
|||
nsIDocShellTreeOwner** aResult);
|
||||
|
||||
private:
|
||||
nsresult CreateChromeWindow(nsIWebBrowserChrome* aParentChrome,
|
||||
nsresult CreateChromeWindow(const nsACString& aFeatures,
|
||||
nsIWebBrowserChrome* aParentChrome,
|
||||
uint32_t aChromeFlags,
|
||||
nsIOpenWindowInfo* aOpenWindowInfo,
|
||||
nsIWebBrowserChrome** aResult);
|
||||
|
||||
void MaybeDisablePersistence(const SizeSpec& sizeSpec,
|
||||
void MaybeDisablePersistence(const nsACString& aFeatures,
|
||||
nsIDocShellTreeOwner* aTreeOwner);
|
||||
|
||||
static uint32_t CalculateChromeFlagsHelper(
|
||||
uint32_t aInitialFlags, const mozilla::dom::WindowFeatures& aFeatures,
|
||||
const SizeSpec& aSizeSpec, bool* presenceFlag = nullptr,
|
||||
bool aHasChromeParent = false);
|
||||
static uint32_t CalculateChromeFlagsHelper(uint32_t aInitialFlags,
|
||||
const nsACString& aFeatures,
|
||||
const SizeSpec& aSizeSpec,
|
||||
bool& presenceFlag,
|
||||
bool aHasChromeParent = false);
|
||||
static uint32_t EnsureFlagsSafeForContent(uint32_t aChromeFlags,
|
||||
bool aChromeURL = false);
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ EXPORTS += [
|
|||
'nsTLiteralString.h',
|
||||
'nsTPromiseFlatString.h',
|
||||
'nsTString.h',
|
||||
'nsTStringHasher.h',
|
||||
'nsTStringRepr.h',
|
||||
'nsTSubstring.h',
|
||||
'nsTSubstringTuple.h',
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/* -*- 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 nsTStringHasher_h___
|
||||
#define nsTStringHasher_h___
|
||||
|
||||
#include "mozilla/HashTable.h" // mozilla::{DefaultHasher, HashNumber, HashString}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename T>
|
||||
struct DefaultHasher<nsTString<T>> {
|
||||
using Key = nsTString<T>;
|
||||
using Lookup = nsTString<T>;
|
||||
|
||||
static mozilla::HashNumber hash(const Lookup& aLookup) {
|
||||
return mozilla::HashString(aLookup.get());
|
||||
}
|
||||
|
||||
static bool match(const Key& aKey, const Lookup& aLookup) {
|
||||
return aKey.Equals(aLookup);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // !defined(nsTStringHasher_h___)
|
Загрузка…
Ссылка в новой задаче