зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to autoland a=merge CLOSED TREE
MozReview-Commit-ID: Ko3lhAvzMJN
This commit is contained in:
Коммит
db7d003ae0
|
@ -95,7 +95,7 @@
|
|||
#endif
|
||||
|
||||
<html:link rel="shortcut icon"
|
||||
href="chrome://browser/skin/preferences/in-content-new/favicon.ico"/>
|
||||
href="chrome://browser/skin/settings.svg"/>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/utilityOverlay.js"/>
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
#endif
|
||||
|
||||
<html:link rel="shortcut icon"
|
||||
href="chrome://browser/skin/preferences/in-content/favicon.ico"/>
|
||||
href="chrome://browser/skin/settings.svg"/>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/utilityOverlay.js"/>
|
||||
|
|
|
@ -7,9 +7,7 @@ MOZ_AUTOMATION_L10N_CHECK=0
|
|||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-dmd
|
||||
|
||||
# Disable stylo until bug 1356926 is fixed and we have >= llvm39 on centos.
|
||||
ac_add_options --disable-stylo
|
||||
unset LLVM_CONFIG
|
||||
. $topsrcdir/build/mozconfig.stylo
|
||||
|
||||
# Use Clang as specified in manifest
|
||||
export CC="$topsrcdir/clang/bin/clang"
|
||||
|
|
|
@ -6,9 +6,7 @@ MOZ_AUTOMATION_L10N_CHECK=0
|
|||
|
||||
ac_add_options --enable-dmd
|
||||
|
||||
# Disable stylo until bug 1356926 is fixed and we have >= llvm39 on centos.
|
||||
ac_add_options --disable-stylo
|
||||
unset LLVM_CONFIG
|
||||
. $topsrcdir/build/mozconfig.stylo
|
||||
|
||||
# Use Clang as specified in manifest
|
||||
CC="$topsrcdir/clang/bin/clang"
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
[
|
||||
{
|
||||
"version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
|
||||
"size": 161014632,
|
||||
"digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12072532,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
[
|
||||
{
|
||||
"size": 12072532,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
|
||||
"size": 161014632,
|
||||
"digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -1,26 +0,0 @@
|
|||
[
|
||||
{
|
||||
"version": "clang 3.8.0, libgcc 4.8.5",
|
||||
"size": 140319580,
|
||||
"digest": "34e219d7e8eaffa81710631c34d21355563d06335b3c00851e94c1f42f9098788fded8463dd0f67dd699f77b47a0245dd7aff754943a7a03fb5fd145a808254f",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12072532,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
|
||||
"size": 161014632,
|
||||
"digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
[
|
||||
{
|
||||
"version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
|
||||
"size": 161014632,
|
||||
"digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12072532,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
[
|
||||
{
|
||||
"version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
|
||||
"size": 161014632,
|
||||
"digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12072532,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -34,6 +34,14 @@
|
|||
background: none;
|
||||
}
|
||||
|
||||
/* Keyboard focus styling */
|
||||
#onboarding-overlay-button:-moz-focusring {
|
||||
outline: solid 2px rgba(0, 0, 0, 0.1);
|
||||
-moz-outline-radius: 5px;
|
||||
outline-offset: 5px;
|
||||
transition: outline-offset 150ms;
|
||||
}
|
||||
|
||||
#onboarding-overlay-button-icon {
|
||||
width: 36px;
|
||||
vertical-align: top;
|
||||
|
@ -308,7 +316,8 @@
|
|||
}
|
||||
|
||||
/* Remove default dotted outline around buttons' text */
|
||||
.onboarding-tour-action-button::-moz-focus-inner {
|
||||
.onboarding-tour-action-button::-moz-focus-inner,
|
||||
#onboarding-overlay-button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,13 +394,14 @@ class Onboarding {
|
|||
this._tourItems = [];
|
||||
this._tourPages = [];
|
||||
|
||||
let { body } = this._window.document;
|
||||
this._overlayIcon = this._renderOverlayButton();
|
||||
this._overlayIcon.addEventListener("click", this);
|
||||
this._window.document.body.appendChild(this._overlayIcon);
|
||||
body.insertBefore(this._overlayIcon, body.firstChild);
|
||||
|
||||
this._overlay = this._renderOverlay();
|
||||
this._overlay.addEventListener("click", this);
|
||||
this._window.document.body.appendChild(this._overlay);
|
||||
body.appendChild(this._overlay);
|
||||
|
||||
this._loadJS(TOUR_AGENT_JS_URI);
|
||||
|
||||
|
@ -827,8 +828,11 @@ class Onboarding {
|
|||
let tooltip = this._bundle.formatStringFromName(tooltipStringId, [BRAND_SHORT_NAME], 1);
|
||||
button.setAttribute("aria-label", tooltip);
|
||||
button.id = "onboarding-overlay-button";
|
||||
button.setAttribute("aria-haspopup", true);
|
||||
button.setAttribute("aria-controls", "onboarding-overlay-dialog");
|
||||
let img = this._window.document.createElement("img");
|
||||
img.id = "onboarding-overlay-button-icon";
|
||||
img.setAttribute("role", "presentation");
|
||||
img.src = "resource://onboarding/img/overlay-icon.svg";
|
||||
button.appendChild(img);
|
||||
return button;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_onboarding_accessibility.js]
|
||||
[browser_onboarding_notification.js]
|
||||
[browser_onboarding_notification_2.js]
|
||||
[browser_onboarding_notification_3.js]
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_onboarding_overlay_button() {
|
||||
resetOnboardingDefaultState();
|
||||
|
||||
info("Wait for onboarding overlay loaded");
|
||||
let tab = await openTab(ABOUT_HOME_URL);
|
||||
await promiseOnboardingOverlayLoaded(tab.linkedBrowser);
|
||||
|
||||
info("Test accessibility and semantics of the overlay button");
|
||||
await ContentTask.spawn(tab.linkedBrowser, {}, function() {
|
||||
let doc = content.document;
|
||||
let button = doc.body.firstChild;
|
||||
is(button.id, "onboarding-overlay-button",
|
||||
"First child is an overlay button");
|
||||
ok(button.getAttribute("aria-label"),
|
||||
"Onboarding button has an accessible label");
|
||||
is(button.getAttribute("aria-haspopup"), "true",
|
||||
"Onboarding button should indicate that it triggers a popup");
|
||||
is(button.getAttribute("aria-controls"), "onboarding-overlay-dialog",
|
||||
"Onboarding button semantically controls an overlay dialog");
|
||||
is(button.firstChild.getAttribute("role"), "presentation",
|
||||
"Onboarding button icon should have presentation only semantics");
|
||||
});
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
|
@ -31,13 +31,11 @@ browser/chrome/browser/content/browser/preferences/in-content-new/security.js
|
|||
browser/chrome/browser/content/browser/preferences/in-content-new/sync.js
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content/search.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content/containers.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content/favicon.ico
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content/icons.svg
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content/preferences.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content/dialog.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content-new/search.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content-new/containers.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content-new/favicon.ico
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content-new/icons.svg
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content-new/preferences.css
|
||||
browser/chrome/browser/skin/classic/browser/preferences/in-content-new/dialog.css
|
||||
|
|
Двоичные данные
browser/themes/shared/incontentprefs-old/favicon.ico
Двоичные данные
browser/themes/shared/incontentprefs-old/favicon.ico
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 933 B |
Двоичные данные
browser/themes/shared/incontentprefs/favicon.ico
Двоичные данные
browser/themes/shared/incontentprefs/favicon.ico
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 933 B |
|
@ -95,13 +95,11 @@
|
|||
skin/classic/browser/panel-icon-magnifier.svg (../shared/panel-icon-magnifier.svg)
|
||||
#endif
|
||||
skin/classic/browser/panel-icon-retry.svg (../shared/panel-icon-retry.svg)
|
||||
skin/classic/browser/preferences/in-content-new/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||
skin/classic/browser/preferences/in-content-new/icons.svg (../shared/incontentprefs/icons.svg)
|
||||
skin/classic/browser/preferences/in-content-new/search-arrow-indicator.svg (../shared/incontentprefs/search-arrow-indicator.svg)
|
||||
skin/classic/browser/preferences/in-content-new/search.css (../shared/incontentprefs/search.css)
|
||||
skin/classic/browser/preferences/in-content-new/siteDataSettings.css (../shared/incontentprefs/siteDataSettings.css)
|
||||
* skin/classic/browser/preferences/in-content-new/containers.css (../shared/incontentprefs/containers.css)
|
||||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs-old/favicon.ico)
|
||||
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs-old/icons.svg)
|
||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs-old/search.css)
|
||||
* skin/classic/browser/preferences/in-content/containers.css (../shared/incontentprefs-old/containers.css)
|
||||
|
|
|
@ -77,6 +77,11 @@
|
|||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
}
|
||||
|
||||
.tab-icon-image[src^="chrome://"] {
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.tab-icon-image[sharing]:not([selected]),
|
||||
.tab-sharing-icon-overlay {
|
||||
animation: 3s linear tab-sharing-icon-pulse infinite;
|
||||
|
|
|
@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = ["Tabs"];
|
|||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const CUST_TAB = "chrome://browser/skin/customizableui/customizeFavicon.ico";
|
||||
const PREFS_TAB = "chrome://browser/skin/preferences/in-content-new/favicon.ico";
|
||||
const PREFS_TAB = "chrome://browser/skin/settings.svg";
|
||||
const DEFAULT_FAVICON_TAB = `data:text/html,<meta charset="utf-8">
|
||||
<title>No favicon</title>`;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ This file adds the necessary compatibility tricks to avoid symbols with
|
|||
version GLIBCXX_3.4.16 and bigger, keeping binary compatibility with
|
||||
libstdc++ 4.6.1.
|
||||
|
||||
WARNING: all symbols from this file must be defined weak.
|
||||
*/
|
||||
|
||||
#define GLIBCXX_VERSION(a, b, c) (((a) << 16) | ((b) << 8) | (c))
|
||||
|
@ -39,7 +40,7 @@ libstdc++ 4.6.1.
|
|||
#include <tr1/unordered_map>
|
||||
namespace std
|
||||
{
|
||||
size_t
|
||||
size_t __attribute__((weak))
|
||||
__detail::_Prime_rehash_policy::_M_next_bkt(size_t __n) const
|
||||
{
|
||||
tr1::__detail::_Prime_rehash_policy policy(_M_max_load_factor);
|
||||
|
@ -48,7 +49,7 @@ namespace std
|
|||
return ret;
|
||||
}
|
||||
|
||||
pair<bool, size_t>
|
||||
pair<bool, size_t> __attribute__((weak))
|
||||
__detail::_Prime_rehash_policy::_M_need_rehash(size_t __n_bkt,
|
||||
size_t __n_elt,
|
||||
size_t __n_ins) const
|
||||
|
@ -67,7 +68,7 @@ namespace std {
|
|||
|
||||
/* We shouldn't be throwing exceptions at all, but it sadly turns out
|
||||
we call STL (inline) functions that do. */
|
||||
void __throw_out_of_range_fmt(char const* fmt, ...)
|
||||
void __attribute__((weak)) __throw_out_of_range_fmt(char const* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024]; // That should be big enough.
|
||||
|
@ -87,7 +88,7 @@ namespace std {
|
|||
/* Technically, this symbol is not in GLIBCXX_3.4.20, but in CXXABI_1.3.8,
|
||||
but that's equivalent, version-wise. Those calls are added by the compiler
|
||||
itself on `new Class[n]` calls. */
|
||||
extern "C" void
|
||||
extern "C" void __attribute__((weak))
|
||||
__cxa_throw_bad_array_new_length()
|
||||
{
|
||||
MOZ_CRASH();
|
||||
|
@ -100,7 +101,7 @@ __cxa_throw_bad_array_new_length()
|
|||
* char const* argument. Older versions only have a constructor with
|
||||
* std::string. */
|
||||
namespace std {
|
||||
runtime_error::runtime_error(char const* s)
|
||||
__attribute__((weak)) runtime_error::runtime_error(char const* s)
|
||||
: runtime_error(std::string(s))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -445,7 +445,7 @@ skip-if = e10s && debug
|
|||
[browser_dbg_watch-expressions-02.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_worker-console-01.js]
|
||||
skip-if = e10s && debug
|
||||
skip-if = true # bug 1368569
|
||||
[browser_dbg_worker-console-02.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_worker-console-03.js]
|
||||
|
|
|
@ -44,4 +44,4 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
|||
subsuite = clipboard
|
||||
skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
|
||||
[browser_computed_style-editor-link.js]
|
||||
skip-if = os == 'mac' # bug 1307846
|
||||
skip-if = true # bug 1307846
|
||||
|
|
|
@ -270,7 +270,7 @@ skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
|||
[browser_rules_strict-search-filter_02.js]
|
||||
[browser_rules_strict-search-filter_03.js]
|
||||
[browser_rules_style-editor-link.js]
|
||||
skip-if = !debug # Bug 1309759
|
||||
skip-if = true # Bug 1309759
|
||||
[browser_rules_url-click-opens-new-tab.js]
|
||||
[browser_rules_urls-clickable.js]
|
||||
[browser_rules_user-agent-styles.js]
|
||||
|
|
|
@ -8631,6 +8631,12 @@ private:
|
|||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
nsDocShell::SandboxFlagsImplyCookies(const uint32_t &aSandboxFlags)
|
||||
{
|
||||
return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::RestoreFromHistory()
|
||||
{
|
||||
|
@ -9291,6 +9297,9 @@ nsDocShell::CreateContentViewer(const nsACString& aContentType,
|
|||
// Mark the channel as being a document URI...
|
||||
aOpenedChannel->GetLoadFlags(&loadFlags);
|
||||
loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
|
||||
if (SandboxFlagsImplyCookies(mSandboxFlags)) {
|
||||
loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
|
||||
}
|
||||
|
||||
aOpenedChannel->SetLoadFlags(loadFlags);
|
||||
|
||||
|
@ -11507,6 +11516,9 @@ nsDocShell::DoChannelLoad(nsIChannel* aChannel,
|
|||
loadFlags |= nsIChannel::LOAD_DOCUMENT_URI |
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS;
|
||||
|
||||
if (SandboxFlagsImplyCookies(mSandboxFlags)) {
|
||||
loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
|
||||
}
|
||||
// Load attributes depend on load type...
|
||||
switch (mLoadType) {
|
||||
case LOAD_HISTORY: {
|
||||
|
|
|
@ -257,6 +257,8 @@ public:
|
|||
|
||||
friend class OnLinkClickEvent;
|
||||
|
||||
static bool SandboxFlagsImplyCookies(const uint32_t &aSandboxFlags);
|
||||
|
||||
// We need dummy OnLocationChange in some cases to update the UI without
|
||||
// updating security info.
|
||||
void FireDummyOnLocationChange()
|
||||
|
|
|
@ -132,48 +132,6 @@ ToChar(SelectionType aSelectionType)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
IsValidSelectionType(RawSelectionType aRawSelectionType)
|
||||
{
|
||||
switch (static_cast<SelectionType>(aRawSelectionType)) {
|
||||
case SelectionType::eNone:
|
||||
case SelectionType::eNormal:
|
||||
case SelectionType::eSpellCheck:
|
||||
case SelectionType::eIMERawClause:
|
||||
case SelectionType::eIMESelectedRawClause:
|
||||
case SelectionType::eIMEConvertedClause:
|
||||
case SelectionType::eIMESelectedClause:
|
||||
case SelectionType::eAccessibility:
|
||||
case SelectionType::eFind:
|
||||
case SelectionType::eURLSecondary:
|
||||
case SelectionType::eURLStrikeout:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SelectionType
|
||||
ToSelectionType(RawSelectionType aRawSelectionType)
|
||||
{
|
||||
if (!IsValidSelectionType(aRawSelectionType)) {
|
||||
return SelectionType::eInvalid;
|
||||
}
|
||||
return static_cast<SelectionType>(aRawSelectionType);
|
||||
}
|
||||
|
||||
RawSelectionType
|
||||
ToRawSelectionType(SelectionType aSelectionType)
|
||||
{
|
||||
return static_cast<RawSelectionType>(aSelectionType);
|
||||
}
|
||||
|
||||
bool operator &(SelectionType aSelectionType,
|
||||
RawSelectionType aRawSelectionTypes)
|
||||
{
|
||||
return (ToRawSelectionType(aSelectionType) & aRawSelectionTypes) != 0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
//#define DEBUG_SELECTION // uncomment for printf describing every collapse and extend.
|
||||
|
|
|
@ -73,8 +73,6 @@ public:
|
|||
NS_DECL_NSISELECTION
|
||||
NS_DECL_NSISELECTIONPRIVATE
|
||||
|
||||
virtual Selection* AsSelection() override { return this; }
|
||||
|
||||
nsresult EndBatchChangesInternal(int16_t aReason = nsISelectionListener::NO_REASON);
|
||||
|
||||
nsIDocument* GetParentObject() const;
|
||||
|
@ -520,6 +518,60 @@ public:
|
|||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
inline bool
|
||||
IsValidSelectionType(RawSelectionType aRawSelectionType)
|
||||
{
|
||||
switch (static_cast<SelectionType>(aRawSelectionType)) {
|
||||
case SelectionType::eNone:
|
||||
case SelectionType::eNormal:
|
||||
case SelectionType::eSpellCheck:
|
||||
case SelectionType::eIMERawClause:
|
||||
case SelectionType::eIMESelectedRawClause:
|
||||
case SelectionType::eIMEConvertedClause:
|
||||
case SelectionType::eIMESelectedClause:
|
||||
case SelectionType::eAccessibility:
|
||||
case SelectionType::eFind:
|
||||
case SelectionType::eURLSecondary:
|
||||
case SelectionType::eURLStrikeout:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline SelectionType
|
||||
ToSelectionType(RawSelectionType aRawSelectionType)
|
||||
{
|
||||
if (!IsValidSelectionType(aRawSelectionType)) {
|
||||
return SelectionType::eInvalid;
|
||||
}
|
||||
return static_cast<SelectionType>(aRawSelectionType);
|
||||
}
|
||||
|
||||
inline RawSelectionType
|
||||
ToRawSelectionType(SelectionType aSelectionType)
|
||||
{
|
||||
return static_cast<RawSelectionType>(aSelectionType);
|
||||
}
|
||||
|
||||
inline RawSelectionType ToRawSelectionType(TextRangeType aTextRangeType)
|
||||
{
|
||||
return ToRawSelectionType(ToSelectionType(aTextRangeType));
|
||||
}
|
||||
|
||||
inline bool operator &(SelectionType aSelectionType,
|
||||
RawSelectionType aRawSelectionTypes)
|
||||
{
|
||||
return (ToRawSelectionType(aSelectionType) & aRawSelectionTypes) != 0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
inline mozilla::dom::Selection*
|
||||
nsISelection::AsSelection()
|
||||
{
|
||||
return static_cast<mozilla::dom::Selection*>(this);
|
||||
}
|
||||
|
||||
#endif // mozilla_Selection_h__
|
||||
|
|
|
@ -2476,6 +2476,17 @@ WarnIfSandboxIneffective(nsIDocShell* aDocShell,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsSynthesized() {
|
||||
nsCOMPtr<nsIHttpChannelInternal> internalChan = do_QueryInterface(mChannel);
|
||||
bool synthesized = false;
|
||||
if (internalChan) {
|
||||
DebugOnly<nsresult> rv = internalChan->GetResponseSynthesized(&synthesized);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "GetResponseSynthesized shouldn't fail.");
|
||||
}
|
||||
return synthesized;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
|
@ -2546,6 +2557,19 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
|||
}
|
||||
}
|
||||
|
||||
if (mChannel) {
|
||||
nsLoadFlags loadFlags;
|
||||
mChannel->GetLoadFlags(&loadFlags);
|
||||
bool isDocument = false;
|
||||
mChannel->GetIsDocument(&isDocument);
|
||||
if (loadFlags & nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE &&
|
||||
isDocument &&
|
||||
IsSynthesized() &&
|
||||
XRE_IsContentProcess()) {
|
||||
ContentChild::UpdateCookieStatus(mChannel);
|
||||
}
|
||||
}
|
||||
|
||||
// If this document is being loaded by a docshell, copy its sandbox flags
|
||||
// to the document, and store the fullscreen enabled flag. These are
|
||||
// immutable after being set here.
|
||||
|
@ -8280,7 +8304,11 @@ nsDocument::AddToRadioGroup(const nsAString& aName,
|
|||
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements");
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(element);
|
||||
NS_ASSERTION(input, "radio controls have to be input elements!");
|
||||
|
||||
if (input->IsRequired()) {
|
||||
radioGroup->mRequiredRadioCount++;
|
||||
}
|
||||
}
|
||||
|
@ -8294,7 +8322,11 @@ nsDocument::RemoveFromRadioGroup(const nsAString& aName,
|
|||
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements");
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(element);
|
||||
NS_ASSERTION(input, "radio controls have to be input elements!");
|
||||
|
||||
if (input->IsRequired()) {
|
||||
NS_ASSERTION(radioGroup->mRequiredRadioCount != 0,
|
||||
"mRequiredRadioCount about to wrap below 0!");
|
||||
radioGroup->mRequiredRadioCount--;
|
||||
|
|
|
@ -667,6 +667,7 @@ public:
|
|||
virtual void ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) override;
|
||||
virtual void UnscheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG) override;
|
||||
virtual void ResolveScheduledSVGPresAttrs() override;
|
||||
bool IsSynthesized();
|
||||
|
||||
private:
|
||||
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
|
||||
|
|
|
@ -161,10 +161,11 @@ interface nsISelection : nsISupports
|
|||
|
||||
%{C++
|
||||
/**
|
||||
* AsSelection() returns a pointer to Selection class if the instance is
|
||||
* derived from it. Otherwise, nullptr but it should never happen
|
||||
* since Selection is the only class implementing nsISelection.
|
||||
* AsSelection() returns a pointer to Selection class.
|
||||
*
|
||||
* In order to avoid circular dependency issues, this method is defined
|
||||
* in mozilla/dom/Selection.h. Consumers need to #include that header.
|
||||
*/
|
||||
virtual mozilla::dom::Selection* AsSelection() = 0;
|
||||
inline mozilla::dom::Selection* AsSelection();
|
||||
%}
|
||||
};
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
%{C++
|
||||
typedef short SelectionRegion;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Selection;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
%}
|
||||
|
||||
interface nsIContent;
|
||||
|
@ -15,6 +20,8 @@ interface nsIDOMNode;
|
|||
interface nsISelection;
|
||||
interface nsISelectionDisplay;
|
||||
|
||||
[ptr] native SelectionPtr(mozilla::dom::Selection);
|
||||
|
||||
[scriptable, uuid(3801c9d4-8e69-4bfc-9edb-b58278621f8f)]
|
||||
interface nsISelectionController : nsISelectionDisplay
|
||||
{
|
||||
|
@ -64,6 +71,11 @@ interface nsISelectionController : nsISelectionDisplay
|
|||
*/
|
||||
nsISelection getSelection(in short type);
|
||||
|
||||
/**
|
||||
* Return the selection object corresponding to a selection type.
|
||||
*/
|
||||
[noscript,nostdcall,notxpcom] SelectionPtr getDOMSelection(in short aType);
|
||||
|
||||
const short SCROLL_SYNCHRONOUS = 1<<1;
|
||||
const short SCROLL_FIRST_ANCESTOR_ONLY = 1<<2;
|
||||
const short SCROLL_CENTER_VERTICALLY = 1<<4;
|
||||
|
@ -312,11 +324,12 @@ enum : size_t
|
|||
kPresentSelectionTypeCount = kSelectionTypeCount - 1
|
||||
};
|
||||
|
||||
// Please include mozilla/dom/Selection.h for the following APIs.
|
||||
const char* ToChar(SelectionType aSelectionType);
|
||||
SelectionType ToSelectionType(RawSelectionType aRawSelectionType);
|
||||
RawSelectionType ToRawSelectionType(SelectionType aSelectionType);
|
||||
bool operator &(SelectionType aSelectionType,
|
||||
RawSelectionType aRawSelectionTypes);
|
||||
inline SelectionType ToSelectionType(RawSelectionType aRawSelectionType);
|
||||
inline RawSelectionType ToRawSelectionType(SelectionType aSelectionType);
|
||||
inline bool operator &(SelectionType aSelectionType,
|
||||
RawSelectionType aRawSelectionTypes);
|
||||
|
||||
} // namespace mozilla
|
||||
%}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
document.write("<p></p>");
|
||||
parent.done();
|
||||
document.close();
|
|
@ -457,6 +457,7 @@ skip-if = toolkit == 'android' #TIMED_OUT
|
|||
[test_bug514487.html]
|
||||
[test_bug515401.html]
|
||||
[test_bug518104.html]
|
||||
support-files = file_bug518104.js
|
||||
[test_bug527896.html]
|
||||
[test_bug540854.html]
|
||||
[test_bug541937.html]
|
||||
|
|
|
@ -26,9 +26,7 @@ function done() {
|
|||
|
||||
</script>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id='iframe' src="data:text/html,
|
||||
<div></div><div></div>
|
||||
<script defer src='data:application/javascript,document.write(%2522<p></p>%2522);parent.done();document.close();'></script>">
|
||||
<iframe id='iframe' srcdoc="<div></div><div></div><script defer src='file_bug518104.js'></script>">
|
||||
</iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
OLD
|
|
@ -0,0 +1 @@
|
|||
NEW
|
|
@ -25,6 +25,9 @@ skip-if = debug == false
|
|||
[test_bug1041646.html]
|
||||
[test_bug1123875.html]
|
||||
[test_barewordGetsWindow.html]
|
||||
support-files =
|
||||
file_barewordGetsWindow_frame1.html
|
||||
file_barewordGetsWindow_frame2.html
|
||||
[test_callback_across_document_open.html]
|
||||
[test_callback_default_thisval.html]
|
||||
[test_cloneAndImportNode.html]
|
||||
|
|
|
@ -27,20 +27,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=936056
|
|||
var qualifiedFunc = frames[0].eval("(function (count) { var doc; for (var i = 0; i < count; ++i) doc = window.document; return doc.documentElement; })");
|
||||
document.querySelector("iframe").onload = function () {
|
||||
// interp
|
||||
is(barewordFunc(1).textContent, "OLD", "Bareword should see own inner 1");
|
||||
is(qualifiedFunc(1).textContent, "NEW",
|
||||
is(barewordFunc(1).innerText, "OLD", "Bareword should see own inner 1");
|
||||
is(qualifiedFunc(1).innerText, "NEW",
|
||||
"Qualified should see current inner 1");
|
||||
// baseline
|
||||
is(barewordFunc(100).textContent, "OLD", "Bareword should see own inner 2");
|
||||
is(qualifiedFunc(100).textContent, "NEW",
|
||||
is(barewordFunc(100).innerText, "OLD", "Bareword should see own inner 2");
|
||||
is(qualifiedFunc(100).innerText, "NEW",
|
||||
"Qualified should see current inner 2");
|
||||
// ion
|
||||
is(barewordFunc(10000).textContent, "OLD", "Bareword should see own inner 3");
|
||||
is(qualifiedFunc(10000).textContent, "NEW",
|
||||
is(barewordFunc(10000).innerText, "OLD", "Bareword should see own inner 3");
|
||||
is(qualifiedFunc(10000).innerText, "NEW",
|
||||
"Qualified should see current inner 2");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
frames[0].location = "data:text/plain,NEW";
|
||||
frames[0].location = "file_barewordGetsWindow_frame2.html";
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=936056
|
|||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936056">Mozilla Bug 936056</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe src="data:text/plain,OLD"></iframe>
|
||||
<iframe src="file_barewordGetsWindow_frame1.html"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
|
|
@ -47,5 +47,6 @@ function runTest() {
|
|||
|
||||
// Disable third-party cookies for this test.
|
||||
addEventListener('testready', function() {
|
||||
SpecialPowers.pushPrefEnv({'set': [['network.cookie.cookieBehavior', 1]]}, runTest);
|
||||
SpecialPowers.pushPrefEnv({'set': [['network.cookie.cookieBehavior', 1],
|
||||
['network.cookie.ipc.sync', true]]}, runTest);
|
||||
});
|
||||
|
|
|
@ -490,7 +490,7 @@ void
|
|||
EventStateManager::TryToFlushPendingNotificationsToIME()
|
||||
{
|
||||
if (mIMEContentObserver) {
|
||||
mIMEContentObserver->TryToFlushPendingNotifications();
|
||||
mIMEContentObserver->TryToFlushPendingNotifications(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -330,6 +330,8 @@ private:
|
|||
|
||||
#define DISABLED_STATES (NS_EVENT_STATE_DISABLED | NS_EVENT_STATE_ENABLED)
|
||||
|
||||
#define REQUIRED_STATES (NS_EVENT_STATE_REQUIRED | NS_EVENT_STATE_OPTIONAL)
|
||||
|
||||
// Event states that can be added and removed through
|
||||
// Element::{Add,Remove}ManuallyManagedStates.
|
||||
//
|
||||
|
@ -350,6 +352,7 @@ private:
|
|||
MANUALLY_MANAGED_STATES | \
|
||||
DIR_ATTR_STATES | \
|
||||
DISABLED_STATES | \
|
||||
REQUIRED_STATES | \
|
||||
NS_EVENT_STATE_ACTIVE | \
|
||||
NS_EVENT_STATE_DRAGOVER | \
|
||||
NS_EVENT_STATE_FOCUS | \
|
||||
|
|
|
@ -1739,10 +1739,10 @@ IMEContentObserver::FlushMergeableNotifications()
|
|||
}
|
||||
|
||||
void
|
||||
IMEContentObserver::TryToFlushPendingNotifications()
|
||||
IMEContentObserver::TryToFlushPendingNotifications(bool aAllowAsync)
|
||||
{
|
||||
if (!mQueuedSender || mSendingNotification != NOTIFY_IME_OF_NOTHING ||
|
||||
XRE_IsContentProcess()) {
|
||||
(XRE_IsContentProcess() && aAllowAsync)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,9 +155,9 @@ public:
|
|||
* TryToFlushPendingNotifications() should be called when pending events
|
||||
* should be flushed. This tries to run the queued IMENotificationSender.
|
||||
* Doesn't do anything in child processes where flushing happens
|
||||
* asynchronously.
|
||||
* asynchronously unless aAllowAsync is false.
|
||||
*/
|
||||
void TryToFlushPendingNotifications();
|
||||
void TryToFlushPendingNotifications(bool aAllowAsync);
|
||||
|
||||
/**
|
||||
* MaybeNotifyCompositionEventHandled() posts composition event handled
|
||||
|
|
|
@ -652,7 +652,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
|||
(" OnChangeFocusInternal(), an "
|
||||
"IMEContentObserver instance is created for plugin and trying to "
|
||||
"flush its pending notifications..."));
|
||||
sActiveIMEContentObserver->TryToFlushPendingNotifications();
|
||||
sActiveIMEContentObserver->TryToFlushPendingNotifications(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -827,7 +827,7 @@ IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
|
|||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
(" OnFocusInEditor(), new IMEContentObserver is "
|
||||
"created, trying to flush pending notifications..."));
|
||||
sActiveIMEContentObserver->TryToFlushPendingNotifications();
|
||||
sActiveIMEContentObserver->TryToFlushPendingNotifications(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2314,7 +2314,10 @@ HTMLFormElement::AddToRadioGroup(const nsAString& aName,
|
|||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements!");
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(element);
|
||||
NS_ASSERTION(input, "radio controls have to be input elements!");
|
||||
|
||||
if (input->IsRequired()) {
|
||||
auto entry = mRequiredRadioButtonCounts.LookupForAdd(aName);
|
||||
if (!entry) {
|
||||
entry.OrInsert([]() { return 1; });
|
||||
|
@ -2329,9 +2332,12 @@ HTMLFormElement::RemoveFromRadioGroup(const nsAString& aName,
|
|||
nsIFormControl* aRadio)
|
||||
{
|
||||
nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
|
||||
NS_ASSERTION(element, "radio controls have to be content elements!");
|
||||
NS_ASSERTION(element, "radio controls have to be content elements");
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(element);
|
||||
NS_ASSERTION(input, "radio controls have to be input elements!");
|
||||
|
||||
if (input->IsRequired()) {
|
||||
auto entry = mRequiredRadioButtonCounts.Lookup(aName);
|
||||
if (!entry) {
|
||||
MOZ_ASSERT_UNREACHABLE("At least one radio button has to be required!");
|
||||
|
|
|
@ -1453,6 +1453,13 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
UpdateDisabledState(aNotify);
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::required && DoesRequiredApply()) {
|
||||
// This *has* to be called *before* UpdateValueMissingValidityState
|
||||
// because UpdateValueMissingValidityState depends on our required
|
||||
// state.
|
||||
UpdateRequiredState(!!aValue, aNotify);
|
||||
}
|
||||
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
// This *has* to be called *after* validity has changed.
|
||||
|
@ -5005,6 +5012,17 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify)
|
|||
mFocusedValue.Truncate();
|
||||
}
|
||||
|
||||
// Update or clear our required states since we may have changed from a
|
||||
// required input type to a non-required input type or viceversa.
|
||||
if (DoesRequiredApply()) {
|
||||
bool isRequired = HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
||||
UpdateRequiredState(isRequired, aNotify);
|
||||
} else if (aNotify) {
|
||||
RemoveStates(REQUIRED_STATES);
|
||||
} else {
|
||||
RemoveStatesSilently(REQUIRED_STATES);
|
||||
}
|
||||
|
||||
UpdateHasRange();
|
||||
|
||||
// Do not notify, it will be done after if needed.
|
||||
|
@ -6554,12 +6572,6 @@ HTMLInputElement::IntrinsicState() const
|
|||
state |= nsImageLoadingContent::ImageState();
|
||||
}
|
||||
|
||||
if (DoesRequiredApply() && HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
state |= NS_EVENT_STATE_REQUIRED;
|
||||
} else {
|
||||
state |= NS_EVENT_STATE_OPTIONAL;
|
||||
}
|
||||
|
||||
if (IsCandidateForConstraintValidation()) {
|
||||
if (IsValid()) {
|
||||
state |= NS_EVENT_STATE_VALID;
|
||||
|
@ -7232,6 +7244,9 @@ HTMLInputElement::UpdateTooShortValidityState()
|
|||
void
|
||||
HTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
||||
{
|
||||
MOZ_ASSERT(mType == NS_FORM_INPUT_RADIO,
|
||||
"This should be called only for radio input types");
|
||||
|
||||
bool notify = mDoneCreating;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selection = GetSelectedRadioButton();
|
||||
|
||||
|
@ -7240,7 +7255,7 @@ HTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
|||
// If there is no selection, that might mean the radio is not in a group.
|
||||
// In that case, we can look for the checked state of the radio.
|
||||
bool selected = selection || (!aIgnoreSelf && mChecked);
|
||||
bool required = !aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
||||
bool required = !aIgnoreSelf && IsRequired();
|
||||
bool valueMissing = false;
|
||||
|
||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
||||
|
@ -7257,7 +7272,7 @@ HTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
|||
// If the current radio is required and not ignored, we can assume the entire
|
||||
// group is required.
|
||||
if (!required) {
|
||||
required = (aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required))
|
||||
required = (aIgnoreSelf && IsRequired())
|
||||
? container->GetRequiredRadioCount(name) - 1
|
||||
: container->GetRequiredRadioCount(name);
|
||||
}
|
||||
|
|
|
@ -941,6 +941,22 @@ public:
|
|||
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* Returns if the required attribute applies for the current type.
|
||||
*/
|
||||
bool DoesRequiredApply() const;
|
||||
|
||||
/**
|
||||
* Returns the current required state of the element. This function differs
|
||||
* from Required() in that this function only returns true for input types
|
||||
* that @required attribute applies and the attribute is set; in contrast,
|
||||
* Required() returns true whenever @required attribute is set.
|
||||
*/
|
||||
bool IsRequired() const
|
||||
{
|
||||
return State().HasState(NS_EVENT_STATE_REQUIRED);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~HTMLInputElement();
|
||||
|
||||
|
@ -1137,11 +1153,6 @@ protected:
|
|||
*/
|
||||
bool DoesReadOnlyApply() const;
|
||||
|
||||
/**
|
||||
* Returns if the required attribute applies for the current type.
|
||||
*/
|
||||
bool DoesRequiredApply() const;
|
||||
|
||||
/**
|
||||
* Returns if the min and max attributes apply for the current type.
|
||||
*/
|
||||
|
|
|
@ -1088,7 +1088,7 @@ HTMLSelectElement::IsOptionDisabled(int32_t aIndex, bool* aIsDisabled)
|
|||
}
|
||||
|
||||
bool
|
||||
HTMLSelectElement::IsOptionDisabled(HTMLOptionElement* aOption)
|
||||
HTMLSelectElement::IsOptionDisabled(HTMLOptionElement* aOption) const
|
||||
{
|
||||
MOZ_ASSERT(aOption);
|
||||
if (aOption->Disabled()) {
|
||||
|
@ -1333,6 +1333,11 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
UpdateValueMissingValidityState();
|
||||
UpdateBarredFromConstraintValidation();
|
||||
} else if (aName == nsGkAtoms::required) {
|
||||
// This *has* to be called *before* UpdateValueMissingValidityState
|
||||
// because UpdateValueMissingValidityState depends on our required
|
||||
// state.
|
||||
UpdateRequiredState(!!aValue, aNotify);
|
||||
|
||||
UpdateValueMissingValidityState();
|
||||
} else if (aName == nsGkAtoms::autocomplete) {
|
||||
// Clear the cached @autocomplete attribute and autocompleteInfo state.
|
||||
|
@ -1530,12 +1535,6 @@ HTMLSelectElement::IntrinsicState() const
|
|||
}
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
state |= NS_EVENT_STATE_REQUIRED;
|
||||
} else {
|
||||
state |= NS_EVENT_STATE_OPTIONAL;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -1781,7 +1780,7 @@ HTMLSelectElement::RebuildOptionsArray(bool aNotify)
|
|||
}
|
||||
|
||||
bool
|
||||
HTMLSelectElement::IsValueMissing()
|
||||
HTMLSelectElement::IsValueMissing() const
|
||||
{
|
||||
if (!Required()) {
|
||||
return false;
|
||||
|
|
|
@ -211,7 +211,7 @@ public:
|
|||
}
|
||||
bool Required() const
|
||||
{
|
||||
return GetBoolAttr(nsGkAtoms::required);
|
||||
return State().HasState(NS_EVENT_STATE_REQUIRED);
|
||||
}
|
||||
void SetRequired(bool aVal, ErrorResult& aRv)
|
||||
{
|
||||
|
@ -341,7 +341,7 @@ public:
|
|||
*/
|
||||
NS_IMETHOD IsOptionDisabled(int32_t aIndex,
|
||||
bool* aIsDisabled);
|
||||
bool IsOptionDisabled(HTMLOptionElement* aOption);
|
||||
bool IsOptionDisabled(HTMLOptionElement* aOption) const;
|
||||
|
||||
/**
|
||||
* Sets multiple options (or just sets startIndex if select is single)
|
||||
|
@ -521,7 +521,7 @@ protected:
|
|||
|
||||
// nsIConstraintValidation
|
||||
void UpdateBarredFromConstraintValidation();
|
||||
bool IsValueMissing();
|
||||
bool IsValueMissing() const;
|
||||
|
||||
/**
|
||||
* Get the index of the first option at, under or following the content in
|
||||
|
|
|
@ -958,12 +958,6 @@ HTMLTextAreaElement::IntrinsicState() const
|
|||
{
|
||||
EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
state |= NS_EVENT_STATE_REQUIRED;
|
||||
} else {
|
||||
state |= NS_EVENT_STATE_OPTIONAL;
|
||||
}
|
||||
|
||||
if (IsCandidateForConstraintValidation()) {
|
||||
if (IsValid()) {
|
||||
state |= NS_EVENT_STATE_VALID;
|
||||
|
@ -1114,6 +1108,13 @@ HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
UpdateDisabledState(aNotify);
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::required) {
|
||||
// This *has* to be called *before* UpdateValueMissingValidityState
|
||||
// because UpdateValueMissingValidityState depends on our required
|
||||
// state.
|
||||
UpdateRequiredState(!!aValue, aNotify);
|
||||
}
|
||||
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
// This *has* to be called *after* validity has changed.
|
||||
|
@ -1218,7 +1219,7 @@ HTMLTextAreaElement::IsTooShort()
|
|||
bool
|
||||
HTMLTextAreaElement::IsValueMissing() const
|
||||
{
|
||||
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
|
||||
if (!Required() || !IsMutable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -252,9 +252,9 @@ public:
|
|||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::readonly, aReadOnly, aError);
|
||||
}
|
||||
bool Required()
|
||||
bool Required() const
|
||||
{
|
||||
return GetBoolAttr(nsGkAtoms::required);
|
||||
return State().HasState(NS_EVENT_STATE_REQUIRED);
|
||||
}
|
||||
|
||||
void SetRangeText(const nsAString& aReplacement, ErrorResult& aRv);
|
||||
|
@ -410,6 +410,7 @@ protected:
|
|||
void GetSelectionRange(uint32_t* aSelectionStart,
|
||||
uint32_t* aSelectionEnd,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
GenericSpecifiedValues* aGenericData);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
bool
|
||||
CheckboxInputType::IsValueMissing() const
|
||||
{
|
||||
if (!mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
if (!mInputElement->IsRequired()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ DateTimeInputTypeBase::IsMutable() const
|
|||
bool
|
||||
DateTimeInputTypeBase::IsValueMissing() const
|
||||
{
|
||||
if (!mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
if (!mInputElement->IsRequired()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
bool
|
||||
FileInputType::IsValueMissing() const
|
||||
{
|
||||
if (!mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
if (!mInputElement->IsRequired()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ NumericInputTypeBase::ConvertNumberToString(mozilla::Decimal aValue,
|
|||
bool
|
||||
NumberInputType::IsValueMissing() const
|
||||
{
|
||||
if (!mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
if (!mInputElement->IsRequired()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ SingleLineTextInputTypeBase::IsTooShort() const
|
|||
bool
|
||||
SingleLineTextInputTypeBase::IsValueMissing() const
|
||||
{
|
||||
if (!mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
if (!mInputElement->IsRequired()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#include "mozilla/StyleSetHandleInlines.h"
|
||||
#include "ReferrerPolicy.h"
|
||||
#include "mozilla/dom/HTMLLabelElement.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -2425,6 +2426,40 @@ void nsGenericHTMLFormElement::UpdateDisabledState(bool aNotify)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::UpdateRequiredState(bool aIsRequired, bool aNotify)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int32_t type = ControlType();
|
||||
#endif
|
||||
MOZ_ASSERT((type & NS_FORM_INPUT_ELEMENT) ||
|
||||
type == NS_FORM_SELECT ||
|
||||
type == NS_FORM_TEXTAREA,
|
||||
"This should be called only on types that @required applies");
|
||||
|
||||
#ifdef DEBUG
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(this);
|
||||
if (input) {
|
||||
MOZ_ASSERT(input->DoesRequiredApply(),
|
||||
"This should be called only on input types that @required applies");
|
||||
}
|
||||
#endif
|
||||
|
||||
EventStates requiredStates;
|
||||
if (aIsRequired) {
|
||||
requiredStates |= NS_EVENT_STATE_REQUIRED;
|
||||
} else {
|
||||
requiredStates |= NS_EVENT_STATE_OPTIONAL;
|
||||
}
|
||||
|
||||
EventStates oldRequiredStates = State() & REQUIRED_STATES;
|
||||
EventStates changedStates = requiredStates ^ oldRequiredStates;
|
||||
|
||||
if (!changedStates.IsEmpty()) {
|
||||
ToggleStates(changedStates, aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(bool aNotify)
|
||||
{
|
||||
|
|
|
@ -1101,6 +1101,11 @@ public:
|
|||
*/
|
||||
void UpdateDisabledState(bool aNotify);
|
||||
|
||||
/**
|
||||
* Update our required/optional flags to match the given aIsRequired boolean.
|
||||
*/
|
||||
void UpdateRequiredState(bool aIsRequired, bool aNotify);
|
||||
|
||||
void FieldSetFirstLegendChanged(bool aNotify) {
|
||||
UpdateFieldSet(aNotify);
|
||||
}
|
||||
|
|
|
@ -2438,6 +2438,9 @@ nsHTMLDocument::CreateAndAddWyciwygChannel(void)
|
|||
nsLoadFlags loadFlags = 0;
|
||||
channel->GetLoadFlags(&loadFlags);
|
||||
loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
|
||||
if (nsDocShell::SandboxFlagsImplyCookies(mSandboxFlags)) {
|
||||
loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
|
||||
}
|
||||
channel->SetLoadFlags(loadFlags);
|
||||
|
||||
channel->SetOriginalURI(wcwgURI);
|
||||
|
|
|
@ -296,6 +296,7 @@ public:
|
|||
NS_IMETHOD GetSelectionFlags(int16_t *aOutEnable) override;
|
||||
NS_IMETHOD GetSelection(RawSelectionType aRawSelectionType,
|
||||
nsISelection** aSelection) override;
|
||||
Selection* GetDOMSelection(RawSelectionType aRawSelectionType) override;
|
||||
NS_IMETHOD ScrollSelectionIntoView(RawSelectionType aRawSelectionType,
|
||||
int16_t aRegion, int16_t aFlags) override;
|
||||
NS_IMETHOD RepaintSelection(RawSelectionType aRawSelectionType) override;
|
||||
|
@ -432,6 +433,12 @@ nsTextInputSelectionImpl::GetSelection(RawSelectionType aRawSelectionType,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
Selection*
|
||||
nsTextInputSelectionImpl::GetDOMSelection(RawSelectionType aRawSelectionType)
|
||||
{
|
||||
return GetSelection(ToSelectionType(aRawSelectionType));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextInputSelectionImpl::ScrollSelectionIntoView(
|
||||
RawSelectionType aRawSelectionType,
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "mozilla/layout/RenderFrameChild.h"
|
||||
#include "mozilla/loader/ScriptCacheActors.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/net/CookieServiceChild.h"
|
||||
#include "mozilla/net/CaptivePortalService.h"
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
|
@ -1947,6 +1948,16 @@ ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
ContentChild::UpdateCookieStatus(nsIChannel *aChannel)
|
||||
{
|
||||
RefPtr<CookieServiceChild> csChild =
|
||||
CookieServiceChild::GetSingleton();
|
||||
NS_ASSERTION(csChild, "Couldn't get CookieServiceChild");
|
||||
|
||||
csChild->TrackCookieLoad(aChannel);
|
||||
}
|
||||
|
||||
PScriptCacheChild*
|
||||
ContentChild::AllocPScriptCacheChild(const FileDescOrError& cacheFile, const bool& wantCacheData)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef mozilla_dom_ContentChild_h
|
||||
#define mozilla_dom_ContentChild_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/ContentBridgeParent.h"
|
||||
#include "mozilla/dom/nsIContentChild.h"
|
||||
|
@ -144,6 +145,8 @@ public:
|
|||
|
||||
static void AppendProcessId(nsACString& aName);
|
||||
|
||||
static void UpdateCookieStatus(nsIChannel *aChannel);
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvInitContentBridgeChild(Endpoint<PContentBridgeChild>&& aEndpoint) override;
|
||||
|
||||
|
@ -757,7 +760,7 @@ private:
|
|||
|
||||
nsClassHashtable<nsUint64HashKey, AnonymousTemporaryFileCallback> mPendingAnonymousTemporaryFiles;
|
||||
|
||||
bool mShuttingDown;
|
||||
mozilla::Atomic<bool> mShuttingDown;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#if defined(XP_WIN) && defined(ACCESSIBILITY)
|
||||
#include "mozilla/a11y/AccessibleWrap.h"
|
||||
#endif
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
#include "mozilla/DataStorage.h"
|
||||
|
@ -80,6 +81,8 @@
|
|||
#include "mozilla/media/MediaParent.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/net/CookieServiceParent.h"
|
||||
#include "mozilla/net/PCookieServiceParent.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ProcessHangMonitor.h"
|
||||
|
@ -108,6 +111,7 @@
|
|||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsICookie.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsIContentProcess.h"
|
||||
#include "nsICycleCollectorListener.h"
|
||||
|
@ -588,6 +592,8 @@ static const char* sObserverTopics[] = {
|
|||
"cacheservice:empty-cache",
|
||||
"intl:app-locales-changed",
|
||||
"intl:requested-locales-changed",
|
||||
"cookie-changed",
|
||||
"private-cookie-changed",
|
||||
};
|
||||
|
||||
// PreallocateProcess is called by the PreallocatedProcessManager.
|
||||
|
@ -2789,6 +2795,41 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
|
||||
Unused << SendUpdateRequestedLocales(requestedLocales);
|
||||
}
|
||||
else if (!strcmp(aTopic, "cookie-changed") ||
|
||||
!strcmp(aTopic, "private-cookie-changed")) {
|
||||
if (!aData) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
PNeckoParent *neckoParent = LoneManagedOrNullAsserts(ManagedPNeckoParent());
|
||||
if (!neckoParent) {
|
||||
return NS_OK;
|
||||
}
|
||||
PCookieServiceParent *csParent = LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
|
||||
if (!csParent) {
|
||||
return NS_OK;
|
||||
}
|
||||
auto *cs = static_cast<CookieServiceParent*>(csParent);
|
||||
if (!nsCRT::strcmp(aData, u"batch-deleted")) {
|
||||
nsCOMPtr<nsIArray> cookieList = do_QueryInterface(aSubject);
|
||||
NS_ASSERTION(cookieList, "couldn't get cookie list");
|
||||
cs->RemoveBatchDeletedCookies(cookieList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!nsCRT::strcmp(aData, u"cleared")) {
|
||||
cs->RemoveAll();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICookie> xpcCookie = do_QueryInterface(aSubject);
|
||||
NS_ASSERTION(xpcCookie, "couldn't get cookie");
|
||||
if (!nsCRT::strcmp(aData, u"deleted")) {
|
||||
cs->RemoveCookie(xpcCookie);
|
||||
} else if ((!nsCRT::strcmp(aData, u"added")) ||
|
||||
(!nsCRT::strcmp(aData, u"changed"))) {
|
||||
cs->AddCookie(xpcCookie);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -5045,6 +5086,17 @@ ContentParent::ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch
|
|||
ProcessHangMonitor::ForcePaint(mHangMonitorActor, aTabParent, aLayerObserverEpoch);
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::UpdateCookieStatus(nsIChannel *aChannel)
|
||||
{
|
||||
PNeckoParent *neckoParent = LoneManagedOrNullAsserts(ManagedPNeckoParent());
|
||||
PCookieServiceParent *csParent = LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
|
||||
if (csParent) {
|
||||
auto *cs = static_cast<CookieServiceParent*>(csParent);
|
||||
cs->TrackCookieLoad(aChannel);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
ContentParent::AboutToLoadHttpFtpWyciwygDocumentForChild(nsIChannel* aChannel)
|
||||
{
|
||||
|
@ -5069,6 +5121,14 @@ ContentParent::AboutToLoadHttpFtpWyciwygDocumentForChild(nsIChannel* aChannel)
|
|||
rv = TransmitPermissionsForPrincipal(principal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsLoadFlags newLoadFlags;
|
||||
aChannel->GetLoadFlags(&newLoadFlags);
|
||||
bool isDocument = false;
|
||||
aChannel->GetIsDocument(&isDocument);
|
||||
if (newLoadFlags & nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE && isDocument) {
|
||||
UpdateCookieStatus(aChannel);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -346,6 +346,8 @@ public:
|
|||
|
||||
bool RequestRunToCompletion();
|
||||
|
||||
void UpdateCookieStatus(nsIChannel *aChannel);
|
||||
|
||||
bool IsAvailable() const
|
||||
{
|
||||
return mIsAvailable;
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
if (!existingBackgroundChild) {
|
||||
LOG(("No existingBackgroundChild"));
|
||||
existingBackgroundChild =
|
||||
ipc::BackgroundChild::SynchronouslyCreateForCurrentThread();
|
||||
ipc::BackgroundChild::GetOrCreateForCurrentThread();
|
||||
LOG(("BackgroundChild: %p", existingBackgroundChild));
|
||||
if (!existingBackgroundChild) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -130,7 +130,7 @@ GetCamerasChild() {
|
|||
// At this point we are in the MediaManager thread, and the thread we are
|
||||
// dispatching to is the specific Cameras IPC thread that was just made
|
||||
// above, so now we will fire off a runnable to run
|
||||
// BackgroundChild::SynchronouslyCreateForCurrentThread there, while we
|
||||
// BackgroundChild::GetOrCreateForCurrentThread there, while we
|
||||
// block in this thread.
|
||||
// We block until the following happens in the Cameras IPC thread:
|
||||
// 1) Creation of PBackground finishes
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1386183 - Meta CSP on data: URI iframe should be merged with toplevel CSP</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content= "img-src https:"/>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="dataFrame" onload="doCSPMergeCheck()"
|
||||
src="data:text/html,<html><head><meta http-equiv='Content-Security-Policy' content='script-src https:'/></head><body>merge csp</body></html>">
|
||||
</iframe>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doCSPMergeCheck() {
|
||||
// get the csp in JSON notation from the principal
|
||||
var frame = document.getElementById("dataFrame");
|
||||
var principal = SpecialPowers.wrap(frame).contentDocument.nodePrincipal;
|
||||
var cspOBJ = JSON.parse(principal.cspJSON);
|
||||
// make sure we got >>two<< policies
|
||||
var policies = cspOBJ["csp-policies"];
|
||||
window.parent.postMessage({result: policies.length}, "*");
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -216,6 +216,7 @@ support-files =
|
|||
file_ignore_xfo.html^headers^
|
||||
file_ro_ignore_xfo.html
|
||||
file_ro_ignore_xfo.html^headers^
|
||||
file_data_csp_merge.html
|
||||
|
||||
[test_base-uri.html]
|
||||
[test_blob_data_schemes.html]
|
||||
|
@ -307,3 +308,4 @@ tags = mcb
|
|||
[test_websocket_self.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_ignore_xfo.html]
|
||||
[test_data_csp_merge.html]
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1386183 - Meta CSP on data: URI iframe should be merged with toplevel CSP</title>
|
||||
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe style="width:100%;" id="testframe"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/* Description of the test:
|
||||
* We load an iframe using a meta CSP which includes another iframe
|
||||
* using a data: URI which also defines a meta CSP. We make sure the
|
||||
* CSP from the including document gets merged with the data: URI
|
||||
* CSP and applies to the data: URI iframe.
|
||||
*/
|
||||
|
||||
window.addEventListener("message", receiveMessage);
|
||||
function receiveMessage(event) {
|
||||
window.removeEventListener("message", receiveMessage);
|
||||
// toplevel CSP + data: URI iframe meta CSP => 2 CSP policies
|
||||
is(event.data.result, 2,
|
||||
"CSP on data: URI iframe gets merged with CSP from including context");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
document.getElementById("testframe").src = "file_data_csp_merge.html";
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -16,6 +16,7 @@ support-files =
|
|||
file_bug1224790-1_nonmodal.xul
|
||||
file_bug1224790-2_modal.xul
|
||||
file_bug1224790-2_nonmodal.xul
|
||||
file_popup_blocker_chrome.html
|
||||
file_subscript_bindings.js
|
||||
focus_frameset.html
|
||||
focus_window2.xul
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<html>
|
||||
<body onload="window.opener.next()">
|
||||
foobar
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -20,35 +20,47 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=662519
|
|||
|
||||
/** Test for Bug 662519 **/
|
||||
|
||||
let w = null;
|
||||
|
||||
let steps = [
|
||||
function() {
|
||||
w = window.open("file_popup_blocker_chrome.html", "", "width=200,height=200");
|
||||
ok(w, "The window object shouldn't be null");
|
||||
// next() is called within file_popup_blocker_chrome.html
|
||||
},
|
||||
function() {
|
||||
w.close();
|
||||
ok(true, "The popup appeared");
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
w = window.open("file_popup_blocker_chrome.html", "_blank", "width=200,height=200");
|
||||
ok(w, "The window object shouldn't be null");
|
||||
// next() is called within file_popup_blocker_chrome.html
|
||||
},
|
||||
function() {
|
||||
w.close();
|
||||
ok(true, "The popup appeared");
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
function next() {
|
||||
if (!steps.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
let step = steps.shift();
|
||||
step();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// We have to enable dom.disable_open_during_load which is disabled
|
||||
// by the test harness.
|
||||
let prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
var gLastDomLoadValue = prefs.getBoolPref("dom.disable_open_during_load");
|
||||
prefs.setBoolPref("dom.disable_open_during_load", true);
|
||||
|
||||
let w = window.open("data:text/html,foobar", "", "width=200,height=200");
|
||||
ok(w, "The window object shouldn't be null");
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
w.close();
|
||||
ok(true, "The popup appeared");
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
let w = window.open("data:text/html,foobar", "", "width=200,height=200");
|
||||
ok(w, "The window object shouldn't be null");
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
w.close();
|
||||
|
||||
ok(true, "The popup appeared");
|
||||
prefs.setBoolPref("dom.disable_open_during_load", gLastDomLoadValue);
|
||||
SimpleTest.finish();
|
||||
}, w, false);
|
||||
});
|
||||
}, w, false);
|
||||
SpecialPowers.pushPrefEnv({'set': [["dom.disable_open_during_load", true]] }, function() {
|
||||
next();
|
||||
});
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
||||
|
|
|
@ -2849,10 +2849,10 @@ WorkerThreadPrimaryRunnable::Run()
|
|||
|
||||
profiler_register_thread(threadName.get(), &stackBaseGuess);
|
||||
|
||||
// Note: SynchronouslyCreateForCurrentThread() must be called prior to
|
||||
// Note: GetOrCreateForCurrentThread() must be called prior to
|
||||
// mWorkerPrivate->SetThread() in order to avoid accidentally consuming
|
||||
// worker messages here.
|
||||
if (NS_WARN_IF(!BackgroundChild::SynchronouslyCreateForCurrentThread())) {
|
||||
if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread())) {
|
||||
// XXX need to fire an error at parent.
|
||||
// Failed in creating BackgroundChild: probably in shutdown. Continue to run
|
||||
// without BackgroundChild created.
|
||||
|
|
|
@ -327,7 +327,7 @@ WorkerThread::Observer::OnProcessNextEvent(nsIThreadInternal* /* aThread */,
|
|||
|
||||
// If the PBackground child is not created yet, then we must permit
|
||||
// blocking event processing to support
|
||||
// BackgroundChild::SynchronouslyCreateForCurrentThread(). If this occurs
|
||||
// BackgroundChild::GetOrCreateCreateForCurrentThread(). If this occurs
|
||||
// then we are spinning on the event queue at the start of
|
||||
// PrimaryWorkerRunnable::Run() and don't want to process the event in
|
||||
// mWorkerPrivate yet.
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "InsertTextTransaction.h" // for InsertTextTransaction
|
||||
#include "JoinNodeTransaction.h" // for JoinNodeTransaction
|
||||
#include "PlaceholderTransaction.h" // for PlaceholderTransaction
|
||||
#include "SetTextTransaction.h" // for SetTextTransaction
|
||||
#include "SplitNodeTransaction.h" // for SplitNodeTransaction
|
||||
#include "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc.
|
||||
#include "TextEditUtils.h" // for TextEditUtils
|
||||
|
@ -166,6 +165,8 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectionController)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode)
|
||||
|
@ -187,6 +188,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
|
|||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionController)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMETextNode)
|
||||
|
@ -225,7 +228,7 @@ EditorBase::Init(nsIDOMDocument* aDOMDocument,
|
|||
}
|
||||
|
||||
// First only set flags, but other stuff shouldn't be initialized now.
|
||||
// Don't move this call after initializing mDocumentWeak.
|
||||
// Don't move this call after initializing mDocument.
|
||||
// SetFlags() can check whether it's called during initialization or not by
|
||||
// them. Note that SetFlags() will be called by PostCreate().
|
||||
#ifdef DEBUG
|
||||
|
@ -234,14 +237,13 @@ EditorBase::Init(nsIDOMDocument* aDOMDocument,
|
|||
SetFlags(aFlags);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed");
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(aDOMDocument);
|
||||
mDocumentWeak = document.get();
|
||||
mDocument = do_QueryInterface(aDOMDocument);
|
||||
// HTML editors currently don't have their own selection controller,
|
||||
// so they'll pass null as aSelCon, and we'll get the selection controller
|
||||
// off of the presshell.
|
||||
nsCOMPtr<nsISelectionController> selectionController;
|
||||
if (aSelectionController) {
|
||||
mSelectionControllerWeak = aSelectionController;
|
||||
mSelectionController = aSelectionController;
|
||||
selectionController = aSelectionController;
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
|
@ -565,14 +567,14 @@ EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
|
|||
already_AddRefed<nsIDocument>
|
||||
EditorBase::GetDocument()
|
||||
{
|
||||
nsCOMPtr<nsIDocument> document = mDocumentWeak.get();
|
||||
nsCOMPtr<nsIDocument> document = mDocument;
|
||||
return document.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMDocument>
|
||||
EditorBase::GetDOMDocument()
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentWeak);
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocument);
|
||||
return domDocument.forget();
|
||||
}
|
||||
|
||||
|
@ -634,19 +636,6 @@ EditorBase::GetSelectionController(nsISelectionController** aSel)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsISelectionController>
|
||||
EditorBase::GetSelectionController()
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selectionController;
|
||||
if (mSelectionControllerWeak) {
|
||||
selectionController = mSelectionControllerWeak.get();
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
selectionController = do_QueryInterface(presShell);
|
||||
}
|
||||
return selectionController.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::DeleteSelection(EDirection aAction,
|
||||
EStripWrappers aStripWrappers)
|
||||
|
@ -667,25 +656,13 @@ EditorBase::GetSelection(SelectionType aSelectionType,
|
|||
{
|
||||
NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
|
||||
*aSelection = nullptr;
|
||||
nsCOMPtr<nsISelectionController> selcon = GetSelectionController();
|
||||
nsISelectionController* selcon = GetSelectionController();
|
||||
if (!selcon) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return selcon->GetSelection(ToRawSelectionType(aSelectionType), aSelection);
|
||||
}
|
||||
|
||||
Selection*
|
||||
EditorBase::GetSelection(SelectionType aSelectionType)
|
||||
{
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
nsresult rv = GetSelection(aSelectionType, getter_AddRefs(sel));
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!sel)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sel->AsSelection();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::DoTransaction(nsITransaction* aTxn)
|
||||
{
|
||||
|
@ -2378,8 +2355,7 @@ EditorBase::CloneAttributes(Element* aDest,
|
|||
nsresult
|
||||
EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
nsISelectionController* selectionController = GetSelectionController();
|
||||
if (!selectionController) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2722,9 +2698,7 @@ nsresult
|
|||
EditorBase::SetTextImpl(Selection& aSelection, const nsAString& aString,
|
||||
Text& aCharData)
|
||||
{
|
||||
SetTextTransaction transaction(aCharData, aString, *this, &mRangeUpdater);
|
||||
|
||||
uint32_t length = aCharData.Length();
|
||||
const uint32_t length = aCharData.Length();
|
||||
|
||||
AutoRules beginRulesSniffing(this, EditAction::setText,
|
||||
nsIEditor::eNext);
|
||||
|
@ -2749,7 +2723,20 @@ EditorBase::SetTextImpl(Selection& aSelection, const nsAString& aString,
|
|||
// We don't support undo here, so we don't really need all of the transaction
|
||||
// machinery, therefore we can run our transaction directly, breaking all of
|
||||
// the rules!
|
||||
nsresult rv = transaction.DoTransaction();
|
||||
nsresult rv = aCharData.SetData(aString);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Only set selection to insertion point if editor gives permission
|
||||
if (GetShouldTxnSetSelection()) {
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
DebugOnly<nsresult> rv = selection->Collapse(&aCharData, length);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Selection could not be collapsed after insert");
|
||||
}
|
||||
mRangeUpdater.SelAdjDeleteText(&aCharData, 0, length);
|
||||
mRangeUpdater.SelAdjInsertText(aCharData, 0, aString);
|
||||
|
||||
// Let listeners know what happened
|
||||
{
|
||||
|
@ -5307,8 +5294,7 @@ EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
|
|||
{
|
||||
MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
|
||||
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
nsISelectionController* selectionController = GetSelectionController();
|
||||
if (NS_WARN_IF(!selectionController)) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
|
||||
#include "mozilla/Maybe.h" // for Maybe
|
||||
#include "mozilla/OwningNonNull.h" // for OwningNonNull
|
||||
#include "mozilla/PresShell.h" // for PresShell
|
||||
#include "mozilla/SelectionState.h" // for RangeUpdater, etc.
|
||||
#include "mozilla/StyleSheet.h" // for StyleSheet
|
||||
#include "mozilla/WeakPtr.h" // for WeakPtr
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/dom/Text.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
@ -119,7 +121,6 @@ class InsertTextTransaction;
|
|||
class JoinNodeTransaction;
|
||||
class PlaceholderTransaction;
|
||||
class RemoveStyleSheetTransaction;
|
||||
class SetTextTransaction;
|
||||
class SplitNodeTransaction;
|
||||
class TextComposition;
|
||||
class TextEditor;
|
||||
|
@ -129,7 +130,6 @@ namespace dom {
|
|||
class DataTransfer;
|
||||
class Element;
|
||||
class EventTarget;
|
||||
class Selection;
|
||||
class Text;
|
||||
} // namespace dom
|
||||
|
||||
|
@ -252,7 +252,7 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
|
||||
|
||||
bool IsInitialized() const { return !!mDocumentWeak; }
|
||||
bool IsInitialized() const { return !!mDocument; }
|
||||
already_AddRefed<nsIDOMDocument> GetDOMDocument();
|
||||
already_AddRefed<nsIDocument> GetDocument();
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
|
@ -567,7 +567,21 @@ protected:
|
|||
*/
|
||||
bool EnsureComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||
|
||||
already_AddRefed<nsISelectionController> GetSelectionController();
|
||||
nsISelectionController* GetSelectionController() const
|
||||
{
|
||||
if (mSelectionController) {
|
||||
return mSelectionController;
|
||||
}
|
||||
if (!mDocument) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIPresShell* presShell = mDocument->GetShell();
|
||||
if (!presShell) {
|
||||
return nullptr;
|
||||
}
|
||||
nsISelectionController* sc = static_cast<PresShell*>(presShell);
|
||||
return sc;
|
||||
}
|
||||
nsresult GetSelection(SelectionType aSelectionType,
|
||||
nsISelection** aSelection);
|
||||
|
||||
|
@ -820,7 +834,15 @@ public:
|
|||
static void DumpNode(nsIDOMNode* aNode, int32_t indent = 0);
|
||||
#endif
|
||||
Selection* GetSelection(SelectionType aSelectionType =
|
||||
SelectionType::eNormal);
|
||||
SelectionType::eNormal)
|
||||
{
|
||||
nsISelectionController* sc = GetSelectionController();
|
||||
if (!sc) {
|
||||
return nullptr;
|
||||
}
|
||||
Selection* selection = sc->GetDOMSelection(ToRawSelectionType(aSelectionType));
|
||||
return selection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helpers to add a node to the selection.
|
||||
|
@ -980,7 +1002,7 @@ public:
|
|||
|
||||
bool HasIndependentSelection() const
|
||||
{
|
||||
return !!mSelectionControllerWeak;
|
||||
return !!mSelectionController;
|
||||
}
|
||||
|
||||
bool IsModifiable() const
|
||||
|
@ -1105,12 +1127,8 @@ public:
|
|||
void HideCaret(bool aHide);
|
||||
|
||||
private:
|
||||
// Weak reference to the nsISelectionController.
|
||||
// Use GetSelectionController() to retrieve actual pointer.
|
||||
CachedWeakPtr<nsISelectionController> mSelectionControllerWeak;
|
||||
// Weak reference to the nsIDocument.
|
||||
// Use GetDocument() to retrieve actual pointer.
|
||||
CachedWeakPtr<nsIDocument> mDocumentWeak;
|
||||
nsCOMPtr<nsISelectionController> mSelectionController;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
|
||||
protected:
|
||||
enum Tristate
|
||||
|
|
|
@ -4272,8 +4272,7 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
|
|||
|
||||
uint32_t length = aNode->TextLength();
|
||||
if (aSafeToAskFrames) {
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
nsISelectionController* selectionController = GetSelectionController();
|
||||
if (NS_WARN_IF(!selectionController)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=78: */
|
||||
/* 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 "SetTextTransaction.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h" // DebugOnly
|
||||
#include "mozilla/EditorBase.h" // mEditorBase
|
||||
#include "mozilla/SelectionState.h" // RangeUpdater
|
||||
#include "mozilla/dom/Selection.h" // Selection local var
|
||||
#include "mozilla/dom/Text.h" // mTextNode
|
||||
#include "nsAString.h" // nsAString parameter
|
||||
#include "nsDebug.h" // for NS_ASSERTION, etc.
|
||||
#include "nsError.h" // for NS_OK, etc.
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
SetTextTransaction::SetTextTransaction(Text& aTextNode,
|
||||
const nsAString& aStringToSet,
|
||||
EditorBase& aEditorBase,
|
||||
RangeUpdater* aRangeUpdater)
|
||||
: mTextNode(&aTextNode)
|
||||
, mStringToSet(aStringToSet)
|
||||
, mEditorBase(&aEditorBase)
|
||||
, mRangeUpdater(aRangeUpdater)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetTextTransaction::DoTransaction()
|
||||
{
|
||||
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = mTextNode->GetData(mPreviousData);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mTextNode->SetData(mStringToSet);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Only set selection to insertion point if editor gives permission
|
||||
if (mEditorBase->GetShouldTxnSetSelection()) {
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
DebugOnly<nsresult> rv =
|
||||
selection->Collapse(mTextNode, mStringToSet.Length());
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Selection could not be collapsed after insert");
|
||||
}
|
||||
mRangeUpdater->SelAdjDeleteText(mTextNode, 0, mPreviousData.Length());
|
||||
mRangeUpdater->SelAdjInsertText(*mTextNode, 0, mStringToSet);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -1,61 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=78: */
|
||||
/* 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_SetTextTransaction_h
|
||||
#define mozilla_SetTextTransaction_h
|
||||
|
||||
#include "mozilla/Attributes.h" // for MOZ_STACK_CLASS
|
||||
#include "nsString.h" // nsString members
|
||||
#include "nscore.h" // NS_IMETHOD, nsAString
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class EditorBase;
|
||||
class RangeUpdater;
|
||||
|
||||
namespace dom {
|
||||
class Text;
|
||||
} // namespace dom
|
||||
|
||||
/**
|
||||
* A fake transaction that inserts text into a content node.
|
||||
*
|
||||
* This class mimics a transaction class but it is not intended to be used as one.
|
||||
*/
|
||||
class MOZ_STACK_CLASS SetTextTransaction final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param aTextNode The text content node.
|
||||
* @param aString The new text to insert.
|
||||
* @param aEditorBase Used to get and set the selection.
|
||||
* @param aRangeUpdater The range updater
|
||||
*/
|
||||
SetTextTransaction(dom::Text& aTextNode,
|
||||
const nsAString& aString, EditorBase& aEditorBase,
|
||||
RangeUpdater* aRangeUpdater);
|
||||
|
||||
nsresult DoTransaction();
|
||||
|
||||
private:
|
||||
// The Text node to operate upon.
|
||||
RefPtr<dom::Text> mTextNode;
|
||||
|
||||
// The text to insert into mTextNode at mOffset.
|
||||
nsString mStringToSet;
|
||||
|
||||
// The previous text for undo
|
||||
nsString mPreviousData;
|
||||
|
||||
// The editor, which we'll need to get the selection.
|
||||
EditorBase* MOZ_NON_OWNING_REF mEditorBase;
|
||||
|
||||
RangeUpdater* mRangeUpdater;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_SetTextTransaction_h
|
|
@ -840,7 +840,7 @@ TextEditRules::WillSetText(Selection& aSelection,
|
|||
|
||||
if (!IsPlaintextEditor() || textEditor->IsIMEComposing() ||
|
||||
aMaxLength != -1) {
|
||||
// SetTextTransaction only supports plain text editor without IME.
|
||||
// SetTextImpl only supports plain text editor without IME.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ UNIFIED_SOURCES += [
|
|||
'JoinNodeTransaction.cpp',
|
||||
'PlaceholderTransaction.cpp',
|
||||
'SelectionState.cpp',
|
||||
'SetTextTransaction.cpp',
|
||||
'SplitNodeTransaction.cpp',
|
||||
'StyleSheetTransactions.cpp',
|
||||
'TextEditor.cpp',
|
||||
|
|
|
@ -90,7 +90,7 @@ skip-if = os == 'android'
|
|||
[test_bug578771.html]
|
||||
skip-if = android_version == '18' # bug 1147989
|
||||
[test_bug586662.html]
|
||||
skip-if = toolkit == 'android'
|
||||
skip-if = true # bug 1376382
|
||||
[test_bug587461.html]
|
||||
[test_bug590554.html]
|
||||
[test_bug592592.html]
|
||||
|
|
|
@ -113,12 +113,33 @@ PaintThread::IsOnPaintThread()
|
|||
void
|
||||
PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
|
||||
gfx::DrawTargetCapture* aCapture,
|
||||
gfx::DrawTarget* aTarget)
|
||||
CapturedPaintState* aState,
|
||||
PrepDrawTargetForPaintingCallback aCallback)
|
||||
{
|
||||
MOZ_ASSERT(IsOnPaintThread());
|
||||
MOZ_ASSERT(aCapture);
|
||||
MOZ_ASSERT(aState);
|
||||
|
||||
DrawTarget* target = aState->mTarget;
|
||||
|
||||
Matrix oldTransform = target->GetTransform();
|
||||
target->SetTransform(aState->mTargetTransform);
|
||||
|
||||
if (!aCallback(aState)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw all the things into the actual dest target.
|
||||
aTarget->DrawCapturedDT(aCapture, Matrix());
|
||||
target->DrawCapturedDT(aCapture, Matrix());
|
||||
target->SetTransform(oldTransform);
|
||||
|
||||
// Textureclient forces a flush once we "end paint", so
|
||||
// users of this texture expect all the drawing to be complete.
|
||||
// Force a flush now.
|
||||
// TODO: This might be a performance bottleneck because
|
||||
// main thread painting only does one flush at the end of all paints
|
||||
// whereas we force a flush after each draw target paint.
|
||||
target->Flush();
|
||||
|
||||
if (aBridge) {
|
||||
aBridge->NotifyFinishedAsyncPaint();
|
||||
|
@ -127,9 +148,12 @@ PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
|
|||
|
||||
void
|
||||
PaintThread::PaintContents(DrawTargetCapture* aCapture,
|
||||
DrawTarget* aTarget)
|
||||
CapturedPaintState* aState,
|
||||
PrepDrawTargetForPaintingCallback aCallback)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCapture);
|
||||
MOZ_ASSERT(aState);
|
||||
|
||||
// If painting asynchronously, we need to acquire the compositor bridge which
|
||||
// owns the underlying MessageChannel. Otherwise we leave it null and use
|
||||
|
@ -140,13 +164,15 @@ PaintThread::PaintContents(DrawTargetCapture* aCapture,
|
|||
cbc->NotifyBeginAsyncPaint();
|
||||
}
|
||||
RefPtr<DrawTargetCapture> capture(aCapture);
|
||||
RefPtr<DrawTarget> target(aTarget);
|
||||
RefPtr<CapturedPaintState> state(aState);
|
||||
|
||||
RefPtr<PaintThread> self = this;
|
||||
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
|
||||
[self, cbc, capture, target]() -> void
|
||||
[self, cbc, capture, state, aCallback]() -> void
|
||||
{
|
||||
self->PaintContentsAsync(cbc, capture, target);
|
||||
self->PaintContentsAsync(cbc, capture,
|
||||
state,
|
||||
aCallback);
|
||||
});
|
||||
|
||||
if (cbc) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define MOZILLA_LAYERS_PAINTTHREAD_H
|
||||
|
||||
#include "base/platform_thread.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
@ -20,6 +21,38 @@ class DrawTargetCapture;
|
|||
|
||||
namespace layers {
|
||||
|
||||
// Holds the key parts from a RotatedBuffer::PaintState
|
||||
// required to draw the captured paint state
|
||||
class CapturedPaintState {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CapturedPaintState)
|
||||
public:
|
||||
CapturedPaintState(nsIntRegion& aRegionToDraw,
|
||||
gfx::DrawTarget* aTarget,
|
||||
gfx::DrawTarget* aTargetOnWhite,
|
||||
gfx::Matrix aTargetTransform,
|
||||
SurfaceMode aSurfaceMode,
|
||||
gfxContentType aContentType)
|
||||
: mRegionToDraw(aRegionToDraw)
|
||||
, mTarget(aTarget)
|
||||
, mTargetOnWhite(aTargetOnWhite)
|
||||
, mTargetTransform(aTargetTransform)
|
||||
, mSurfaceMode(aSurfaceMode)
|
||||
, mContentType(aContentType)
|
||||
{}
|
||||
|
||||
nsIntRegion mRegionToDraw;
|
||||
RefPtr<gfx::DrawTarget> mTarget;
|
||||
RefPtr<gfx::DrawTarget> mTargetOnWhite;
|
||||
gfx::Matrix mTargetTransform;
|
||||
SurfaceMode mSurfaceMode;
|
||||
gfxContentType mContentType;
|
||||
|
||||
protected:
|
||||
virtual ~CapturedPaintState() {}
|
||||
};
|
||||
|
||||
typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState* aPaintState);
|
||||
|
||||
class CompositorBridgeChild;
|
||||
|
||||
class PaintThread final
|
||||
|
@ -31,7 +64,8 @@ public:
|
|||
static void Shutdown();
|
||||
static PaintThread* Get();
|
||||
void PaintContents(gfx::DrawTargetCapture* aCapture,
|
||||
gfx::DrawTarget* aTarget);
|
||||
CapturedPaintState* aState,
|
||||
PrepDrawTargetForPaintingCallback aCallback);
|
||||
|
||||
// Sync Runnables need threads to be ref counted,
|
||||
// But this thread lives through the whole process.
|
||||
|
@ -49,7 +83,8 @@ private:
|
|||
void InitOnPaintThread();
|
||||
void PaintContentsAsync(CompositorBridgeChild* aBridge,
|
||||
gfx::DrawTargetCapture* aCapture,
|
||||
gfx::DrawTarget* aTarget);
|
||||
CapturedPaintState* aState,
|
||||
PrepDrawTargetForPaintingCallback aCallback);
|
||||
|
||||
static StaticAutoPtr<PaintThread> sSingleton;
|
||||
static StaticRefPtr<nsIThread> sThread;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "gfx2DGlue.h"
|
||||
#include "nsLayoutUtils.h" // for invalidation debugging
|
||||
#include "PaintThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -730,6 +731,77 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
|
|||
return result;
|
||||
}
|
||||
|
||||
DrawTarget*
|
||||
RotatedContentBuffer::BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||
DrawIterator* aIter /* = nullptr */)
|
||||
{
|
||||
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(),
|
||||
BUFFER_BOTH, aIter);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*static */ bool
|
||||
RotatedContentBuffer::PrepareDrawTargetForPainting(CapturedPaintState* aState)
|
||||
{
|
||||
RefPtr<DrawTarget> target = aState->mTarget;
|
||||
RefPtr<DrawTarget> whiteTarget = aState->mTargetOnWhite;
|
||||
|
||||
if (aState->mSurfaceMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
|
||||
if (!target || !target->IsValid() ||
|
||||
!aState->mTargetOnWhite || !aState->mTargetOnWhite->IsValid()) {
|
||||
// This can happen in release builds if allocating one of the two buffers
|
||||
// failed. This in turn can happen if unreasonably large textures are
|
||||
// requested.
|
||||
return false;
|
||||
}
|
||||
for (auto iter = aState->mRegionToDraw.RectIter(); !iter.Done(); iter.Next()) {
|
||||
const IntRect& rect = iter.Get();
|
||||
target->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
||||
ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
|
||||
whiteTarget->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
||||
ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
|
||||
}
|
||||
} else if (aState->mContentType == gfxContentType::COLOR_ALPHA &&
|
||||
target->IsValid()) {
|
||||
// HaveBuffer() => we have an existing buffer that we must clear
|
||||
for (auto iter = aState->mRegionToDraw.RectIter(); !iter.Done(); iter.Next()) {
|
||||
const IntRect& rect = iter.Get();
|
||||
target->ClearRect(Rect(rect.x, rect.y, rect.width, rect.height));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RotatedContentBuffer::ExpandDrawRegion(PaintState& aPaintState,
|
||||
DrawIterator* aIter,
|
||||
BackendType aBackendType)
|
||||
{
|
||||
nsIntRegion* drawPtr = &aPaintState.mRegionToDraw;
|
||||
if (aIter) {
|
||||
// The iterators draw region currently only contains the bounds of the region,
|
||||
// this makes it the precise region.
|
||||
aIter->mDrawRegion.And(aIter->mDrawRegion, aPaintState.mRegionToDraw);
|
||||
drawPtr = &aIter->mDrawRegion;
|
||||
}
|
||||
if (aBackendType == BackendType::DIRECT2D ||
|
||||
aBackendType == BackendType::DIRECT2D1_1) {
|
||||
// Simplify the draw region to avoid hitting expensive drawing paths
|
||||
// for complex regions.
|
||||
drawPtr->SimplifyOutwardByArea(100 * 100);
|
||||
}
|
||||
}
|
||||
|
||||
DrawTarget*
|
||||
RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
|
||||
DrawIterator* aIter /* = nullptr */)
|
||||
|
@ -744,41 +816,22 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsIntRegion* drawPtr = &aPaintState.mRegionToDraw;
|
||||
if (aIter) {
|
||||
// The iterators draw region currently only contains the bounds of the region,
|
||||
// this makes it the precise region.
|
||||
aIter->mDrawRegion.And(aIter->mDrawRegion, aPaintState.mRegionToDraw);
|
||||
drawPtr = &aIter->mDrawRegion;
|
||||
}
|
||||
if (result->GetBackendType() == BackendType::DIRECT2D ||
|
||||
result->GetBackendType() == BackendType::DIRECT2D1_1) {
|
||||
// Simplify the draw region to avoid hitting expensive drawing paths
|
||||
// for complex regions.
|
||||
drawPtr->SimplifyOutwardByArea(100 * 100);
|
||||
}
|
||||
ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
|
||||
|
||||
if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
|
||||
if (!mDTBuffer || !mDTBuffer->IsValid() ||
|
||||
!mDTBufferOnWhite || !mDTBufferOnWhite->IsValid()) {
|
||||
// This can happen in release builds if allocating one of the two buffers
|
||||
// failed. This in turn can happen if unreasonably large textures are
|
||||
// requested.
|
||||
return nullptr;
|
||||
}
|
||||
for (auto iter = drawPtr->RectIter(); !iter.Done(); iter.Next()) {
|
||||
const IntRect& rect = iter.Get();
|
||||
mDTBuffer->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
||||
ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
|
||||
mDTBufferOnWhite->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
|
||||
ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
|
||||
}
|
||||
} else if (aPaintState.mContentType == gfxContentType::COLOR_ALPHA && HaveBuffer()) {
|
||||
// HaveBuffer() => we have an existing buffer that we must clear
|
||||
for (auto iter = drawPtr->RectIter(); !iter.Done(); iter.Next()) {
|
||||
const IntRect& rect = iter.Get();
|
||||
result->ClearRect(Rect(rect.x, rect.y, rect.width, rect.height));
|
||||
}
|
||||
nsIntRegion regionToDraw = aIter ? aIter->mDrawRegion
|
||||
: aPaintState.mRegionToDraw;
|
||||
|
||||
// Can't stack allocate refcounted objects.
|
||||
RefPtr<CapturedPaintState> capturedPaintState =
|
||||
MakeAndAddRef<CapturedPaintState>(regionToDraw,
|
||||
mDTBuffer,
|
||||
mDTBufferOnWhite,
|
||||
Matrix(),
|
||||
aPaintState.mMode,
|
||||
aPaintState.mContentType);
|
||||
|
||||
if (!RotatedContentBuffer::PrepareDrawTargetForPainting(capturedPaintState)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CapturedPaintState;
|
||||
|
||||
typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState*);
|
||||
|
||||
class TextureClient;
|
||||
class PaintedLayer;
|
||||
|
||||
|
@ -293,6 +297,14 @@ public:
|
|||
gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
|
||||
DrawIterator* aIter = nullptr);
|
||||
|
||||
gfx::DrawTarget* BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||
DrawIterator* aIter = nullptr);
|
||||
|
||||
void ExpandDrawRegion(PaintState& aPaintState,
|
||||
DrawIterator* aIter,
|
||||
gfx::BackendType aBackendType);
|
||||
|
||||
static bool PrepareDrawTargetForPainting(CapturedPaintState*);
|
||||
enum {
|
||||
BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
|
||||
// component alpha.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "PaintThread.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
#include "RotatedBuffer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -188,6 +189,29 @@ ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUp
|
|||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* If we can, let's paint this ClientPaintedLayer's contents off the main thread.
|
||||
* The essential idea is that we ask the ContentClient for a DrawTarget and record
|
||||
* the moz2d commands. On the Paint Thread, we replay those commands to the
|
||||
* destination draw target. There are a couple of lifetime issues here though:
|
||||
*
|
||||
* 1) TextureClient owns the underlying buffer and DrawTarget. Because of this
|
||||
* we have to keep the TextureClient and DrawTarget alive but trick the
|
||||
* TextureClient into thinking it's already returned the DrawTarget
|
||||
* since we iterate through different Rects to get DrawTargets*. If
|
||||
* the TextureClient goes away, the DrawTarget and thus buffer can too.
|
||||
* 2) When ContentClient::EndPaint happens, it flushes the DrawTarget. We have
|
||||
* to Reflush on the Paint Thread
|
||||
* 3) DrawTarget API is NOT thread safe. We get around this by recording
|
||||
* on the main thread and painting on the paint thread. Logically,
|
||||
* ClientLayerManager will force a flushed paint and block the main thread
|
||||
* if we have another transaction. Thus we have a gap between when the main
|
||||
* thread records, the paint thread paints, and we block the main thread
|
||||
* from trying to paint again. The underlying API however is NOT thread safe.
|
||||
* 4) We have both "sync" and "async" OMTP. Sync OMTP means we paint on the main thread
|
||||
* but block the main thread while the paint thread paints. Async OMTP doesn't block
|
||||
* the main thread. Sync OMTP is only meant to be used as a debugging tool.
|
||||
*/
|
||||
bool
|
||||
ClientPaintedLayer::PaintOffMainThread()
|
||||
{
|
||||
|
@ -202,7 +226,8 @@ ClientPaintedLayer::PaintOffMainThread()
|
|||
|
||||
bool didUpdate = false;
|
||||
RotatedContentBuffer::DrawIterator iter;
|
||||
while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
|
||||
// Debug Protip: Change to BorrowDrawTargetForPainting if using sync OMTP.
|
||||
while (DrawTarget* target = mContentClient->BorrowDrawTargetForRecording(state, &iter)) {
|
||||
if (!target || !target->IsValid()) {
|
||||
if (target) {
|
||||
mContentClient->ReturnDrawTargetToBuffer(target);
|
||||
|
@ -210,14 +235,15 @@ ClientPaintedLayer::PaintOffMainThread()
|
|||
continue;
|
||||
}
|
||||
|
||||
// We don't clear the rect here like WRPaintedBlobLayers do
|
||||
// because ContentClient already clears the surface for us during BeginPaint.
|
||||
RefPtr<DrawTargetCapture> captureDT =
|
||||
Factory::CreateCaptureDrawTarget(target->GetBackendType(),
|
||||
target->GetSize(),
|
||||
target->GetFormat());
|
||||
captureDT->SetTransform(target->GetTransform());
|
||||
|
||||
Matrix capturedTransform = target->GetTransform();
|
||||
captureDT->SetTransform(capturedTransform);
|
||||
|
||||
// TODO: Capture AA Flags and reset them in PaintThread
|
||||
SetAntialiasingFlags(this, captureDT);
|
||||
SetAntialiasingFlags(this, target);
|
||||
|
||||
|
@ -234,12 +260,23 @@ ClientPaintedLayer::PaintOffMainThread()
|
|||
|
||||
ctx = nullptr;
|
||||
|
||||
PaintThread::Get()->PaintContents(captureDT, target);
|
||||
// TODO: Fixup component alpha
|
||||
DrawTarget* targetOnWhite = nullptr;
|
||||
RefPtr<CapturedPaintState> capturedState
|
||||
= MakeAndAddRef<CapturedPaintState>(state.mRegionToDraw,
|
||||
target, targetOnWhite,
|
||||
capturedTransform,
|
||||
state.mMode,
|
||||
state.mContentType);
|
||||
|
||||
PaintThread::Get()->PaintContents(captureDT,
|
||||
capturedState,
|
||||
RotatedContentBuffer::PrepareDrawTargetForPainting);
|
||||
|
||||
mContentClient->ReturnDrawTargetToBuffer(target);
|
||||
|
||||
didUpdate = true;
|
||||
}
|
||||
|
||||
mContentClient->EndPaint(nullptr);
|
||||
|
||||
if (didUpdate) {
|
||||
|
|
|
@ -96,7 +96,8 @@ public:
|
|||
virtual gfx::DrawTarget* BorrowDrawTargetForPainting(RotatedContentBuffer::PaintState& aPaintState,
|
||||
RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
|
||||
|
||||
virtual gfx::DrawTarget* BorrowDrawTargetForRecording(RotatedContentBuffer::PaintState& aPaintState,
|
||||
RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
|
||||
// Called as part of the layers transation reply. Conveys data about our
|
||||
// buffer(s) from the compositor. If appropriate we should swap references
|
||||
// to our buffers.
|
||||
|
@ -151,6 +152,11 @@ public:
|
|||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
|
||||
}
|
||||
virtual gfx::DrawTarget* BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||
RotatedContentBuffer::DrawIterator* aIter = nullptr) override
|
||||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForRecording(aPaintState, aIter);
|
||||
}
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
|
||||
{
|
||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||
|
@ -234,6 +240,11 @@ public:
|
|||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
|
||||
}
|
||||
virtual gfx::DrawTarget* BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||
RotatedContentBuffer::DrawIterator* aIter = nullptr) override
|
||||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForRecording(aPaintState, aIter);
|
||||
}
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
|
||||
{
|
||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||
|
|
|
@ -218,6 +218,7 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::Pipeli
|
|||
// This was observed during Tab move between different windows.
|
||||
NS_WARNING("Created child without a matching parent?");
|
||||
parent = WebRenderBridgeParent::CreateDestroyed();
|
||||
parent->AddRef(); // IPDL reference
|
||||
*aIdNamespace = parent->GetIdNamespace();
|
||||
*aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
|
||||
return parent;
|
||||
|
@ -228,8 +229,8 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::Pipeli
|
|||
RefPtr<AsyncImagePipelineManager> holder = root->AsyncImageManager();
|
||||
RefPtr<CompositorAnimationStorage> animStorage = cbp->GetAnimationStorage();
|
||||
parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, root->CompositorScheduler(), Move(api), Move(holder), Move(animStorage));
|
||||
|
||||
parent->AddRef(); // IPDL reference
|
||||
|
||||
sIndirectLayerTrees[layersId].mCrossProcessParent = this;
|
||||
sIndirectLayerTrees[layersId].mWrBridge = parent;
|
||||
*aTextureFactoryIdentifier = parent->GetTextureFactoryIdentifier();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "mozilla/layers/WebRenderLayer.h"
|
||||
#include "UnitTransforms.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -17,33 +18,6 @@ StackingContextHelper::StackingContextHelper()
|
|||
// mOrigin remains at 0,0
|
||||
}
|
||||
|
||||
StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
LayerRect aBoundForSC,
|
||||
LayerPoint aOrigin,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters,
|
||||
const gfx::CompositionOp& aMixBlendMode)
|
||||
: mBuilder(&aBuilder)
|
||||
{
|
||||
wr::LayoutRect scBounds = aParentSC.ToRelativeLayoutRect(aBoundForSC);
|
||||
if (aTransformPtr) {
|
||||
mTransform = *aTransformPtr;
|
||||
}
|
||||
|
||||
mBuilder->PushStackingContext(scBounds,
|
||||
aAnimationsId,
|
||||
aOpacityPtr,
|
||||
aTransformPtr,
|
||||
wr::TransformStyle::Flat,
|
||||
wr::ToMixBlendMode(aMixBlendMode),
|
||||
aFilters);
|
||||
|
||||
mOrigin = aOrigin;
|
||||
}
|
||||
|
||||
StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
WebRenderLayer* aLayer,
|
||||
|
@ -88,6 +62,47 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
|
|||
mOrigin = aLayer->Bounds().TopLeft();
|
||||
}
|
||||
|
||||
StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsDisplayList* aDisplayList,
|
||||
gfx::Matrix4x4Typed<LayerPixel, LayerPixel>* aBoundTransform,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters,
|
||||
const gfx::CompositionOp& aMixBlendMode)
|
||||
: mBuilder(&aBuilder)
|
||||
{
|
||||
nsRect itemBounds = aDisplayList->GetClippedBoundsWithRespectToASR(aDisplayListBuilder, aItem->GetActiveScrolledRoot());
|
||||
nsRect childrenVisible = aItem->GetVisibleRectForChildren();
|
||||
nsRect visibleRect = itemBounds.Intersect(childrenVisible);
|
||||
float appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
|
||||
LayerRect bounds = ViewAs<LayerPixel>(LayoutDeviceRect::FromAppUnits(visibleRect, appUnitsPerDevPixel),
|
||||
PixelCastJustification::WebRenderHasUnitResolution);
|
||||
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
if (aBoundTransform && !aBoundTransform->IsIdentity()) {
|
||||
bounds.MoveTo(aBoundTransform->TransformPoint(bounds.TopLeft()));
|
||||
}
|
||||
|
||||
wr::LayoutRect scBounds = aParentSC.ToRelativeLayoutRect(bounds);
|
||||
if (aTransformPtr) {
|
||||
mTransform = *aTransformPtr;
|
||||
}
|
||||
|
||||
mBuilder->PushStackingContext(scBounds,
|
||||
aAnimationsId,
|
||||
aOpacityPtr,
|
||||
aTransformPtr,
|
||||
wr::TransformStyle::Flat,
|
||||
wr::ToMixBlendMode(aMixBlendMode),
|
||||
aFilters);
|
||||
|
||||
mOrigin = bounds.TopLeft();
|
||||
}
|
||||
|
||||
StackingContextHelper::~StackingContextHelper()
|
||||
{
|
||||
if (mBuilder) {
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "Units.h"
|
||||
|
||||
class nsDisplayListBuilder;
|
||||
class nsDisplayItem;
|
||||
class nsDisplayList;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -45,8 +49,10 @@ public:
|
|||
// The constructor for layers-free mode.
|
||||
StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
LayerRect aBoundForSC,
|
||||
LayerPoint aOrigin,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsDisplayList* aDisplayList,
|
||||
gfx::Matrix4x4Typed<LayerPixel, LayerPixel>* aBoundTransform,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
|
|
|
@ -1266,6 +1266,7 @@ gfxDWriteFontList::GetStandardFamilyName(const nsAString& aFontName,
|
|||
bool
|
||||
gfxDWriteFontList::FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle,
|
||||
gfxFloat aDevToCssSize)
|
||||
{
|
||||
|
@ -1282,7 +1283,10 @@ gfxDWriteFontList::FindAndAddFamilies(const nsAString& aFamily,
|
|||
return false;
|
||||
}
|
||||
|
||||
return gfxPlatformFontList::FindAndAddFamilies(aFamily, aOutput, aStyle,
|
||||
return gfxPlatformFontList::FindAndAddFamilies(aFamily,
|
||||
aOutput,
|
||||
aDeferOtherFamilyNamesLoading,
|
||||
aStyle,
|
||||
aDevToCssSize);
|
||||
}
|
||||
|
||||
|
|
|
@ -379,6 +379,7 @@ public:
|
|||
|
||||
bool FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle = nullptr,
|
||||
gfxFloat aDevToCssSize = 1.0) override;
|
||||
|
||||
|
|
|
@ -1483,6 +1483,7 @@ gfxFcPlatformFontList::MakePlatformFont(const nsAString& aFontName,
|
|||
bool
|
||||
gfxFcPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle,
|
||||
gfxFloat aDevToCssSize)
|
||||
{
|
||||
|
@ -1565,7 +1566,9 @@ gfxFcPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
|||
FcStrCmp(substName, sentinelFirstFamily) == 0) {
|
||||
break;
|
||||
}
|
||||
gfxPlatformFontList::FindAndAddFamilies(subst, &cachedFamilies);
|
||||
gfxPlatformFontList::FindAndAddFamilies(subst,
|
||||
&cachedFamilies,
|
||||
aDeferOtherFamilyNamesLoading);
|
||||
}
|
||||
|
||||
// Cache the resulting list, so we don't have to do this again.
|
||||
|
@ -1847,7 +1850,8 @@ gfxFcPlatformFontList::FindGenericFamilies(const nsAString& aGeneric,
|
|||
NS_ConvertUTF8toUTF16 mappedGenericName(ToCharPtr(mappedGeneric));
|
||||
AutoTArray<gfxFontFamily*,1> genericFamilies;
|
||||
if (gfxPlatformFontList::FindAndAddFamilies(mappedGenericName,
|
||||
&genericFamilies)) {
|
||||
&genericFamilies,
|
||||
true)) {
|
||||
MOZ_ASSERT(genericFamilies.Length() == 1,
|
||||
"expected a single family");
|
||||
if (!prefFonts->Contains(genericFamilies[0])) {
|
||||
|
|
|
@ -251,6 +251,7 @@ public:
|
|||
|
||||
bool FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle = nullptr,
|
||||
gfxFloat aDevToCssSize = 1.0) override;
|
||||
|
||||
|
|
|
@ -912,6 +912,7 @@ gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
|
|||
bool
|
||||
gfxGDIFontList::FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle,
|
||||
gfxFloat aDevToCssSize)
|
||||
{
|
||||
|
@ -928,7 +929,10 @@ gfxGDIFontList::FindAndAddFamilies(const nsAString& aFamily,
|
|||
return false;
|
||||
}
|
||||
|
||||
return gfxPlatformFontList::FindAndAddFamilies(aFamily, aOutput, aStyle,
|
||||
return gfxPlatformFontList::FindAndAddFamilies(aFamily,
|
||||
aOutput,
|
||||
aDeferOtherFamilyNamesLoading,
|
||||
aStyle,
|
||||
aDevToCssSize);
|
||||
}
|
||||
|
||||
|
|
|
@ -309,6 +309,7 @@ public:
|
|||
|
||||
bool FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle = nullptr,
|
||||
gfxFloat aDevToCssSize = 1.0) override;
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ public:
|
|||
|
||||
bool FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle = nullptr,
|
||||
gfxFloat aDevToCssSize = 1.0) override;
|
||||
|
||||
|
|
|
@ -1253,6 +1253,7 @@ static const char kSystemFont_system[] = "-apple-system";
|
|||
bool
|
||||
gfxMacPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle,
|
||||
gfxFloat aDevToCssSize)
|
||||
{
|
||||
|
@ -1267,7 +1268,10 @@ gfxMacPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
|||
return true;
|
||||
}
|
||||
|
||||
return gfxPlatformFontList::FindAndAddFamilies(aFamily, aOutput, aStyle,
|
||||
return gfxPlatformFontList::FindAndAddFamilies(aFamily,
|
||||
aOutput,
|
||||
aDeferOtherFamilyNamesLoading,
|
||||
aStyle,
|
||||
aDevToCssSize);
|
||||
}
|
||||
|
||||
|
|
|
@ -266,9 +266,11 @@ gfxPlatformFontList::InitFontList()
|
|||
|
||||
gfxPlatform::PurgeSkiaFontCache();
|
||||
|
||||
CancelInitOtherFamilyNamesTask();
|
||||
mFontFamilies.Clear();
|
||||
mOtherFamilyNames.Clear();
|
||||
mOtherFamilyNamesInitialized = false;
|
||||
|
||||
if (mExtraNames) {
|
||||
mExtraNames->mFullnames.Clear();
|
||||
mExtraNames->mPostscriptNames.Clear();
|
||||
|
@ -304,37 +306,20 @@ gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& a
|
|||
#define OTHERNAMES_TIMEOUT 200
|
||||
|
||||
void
|
||||
gfxPlatformFontList::InitOtherFamilyNames()
|
||||
gfxPlatformFontList::InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading)
|
||||
{
|
||||
if (mOtherFamilyNamesInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
bool timedOut = false;
|
||||
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<gfxFontFamily>& family = iter.Data();
|
||||
family->ReadOtherFamilyNames(this);
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
|
||||
timedOut = true;
|
||||
break;
|
||||
if (aDeferOtherFamilyNamesLoading) {
|
||||
if (!mPendingOtherFamilyNameTask) {
|
||||
RefPtr<mozilla::CancelableRunnable> task = new InitOtherFamilyNamesRunnable();
|
||||
mPendingOtherFamilyNameTask = task;
|
||||
NS_IdleDispatchToCurrentThread(task.forget());
|
||||
}
|
||||
}
|
||||
|
||||
if (!timedOut) {
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
}
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES,
|
||||
start, end);
|
||||
|
||||
if (LOG_FONTINIT_ENABLED()) {
|
||||
TimeDuration elapsed = end - start;
|
||||
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s",
|
||||
elapsed.ToMilliseconds(),
|
||||
(timedOut ? "timeout" : "")));
|
||||
} else {
|
||||
InitOtherFamilyNamesInternal(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,8 +352,8 @@ gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName)
|
|||
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) {
|
||||
timedOut = true;
|
||||
break;
|
||||
timedOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,9 +682,10 @@ gfxPlatformFontList::CheckFamily(gfxFontFamily *aFamily)
|
|||
return aFamily;
|
||||
}
|
||||
|
||||
bool
|
||||
bool
|
||||
gfxPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle,
|
||||
gfxFloat aDevToCssSize)
|
||||
{
|
||||
|
@ -722,7 +708,7 @@ gfxPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
|||
// although ASCII localized family names are possible they don't occur
|
||||
// in practice so avoid pulling in names at startup
|
||||
if (!familyEntry && !mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
|
||||
InitOtherFamilyNames();
|
||||
InitOtherFamilyNames(aDeferOtherFamilyNamesLoading);
|
||||
familyEntry = mOtherFamilyNames.GetWeak(key);
|
||||
if (!familyEntry && !mOtherFamilyNamesInitialized) {
|
||||
// localized family names load timed out, add name to list of
|
||||
|
@ -896,7 +882,7 @@ gfxPlatformFontList::ResolveGenericFontNames(
|
|||
style.language = langGroup;
|
||||
style.systemFont = false;
|
||||
AutoTArray<gfxFontFamily*,10> families;
|
||||
FindAndAddFamilies(genericFamily, &families, &style);
|
||||
FindAndAddFamilies(genericFamily, &families, true, &style);
|
||||
for (gfxFontFamily* f : families) {
|
||||
if (!aGenericFamilies->Contains(f)) {
|
||||
aGenericFamilies->AppendElement(f);
|
||||
|
@ -1495,13 +1481,14 @@ gfxPlatformFontList::LoadFontInfo()
|
|||
|
||||
if (done) {
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
CancelInitOtherFamilyNamesTask();
|
||||
mFaceNameListsInitialized = true;
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
gfxPlatformFontList::CleanupLoader()
|
||||
{
|
||||
mFontFamiliesToLoad.Clear();
|
||||
|
@ -1522,7 +1509,7 @@ gfxPlatformFontList::CleanupLoader()
|
|||
|
||||
if (mOtherNamesMissed) {
|
||||
for (auto it = mOtherNamesMissed->Iter(); !it.Done(); it.Next()) {
|
||||
if (FindFamily(it.Get()->GetKey())) {
|
||||
if (FindFamily(it.Get()->GetKey(), false)) {
|
||||
forceReflow = true;
|
||||
ForceGlobalReflow();
|
||||
break;
|
||||
|
@ -1691,5 +1678,72 @@ gfxPlatformFontList::IsFontFamilyWhitelistActive()
|
|||
return mFontFamilyWhitelistActive;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading)
|
||||
{
|
||||
if (mOtherFamilyNamesInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDeferOtherFamilyNamesLoading) {
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
bool timedOut = false;
|
||||
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<gfxFontFamily>& family = iter.Data();
|
||||
family->ReadOtherFamilyNames(this);
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
|
||||
timedOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!timedOut) {
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
CancelInitOtherFamilyNamesTask();
|
||||
}
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES,
|
||||
start, end);
|
||||
|
||||
if (LOG_FONTINIT_ENABLED()) {
|
||||
TimeDuration elapsed = end - start;
|
||||
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s",
|
||||
elapsed.ToMilliseconds(),
|
||||
(timedOut ? "timeout" : "")));
|
||||
}
|
||||
} else {
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<gfxFontFamily>& family = iter.Data();
|
||||
family->ReadOtherFamilyNames(this);
|
||||
}
|
||||
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
CancelInitOtherFamilyNamesTask();
|
||||
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES_NO_DEFERRING,
|
||||
start, end);
|
||||
|
||||
if (LOG_FONTINIT_ENABLED()) {
|
||||
TimeDuration elapsed = end - start;
|
||||
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames without deferring took %8.2f ms",
|
||||
elapsed.ToMilliseconds()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::CancelInitOtherFamilyNamesTask()
|
||||
{
|
||||
if (mPendingOtherFamilyNameTask) {
|
||||
mPendingOtherFamilyNameTask->Cancel();
|
||||
mPendingOtherFamilyNameTask = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
|
|
|
@ -90,6 +90,8 @@ class gfxUserFontSet;
|
|||
|
||||
class gfxPlatformFontList : public gfxFontInfoLoader
|
||||
{
|
||||
friend class InitOtherFamilyNamesRunnable;
|
||||
|
||||
public:
|
||||
typedef mozilla::unicode::Script Script;
|
||||
|
||||
|
@ -137,6 +139,7 @@ public:
|
|||
virtual bool
|
||||
FindAndAddFamilies(const nsAString& aFamily,
|
||||
nsTArray<gfxFontFamily*>* aOutput,
|
||||
bool aDeferOtherFamilyNamesLoading,
|
||||
gfxFontStyle* aStyle = nullptr,
|
||||
gfxFloat aDevToCssSize = 1.0);
|
||||
|
||||
|
@ -262,6 +265,42 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable
|
||||
{
|
||||
public:
|
||||
InitOtherFamilyNamesRunnable()
|
||||
: CancelableRunnable("gfxPlatformFontList::InitOtherFamilyNamesRunnable")
|
||||
, mIsCanceled(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
if (mIsCanceled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
|
||||
if (!fontList) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
fontList->InitOtherFamilyNamesInternal(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual nsresult Cancel() override
|
||||
{
|
||||
mIsCanceled = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mIsCanceled;
|
||||
};
|
||||
|
||||
class MemoryReporter final : public nsIMemoryReporter
|
||||
{
|
||||
~MemoryReporter() {}
|
||||
|
@ -318,12 +357,17 @@ protected:
|
|||
// Convenience method to return the first matching family (if any) as found
|
||||
// by FindAndAddFamilies().
|
||||
gfxFontFamily*
|
||||
FindFamily(const nsAString& aFamily, gfxFontStyle* aStyle = nullptr,
|
||||
FindFamily(const nsAString& aFamily,
|
||||
bool aDeferOtherFamilyNamesLoading = true,
|
||||
gfxFontStyle* aStyle = nullptr,
|
||||
gfxFloat aDevToCssSize = 1.0)
|
||||
{
|
||||
AutoTArray<gfxFontFamily*,1> families;
|
||||
return FindAndAddFamilies(aFamily, &families, aStyle, aDevToCssSize)
|
||||
? families[0] : nullptr;
|
||||
return FindAndAddFamilies(aFamily,
|
||||
&families,
|
||||
aDeferOtherFamilyNamesLoading,
|
||||
aStyle,
|
||||
aDevToCssSize) ? families[0] : nullptr;
|
||||
}
|
||||
|
||||
// Lookup family name in global family list without substitutions or
|
||||
|
@ -374,7 +418,9 @@ protected:
|
|||
gfxFontFamily* CheckFamily(gfxFontFamily *aFamily);
|
||||
|
||||
// initialize localized family names
|
||||
void InitOtherFamilyNames();
|
||||
void InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading);
|
||||
void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading);
|
||||
void CancelInitOtherFamilyNamesTask();
|
||||
|
||||
// search through font families, looking for a given name, initializing
|
||||
// facename lists along the way. first checks all families with names
|
||||
|
@ -454,6 +500,9 @@ protected:
|
|||
// flag set after InitOtherFamilyNames is called upon first name lookup miss
|
||||
bool mOtherFamilyNamesInitialized;
|
||||
|
||||
// The pending InitOtherFamilyNames() task.
|
||||
RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask;
|
||||
|
||||
// flag set after fullname and Postcript name lists are populated
|
||||
bool mFaceNameListsInitialized;
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче