merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: CsjtXJM2vcs
|
@ -1,7 +1,7 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-opacity=".05" d="M15,2H1v12c0,0.6,0.5,1,1,1h12c0.6,0,1-0.4,1-1V2L15,2z"/>
|
||||
<path d="M3,5v1h2V5H3z M3,9h2V8H3V9z M3,12h2v-1H3V12z"/>
|
||||
<path fill-opacity=".9" d="M6,5v1h7V5H6z M12,8H6v1h6V8z M6,12h7v-1H6V12z"/>
|
||||
|
|
До Ширина: | Высота: | Размер: 687 B После Ширина: | Высота: | Размер: 723 B |
|
@ -1,7 +1,7 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-opacity=".15" d="M15,14H1c-0.6,0-1-0.4-1-1V3c0-0.5,0.4-1,1-1h14c0.6,0,1,0.5,1,1v10C16,13.6,15.6,14,15,14z"/>
|
||||
<path d="M8.4,4.2l1,2.1l2.3,0.3c0.3,0,0.5,0.4,0.2,0.7l-1.7,1.7l0.4,2.4c0.1,0.3-0.3,0.6-0.6,0.4L8,10.8L6,12 c-0.3,0.1-0.6-0.1-0.6-0.4l0.4-2.4L4.1,7.4C3.9,7.2,4,6.8,4.3,6.7l2.3-0.3l1-2.1C7.8,3.9,8.2,3.9,8.4,4.2z"/>
|
||||
<path d="M15,2H1C0.5,2,0,2.5,0,3v10c0,0.5,0.5,1,1,1h14c0.5,0,1-0.5,1-1V3C16,2.5,15.5,2,15,2z M15,12.5 c0,0.3-0.2,0.5-0.5,0.5h-13C1.2,13,1,12.8,1,12.5v-9C1,3.2,1.2,3,1.5,3h13C14.8,3,15,3.2,15,3.5V12.5z"/>
|
||||
|
|
До Ширина: | Высота: | Размер: 866 B После Ширина: | Высота: | Размер: 902 B |
|
@ -1,6 +1,6 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="context-fill" d="M3.5,10A2.5,2.5,0,1,0,6,12.5,2.5,2.5,0,0,0,3.5,10ZM2,1A1,1,0,0,0,2,3,10.883,10.883,0,0,1,13,14a1,1,0,0,0,2,0A12.862,12.862,0,0,0,2,1ZM2,5A1,1,0,0,0,2,7a6.926,6.926,0,0,1,7,7,1,1,0,0,0,2,0A8.9,8.9,0,0,0,2,5Z"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.5,10A2.5,2.5,0,1,0,6,12.5,2.5,2.5,0,0,0,3.5,10ZM2,1A1,1,0,0,0,2,3,10.883,10.883,0,0,1,13,14a1,1,0,0,0,2,0A12.862,12.862,0,0,0,2,1ZM2,5A1,1,0,0,0,2,7a6.926,6.926,0,0,1,7,7,1,1,0,0,0,2,0A8.9,8.9,0,0,0,2,5Z"/>
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 544 B После Ширина: | Высота: | Размер: 580 B |
|
@ -1,6 +1,6 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="context-fill" d="M14,7H12.9a4.967,4.967,0,0,0-.732-1.753l.782-.783A1,1,0,1,0,11.535,3.05l-.782.783A4.968,4.968,0,0,0,9,3.1V2A1,1,0,0,0,7,2V3.1a4.968,4.968,0,0,0-1.753.732L4.464,3.05A1,1,0,0,0,3.05,4.464l.783.783A4.968,4.968,0,0,0,3.1,7H2A1,1,0,0,0,2,9H3.1a4.968,4.968,0,0,0,.732,1.753l-.783.782a1,1,0,1,0,1.414,1.414l.783-.782A4.967,4.967,0,0,0,7,12.9V14a1,1,0,0,0,2,0V12.9a4.968,4.968,0,0,0,1.753-.732l.782.782a1,1,0,0,0,1.414-1.414l-.782-.782A4.968,4.968,0,0,0,12.9,9H14a1,1,0,0,0,0-2ZM8,11a3,3,0,1,1,3-3A3,3,0,0,1,8,11Z"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14,7H12.9a4.967,4.967,0,0,0-.732-1.753l.782-.783A1,1,0,1,0,11.535,3.05l-.782.783A4.968,4.968,0,0,0,9,3.1V2A1,1,0,0,0,7,2V3.1a4.968,4.968,0,0,0-1.753.732L4.464,3.05A1,1,0,0,0,3.05,4.464l.783.783A4.968,4.968,0,0,0,3.1,7H2A1,1,0,0,0,2,9H3.1a4.968,4.968,0,0,0,.732,1.753l-.783.782a1,1,0,1,0,1.414,1.414l.783-.782A4.967,4.967,0,0,0,7,12.9V14a1,1,0,0,0,2,0V12.9a4.968,4.968,0,0,0,1.753-.732l.782.782a1,1,0,0,0,1.414-1.414l-.782-.782A4.968,4.968,0,0,0,12.9,9H14a1,1,0,0,0,0-2ZM8,11a3,3,0,1,1,3-3A3,3,0,0,1,8,11Z"/>
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 843 B После Ширина: | Высота: | Размер: 880 B |
|
@ -1,7 +1,7 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-opacity=".15" d="M5,1H1C0.4,1,0,1.4,0,2v12.1C0,14.6,0.4,15,0.9,15h14.2c0.5,0,0.9-0.4,0.9-0.9V3.9C16,3.4,15.6,3,15.1,3H7 L6.2,1.9C6.2,1.9,5.6,1,5,1L5,1z"/>
|
||||
<path d="M4.9,2C5,2.1,5.2,2.3,5.4,2.5l0.8,1.1L6.5,4H7h7.5C14.8,4,15,4.2,15,4.5v9c0,0.3-0.2,0.5-0.5,0.5h-13 C1.2,14,1,13.8,1,13.5v-11C1,2.2,1.2,2,1.5,2H4.9 M5,1H1C0.4,1,0,1.4,0,2v12.1C0,14.6,0.4,15,0.9,15h14.2c0.5,0,0.9-0.4,0.9-0.9V3.9 C16,3.4,15.6,3,15.1,3H7L6.2,1.9C6.2,1.9,5.6,1,5,1L5,1z"/>
|
||||
<path fill-opacity=".15" d="M14,5H2C0.9,5,0,5.9,0,7v7c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1V7C16,5.9,15.1,5,14,5L14,5z"/>
|
||||
|
|
До Ширина: | Высота: | Размер: 1.2 KiB После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -1,7 +1,7 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-opacity=".05" d="M12.7,1H3.3l-.2.6L.1,9,0,9.2V13a2.006,2.006,0,0,0,2,2H14a2.006,2.006,0,0,0,2-2V9.2L15.9,9l-3-7.4L12.7,1Z"/>
|
||||
<path d="M12,2l3,7.4V13a.945.945,0,0,1-1,1H2a.945.945,0,0,1-1-1V9.4L4,2h8m.7-1H3.3L.1,9.1,0,9.2V13a2.006,2.006,0,0,0,2,2H14a2.006,2.006,0,0,0,2-2V9.2L15.9,9,12.7,1Z"/>
|
||||
<path fill-opacity=".05" d="M14.988,9,12,2H4L.851,9H5.023A2.931,2.931,0,0,0,8,11.6,2.889,2.889,0,0,0,11.012,9Z"/>
|
||||
|
|
До Ширина: | Высота: | Размер: 823 B После Ширина: | Высота: | Размер: 859 B |
|
@ -526,8 +526,9 @@ toolbar[brighttext] {
|
|||
|
||||
.bookmark-item {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: currentColor;
|
||||
fill-opacity: var(--toolbarbutton-icon-fill-opacity);
|
||||
}
|
||||
|
||||
.bookmark-item[container] {
|
||||
|
|
|
@ -258,6 +258,7 @@ def get_tool(config, key):
|
|||
# clang/
|
||||
# bin/
|
||||
# clang-tidy
|
||||
# clang-apply-replacements
|
||||
# include/
|
||||
# * (nothing will be deleted here)
|
||||
# lib/
|
||||
|
@ -278,8 +279,10 @@ def prune_final_dir_for_clang_tidy(final_dir):
|
|||
if not os.path.isdir(f):
|
||||
raise Exception("Expected %s to be a directory" %f)
|
||||
|
||||
# In bin/, only keep clang-tidy.
|
||||
re_clang_tidy = re.compile(r"^clang-tidy(\.exe)?$", re.I)
|
||||
# In bin/, only keep clang-tidy and clang-apply-replacements. The last one
|
||||
# is used to auto-fix some of the issues detected by clang-tidy.
|
||||
re_clang_tidy = re.compile(
|
||||
r"^clang-(tidy|apply-replacements)(\.exe)?$", re.I)
|
||||
for f in glob.glob("%s/bin/*" % final_dir):
|
||||
if re_clang_tidy.search(os.path.basename(f)) is None:
|
||||
delete(f)
|
||||
|
|
|
@ -59,7 +59,7 @@ pref("devtools.inspector.showAllAnonymousContent", false);
|
|||
// Enable the new color widget
|
||||
pref("devtools.inspector.colorWidget.enabled", false);
|
||||
// Enable the CSS shapes highlighter
|
||||
pref("devtools.inspector.shapesHighlighter.enabled", false);
|
||||
pref("devtools.inspector.shapesHighlighter.enabled", true);
|
||||
|
||||
// Enable the Font Inspector
|
||||
pref("devtools.fontinspector.enabled", true);
|
||||
|
|
|
@ -29,6 +29,7 @@ const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
|
|||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
|
||||
const CSS_SHAPES_ENABLED_PREF = "devtools.inspector.shapesHighlighter.enabled";
|
||||
const CSS_SHAPE_OUTSIDE_ENABLED_PREF = "layout.css.shape-outside.enabled";
|
||||
|
||||
/**
|
||||
* This module is used to process text for output by developer tools. This means
|
||||
|
@ -88,7 +89,9 @@ OutputParser.prototype = {
|
|||
options.expectCubicBezier = this.supportsType(name, CSS_TYPES.TIMING_FUNCTION);
|
||||
options.expectDisplay = name === "display";
|
||||
options.expectFilter = name === "filter";
|
||||
options.expectShape = name === "clip-path" || name === "shape-outside";
|
||||
options.expectShape = name === "clip-path" ||
|
||||
(name === "shape-outside"
|
||||
&& Services.prefs.getBoolPref(CSS_SHAPE_OUTSIDE_ENABLED_PREF));
|
||||
options.supportsColor = this.supportsType(name, CSS_TYPES.COLOR) ||
|
||||
this.supportsType(name, CSS_TYPES.GRADIENT);
|
||||
|
||||
|
|
|
@ -2087,12 +2087,12 @@ protected:
|
|||
mozilla::ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Parse the given selector string into a SelectorList.
|
||||
* Parse the given selector string a SelectorList, depending on whether we're
|
||||
* in a Servo or Gecko-backed document, and execute either aServoFunctor or
|
||||
* aGeckoFunctor on it.
|
||||
*
|
||||
* A null return value with a non-failing aRv means the string only
|
||||
* contained pseudo-element selectors.
|
||||
*
|
||||
* A failing aRv means the string was not a valid selector.
|
||||
* Note that the selector list is owned by the owner doc's selector cache
|
||||
* which can get expired, so you shouldn't keep it around for long.
|
||||
*/
|
||||
template<typename Ret, typename ServoFunctor, typename GeckoFunctor>
|
||||
Ret WithSelectorList(
|
||||
|
|
|
@ -875,10 +875,10 @@ LockedDirectoryPaddingRestore(nsIFile* aBaseDir, mozIStorageConnection* aConn)
|
|||
|
||||
// The content of padding file is untrusted, so remove it here.
|
||||
nsresult rv = LockedDirectoryPaddingDeleteFile(aBaseDir,
|
||||
DirPaddingFile::TMP_FILE);
|
||||
DirPaddingFile::FILE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE);
|
||||
rv = LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
int64_t paddingSize = 0;
|
||||
|
|
|
@ -495,6 +495,13 @@ public:
|
|||
virtual void
|
||||
CompleteOnInitiatingThread(nsresult aRv) override
|
||||
{
|
||||
// If the transaction fails, we shouldn't delete the body files and decrease
|
||||
// their padding size.
|
||||
if (NS_FAILED(aRv)) {
|
||||
mDeletedBodyIdList.Clear();
|
||||
mDeletedPaddingSize = 0;
|
||||
}
|
||||
|
||||
mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
|
||||
|
||||
if (mDeletedPaddingSize > 0) {
|
||||
|
@ -867,6 +874,13 @@ private:
|
|||
mList[i].mResponseStream = nullptr;
|
||||
}
|
||||
|
||||
// If the transaction fails, we shouldn't delete the body files and decrease
|
||||
// their padding size.
|
||||
if (NS_FAILED(aRv)) {
|
||||
mDeletedBodyIdList.Clear();
|
||||
mDeletedPaddingSize = 0;
|
||||
}
|
||||
|
||||
mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
|
||||
|
||||
if (mDeletedPaddingSize > 0) {
|
||||
|
@ -1107,6 +1121,13 @@ public:
|
|||
virtual void
|
||||
Complete(Listener* aListener, ErrorResult&& aRv) override
|
||||
{
|
||||
// If the transaction fails, we shouldn't delete the body files and decrease
|
||||
// their padding size.
|
||||
if (aRv.Failed()) {
|
||||
mDeletedBodyIdList.Clear();
|
||||
mDeletedPaddingSize = 0;
|
||||
}
|
||||
|
||||
mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
|
||||
|
||||
if (mDeletedPaddingSize > 0) {
|
||||
|
|
|
@ -329,23 +329,34 @@ public:
|
|||
aDecreaseSize,
|
||||
temporaryPaddingFileExist);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mozilla::dom::cache::
|
||||
LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE);
|
||||
// Don't delete the temporary padding file here to force the next action
|
||||
// recalculate the padding size.
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = aCommitHook();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mozilla::dom::cache::
|
||||
LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE);
|
||||
// Don't delete the temporary padding file here to force the next action
|
||||
// recalculate the padding size.
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mozilla::dom::cache::LockedDirectoryPaddingFinalizeWrite(aBaseDir);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Force restore file next time.
|
||||
mozilla::dom::cache::
|
||||
LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE);
|
||||
Unused << mozilla::dom::cache::
|
||||
LockedDirectoryPaddingDeleteFile(aBaseDir,
|
||||
DirPaddingFile::FILE);
|
||||
|
||||
// Ensure that we are able to force the padding file to be restored.
|
||||
MOZ_ASSERT(
|
||||
mozilla::dom::cache::
|
||||
DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
|
||||
|
||||
// Since both the body file and header have been stored in the
|
||||
// file-system, just make the action be resolve and let the padding file
|
||||
// be restored in the next action.
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,8 @@ WebRenderBridgeChild::UpdateResources(wr::IpcResourceUpdateQueue& aResources)
|
|||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeChild::EndTransaction(wr::DisplayListBuilder &aBuilder,
|
||||
WebRenderBridgeChild::EndTransaction(const wr::LayoutSize& aContentSize,
|
||||
wr::BuiltDisplayList& aDL,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
const gfx::IntSize& aSize,
|
||||
bool aIsSync,
|
||||
|
@ -126,10 +127,7 @@ WebRenderBridgeChild::EndTransaction(wr::DisplayListBuilder &aBuilder,
|
|||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(mIsInTransaction);
|
||||
|
||||
wr::BuiltDisplayList dl;
|
||||
wr::LayoutSize contentSize;
|
||||
aBuilder.Finalize(contentSize, dl);
|
||||
ByteBuffer dlData(Move(dl.dl));
|
||||
ByteBuffer dlData(Move(aDL.dl));
|
||||
|
||||
TimeStamp fwdTime;
|
||||
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
||||
|
@ -144,13 +142,13 @@ WebRenderBridgeChild::EndTransaction(wr::DisplayListBuilder &aBuilder,
|
|||
if (aIsSync) {
|
||||
this->SendSetDisplayListSync(aSize, mParentCommands, mDestroyedActors,
|
||||
GetFwdTransactionId(), aTransactionId,
|
||||
contentSize, dlData, dl.dl_desc, aScrollData,
|
||||
aContentSize, dlData, aDL.dl_desc, aScrollData,
|
||||
Move(resourceUpdates), Move(smallShmems), Move(largeShmems),
|
||||
mIdNamespace, aTxnStartTime, fwdTime);
|
||||
} else {
|
||||
this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
|
||||
GetFwdTransactionId(), aTransactionId,
|
||||
contentSize, dlData, dl.dl_desc, aScrollData,
|
||||
aContentSize, dlData, aDL.dl_desc, aScrollData,
|
||||
Move(resourceUpdates), Move(smallShmems), Move(largeShmems),
|
||||
mIdNamespace, aTxnStartTime, fwdTime);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,8 @@ public:
|
|||
|
||||
void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
|
||||
bool BeginTransaction(const gfx::IntSize& aSize);
|
||||
void EndTransaction(wr::DisplayListBuilder &aBuilder,
|
||||
void EndTransaction(const wr::LayoutSize& aContentSize,
|
||||
wr::BuiltDisplayList& dl,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
const gfx::IntSize& aSize,
|
||||
bool aIsSync, uint64_t aTransactionId,
|
||||
|
|
|
@ -49,8 +49,6 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
|
|||
CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc,
|
||||
aBuilder, aResourceUpdates);
|
||||
|
||||
aBuilder.Finalize(aContentSize, mBuiltDisplayList);
|
||||
|
||||
// Make a "root" layer data that has everything else as descendants
|
||||
mLayerScrollData.emplace_back();
|
||||
mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
|
||||
|
@ -81,7 +79,6 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
|
|||
RemoveUnusedAndResetWebRenderUserData();
|
||||
}
|
||||
|
||||
aBuilder.PushBuiltDisplayList(mBuiltDisplayList);
|
||||
mManager->WrBridge()->AddWebRenderParentCommands(mParentCommands);
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,6 @@ private:
|
|||
|
||||
// These fields are used to save a copy of the display list for
|
||||
// empty transactions in layers-free mode.
|
||||
wr::BuiltDisplayList mBuiltDisplayList;
|
||||
nsTArray<WebRenderParentCommand> mParentCommands;
|
||||
|
||||
// We use this as a temporary data structure while building the mScrollData
|
||||
|
|
|
@ -34,6 +34,7 @@ WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
|
|||
, mTarget(nullptr)
|
||||
, mPaintSequenceNumber(0)
|
||||
, mWebRenderCommandBuilder(this)
|
||||
, mLastDisplayListSize(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WebRenderLayerManager);
|
||||
}
|
||||
|
@ -244,7 +245,7 @@ WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
|||
DiscardCompositorAnimations();
|
||||
|
||||
wr::LayoutSize contentSize { (float)size.width, (float)size.height };
|
||||
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
|
||||
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize, mLastDisplayListSize);
|
||||
wr::IpcResourceUpdateQueue resourceUpdates(WrBridge()->GetShmemAllocator());
|
||||
|
||||
mWebRenderCommandBuilder.BuildWebRenderCommands(builder,
|
||||
|
@ -295,10 +296,15 @@ WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
|||
WrBridge()->GetSyncObject()->Synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
wr::BuiltDisplayList dl;
|
||||
builder.Finalize(contentSize, dl);
|
||||
mLastDisplayListSize = dl.dl.inner.capacity;
|
||||
|
||||
{
|
||||
AutoProfilerTracing
|
||||
tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
|
||||
WrBridge()->EndTransaction(builder, resourceUpdates, size.ToUnknownSize(), sync,
|
||||
WrBridge()->EndTransaction(contentSize, dl, resourceUpdates, size.ToUnknownSize(), sync,
|
||||
mLatestTransactionId, mScrollData, transactionStart);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,8 @@ private:
|
|||
APZTestData mApzTestData;
|
||||
|
||||
WebRenderCommandBuilder mWebRenderCommandBuilder;
|
||||
|
||||
size_t mLastDisplayListSize;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -538,7 +538,7 @@ private:
|
|||
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram", FPSPrintHistogram, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.acceleration.force-enabled", LayersAccelerationForceEnabledDoNotUseDirectly, bool, false);
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.background-color", LayersAllowBackgroundColorLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_GFX_PREF(Live, "layers.advanced.background-color", LayersAllowBackgroundColorLayers, bool, false);
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.background-image", LayersAllowBackgroundImage, gfxPrefs::OverrideBase_WebRender());
|
||||
DECL_GFX_PREF(Live, "layers.advanced.basic-layer.enabled", LayersAdvancedBasicLayerEnabled, bool, false);
|
||||
DECL_OVERRIDE_PREF(Live, "layers.advanced.border-layers", LayersAllowBorderLayers, gfxPrefs::OverrideBase_WebRender());
|
||||
|
|
|
@ -623,11 +623,12 @@ WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent)
|
|||
}
|
||||
|
||||
DisplayListBuilder::DisplayListBuilder(PipelineId aId,
|
||||
const wr::LayoutSize& aContentSize)
|
||||
const wr::LayoutSize& aContentSize,
|
||||
size_t aCapacity)
|
||||
: mMaskClipCount(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DisplayListBuilder);
|
||||
mWrState = wr_state_new(aId, aContentSize);
|
||||
mWrState = wr_state_new(aId, aContentSize, aCapacity);
|
||||
}
|
||||
|
||||
DisplayListBuilder::~DisplayListBuilder()
|
||||
|
|
|
@ -202,7 +202,8 @@ protected:
|
|||
class DisplayListBuilder {
|
||||
public:
|
||||
explicit DisplayListBuilder(wr::PipelineId aId,
|
||||
const wr::LayoutSize& aContentSize);
|
||||
const wr::LayoutSize& aContentSize,
|
||||
size_t aCapacity = 0);
|
||||
DisplayListBuilder(DisplayListBuilder&&) = default;
|
||||
|
||||
~DisplayListBuilder();
|
||||
|
|
|
@ -1062,6 +1062,15 @@ impl WebRenderFrameBuilder {
|
|||
dl_builder: webrender_api::DisplayListBuilder::new(root_pipeline_id, content_size),
|
||||
}
|
||||
}
|
||||
pub fn with_capacity(root_pipeline_id: WrPipelineId,
|
||||
content_size: LayoutSize,
|
||||
capacity: usize) -> WebRenderFrameBuilder {
|
||||
WebRenderFrameBuilder {
|
||||
root_pipeline_id: root_pipeline_id,
|
||||
dl_builder: webrender_api::DisplayListBuilder::with_capacity(root_pipeline_id, content_size, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct WrState {
|
||||
|
@ -1071,13 +1080,15 @@ pub struct WrState {
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_state_new(pipeline_id: WrPipelineId,
|
||||
content_size: LayoutSize) -> *mut WrState {
|
||||
content_size: LayoutSize,
|
||||
capacity: usize) -> *mut WrState {
|
||||
assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let state = Box::new(WrState {
|
||||
pipeline_id: pipeline_id,
|
||||
frame_builder: WebRenderFrameBuilder::new(pipeline_id,
|
||||
content_size),
|
||||
frame_builder: WebRenderFrameBuilder::with_capacity(pipeline_id,
|
||||
content_size,
|
||||
capacity),
|
||||
});
|
||||
|
||||
Box::into_raw(state)
|
||||
|
|
|
@ -1307,7 +1307,8 @@ WR_DESTRUCTOR_SAFE_FUNC;
|
|||
|
||||
WR_INLINE
|
||||
WrState *wr_state_new(WrPipelineId aPipelineId,
|
||||
LayoutSize aContentSize)
|
||||
LayoutSize aContentSize,
|
||||
size_t aCapacity)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
|
|
@ -4262,15 +4262,15 @@ nsDisplayBackgroundColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilde
|
|||
mozilla::layers::WebRenderLayerManager* aManager,
|
||||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
ContainerLayerParameters parameter;
|
||||
if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mColor == Color()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[0].mClip;
|
||||
if (clip == StyleGeometryBox::Text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
|
||||
mBackgroundRect, mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
wr::LayoutRect transformedRect = aSc.ToRelativeLayoutRect(bounds);
|
||||
|
|
|
@ -5888,7 +5888,7 @@ pref("layers.mlgpu.enable-on-windows7", true);
|
|||
// it to a boolean as appropriate. In particular, do NOT add ifdefs here to
|
||||
// turn these on and off, instead use the conditional-pref code in gfxPrefs.h
|
||||
// to do that.
|
||||
pref("layers.advanced.background-color", 2);
|
||||
pref("layers.advanced.background-color", false);
|
||||
pref("layers.advanced.background-image", 2);
|
||||
pref("layers.advanced.border-layers", 2);
|
||||
pref("layers.advanced.boxshadow-inset-layers", 2);
|
||||
|
|
|
@ -3320,7 +3320,7 @@ nsCookieService::GetCookiesForURI(nsIURI *aHostURI,
|
|||
}
|
||||
|
||||
// Note: The following permissions logic is mirrored in
|
||||
// toolkit/modules/addons/MatchPattern.jsm:MatchPattern.matchesCookie().
|
||||
// extensions::MatchPattern::MatchesCookie.
|
||||
// If it changes, please update that function, or file a bug for someone
|
||||
// else to do so.
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
/* global tabTracker */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MatchURLFilters",
|
||||
"resource://gre/modules/MatchPattern.jsm");
|
||||
"resource://gre/modules/MatchURLFilters.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebNavigation",
|
||||
"resource://gre/modules/WebNavigation.jsm");
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ skip-if = os == 'android' # Bug 1350559
|
|||
[test_chrome_ext_webrequest_errors.html]
|
||||
[test_chrome_ext_webrequest_host_permissions.html]
|
||||
[test_chrome_ext_webrequest_mozextension.html]
|
||||
skip-if = true # Bug 1404172
|
||||
[test_chrome_native_messaging_paths.html]
|
||||
skip-if = os != "mac" && os != "linux"
|
||||
[test_ext_cookies_expiry.html]
|
||||
|
|
|
@ -1,424 +0,0 @@
|
|||
/* 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";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MatchPattern", "MatchGlobs", "MatchURLFilters"];
|
||||
|
||||
/* globals MatchPattern, MatchGlobs */
|
||||
|
||||
const PERMITTED_SCHEMES = ["http", "https", "ws", "wss", "file", "ftp", "data"];
|
||||
const PERMITTED_SCHEMES_REGEXP = [...PERMITTED_SCHEMES, "moz-extension"].join("|");
|
||||
|
||||
// The basic RE for matching patterns
|
||||
const PATTERN_REGEXP = new RegExp(`^(${PERMITTED_SCHEMES_REGEXP}|\\*)://(\\*|\\*\\.[^*/]+|[^*/]+|)(/.*)$`);
|
||||
|
||||
// The schemes/protocols implied by a pattern that starts with *://
|
||||
const WILDCARD_SCHEMES = ["http", "https"];
|
||||
|
||||
// This function converts a glob pattern (containing * and possibly ?
|
||||
// as wildcards) to a regular expression.
|
||||
function globToRegexp(pat, allowQuestion) {
|
||||
// Escape everything except ? and *.
|
||||
pat = pat.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
||||
|
||||
if (allowQuestion) {
|
||||
pat = pat.replace(/\?/g, ".");
|
||||
} else {
|
||||
pat = pat.replace(/\?/g, "\\?");
|
||||
}
|
||||
pat = pat.replace(/\*/g, ".*");
|
||||
return new RegExp("^" + pat + "$");
|
||||
}
|
||||
|
||||
// These patterns follow the syntax in
|
||||
// https://developer.chrome.com/extensions/match_patterns
|
||||
function SingleMatchPattern(pat) {
|
||||
this.pat = pat;
|
||||
if (pat == "<all_urls>") {
|
||||
this.schemes = PERMITTED_SCHEMES;
|
||||
this.hostMatch = () => true;
|
||||
this.pathMatch = () => true;
|
||||
} else if (!pat) {
|
||||
this.schemes = [];
|
||||
} else {
|
||||
let match = PATTERN_REGEXP.exec(pat);
|
||||
if (!match) {
|
||||
Cu.reportError(`Invalid match pattern: '${pat}'`);
|
||||
this.schemes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (match[1] == "*") {
|
||||
this.schemes = WILDCARD_SCHEMES;
|
||||
} else {
|
||||
this.schemes = [match[1]];
|
||||
}
|
||||
|
||||
// We allow the host to be empty for file URLs.
|
||||
if (match[2] == "" && this.schemes[0] != "file") {
|
||||
Cu.reportError(`Invalid match pattern: '${pat}'`);
|
||||
this.schemes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// We disallow the host to be * for moz-extension URLs.
|
||||
if (match[2] == "*" && this.schemes[0] == "moz-extension") {
|
||||
Cu.reportError(`Invalid match pattern: '${pat}'`);
|
||||
this.schemes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.host = match[2];
|
||||
this.hostMatch = this.getHostMatcher(match[2]);
|
||||
|
||||
let pathMatch = globToRegexp(match[3], false);
|
||||
this.pathMatch = pathMatch.test.bind(pathMatch);
|
||||
}
|
||||
}
|
||||
|
||||
SingleMatchPattern.prototype = {
|
||||
getHostMatcher(host) {
|
||||
// This code ignores the port, as Chrome does.
|
||||
if (host == "*") {
|
||||
return () => true;
|
||||
}
|
||||
if (host.startsWith("*.")) {
|
||||
let suffix = host.substr(2);
|
||||
let dotSuffix = "." + suffix;
|
||||
|
||||
return ({host}) => host === suffix || host.endsWith(dotSuffix);
|
||||
}
|
||||
return uri => uri.host === host;
|
||||
},
|
||||
|
||||
matches(uri, ignorePath = false) {
|
||||
return (
|
||||
this.schemes.includes(uri.scheme) &&
|
||||
this.hostMatch(uri) &&
|
||||
(ignorePath || (
|
||||
this.pathMatch(uri.cloneIgnoringRef().pathQueryRef)
|
||||
))
|
||||
);
|
||||
},
|
||||
|
||||
// Tests if this can possibly overlap with the |other| SingleMatchPattern.
|
||||
overlapsIgnoringPath(other) {
|
||||
return this.schemes.some(scheme => other.schemes.includes(scheme)) &&
|
||||
(this.hostMatch(other) || other.hostMatch(this));
|
||||
},
|
||||
|
||||
get pattern() { return this.pat; },
|
||||
};
|
||||
|
||||
this.MatchPattern = function(pat) {
|
||||
this.pat = pat;
|
||||
if (!pat) {
|
||||
this.matchers = [];
|
||||
} else if (pat instanceof String || typeof(pat) == "string") {
|
||||
this.matchers = [new SingleMatchPattern(pat)];
|
||||
} else {
|
||||
this.matchers = pat.map(p => new SingleMatchPattern(p));
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "explicitMatchers", () => {
|
||||
return this.matchers.filter(matcher => matcher.pat != "<all_urls>" &&
|
||||
matcher.host &&
|
||||
!matcher.host.startsWith("*"));
|
||||
});
|
||||
};
|
||||
|
||||
MatchPattern.prototype = {
|
||||
// |uri| should be an nsIURI.
|
||||
matches(uri) {
|
||||
return this.matchers.some(matcher => matcher.matches(uri));
|
||||
},
|
||||
|
||||
get patterns() { return this.matchers; },
|
||||
|
||||
matchesIgnoringPath(uri, explicit = false) {
|
||||
if (explicit) {
|
||||
return this.explicitMatchers.some(matcher => matcher.matches(uri, true));
|
||||
}
|
||||
return this.matchers.some(matcher => matcher.matches(uri, true));
|
||||
},
|
||||
|
||||
// Checks that this match pattern grants access to read the given
|
||||
// cookie. |cookie| should be an |nsICookie2| instance.
|
||||
matchesCookie(cookie) {
|
||||
// First check for simple matches.
|
||||
let secureURI = NetUtil.newURI(`https://${cookie.rawHost}/`);
|
||||
if (this.matchesIgnoringPath(secureURI)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let plainURI = NetUtil.newURI(`http://${cookie.rawHost}/`);
|
||||
if (!cookie.isSecure && this.matchesIgnoringPath(plainURI)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cookie.isDomain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Things get tricker for domain cookies. The extension needs to be able
|
||||
// to read any cookies that could be read any host it has permissions
|
||||
// for. This means that our normal host matching checks won't work,
|
||||
// since the pattern "*://*.foo.example.com/" doesn't match ".example.com",
|
||||
// but it does match "bar.foo.example.com", which can read cookies
|
||||
// with the domain ".example.com".
|
||||
//
|
||||
// So, instead, we need to manually check our filters, and accept any
|
||||
// with hosts that end with our cookie's host.
|
||||
|
||||
let {host, isSecure} = cookie;
|
||||
|
||||
for (let matcher of this.matchers) {
|
||||
let schemes = matcher.schemes;
|
||||
if (schemes.includes("https") || (!isSecure && schemes.includes("http"))) {
|
||||
if (matcher.host.endsWith(host)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// Checks if every part of this filter overlaps with
|
||||
// some of the |hosts| or |optional| permissions MatchPatterns.
|
||||
overlapsPermissions(hosts, optional) {
|
||||
const perms = hosts.matchers.concat(optional.matchers);
|
||||
return this.matchers.length &&
|
||||
this.matchers.every(m => perms.some(p => p.overlapsIgnoringPath(m)));
|
||||
},
|
||||
|
||||
// Test if this MatchPattern subsumes the given pattern (i.e., whether
|
||||
// this pattern matches everything the given pattern does).
|
||||
// Note, this method considers only to protocols and hosts/domains,
|
||||
// paths are ignored.
|
||||
subsumes(pattern) {
|
||||
let match = PATTERN_REGEXP.exec(pattern);
|
||||
if (!match) {
|
||||
throw new Error("Invalid match pattern");
|
||||
}
|
||||
|
||||
if (match[1] == "*") {
|
||||
return WILDCARD_SCHEMES.every(scheme => this.matchesIgnoringPath({scheme, host: match[2]}));
|
||||
}
|
||||
|
||||
return this.matchesIgnoringPath({scheme: match[1], host: match[2]});
|
||||
},
|
||||
|
||||
serialize() {
|
||||
return this.pat;
|
||||
},
|
||||
|
||||
removeOne(pattern) {
|
||||
if (!Array.isArray(this.pat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this.pat.indexOf(pattern);
|
||||
if (index >= 0) {
|
||||
if (this.matchers[index].pat != pattern) {
|
||||
throw new Error("pat/matcher mismatch in removeOne()");
|
||||
}
|
||||
this.pat.splice(index, 1);
|
||||
this.matchers.splice(index, 1);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Globs can match everything. Be careful, this DOES NOT filter by allowed schemes!
|
||||
this.MatchGlobs = function(globs) {
|
||||
this.original = globs;
|
||||
if (globs) {
|
||||
this.regexps = Array.from(globs, (glob) => globToRegexp(glob, true));
|
||||
} else {
|
||||
this.regexps = [];
|
||||
}
|
||||
};
|
||||
|
||||
MatchGlobs.prototype = {
|
||||
matches(str) {
|
||||
return this.regexps.some(regexp => regexp.test(str));
|
||||
},
|
||||
serialize() {
|
||||
return this.original;
|
||||
},
|
||||
};
|
||||
|
||||
// Match WebNavigation URL Filters.
|
||||
this.MatchURLFilters = function(filters) {
|
||||
if (!Array.isArray(filters)) {
|
||||
throw new TypeError("filters should be an array");
|
||||
}
|
||||
|
||||
if (filters.length == 0) {
|
||||
throw new Error("filters array should not be empty");
|
||||
}
|
||||
|
||||
this.filters = filters;
|
||||
};
|
||||
|
||||
MatchURLFilters.prototype = {
|
||||
matches(url) {
|
||||
let uri = NetUtil.newURI(url);
|
||||
// Set uriURL to an empty object (needed because some schemes, e.g. about doesn't support nsIURL).
|
||||
let uriURL = {};
|
||||
if (uri instanceof Ci.nsIURL) {
|
||||
uriURL = uri;
|
||||
}
|
||||
|
||||
// Set host to a empty string by default (needed so that schemes without an host,
|
||||
// e.g. about, can pass an empty string for host based event filtering as expected).
|
||||
let host = "";
|
||||
try {
|
||||
host = uri.host;
|
||||
} catch (e) {
|
||||
// 'uri.host' throws an exception with some uri schemes (e.g. about).
|
||||
}
|
||||
|
||||
let port;
|
||||
try {
|
||||
port = uri.port;
|
||||
} catch (e) {
|
||||
// 'uri.port' throws an exception with some uri schemes (e.g. about),
|
||||
// in which case it will be |undefined|.
|
||||
}
|
||||
|
||||
let data = {
|
||||
// NOTE: This properties are named after the name of their related
|
||||
// filters (e.g. `pathContains/pathEquals/...` will be tested against the
|
||||
// `data.path` property, and the same is done for the `host`, `query` and `url`
|
||||
// components as well).
|
||||
path: uriURL.filePath,
|
||||
query: uriURL.query,
|
||||
host,
|
||||
port,
|
||||
url,
|
||||
};
|
||||
|
||||
// If any of the filters matches, matches returns true.
|
||||
return this.filters.some(filter => this.matchURLFilter({filter, data, uri, uriURL}));
|
||||
},
|
||||
|
||||
matchURLFilter({filter, data, uri, uriURL}) {
|
||||
// Test for scheme based filtering.
|
||||
if (filter.schemes) {
|
||||
// Return false if none of the schemes matches.
|
||||
if (!filter.schemes.some((scheme) => uri.schemeIs(scheme))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for exact port matching or included in a range of ports.
|
||||
if (filter.ports) {
|
||||
let port = data.port;
|
||||
if (port === -1) {
|
||||
// NOTE: currently defaultPort for "resource" and "chrome" schemes defaults to -1,
|
||||
// for "about", "data" and "javascript" schemes defaults to undefined.
|
||||
if (["resource", "chrome"].includes(uri.scheme)) {
|
||||
port = undefined;
|
||||
} else {
|
||||
port = Services.io.getProtocolHandler(uri.scheme).defaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
// Return false if none of the ports (or port ranges) is verified
|
||||
return filter.ports.some((filterPort) => {
|
||||
if (Array.isArray(filterPort)) {
|
||||
let [lower, upper] = filterPort;
|
||||
return port >= lower && port <= upper;
|
||||
}
|
||||
|
||||
return port === filterPort;
|
||||
});
|
||||
}
|
||||
|
||||
// Filters on host, url, path, query:
|
||||
// hostContains, hostEquals, hostSuffix, hostPrefix,
|
||||
// urlContains, urlEquals, ...
|
||||
for (let urlComponent of ["host", "path", "query", "url"]) {
|
||||
if (!this.testMatchOnURLComponent({urlComponent, data, filter})) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// urlMatches is a regular expression string and it is tested for matches
|
||||
// on the "url without the ref".
|
||||
if (filter.urlMatches) {
|
||||
let urlWithoutRef = uri.specIgnoringRef;
|
||||
if (!urlWithoutRef.match(filter.urlMatches)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// originAndPathMatches is a regular expression string and it is tested for matches
|
||||
// on the "url without the query and the ref".
|
||||
if (filter.originAndPathMatches) {
|
||||
let urlWithoutQueryAndRef = uri.resolve(uriURL.filePath);
|
||||
// The above 'uri.resolve(...)' will be null for some URI schemes
|
||||
// (e.g. about).
|
||||
// TODO: handle schemes which will not be able to resolve the filePath
|
||||
// (e.g. for "about:blank", 'urlWithoutQueryAndRef' should be "about:blank" instead
|
||||
// of null)
|
||||
if (!urlWithoutQueryAndRef ||
|
||||
!urlWithoutQueryAndRef.match(filter.originAndPathMatches)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
testMatchOnURLComponent({urlComponent: key, data, filter}) {
|
||||
// Test for equals.
|
||||
// NOTE: an empty string should not be considered a filter to skip.
|
||||
if (filter[`${key}Equals`] != null) {
|
||||
if (data[key] !== filter[`${key}Equals`]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for contains.
|
||||
if (filter[`${key}Contains`]) {
|
||||
let value = (key == "host" ? "." : "") + data[key];
|
||||
if (!data[key] || !value.includes(filter[`${key}Contains`])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for prefix.
|
||||
if (filter[`${key}Prefix`]) {
|
||||
if (!data[key] || !data[key].startsWith(filter[`${key}Prefix`])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for suffix.
|
||||
if (filter[`${key}Suffix`]) {
|
||||
if (!data[key] || !data[key].endsWith(filter[`${key}Suffix`])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
serialize() {
|
||||
return this.filters;
|
||||
},
|
||||
};
|
|
@ -0,0 +1,180 @@
|
|||
/* 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";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
/* exported MatchURLFilters */
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MatchURLFilters"];
|
||||
|
||||
// Match WebNavigation URL Filters.
|
||||
class MatchURLFilters {
|
||||
constructor(filters) {
|
||||
if (!Array.isArray(filters)) {
|
||||
throw new TypeError("filters should be an array");
|
||||
}
|
||||
|
||||
if (filters.length == 0) {
|
||||
throw new Error("filters array should not be empty");
|
||||
}
|
||||
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
matches(url) {
|
||||
let uri = Services.io.newURI(url);
|
||||
// Set uriURL to an empty object (needed because some schemes, e.g. about doesn't support nsIURL).
|
||||
let uriURL = {};
|
||||
if (uri instanceof Ci.nsIURL) {
|
||||
uriURL = uri;
|
||||
}
|
||||
|
||||
// Set host to a empty string by default (needed so that schemes without an host,
|
||||
// e.g. about, can pass an empty string for host based event filtering as expected).
|
||||
let host = "";
|
||||
try {
|
||||
host = uri.host;
|
||||
} catch (e) {
|
||||
// 'uri.host' throws an exception with some uri schemes (e.g. about).
|
||||
}
|
||||
|
||||
let port;
|
||||
try {
|
||||
port = uri.port;
|
||||
} catch (e) {
|
||||
// 'uri.port' throws an exception with some uri schemes (e.g. about),
|
||||
// in which case it will be |undefined|.
|
||||
}
|
||||
|
||||
let data = {
|
||||
// NOTE: This properties are named after the name of their related
|
||||
// filters (e.g. `pathContains/pathEquals/...` will be tested against the
|
||||
// `data.path` property, and the same is done for the `host`, `query` and `url`
|
||||
// components as well).
|
||||
path: uriURL.filePath,
|
||||
query: uriURL.query,
|
||||
host,
|
||||
port,
|
||||
url,
|
||||
};
|
||||
|
||||
// If any of the filters matches, matches returns true.
|
||||
return this.filters.some(filter => this.matchURLFilter({filter, data, uri, uriURL}));
|
||||
}
|
||||
|
||||
matchURLFilter({filter, data, uri, uriURL}) {
|
||||
// Test for scheme based filtering.
|
||||
if (filter.schemes) {
|
||||
// Return false if none of the schemes matches.
|
||||
if (!filter.schemes.some((scheme) => uri.schemeIs(scheme))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for exact port matching or included in a range of ports.
|
||||
if (filter.ports) {
|
||||
let port = data.port;
|
||||
if (port === -1) {
|
||||
// NOTE: currently defaultPort for "resource" and "chrome" schemes defaults to -1,
|
||||
// for "about", "data" and "javascript" schemes defaults to undefined.
|
||||
if (["resource", "chrome"].includes(uri.scheme)) {
|
||||
port = undefined;
|
||||
} else {
|
||||
port = Services.io.getProtocolHandler(uri.scheme).defaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
// Return false if none of the ports (or port ranges) is verified
|
||||
return filter.ports.some((filterPort) => {
|
||||
if (Array.isArray(filterPort)) {
|
||||
let [lower, upper] = filterPort;
|
||||
return port >= lower && port <= upper;
|
||||
}
|
||||
|
||||
return port === filterPort;
|
||||
});
|
||||
}
|
||||
|
||||
// Filters on host, url, path, query:
|
||||
// hostContains, hostEquals, hostSuffix, hostPrefix,
|
||||
// urlContains, urlEquals, ...
|
||||
for (let urlComponent of ["host", "path", "query", "url"]) {
|
||||
if (!this.testMatchOnURLComponent({urlComponent, data, filter})) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// urlMatches is a regular expression string and it is tested for matches
|
||||
// on the "url without the ref".
|
||||
if (filter.urlMatches) {
|
||||
let urlWithoutRef = uri.specIgnoringRef;
|
||||
if (!urlWithoutRef.match(filter.urlMatches)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// originAndPathMatches is a regular expression string and it is tested for matches
|
||||
// on the "url without the query and the ref".
|
||||
if (filter.originAndPathMatches) {
|
||||
let urlWithoutQueryAndRef = uri.resolve(uriURL.filePath);
|
||||
// The above 'uri.resolve(...)' will be null for some URI schemes
|
||||
// (e.g. about).
|
||||
// TODO: handle schemes which will not be able to resolve the filePath
|
||||
// (e.g. for "about:blank", 'urlWithoutQueryAndRef' should be "about:blank" instead
|
||||
// of null)
|
||||
if (!urlWithoutQueryAndRef ||
|
||||
!urlWithoutQueryAndRef.match(filter.originAndPathMatches)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
testMatchOnURLComponent({urlComponent: key, data, filter}) {
|
||||
// Test for equals.
|
||||
// NOTE: an empty string should not be considered a filter to skip.
|
||||
if (filter[`${key}Equals`] != null) {
|
||||
if (data[key] !== filter[`${key}Equals`]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for contains.
|
||||
if (filter[`${key}Contains`]) {
|
||||
let value = (key == "host" ? "." : "") + data[key];
|
||||
if (!data[key] || !value.includes(filter[`${key}Contains`])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for prefix.
|
||||
if (filter[`${key}Prefix`]) {
|
||||
if (!data[key] || !data[key].startsWith(filter[`${key}Prefix`])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for suffix.
|
||||
if (filter[`${key}Suffix`]) {
|
||||
if (!data[key] || !data[key].endsWith(filter[`${key}Suffix`])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return this.filters;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Managed via the message managers.
|
||||
/* global initialProcessData */
|
||||
/* globals MatchPatternSet, initialProcessData */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -15,8 +15,6 @@ var Cr = Components.results;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
|
||||
"resource://gre/modules/MatchPattern.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebRequestCommon",
|
||||
"resource://gre/modules/WebRequestCommon.jsm");
|
||||
|
||||
|
@ -53,7 +51,7 @@ var ContentPolicy = {
|
|||
this.register();
|
||||
}
|
||||
if (filter.urls) {
|
||||
filter.urls = new MatchPattern(filter.urls);
|
||||
filter.urls = new MatchPatternSet(filter.urls);
|
||||
}
|
||||
this.contentPolicies.set(id, {blocking, filter});
|
||||
},
|
||||
|
|
|
@ -163,7 +163,7 @@ TESTING_JS_MODULES += [
|
|||
SPHINX_TREES['toolkit_modules'] = 'docs'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'addons/MatchPattern.jsm',
|
||||
'addons/MatchURLFilters.jsm',
|
||||
'addons/WebNavigation.jsm',
|
||||
'addons/WebNavigationContent.js',
|
||||
'addons/WebNavigationFrames.jsm',
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/MatchPattern.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test(url, pattern) {
|
||||
let uri = Services.io.newURI(url);
|
||||
let m = new MatchGlobs(pattern);
|
||||
return m.matches(uri.spec);
|
||||
}
|
||||
|
||||
function pass({url, pattern}) {
|
||||
ok(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
|
||||
}
|
||||
|
||||
function fail({url, pattern}) {
|
||||
ok(!test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let moz = "http://mozilla.org";
|
||||
|
||||
pass({url: moz, pattern: ["*"]});
|
||||
pass({url: moz, pattern: ["http://*"]}),
|
||||
pass({url: moz, pattern: ["*mozilla*"]});
|
||||
pass({url: moz, pattern: ["*example*", "*mozilla*"]});
|
||||
|
||||
pass({url: moz, pattern: ["*://*"]});
|
||||
pass({url: "https://mozilla.org", pattern: ["*://*"]});
|
||||
|
||||
// Documentation example
|
||||
pass({url: "http://www.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
|
||||
pass({url: "http://the.example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
|
||||
fail({url: "http://my.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
|
||||
fail({url: "http://example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
|
||||
fail({url: "http://www.example.com/foo", pattern: ["http://???.example.com/foo/*"]});
|
||||
|
||||
// Matches path
|
||||
let path = moz + "/abc/def";
|
||||
pass({url: path, pattern: ["*def"]});
|
||||
pass({url: path, pattern: ["*c/d*"]});
|
||||
pass({url: path, pattern: ["*org/abc*"]});
|
||||
fail({url: path + "/", pattern: ["*def"]});
|
||||
|
||||
// Trailing slash
|
||||
pass({url: moz, pattern: ["*.org/"]});
|
||||
fail({url: moz, pattern: ["*.org"]});
|
||||
|
||||
// Wrong TLD
|
||||
fail({url: moz, pattern: ["www*.m*.com/"]});
|
||||
// Case sensitive
|
||||
fail({url: moz, pattern: ["*.ORG/"]});
|
||||
|
||||
fail({url: moz, pattern: []});
|
||||
}
|
|
@ -1,158 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/MatchPattern.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test_matches() {
|
||||
function test(url, pattern) {
|
||||
let uri = Services.io.newURI(url);
|
||||
let m = new MatchPattern(pattern);
|
||||
return m.matches(uri);
|
||||
}
|
||||
|
||||
function pass({url, pattern}) {
|
||||
do_check_true(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
|
||||
}
|
||||
|
||||
function fail({url, pattern}) {
|
||||
do_check_false(test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
|
||||
}
|
||||
|
||||
// Invalid pattern.
|
||||
fail({url: "http://mozilla.org", pattern: ""});
|
||||
|
||||
// Pattern must include trailing slash.
|
||||
fail({url: "http://mozilla.org", pattern: "http://mozilla.org"});
|
||||
|
||||
// Protocol not allowed.
|
||||
fail({url: "http://mozilla.org", pattern: "gopher://wuarchive.wustl.edu/"});
|
||||
|
||||
pass({url: "http://mozilla.org", pattern: "http://mozilla.org/"});
|
||||
pass({url: "http://mozilla.org/", pattern: "http://mozilla.org/"});
|
||||
|
||||
pass({url: "http://mozilla.org/", pattern: "*://mozilla.org/"});
|
||||
pass({url: "https://mozilla.org/", pattern: "*://mozilla.org/"});
|
||||
fail({url: "file://mozilla.org/", pattern: "*://mozilla.org/"});
|
||||
fail({url: "ftp://mozilla.org/", pattern: "*://mozilla.org/"});
|
||||
|
||||
fail({url: "http://mozilla.com", pattern: "http://*mozilla.com*/"});
|
||||
fail({url: "http://mozilla.com", pattern: "http://mozilla.*/"});
|
||||
fail({url: "http://mozilla.com", pattern: "http:/mozilla.com/"});
|
||||
|
||||
pass({url: "http://google.com", pattern: "http://*.google.com/"});
|
||||
pass({url: "http://docs.google.com", pattern: "http://*.google.com/"});
|
||||
|
||||
pass({url: "http://mozilla.org:8080", pattern: "http://mozilla.org/"});
|
||||
pass({url: "http://mozilla.org:8080", pattern: "*://mozilla.org/"});
|
||||
fail({url: "http://mozilla.org:8080", pattern: "http://mozilla.org:8080/"});
|
||||
|
||||
// Now try with * in the path.
|
||||
pass({url: "http://mozilla.org", pattern: "http://mozilla.org/*"});
|
||||
pass({url: "http://mozilla.org/", pattern: "http://mozilla.org/*"});
|
||||
|
||||
pass({url: "http://mozilla.org/", pattern: "*://mozilla.org/*"});
|
||||
pass({url: "https://mozilla.org/", pattern: "*://mozilla.org/*"});
|
||||
fail({url: "file://mozilla.org/", pattern: "*://mozilla.org/*"});
|
||||
fail({url: "http://mozilla.com", pattern: "http://mozilla.*/*"});
|
||||
|
||||
pass({url: "http://google.com", pattern: "http://*.google.com/*"});
|
||||
pass({url: "http://docs.google.com", pattern: "http://*.google.com/*"});
|
||||
|
||||
// Check path stuff.
|
||||
fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/"});
|
||||
pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*"});
|
||||
pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/a*f"});
|
||||
pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/a*"});
|
||||
pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*f"});
|
||||
fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*e"});
|
||||
fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*c"});
|
||||
|
||||
fail({url: "http:///a.html", pattern: "http:///a.html"});
|
||||
pass({url: "file:///foo", pattern: "file:///foo*"});
|
||||
pass({url: "file:///foo/bar.html", pattern: "file:///foo*"});
|
||||
|
||||
pass({url: "http://mozilla.org/a", pattern: "<all_urls>"});
|
||||
pass({url: "https://mozilla.org/a", pattern: "<all_urls>"});
|
||||
pass({url: "ftp://mozilla.org/a", pattern: "<all_urls>"});
|
||||
pass({url: "file:///a", pattern: "<all_urls>"});
|
||||
fail({url: "gopher://wuarchive.wustl.edu/a", pattern: "<all_urls>"});
|
||||
|
||||
// Multiple patterns.
|
||||
pass({url: "http://mozilla.org", pattern: ["http://mozilla.org/"]});
|
||||
pass({url: "http://mozilla.org", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
|
||||
pass({url: "http://mozilla.com", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
|
||||
fail({url: "http://mozilla.biz", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
|
||||
|
||||
// Match url with fragments.
|
||||
pass({url: "http://mozilla.org/base#some-fragment", pattern: "http://mozilla.org/base"});
|
||||
}
|
||||
|
||||
function test_overlaps() {
|
||||
function test(filter, hosts, optional) {
|
||||
const f = new MatchPattern(filter);
|
||||
return f.overlapsPermissions(new MatchPattern(hosts), new MatchPattern(optional));
|
||||
}
|
||||
|
||||
function pass({filter = [], hosts = [], optional = []}) {
|
||||
ok(test(filter, hosts, optional), `Expected overlap: ${filter}, ${hosts} (${optional})`);
|
||||
}
|
||||
|
||||
function fail({filter = [], hosts = [], optional = []}) {
|
||||
ok(!test(filter, hosts, optional), `Expected no overlap: ${filter}, ${hosts} (${optional})`);
|
||||
}
|
||||
|
||||
// Direct comparison.
|
||||
pass({hosts: "http://ab.cd/", filter: "http://ab.cd/"});
|
||||
fail({hosts: "http://ab.cd/", filter: "ftp://ab.cd/"});
|
||||
|
||||
// Wildcard protocol.
|
||||
pass({hosts: "*://ab.cd/", filter: "https://ab.cd/"});
|
||||
fail({hosts: "*://ab.cd/", filter: "ftp://ab.cd/"});
|
||||
|
||||
// Wildcard subdomain.
|
||||
pass({hosts: "http://*.ab.cd/", filter: "http://ab.cd/"});
|
||||
pass({hosts: "http://*.ab.cd/", filter: "http://www.ab.cd/"});
|
||||
fail({hosts: "http://*.ab.cd/", filter: "http://ab.cd.ef/"});
|
||||
fail({hosts: "http://*.ab.cd/", filter: "http://www.cd/"});
|
||||
|
||||
// Wildcard subsumed.
|
||||
pass({hosts: "http://*.ab.cd/", filter: "http://*.cd/"});
|
||||
fail({hosts: "http://*.cd/", filter: "http://*.xy/"});
|
||||
|
||||
// Subdomain vs substring.
|
||||
fail({hosts: "http://*.ab.cd/", filter: "http://fake-ab.cd/"});
|
||||
fail({hosts: "http://*.ab.cd/", filter: "http://*.fake-ab.cd/"});
|
||||
|
||||
// Wildcard domain.
|
||||
pass({hosts: "http://*/", filter: "http://ab.cd/"});
|
||||
fail({hosts: "http://*/", filter: "https://ab.cd/"});
|
||||
|
||||
// Wildcard wildcards.
|
||||
pass({hosts: "<all_urls>", filter: "ftp://ab.cd/"});
|
||||
fail({hosts: "<all_urls>", filter: ""});
|
||||
fail({hosts: "<all_urls>"});
|
||||
|
||||
// Multiple hosts.
|
||||
pass({hosts: ["http://ab.cd/"], filter: ["http://ab.cd/"]});
|
||||
pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.cd/"});
|
||||
pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.xy/"});
|
||||
fail({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.zz/"});
|
||||
|
||||
// Multiple Multiples.
|
||||
pass({hosts: ["http://*.ab.cd/"], filter: ["http://ab.cd/", "http://www.ab.cd/"]});
|
||||
pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: ["http://ab.cd/", "http://ab.xy/"]});
|
||||
fail({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: ["http://ab.cd/", "http://ab.zz/"]});
|
||||
|
||||
// Optional.
|
||||
pass({hosts: [], optional: "http://ab.cd/", filter: "http://ab.cd/"});
|
||||
pass({hosts: "http://ab.cd/", optional: "http://ab.xy/", filter: ["http://ab.cd/", "http://ab.xy/"]});
|
||||
fail({hosts: "http://ab.cd/", optional: "https://ab.xy/", filter: "http://ab.xy/"});
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
test_matches();
|
||||
test_overlaps();
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/MatchPattern.jsm");
|
||||
Components.utils.import("resource://gre/modules/MatchURLFilters.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function createTestFilter({url, filters}) {
|
||||
|
|
|
@ -28,10 +28,6 @@ skip-if = toolkit == 'android'
|
|||
skip-if = toolkit == 'android'
|
||||
[test_Log.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_MatchPattern.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_MatchGlobs.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_MatchURLFilters.js]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_NewTabUtils.js]
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
"lz4.js": ["Lz4"],
|
||||
"lz4_internal.js": ["Primitives"],
|
||||
"main.js": ["Weave"],
|
||||
"MatchPattern.jsm": ["MatchPattern", "MatchGlobs", "MatchURLFilters"],
|
||||
"MatchURLFilters.jsm": ["MatchURLFilters"],
|
||||
"mcc_iso3166_table.jsm": ["MCC_ISO3166_TABLE"],
|
||||
"message.js": ["Command", "Message", "MessageOrigin", "Response"],
|
||||
"MessageContext.jsm": ["MessageContext"],
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsISelection.h"
|
||||
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
#include "mozilla/TextComposition.h"
|
||||
#include "mozilla/TextEventDispatcherListener.h"
|
||||
|
@ -1153,9 +1154,11 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
|
|||
aAction.mCause, aAction.mFocusChange);
|
||||
|
||||
mInputContext = aContext;
|
||||
const bool isUserAction = EventStateManager::IsHandlingUserInput();
|
||||
|
||||
if (mInputContext.mIMEState.mEnabled == IMEState::ENABLED &&
|
||||
aAction.UserMightRequestOpenVKB()) {
|
||||
isUserAction &&
|
||||
aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
|
||||
// Don't reset keyboard when we should simply open the vkb
|
||||
mEditable->NotifyIME(GeckoEditableListener::NOTIFY_IME_OPEN_VKB);
|
||||
return;
|
||||
|
@ -1167,8 +1170,6 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
|
|||
mIMEUpdatingContext = true;
|
||||
|
||||
RefPtr<GeckoEditableSupport> self(this);
|
||||
bool isUserAction = aAction.IsUserAction();
|
||||
|
||||
nsAppShell::PostEvent([this, self, isUserAction] {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
||||
|
|