mirror of
https://github.com/roytam1/basilisk55.git
synced 2026-05-26 15:02:46 +00:00
cherry-picked mozilla upstream changes:
bug1346389, bug1382303, bug1383000, bug1339931, bug1346620, bug1351349, bug546387, bug1368150, bug1361132, bug1345781, bug1343781, bug1390980, bug1387918, bug1373222, bug1385272, bug1390002, bug1379539, bug1371657, bug1386905, bug1379540, bug1379536, bug1384308, bug1317900, bug1279171, bug1384801, bug1396320, bug1396570, bug1368269, bug1394024, bug1400721, bug1367482, bug1359624, bug1376163, bug1392988, bug1389908
This commit is contained in:
@@ -2149,6 +2149,8 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
|
||||
|
||||
if (MoveChild(child, aOwner, insertIdx)) {
|
||||
child->SetRelocated(true);
|
||||
MOZ_ASSERT(owned == mARIAOwnsHash.Get(aOwner));
|
||||
owned = mARIAOwnsHash.LookupOrAdd(aOwner);
|
||||
owned->InsertElementAt(idx, child);
|
||||
idx++;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ XULTreeAccessible::Value(nsString& aValue)
|
||||
void
|
||||
XULTreeAccessible::Shutdown()
|
||||
{
|
||||
if (!mDoc->IsDefunct()) {
|
||||
if (mDoc && !mDoc->IsDefunct()) {
|
||||
UnbindCacheEntriesFromDocument(mAccessibleCache);
|
||||
}
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
|
||||
void
|
||||
XULTreeGridRowAccessible::Shutdown()
|
||||
{
|
||||
if (!mDoc->IsDefunct()) {
|
||||
if (mDoc && !mDoc->IsDefunct()) {
|
||||
UnbindCacheEntriesFromDocument(mAccessibleCache);
|
||||
}
|
||||
|
||||
|
||||
@@ -179,11 +179,8 @@ AC_SUBST_LIST(NSPR_CFLAGS)
|
||||
AC_SUBST(NSPR_INCLUDE_DIR)
|
||||
AC_SUBST(NSPR_LIB_DIR)
|
||||
|
||||
NSPR_PKGCONF_CHECK="nspr"
|
||||
PKGCONF_REQUIRES_PRIVATE="Requires.private: nspr"
|
||||
if test -n "$MOZ_SYSTEM_NSPR"; then
|
||||
# piggy back on $MOZ_SYSTEM_NSPR to set a variable for the nspr check for js.pc
|
||||
NSPR_PKGCONF_CHECK="nspr >= $NSPR_MINVER"
|
||||
|
||||
_SAVE_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS $NSPR_CFLAGS"
|
||||
AC_TRY_COMPILE([#include "prlog.h"],
|
||||
@@ -193,8 +190,12 @@ if test -n "$MOZ_SYSTEM_NSPR"; then
|
||||
,
|
||||
AC_MSG_ERROR([system NSPR does not support PR_STATIC_ASSERT]))
|
||||
CFLAGS=$_SAVE_CFLAGS
|
||||
# piggy back on $MOZ_SYSTEM_NSPR to set a variable for the nspr check for js.pc
|
||||
PKGCONF_REQUIRES_PRIVATE="Requires.private: nspr >= $NSPR_MINVER"
|
||||
elif test -n "$JS_POSIX_NSPR"; then
|
||||
PKGCONF_REQUIRES_PRIVATE=
|
||||
fi
|
||||
AC_SUBST(NSPR_PKGCONF_CHECK)
|
||||
AC_SUBST([PKGCONF_REQUIRES_PRIVATE])
|
||||
|
||||
fi # _IS_OUTER_CONFIGURE
|
||||
|
||||
|
||||
@@ -89,15 +89,28 @@ option(env='OLD_CONFIGURE', nargs=1, help='Path to the old configure script')
|
||||
option(env='MOZ_CURRENT_PROJECT', nargs=1, help='Current build project')
|
||||
option(env='MOZCONFIG', nargs=1, help='Mozconfig location')
|
||||
|
||||
option('--with-external-source-dir', env='EXTERNAL_SOURCE_DIR', nargs=1,
|
||||
help='External directory containing additional build files')
|
||||
|
||||
@depends('--with-external-source-dir')
|
||||
def external_source_dir(value):
|
||||
if value:
|
||||
return value[0]
|
||||
|
||||
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
|
||||
add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir)
|
||||
|
||||
# Read user mozconfig
|
||||
# ==============================================================
|
||||
# Note: the dependency on --help is only there to always read the mozconfig,
|
||||
# even when --help is passed. Without this dependency, the function wouldn't
|
||||
# be called when --help is passed, and the mozconfig wouldn't be read.
|
||||
@depends('MOZ_CURRENT_PROJECT', 'MOZCONFIG', 'OLD_CONFIGURE',
|
||||
check_build_environment, '--help')
|
||||
check_build_environment, '--with-external-source-dir',
|
||||
'--help')
|
||||
@imports(_from='mozbuild.mozconfig', _import='MozconfigLoader')
|
||||
def mozconfig(current_project, mozconfig, old_configure, build_env, help):
|
||||
def mozconfig(current_project, mozconfig, old_configure, build_env,
|
||||
external_source_dir, help):
|
||||
if not old_configure:
|
||||
die('The OLD_CONFIGURE environment variable must be set')
|
||||
|
||||
@@ -120,7 +133,10 @@ def mozconfig(current_project, mozconfig, old_configure, build_env, help):
|
||||
if os.path.dirname(os.path.abspath(old_configure[0])).endswith('/js/src'):
|
||||
return {'path': None}
|
||||
|
||||
loader = MozconfigLoader(build_env.topsrcdir)
|
||||
topsrcdir = build_env.topsrcdir
|
||||
if external_source_dir:
|
||||
topsrcdir = external_source_dir[0]
|
||||
loader = MozconfigLoader(topsrcdir)
|
||||
current_project = current_project[0] if current_project else None
|
||||
mozconfig = mozconfig[0] if mozconfig else None
|
||||
mozconfig = loader.find_mozconfig(env={'MOZCONFIG': mozconfig})
|
||||
@@ -610,9 +626,6 @@ def default_project(build_env, help):
|
||||
option('--enable-project', nargs=1, default=default_project,
|
||||
help='Project to build')
|
||||
|
||||
option('--with-external-source-dir', env='EXTERNAL_SOURCE_DIR', nargs=1,
|
||||
help='External directory containing additional build files')
|
||||
|
||||
@depends('--enable-project', '--with-external-source-dir',
|
||||
check_build_environment, '--help')
|
||||
@imports(_from='os.path', _import='exists')
|
||||
@@ -640,14 +653,6 @@ def include_project_configure(project, external_source_dir, build_env, help):
|
||||
else:
|
||||
die('Cannot find project %s', build_app)
|
||||
|
||||
@depends('--with-external-source-dir')
|
||||
def external_source_dir(value):
|
||||
if value:
|
||||
return value[0]
|
||||
|
||||
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
|
||||
add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir)
|
||||
|
||||
|
||||
@depends(include_project_configure, check_build_environment, '--help')
|
||||
def build_project(include_project_configure, build_env, help):
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
try { o1 = document.createElement("tr") } catch(e) { }
|
||||
try { o2 = document.createElement("td") } catch(e) { }
|
||||
try { o3 = document.createElement("tr") } catch(e) { }
|
||||
try { o4 = document.createElement("div") } catch(e) { }
|
||||
try { o5 = document.createElement("input") } catch(e) { }
|
||||
try { o6 = document.createElement('map') } catch(e) { }
|
||||
try { o7 = document.createElement('select') } catch(e) { }
|
||||
try { o8 = document.createElement("canvas") } catch(e) { }
|
||||
try { o9 = document.createElement("area") } catch(e) { };
|
||||
try { o1.appendChild(o2) } catch(e) { }
|
||||
try { document.documentElement.appendChild(o3) } catch(e) { }
|
||||
try { document.documentElement.appendChild(o4) } catch(e) { }
|
||||
try { document.documentElement.appendChild(o6) } catch(e) { }
|
||||
try { o3.appendChild(o7) } catch(e) { }
|
||||
try { o4.appendChild(o8) } catch(e) { }
|
||||
try { o3.appendChild(o5); } catch(e) { }
|
||||
try { o3.appendChild(o1); } catch(e) { }
|
||||
try { o6.contentEditable = "true" } catch(e) { };
|
||||
try { o6.offsetHeight } catch(e) { };
|
||||
try { o4.appendChild(o9) } catch(e) { };
|
||||
try { o2.insertAdjacentHTML("beforeBegin", "<button id='id0'></button>\n"); } catch(e) { }
|
||||
try { document.replaceChild(document.documentElement, document.documentElement); } catch(e) { }
|
||||
try { document.execCommand("selectall",false,null) } catch(e) { }
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
@@ -208,6 +208,7 @@ load xhr_html_nullresponse.html
|
||||
load 1230422.html
|
||||
load 1251361.html
|
||||
load 1304437.html
|
||||
pref(clipboard.autocopy,true) load 1385272-1.html
|
||||
pref(dom.IntersectionObserver.enabled,true) load 1324209.html
|
||||
pref(dom.IntersectionObserver.enabled,true) load 1326194-1.html
|
||||
pref(dom.IntersectionObserver.enabled,true) load 1326194-2.html
|
||||
|
||||
@@ -1002,6 +1002,14 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
|
||||
return EncodeToStringWithMaxLength(0, aOutputString);
|
||||
}
|
||||
|
||||
static bool ParentIsTR(nsIContent* aContent) {
|
||||
mozilla::dom::Element* parent = aContent->GetParentElement();
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
return parent->IsHTMLElement(nsGkAtoms::tr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
|
||||
nsAString& aOutputString)
|
||||
@@ -1069,7 +1077,7 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||
if (content && content->IsHTMLElement(nsGkAtoms::tr)) {
|
||||
if (content && content->IsHTMLElement(nsGkAtoms::tr) && !ParentIsTR(content)) {
|
||||
nsINode* n = content;
|
||||
if (!prevNode) {
|
||||
// Went from a non-<tr> to a <tr>
|
||||
|
||||
@@ -405,6 +405,14 @@ MutableBlobStorage::GetBlobWhenReady(nsISupports* aParent,
|
||||
return mDataLen;
|
||||
}
|
||||
|
||||
// If we are waiting for the temporary file, it's better to wait...
|
||||
if (previousState == eWaitingForTemporaryFile) {
|
||||
mPendingParent = aParent;
|
||||
mPendingContentType = aContentType;
|
||||
mPendingCallback = aCallback;
|
||||
return mDataLen;
|
||||
}
|
||||
|
||||
RefPtr<BlobImpl> blobImpl;
|
||||
|
||||
if (mData) {
|
||||
@@ -544,16 +552,25 @@ MutableBlobStorage::TemporaryFileCreated(PRFileDesc* aFD)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mStorageState == eWaitingForTemporaryFile ||
|
||||
mStorageState == eClosed);
|
||||
MOZ_ASSERT_IF(mPendingCallback, mStorageState == eClosed);
|
||||
|
||||
if (mStorageState == eClosed) {
|
||||
// If the object has been already closed and we don't need to execute a
|
||||
// callback, we need just to close the file descriptor in the correct thread.
|
||||
if (mStorageState == eClosed && !mPendingCallback) {
|
||||
RefPtr<Runnable> runnable = new CloseFileRunnable(aFD);
|
||||
DispatchToIOThread(runnable.forget());
|
||||
return;
|
||||
}
|
||||
|
||||
mStorageState = eInTemporaryFile;
|
||||
// If we still receiving data, we can proceed in temporary-file mode.
|
||||
if (mStorageState == eWaitingForTemporaryFile) {
|
||||
mStorageState = eInTemporaryFile;
|
||||
}
|
||||
|
||||
mFD = aFD;
|
||||
|
||||
// This runnable takes the ownership of mData and it will write this buffer
|
||||
// into the temporary file.
|
||||
RefPtr<WriteRunnable> runnable =
|
||||
WriteRunnable::AdoptBuffer(this, mFD, mData, mDataLen);
|
||||
MOZ_ASSERT(runnable);
|
||||
@@ -561,6 +578,23 @@ MutableBlobStorage::TemporaryFileCreated(PRFileDesc* aFD)
|
||||
mData = nullptr;
|
||||
|
||||
DispatchToIOThread(runnable.forget());
|
||||
|
||||
// If we are closed, it means that GetBlobWhenReady() has been called when we
|
||||
// were already waiting for a temporary file-descriptor. Finally we are here,
|
||||
// AdoptBuffer runnable is going to write the current buffer into this file.
|
||||
// After that, there is nothing else to write, and we dispatch LastRunnable
|
||||
// which ends up calling mPendingCallback via CreateBlobRunnable.
|
||||
if (mStorageState == eClosed) {
|
||||
MOZ_ASSERT(mPendingCallback);
|
||||
|
||||
RefPtr<Runnable> runnable =
|
||||
new LastRunnable(this, mPendingParent, mPendingContentType,
|
||||
mPendingCallback);
|
||||
DispatchToIOThread(runnable.forget());
|
||||
|
||||
mPendingParent = nullptr;
|
||||
mPendingCallback = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -95,6 +95,10 @@ private:
|
||||
nsresult mErrorResult;
|
||||
|
||||
RefPtr<TaskQueue> mTaskQueue;
|
||||
|
||||
nsCOMPtr<nsISupports> mPendingParent;
|
||||
nsCString mPendingContentType;
|
||||
RefPtr<MutableBlobStorageCallback> mPendingCallback;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -5802,8 +5802,7 @@ bool HTMLMediaElement::CanActivateAutoplay()
|
||||
|
||||
bool hasData =
|
||||
(mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
|
||||
(mSrcStream && mSrcStream->Active()) ||
|
||||
mMediaSource;
|
||||
(mSrcStream && mSrcStream->Active());
|
||||
|
||||
return hasData;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
document.documentElement.getBoundingClientRect()
|
||||
document.documentElement.innerHTML = "<input placeholder=e type=number readonly>"
|
||||
document.designMode = "on"
|
||||
document.execCommand("inserttext", false, "")
|
||||
document.designMode = "off"
|
||||
document.documentElement.style.display = 'none'
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
@@ -78,4 +78,5 @@ load 1237633.html
|
||||
load 1281972-1.html
|
||||
load 1282894.html
|
||||
load 1290904.html
|
||||
load 1386905.html
|
||||
asserts(0-3) load 1350972.html
|
||||
|
||||
@@ -1751,6 +1751,8 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
}
|
||||
|
||||
mBoundFrame = nullptr;
|
||||
// Clear mRootNode so that we don't unexpectedly notify below.
|
||||
nsCOMPtr<Element> rootNode = mRootNode.forget();
|
||||
|
||||
// Now that we don't have a frame any more, store the value in the text buffer.
|
||||
// The only case where we don't do this is if a value transfer is in progress.
|
||||
@@ -1760,15 +1762,15 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
NS_ENSURE_TRUE_VOID(success);
|
||||
}
|
||||
|
||||
if (mRootNode && mMutationObserver) {
|
||||
mRootNode->RemoveMutationObserver(mMutationObserver);
|
||||
if (rootNode && mMutationObserver) {
|
||||
rootNode->RemoveMutationObserver(mMutationObserver);
|
||||
mMutationObserver = nullptr;
|
||||
}
|
||||
|
||||
// Unbind the anonymous content from the tree.
|
||||
// We actually hold a reference to the content nodes so that
|
||||
// they're not actually destroyed.
|
||||
nsContentUtils::DestroyAnonymousContent(&mRootNode);
|
||||
nsContentUtils::DestroyAnonymousContent(&rootNode);
|
||||
nsContentUtils::DestroyAnonymousContent(&mPlaceholderDiv);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@ using mozilla::ipc::GoannaChildProcessHost;
|
||||
using base::ProcessArchitecture;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
extern LogModule* GetGMPLog();
|
||||
#define GMP_LOG(msg, ...) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, (msg, ##__VA_ARGS__))
|
||||
|
||||
namespace gmp {
|
||||
|
||||
GMPProcessParent::GMPProcessParent(const std::string& aGMPPath)
|
||||
@@ -51,10 +55,13 @@ GMPProcessParent::Launch(int32_t aTimeoutMs)
|
||||
// symbolic links or junction points. Sometimes the Users folder has been
|
||||
// moved to another drive using a junction point, so allow for this specific
|
||||
// case. See bug 1236680 for details.
|
||||
if (!widget::WinUtils::ResolveMovedUsersFolder(wGMPPath)) {
|
||||
NS_WARNING("ResolveMovedUsersFolder failed for GMP path.");
|
||||
if (!widget::WinUtils::ResolveJunctionPointsAndSymLinks(wGMPPath)) {
|
||||
GMP_LOG("ResolveJunctionPointsAndSymLinks failed for GMP path=%S",
|
||||
wGMPPath.c_str());
|
||||
NS_WARNING("ResolveJunctionPointsAndSymLinks failed for GMP path.");
|
||||
return false;
|
||||
}
|
||||
GMP_LOG("GMPProcessParent::Launch() resolved path to %S", wGMPPath.c_str());
|
||||
|
||||
// If the GMP path is a network path that is not mapped to a drive letter,
|
||||
// then we need to fix the path format for the sandbox rule.
|
||||
|
||||
@@ -316,12 +316,12 @@ MediaSourceDecoder::CanPlayThrough()
|
||||
} else if (duration <= currentPosition) {
|
||||
return true;
|
||||
}
|
||||
// If we have data up to the mediasource's duration or 30s ahead, we can
|
||||
// If we have data up to the mediasource's duration or 10s ahead, we can
|
||||
// assume that we can play without interruption.
|
||||
TimeIntervals buffered = GetBuffered();
|
||||
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
|
||||
TimeUnit timeAhead =
|
||||
std::min(duration, currentPosition + TimeUnit::FromSeconds(30));
|
||||
std::min(duration, currentPosition + TimeUnit::FromSeconds(10));
|
||||
TimeInterval interval(currentPosition, timeAhead);
|
||||
return buffered.ContainsStrict(ClampIntervalToEnd(interval));
|
||||
}
|
||||
|
||||
@@ -91,6 +91,8 @@ skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not
|
||||
[test_OnEvents.html]
|
||||
[test_PlayEvents.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3
|
||||
[test_PlayEventsAutoPlaying.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3
|
||||
[test_ResumeAfterClearing_mp4.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3
|
||||
[test_SeekableAfterEndOfStream.html]
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>MSE: basic functionality</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="mediasource.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// This test checks that readyState is properly set and the appropriate events are being fired accordingly:
|
||||
// 1. Ensure that play/playing aren't fired before any media data been added.
|
||||
// 2. Load 1.6s of data and ensure that canplay, play and playing events are fired.
|
||||
|
||||
runWithMSE(function(ms, el) {
|
||||
el.controls = true;
|
||||
el.autoplay = true;
|
||||
var eventCounts = { play: 0, playing: 0};
|
||||
function ForbiddenEvents(e) {
|
||||
var v = e.target;
|
||||
ok(v.readyState >= v.HAVE_FUTURE_DATA, "Must not have received event too early");
|
||||
is(eventCounts[e.type], 0, "event should have only be fired once");
|
||||
eventCounts[e.type]++;
|
||||
}
|
||||
once(ms, 'sourceopen').then(function() {
|
||||
// Log events for debugging.
|
||||
var events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
|
||||
"loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort",
|
||||
"waiting", "pause", "durationchange", "seeking", "seeked"];
|
||||
function logEvent(e) {
|
||||
info("got " + e.type + " event");
|
||||
}
|
||||
events.forEach(function(e) {
|
||||
el.addEventListener(e, logEvent);
|
||||
});
|
||||
el.addEventListener("play", ForbiddenEvents);
|
||||
el.addEventListener("playing", ForbiddenEvents);
|
||||
|
||||
ok(true, "Receive a sourceopen event");
|
||||
var videosb = ms.addSourceBuffer("video/mp4");
|
||||
is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
|
||||
var promises = [];
|
||||
promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4'));
|
||||
promises.push(once(el, 'loadedmetadata'));
|
||||
Promise.all(promises)
|
||||
.then(function() {
|
||||
ok(true, "got loadedmetadata event");
|
||||
var promises = [];
|
||||
promises.push(once(el, 'loadeddata'));
|
||||
promises.push(once(el, 'canplay'));
|
||||
promises.push(once(el, 'play'));
|
||||
promises.push(once(el, 'playing'));
|
||||
promises.push(once(el, 'ended'));
|
||||
// We're only adding 1.6s worth of data, not enough for readyState to change to HAVE_ENOUGH_DATA
|
||||
// So we end the media source so that all the playable data is available.
|
||||
promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s')
|
||||
.then(() => ms.endOfStream()));
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(function() {
|
||||
ok(true, "got all required event");
|
||||
SimpleTest.finish();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "WMFDecoderModule.h"
|
||||
|
||||
#endif
|
||||
#ifdef MOZ_FFVPX
|
||||
#include "FFVPXRuntimeLinker.h"
|
||||
@@ -372,7 +373,16 @@ PDMFactory::CreatePDMs()
|
||||
}
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
if (MediaPrefs::PDMWMFEnabled()) {
|
||||
if (MediaPrefs::PDMWMFEnabled() && IsVistaOrLater() && !IsWin7AndPre2000Compatible()) {
|
||||
// *Only* use WMF on Vista and later, as if Firefox is run in Windows 95
|
||||
// compatibility mode on Windows 7 (it does happen!) we may crash trying
|
||||
// to startup WMF. So we need to detect the OS version here, as in
|
||||
// compatibility mode IsVistaOrLater() and friends behave as if we're on
|
||||
// the emulated version of Windows. See bug 1279171.
|
||||
// Additionally, we don't want to start the RemoteDecoderModule if we
|
||||
// expect it's not going to work (i.e. on Windows older than Vista).
|
||||
// IsWin7AndPre2000Compatible() uses GetVersionEx as the user specified OS version can
|
||||
// be reflected when compatibility mode is in effect.
|
||||
m = new WMFDecoderModule();
|
||||
RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m);
|
||||
StartupPDM(remote);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "VideoUtils.h"
|
||||
#include <initguid.h>
|
||||
#include "nsTArray.h"
|
||||
@@ -204,6 +205,16 @@ LoadDLLs()
|
||||
HRESULT
|
||||
MFStartup()
|
||||
{
|
||||
if (!IsVistaOrLater() || IsWin7AndPre2000Compatible()) {
|
||||
// *Only* use WMF on Vista and later, as if Firefox is run in Windows 95
|
||||
// compatibility mode on Windows 7 (it does happen!) we may crash trying
|
||||
// to startup WMF. So we need to detect the OS version here, as in
|
||||
// compatibility mode IsVistaOrLater() and friends behave as if we're on
|
||||
// the emulated version of Windows. See bug 1279171.
|
||||
// Using GetVersionEx API which takes compatibility mode into account.
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT hr = LoadDLLs();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
||||
+199
-199
@@ -1,22 +1,22 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/* PluginUtilsWin.cpp - top-level Windows plugin management code */
|
||||
|
||||
#include <mmdeviceapi.h>
|
||||
#include "PluginUtilsWin.h"
|
||||
#include "PluginModuleParent.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
namespace PluginUtilsWin {
|
||||
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/* PluginUtilsWin.cpp - top-level Windows plugin management code */
|
||||
|
||||
#include <mmdeviceapi.h>
|
||||
#include "PluginUtilsWin.h"
|
||||
#include "PluginModuleParent.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
namespace PluginUtilsWin {
|
||||
|
||||
typedef nsTHashtable<nsPtrHashKey<PluginModuleParent>> PluginModuleSet;
|
||||
StaticMutex sMutex;
|
||||
|
||||
StaticMutex sMutex;
|
||||
|
||||
class AudioDeviceChangedRunnable : public Runnable
|
||||
{
|
||||
public:
|
||||
@@ -28,10 +28,10 @@ public:
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
PLUGIN_LOG_DEBUG(("Notifying %d plugins of audio device change.",
|
||||
mAudioNotificationSet->Count()));
|
||||
|
||||
|
||||
for (auto iter = mAudioNotificationSet->ConstIter(); !iter.Done(); iter.Next()) {
|
||||
PluginModuleParent* pluginModule = iter.Get()->GetKey();
|
||||
pluginModule->SendNPP_SetValue_NPNVaudioDeviceChangeDetails(mChangeDetails);
|
||||
@@ -43,195 +43,195 @@ protected:
|
||||
NPAudioDeviceChangeDetailsIPC mChangeDetails;
|
||||
const PluginModuleSet* mAudioNotificationSet;
|
||||
};
|
||||
|
||||
class AudioNotification : public IMMNotificationClient
|
||||
{
|
||||
public:
|
||||
AudioNotification() :
|
||||
mRefCt(1)
|
||||
, mIsRegistered(false)
|
||||
{
|
||||
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
|
||||
NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&mDeviceEnum));
|
||||
if (FAILED(hr)) {
|
||||
mDeviceEnum = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
hr = mDeviceEnum->RegisterEndpointNotificationCallback(this);
|
||||
if (FAILED(hr)) {
|
||||
mDeviceEnum->Release();
|
||||
mDeviceEnum = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
mIsRegistered = true;
|
||||
}
|
||||
|
||||
~AudioNotification()
|
||||
{
|
||||
MOZ_ASSERT(!mIsRegistered,
|
||||
"Destroying AudioNotification without first calling Unregister");
|
||||
if (mDeviceEnum) {
|
||||
mDeviceEnum->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// IMMNotificationClient Implementation
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR device_id) override
|
||||
{
|
||||
NPAudioDeviceChangeDetailsIPC changeDetails;
|
||||
changeDetails.flow = (int32_t)flow;
|
||||
changeDetails.role = (int32_t)role;
|
||||
changeDetails.defaultDevice = std::wstring(device_id);
|
||||
|
||||
|
||||
class AudioNotification : public IMMNotificationClient
|
||||
{
|
||||
public:
|
||||
AudioNotification() :
|
||||
mRefCt(1)
|
||||
, mIsRegistered(false)
|
||||
{
|
||||
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
|
||||
NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&mDeviceEnum));
|
||||
if (FAILED(hr)) {
|
||||
mDeviceEnum = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
hr = mDeviceEnum->RegisterEndpointNotificationCallback(this);
|
||||
if (FAILED(hr)) {
|
||||
mDeviceEnum->Release();
|
||||
mDeviceEnum = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
mIsRegistered = true;
|
||||
}
|
||||
|
||||
~AudioNotification()
|
||||
{
|
||||
MOZ_ASSERT(!mIsRegistered,
|
||||
"Destroying AudioNotification without first calling Unregister");
|
||||
if (mDeviceEnum) {
|
||||
mDeviceEnum->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// IMMNotificationClient Implementation
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR device_id) override
|
||||
{
|
||||
NPAudioDeviceChangeDetailsIPC changeDetails;
|
||||
changeDetails.flow = (int32_t)flow;
|
||||
changeDetails.role = (int32_t)role;
|
||||
changeDetails.defaultDevice = device_id ? std::wstring(device_id) : L"";
|
||||
|
||||
// Make sure that plugin is notified on the main thread.
|
||||
RefPtr<AudioDeviceChangedRunnable> runnable =
|
||||
new AudioDeviceChangedRunnable(&mAudioNotificationSet, changeDetails);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDeviceAdded(LPCWSTR device_id) override
|
||||
{
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDeviceRemoved(LPCWSTR device_id) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDeviceStateChanged(LPCWSTR device_id, DWORD new_state) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnPropertyValueChanged(LPCWSTR device_id, const PROPERTYKEY key) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IUnknown Implementation
|
||||
ULONG STDMETHODCALLTYPE
|
||||
AddRef() override
|
||||
{
|
||||
return InterlockedIncrement(&mRefCt);
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE
|
||||
Release() override
|
||||
{
|
||||
ULONG ulRef = InterlockedDecrement(&mRefCt);
|
||||
if (0 == ulRef) {
|
||||
delete this;
|
||||
}
|
||||
return ulRef;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
QueryInterface(REFIID riid, VOID **ppvInterface) override
|
||||
{
|
||||
if (__uuidof(IUnknown) == riid) {
|
||||
AddRef();
|
||||
*ppvInterface = (IUnknown*)this;
|
||||
} else if (__uuidof(IMMNotificationClient) == riid) {
|
||||
AddRef();
|
||||
*ppvInterface = (IMMNotificationClient*)this;
|
||||
} else {
|
||||
*ppvInterface = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* A Valid instance must be Unregistered before Releasing it.
|
||||
*/
|
||||
void Unregister()
|
||||
{
|
||||
if (mDeviceEnum) {
|
||||
mDeviceEnum->UnregisterEndpointNotificationCallback(this);
|
||||
}
|
||||
mIsRegistered = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* True whenever the notification server is set to report events to this object.
|
||||
*/
|
||||
bool IsRegistered() {
|
||||
return mIsRegistered;
|
||||
}
|
||||
|
||||
void AddModule(PluginModuleParent* aModule) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDeviceAdded(LPCWSTR device_id) override
|
||||
{
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDeviceRemoved(LPCWSTR device_id) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnDeviceStateChanged(LPCWSTR device_id, DWORD new_state) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnPropertyValueChanged(LPCWSTR device_id, const PROPERTYKEY key) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IUnknown Implementation
|
||||
ULONG STDMETHODCALLTYPE
|
||||
AddRef() override
|
||||
{
|
||||
return InterlockedIncrement(&mRefCt);
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE
|
||||
Release() override
|
||||
{
|
||||
ULONG ulRef = InterlockedDecrement(&mRefCt);
|
||||
if (0 == ulRef) {
|
||||
delete this;
|
||||
}
|
||||
return ulRef;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
QueryInterface(REFIID riid, VOID **ppvInterface) override
|
||||
{
|
||||
if (__uuidof(IUnknown) == riid) {
|
||||
AddRef();
|
||||
*ppvInterface = (IUnknown*)this;
|
||||
} else if (__uuidof(IMMNotificationClient) == riid) {
|
||||
AddRef();
|
||||
*ppvInterface = (IMMNotificationClient*)this;
|
||||
} else {
|
||||
*ppvInterface = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* A Valid instance must be Unregistered before Releasing it.
|
||||
*/
|
||||
void Unregister()
|
||||
{
|
||||
if (mDeviceEnum) {
|
||||
mDeviceEnum->UnregisterEndpointNotificationCallback(this);
|
||||
}
|
||||
mIsRegistered = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* True whenever the notification server is set to report events to this object.
|
||||
*/
|
||||
bool IsRegistered() {
|
||||
return mIsRegistered;
|
||||
}
|
||||
|
||||
void AddModule(PluginModuleParent* aModule) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
mAudioNotificationSet.PutEntry(aModule);
|
||||
}
|
||||
|
||||
void RemoveModule(PluginModuleParent* aModule) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
}
|
||||
|
||||
void RemoveModule(PluginModuleParent* aModule) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
mAudioNotificationSet.RemoveEntry(aModule);
|
||||
}
|
||||
|
||||
/*
|
||||
* Are any modules registered for audio notifications?
|
||||
*/
|
||||
bool HasModules() {
|
||||
return !mAudioNotificationSet.IsEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
bool mIsRegistered; // only used to make sure that Unregister is called before destroying a Valid instance.
|
||||
LONG mRefCt;
|
||||
IMMDeviceEnumerator* mDeviceEnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Are any modules registered for audio notifications?
|
||||
*/
|
||||
bool HasModules() {
|
||||
return !mAudioNotificationSet.IsEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
bool mIsRegistered; // only used to make sure that Unregister is called before destroying a Valid instance.
|
||||
LONG mRefCt;
|
||||
IMMDeviceEnumerator* mDeviceEnum;
|
||||
|
||||
// Set of plugin modules that have registered to be notified when the audio device
|
||||
// changes.
|
||||
PluginModuleSet mAudioNotificationSet;
|
||||
}; // class AudioNotification
|
||||
|
||||
// callback that gets notified of audio device events, or NULL
|
||||
AudioNotification* sAudioNotification = nullptr;
|
||||
|
||||
nsresult
|
||||
RegisterForAudioDeviceChanges(PluginModuleParent* aModuleParent, bool aShouldRegister)
|
||||
{
|
||||
// Hold the AudioNotification singleton iff there are PluginModuleParents
|
||||
// that are subscribed to it.
|
||||
if (aShouldRegister) {
|
||||
if (!sAudioNotification) {
|
||||
// We are registering the first module. Create the singleton.
|
||||
sAudioNotification = new AudioNotification();
|
||||
if (!sAudioNotification->IsRegistered()) {
|
||||
}; // class AudioNotification
|
||||
|
||||
// callback that gets notified of audio device events, or NULL
|
||||
AudioNotification* sAudioNotification = nullptr;
|
||||
|
||||
nsresult
|
||||
RegisterForAudioDeviceChanges(PluginModuleParent* aModuleParent, bool aShouldRegister)
|
||||
{
|
||||
// Hold the AudioNotification singleton iff there are PluginModuleParents
|
||||
// that are subscribed to it.
|
||||
if (aShouldRegister) {
|
||||
if (!sAudioNotification) {
|
||||
// We are registering the first module. Create the singleton.
|
||||
sAudioNotification = new AudioNotification();
|
||||
if (!sAudioNotification->IsRegistered()) {
|
||||
PLUGIN_LOG_DEBUG(("Registered for plugin audio device notification failed."));
|
||||
sAudioNotification->Release();
|
||||
sAudioNotification = nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
sAudioNotification->Release();
|
||||
sAudioNotification = nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PLUGIN_LOG_DEBUG(("Registered for plugin audio device notification."));
|
||||
}
|
||||
sAudioNotification->AddModule(aModuleParent);
|
||||
}
|
||||
else if (!aShouldRegister && sAudioNotification) {
|
||||
sAudioNotification->RemoveModule(aModuleParent);
|
||||
if (!sAudioNotification->HasModules()) {
|
||||
// We have removed the last module from the notification mechanism
|
||||
// so we can destroy the singleton.
|
||||
}
|
||||
sAudioNotification->AddModule(aModuleParent);
|
||||
}
|
||||
else if (!aShouldRegister && sAudioNotification) {
|
||||
sAudioNotification->RemoveModule(aModuleParent);
|
||||
if (!sAudioNotification->HasModules()) {
|
||||
// We have removed the last module from the notification mechanism
|
||||
// so we can destroy the singleton.
|
||||
PLUGIN_LOG_DEBUG(("Unregistering for plugin audio device notification."));
|
||||
sAudioNotification->Unregister();
|
||||
sAudioNotification->Release();
|
||||
sAudioNotification = nullptr;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace PluginUtilsWin
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
sAudioNotification->Unregister();
|
||||
sAudioNotification->Release();
|
||||
sAudioNotification = nullptr;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace PluginUtilsWin
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
}
|
||||
</script>
|
||||
<script src='file_sandbox_fail.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with only inline "allow-scripts"
|
||||
|
||||
<!-- Content-Security-Policy: default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img13_bad&type=img/png" />
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img13a_bad&type=img/png"> </img>
|
||||
<script src='/tests/dom/security/test/csp/file_CSP.sjs?testid=script13_bad&type=text/javascript'></script>
|
||||
<script src='http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=script13a_bad&type=text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>Bug 1396320: Fix CSP sandbox regression for allow-scripts</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type='application/javascript'>
|
||||
window.parent.postMessage({result: document.domain }, '*');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Content-Security-Policy: sandbox allow-scripts;
|
||||
@@ -185,6 +185,7 @@ support-files =
|
||||
file_sandbox_10.html
|
||||
file_sandbox_11.html
|
||||
file_sandbox_12.html
|
||||
file_sandbox_13.html
|
||||
file_require_sri_meta.sjs
|
||||
file_require_sri_meta.js
|
||||
file_sendbeacon.html
|
||||
@@ -329,3 +330,7 @@ support-files =
|
||||
file_frame_src_child_governs.html
|
||||
file_frame_src.js
|
||||
file_frame_src_inner.html
|
||||
[test_sandbox_allow_scripts.html]
|
||||
support-files =
|
||||
file_sandbox_allow_scripts.html
|
||||
file_sandbox_allow_scripts.html^headers^
|
||||
|
||||
@@ -111,7 +111,7 @@ var testCases = [
|
||||
// * using sandbox flag 'allow-scripts' in CSP and not as iframe attribute
|
||||
// * not using allow-same-origin in CSP (so a new NullPrincipal is created).
|
||||
csp: "default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts",
|
||||
file: "file_sandbox_5.html",
|
||||
file: "file_sandbox_13.html",
|
||||
results: { img13_bad: -1, img13a_bad: -1, script13_bad: -1, script13a_bad: -1 },
|
||||
nrOKmessages: 2 // sends 2 ok message
|
||||
},
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1396320: Fix CSP sandbox regression for allow-scripts</title>
|
||||
<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">
|
||||
|
||||
/* Description of the test:
|
||||
* Load an iframe using a CSP of 'sandbox allow-scripts' and make sure
|
||||
* the security context of the iframe is sandboxed (cross origin)
|
||||
*/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("message", receiveMessage);
|
||||
function receiveMessage(event) {
|
||||
is(event.data.result, "",
|
||||
"document.domain of sandboxed iframe should be opaque");
|
||||
window.removeEventListener("message", receiveMessage);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
let testframe = document.getElementById("testframe");
|
||||
testframe.src = "file_sandbox_allow_scripts.html";
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -275,6 +275,10 @@ HTMLEditor::Init(nsIDOMDocument* aDoc,
|
||||
nsCOMPtr<nsINode> document = do_QueryInterface(aDoc);
|
||||
document->AddMutationObserverUnlessExists(this);
|
||||
|
||||
if (!mRootElement) {
|
||||
UpdateRootElement();
|
||||
}
|
||||
|
||||
// disable Composer-only features
|
||||
if (IsMailEditor()) {
|
||||
SetAbsolutePositioningEnabled(false);
|
||||
@@ -346,45 +350,27 @@ HTMLEditor::PreDestroy(bool aDestroyingFrames)
|
||||
return TextEditor::PreDestroy(aDestroyingFrames);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLEditor::GetRootElement(nsIDOMElement** aRootElement)
|
||||
void
|
||||
HTMLEditor::UpdateRootElement()
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRootElement);
|
||||
|
||||
if (mRootElement) {
|
||||
return EditorBase::GetRootElement(aRootElement);
|
||||
}
|
||||
|
||||
*aRootElement = nullptr;
|
||||
|
||||
// Use the HTML documents body element as the editor root if we didn't
|
||||
// get a root element during initialization.
|
||||
|
||||
nsCOMPtr<nsIDOMElement> rootElement;
|
||||
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
|
||||
nsresult rv = GetBodyElement(getter_AddRefs(bodyElement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (bodyElement) {
|
||||
rootElement = bodyElement;
|
||||
} else {
|
||||
// If there is no HTML body element,
|
||||
// we should use the document root element instead.
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
rv = doc->GetDocumentElement(getter_AddRefs(rootElement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Document can have no elements
|
||||
if (!rootElement) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
if (doc) {
|
||||
doc->GetDocumentElement(getter_AddRefs(rootElement));
|
||||
}
|
||||
}
|
||||
|
||||
mRootElement = do_QueryInterface(rootElement);
|
||||
rootElement.forget(aRootElement);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIContent>
|
||||
@@ -3234,8 +3220,9 @@ HTMLEditor::DoContentInserted(nsIDocument* aDocument,
|
||||
nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
|
||||
|
||||
if (ShouldReplaceRootElement()) {
|
||||
UpdateRootElement();
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod(
|
||||
this, &HTMLEditor::ResetRootElementAndEventTarget));
|
||||
this, &HTMLEditor::NotifyRootChanged));
|
||||
}
|
||||
// We don't need to handle our own modifications
|
||||
else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
|
||||
@@ -3282,8 +3269,9 @@ HTMLEditor::ContentRemoved(nsIDocument* aDocument,
|
||||
nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
|
||||
|
||||
if (SameCOMIdentity(aChild, mRootElement)) {
|
||||
mRootElement = nullptr;
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod(
|
||||
this, &HTMLEditor::ResetRootElementAndEventTarget));
|
||||
this, &HTMLEditor::NotifyRootChanged));
|
||||
}
|
||||
// We don't need to handle our own modifications
|
||||
else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
|
||||
@@ -5044,24 +5032,18 @@ HTMLEditor::ShouldReplaceRootElement()
|
||||
}
|
||||
|
||||
void
|
||||
HTMLEditor::ResetRootElementAndEventTarget()
|
||||
HTMLEditor::NotifyRootChanged()
|
||||
{
|
||||
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
|
||||
|
||||
// Need to remove the event listeners first because BeginningOfDocument
|
||||
// could set a new root (and event target is set by InstallEventListeners())
|
||||
// and we won't be able to remove them from the old event target then.
|
||||
RemoveEventListeners();
|
||||
mRootElement = nullptr;
|
||||
nsresult rv = InstallEventListeners();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We must have mRootElement now.
|
||||
nsCOMPtr<nsIDOMElement> root;
|
||||
rv = GetRootElement(getter_AddRefs(root));
|
||||
if (NS_FAILED(rv) || !mRootElement) {
|
||||
UpdateRootElement();
|
||||
if (!mRootElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -363,8 +363,6 @@ public:
|
||||
|
||||
NS_IMETHOD SelectAll() override;
|
||||
|
||||
NS_IMETHOD GetRootElement(nsIDOMElement** aRootElement) override;
|
||||
|
||||
// nsICSSLoaderObserver
|
||||
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
|
||||
bool aWasAlternate, nsresult aStatus) override;
|
||||
@@ -477,7 +475,7 @@ protected:
|
||||
virtual void RemoveEventListeners() override;
|
||||
|
||||
bool ShouldReplaceRootElement();
|
||||
void ResetRootElementAndEventTarget();
|
||||
void NotifyRootChanged();
|
||||
nsresult GetBodyElement(nsIDOMHTMLElement** aBody);
|
||||
|
||||
/**
|
||||
@@ -940,6 +938,8 @@ protected:
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild);
|
||||
|
||||
void UpdateRootElement();
|
||||
|
||||
// resizing
|
||||
bool mIsObjectResizingEnabled;
|
||||
bool mIsResizing;
|
||||
|
||||
@@ -210,7 +210,7 @@ static const mozilla::Module::ContractIDEntry kAuthContracts[] = {
|
||||
{ NS_AUTH_MODULE_CONTRACTID_PREFIX "negotiate-sspi", &kNS_NEGOTIATEAUTHSSPI_CID },
|
||||
{ NS_AUTH_MODULE_CONTRACTID_PREFIX "kerb-sspi", &kNS_KERBAUTHSSPI_CID },
|
||||
{ NS_AUTH_MODULE_CONTRACTID_PREFIX "sys-ntlm", &kNS_SYSNTLMAUTH_CID },
|
||||
#else
|
||||
#elif !defined(XP_MACOSX)
|
||||
{ NS_AUTH_MODULE_CONTRACTID_PREFIX "sys-ntlm", &kNS_SAMBANTLMAUTH_CID },
|
||||
#endif
|
||||
{ NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX "negotiate", &kNS_HTTPNEGOTIATEAUTH_CID },
|
||||
|
||||
@@ -681,10 +681,15 @@ void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
|
||||
glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax));
|
||||
glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin));
|
||||
|
||||
if (isLCD(fRec) &&
|
||||
gSetLcdFilter &&
|
||||
(fLcdFilter == FT_LCD_FILTER_DEFAULT ||
|
||||
fLcdFilter == FT_LCD_FILTER_LIGHT)) {
|
||||
if (isLCD(fRec)) {
|
||||
// In FreeType < 2.8.1, LCD filtering, if explicitly used, may
|
||||
// add padding to the glyph. When not used, there is no padding.
|
||||
// As of 2.8.1, LCD filtering is now always supported and may
|
||||
// add padding even if an LCD filter is not explicitly set.
|
||||
// Regardless, if no LCD filtering is used, or if LCD filtering
|
||||
// doesn't add padding, it is safe to modify the glyph's bounds
|
||||
// here. generateGlyphImage will detect if the mask is smaller
|
||||
// than the bounds and clip things appropriately.
|
||||
if (fRec.fFlags & kLCD_Vertical_Flag) {
|
||||
glyph->fTop -= 1;
|
||||
glyph->fHeight += 2;
|
||||
|
||||
@@ -221,7 +221,11 @@ MacOSFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
||||
// Blacklist these so that font fallback will not use them.
|
||||
if (mRequiresAAT && (FamilyName().EqualsLiteral("Songti SC") ||
|
||||
FamilyName().EqualsLiteral("Songti TC") ||
|
||||
FamilyName().EqualsLiteral("STSong"))) {
|
||||
FamilyName().EqualsLiteral("STSong") ||
|
||||
// Bug 1390980: on 10.11, the Kaiti fonts are also affected.
|
||||
FamilyName().EqualsLiteral("Kaiti SC") ||
|
||||
FamilyName().EqualsLiteral("Kaiti TC") ||
|
||||
FamilyName().EqualsLiteral("STKaiti"))) {
|
||||
charmap->ClearRange(0x0f6b, 0x0f70);
|
||||
charmap->ClearRange(0x0f8c, 0x0f8f);
|
||||
charmap->clear(0x0f98);
|
||||
|
||||
@@ -687,6 +687,14 @@ gfxPlatform::Init()
|
||||
gpu->LaunchGPUProcess();
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (gfxPlatform::ForceSoftwareVsync()) {
|
||||
gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
|
||||
} else {
|
||||
gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkGraphics::Init();
|
||||
# ifdef MOZ_ENABLE_FREETYPE
|
||||
@@ -774,14 +782,6 @@ gfxPlatform::Init()
|
||||
|
||||
RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (gfxPlatform::ForceSoftwareVsync()) {
|
||||
gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
|
||||
} else {
|
||||
gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_SKIA
|
||||
uint32_t skiaCacheSize = GetSkiaGlyphCacheSize();
|
||||
if (skiaCacheSize != kDefaultGlyphCacheSize) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@@ -1441,6 +1442,21 @@ gfxWindowsPlatform::InitializeD3D11Config()
|
||||
|
||||
d3d11.EnableByDefault();
|
||||
|
||||
if (!IsWin8OrLater() &&
|
||||
!DeviceManagerDx::Get()->CheckRemotePresentSupport()) {
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo;
|
||||
gfxInfo = services::GetGfxInfo();
|
||||
nsAutoString adaptorId;
|
||||
gfxInfo->GetAdapterDeviceID(adaptorId);
|
||||
// Blacklist Intel HD Graphics 510/520/530 on Windows 7 without platform
|
||||
// update due to the crashes in Bug 1351349.
|
||||
if (adaptorId.EqualsLiteral("0x1912") || adaptorId.EqualsLiteral("0x1916") ||
|
||||
adaptorId.EqualsLiteral("0x1902")) {
|
||||
d3d11.Disable(FeatureStatus::Blacklisted, "Blacklisted, see bug 1351349",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_BUG_1351349"));
|
||||
}
|
||||
}
|
||||
|
||||
// If the user prefers D3D9, act as though they disabled D3D11.
|
||||
if (gfxPrefs::LayersPreferD3D9()) {
|
||||
d3d11.UserDisable("Disabled due to user preference for Direct3D 9",
|
||||
|
||||
@@ -300,7 +300,7 @@ class MOZ_STACK_CLASS CallArgs : public detail::CallArgsBase<detail::IncludeUsed
|
||||
* Returns true if there are at least |required| arguments passed in. If
|
||||
* false, it reports an error message on the context.
|
||||
*/
|
||||
bool requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const;
|
||||
JS_PUBLIC_API(bool) requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -340,7 +340,7 @@ GetDebuggeeGlobals(JSContext* cx, JSObject& dbgObj, AutoObjectVector& vector);
|
||||
// call the appropriate |Entry| member function to indicate where we've begun
|
||||
// execution.
|
||||
|
||||
class MOZ_STACK_CLASS AutoEntryMonitor {
|
||||
class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEntryMonitor) {
|
||||
JSRuntime* runtime_;
|
||||
AutoEntryMonitor* savedMonitor_;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "js/StructuredClone.h"
|
||||
|
||||
namespace js {
|
||||
struct PerformanceGroup;
|
||||
struct JS_PUBLIC_API(PerformanceGroup);
|
||||
} // namespace js
|
||||
|
||||
struct JSPrincipals {
|
||||
|
||||
@@ -183,10 +183,13 @@ struct ForEachProfiledFrameOp
|
||||
bool hasTrackedOptimizations() const { return optsIndex_.isSome(); }
|
||||
void* canonicalAddress() const { return canonicalAddr_; }
|
||||
|
||||
ProfilingFrameIterator::FrameKind frameKind() const;
|
||||
void forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
|
||||
JSScript** scriptOut, jsbytecode** pcOut) const;
|
||||
void forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const;
|
||||
JS_PUBLIC_API(ProfilingFrameIterator::FrameKind) frameKind() const;
|
||||
JS_PUBLIC_API(void) forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
|
||||
JSScript** scriptOut,
|
||||
jsbytecode** pcOut) const;
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const;
|
||||
};
|
||||
|
||||
// Called once per frame.
|
||||
|
||||
@@ -161,7 +161,7 @@ class ProfileEntry
|
||||
MOZ_ASSERT(!isJs());
|
||||
return spOrScript;
|
||||
}
|
||||
JSScript* script() const volatile;
|
||||
JS_PUBLIC_API(JSScript*) script() const volatile;
|
||||
uint32_t line() const volatile {
|
||||
MOZ_ASSERT(!isJs());
|
||||
return static_cast<uint32_t>(lineOrPcOffset);
|
||||
|
||||
@@ -211,7 +211,8 @@ namespace js
|
||||
};
|
||||
}
|
||||
|
||||
class MOZ_NON_MEMMOVABLE JSStructuredCloneData : public mozilla::BufferList<js::SystemAllocPolicy>
|
||||
class MOZ_NON_MEMMOVABLE JS_PUBLIC_API(JSStructuredCloneData) :
|
||||
public mozilla::BufferList<js::SystemAllocPolicy>
|
||||
{
|
||||
typedef js::SystemAllocPolicy AllocPolicy;
|
||||
typedef mozilla::BufferList<js::SystemAllocPolicy> BufferList;
|
||||
|
||||
+15
-13
@@ -193,7 +193,7 @@ using Vector = mozilla::Vector<T, 0, js::SystemAllocPolicy>;
|
||||
// heap snapshots store their strings as const char16_t*. In order to provide
|
||||
// zero-cost accessors to these strings in a single interface that works with
|
||||
// both cases, we use this variant type.
|
||||
class AtomOrTwoByteChars : public Variant<JSAtom*, const char16_t*> {
|
||||
class JS_PUBLIC_API(AtomOrTwoByteChars) : public Variant<JSAtom*, const char16_t*> {
|
||||
using Base = Variant<JSAtom*, const char16_t*>;
|
||||
|
||||
public:
|
||||
@@ -466,8 +466,10 @@ class ConcreteStackFrame<void> : public BaseStackFrame {
|
||||
bool isSelfHosted(JSContext* cx) const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
|
||||
};
|
||||
|
||||
MOZ_MUST_USE bool ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFrame& frame,
|
||||
MutableHandleObject outSavedFrameStack);
|
||||
MOZ_MUST_USE JS_PUBLIC_API(bool)
|
||||
ConstructSavedFrameStackSlow(JSContext* cx,
|
||||
JS::ubi::StackFrame& frame,
|
||||
MutableHandleObject outSavedFrameStack);
|
||||
|
||||
|
||||
/*** ubi::Node ************************************************************************************/
|
||||
@@ -518,7 +520,7 @@ Uint32ToCoarseType(uint32_t n)
|
||||
|
||||
// The base class implemented by each ubi::Node referent type. Subclasses must
|
||||
// not add data members to this class.
|
||||
class Base {
|
||||
class JS_PUBLIC_API(Base) {
|
||||
friend class Node;
|
||||
|
||||
// For performance's sake, we'd prefer to avoid a virtual destructor; and
|
||||
@@ -969,7 +971,7 @@ class PreComputedEdgeRange : public EdgeRange {
|
||||
//
|
||||
// ...
|
||||
// }
|
||||
class MOZ_STACK_CLASS RootList {
|
||||
class MOZ_STACK_CLASS JS_PUBLIC_API(RootList) {
|
||||
Maybe<AutoCheckCannotGC>& noGC;
|
||||
|
||||
public:
|
||||
@@ -1001,7 +1003,7 @@ class MOZ_STACK_CLASS RootList {
|
||||
/*** Concrete classes for ubi::Node referent types ************************************************/
|
||||
|
||||
template<>
|
||||
class Concrete<RootList> : public Base {
|
||||
class JS_PUBLIC_API(Concrete<RootList>) : public Base {
|
||||
protected:
|
||||
explicit Concrete(RootList* ptr) : Base(ptr) { }
|
||||
RootList& get() const { return *static_cast<RootList*>(ptr); }
|
||||
@@ -1018,7 +1020,7 @@ class Concrete<RootList> : public Base {
|
||||
// A reusable ubi::Concrete specialization base class for types supported by
|
||||
// JS::TraceChildren.
|
||||
template<typename Referent>
|
||||
class TracerConcrete : public Base {
|
||||
class JS_PUBLIC_API(TracerConcrete) : public Base {
|
||||
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
|
||||
JS::Zone* zone() const override;
|
||||
|
||||
@@ -1029,7 +1031,7 @@ class TracerConcrete : public Base {
|
||||
|
||||
// For JS::TraceChildren-based types that have a 'compartment' method.
|
||||
template<typename Referent>
|
||||
class TracerConcreteWithCompartment : public TracerConcrete<Referent> {
|
||||
class JS_PUBLIC_API(TracerConcreteWithCompartment) : public TracerConcrete<Referent> {
|
||||
typedef TracerConcrete<Referent> TracerBase;
|
||||
JSCompartment* compartment() const override;
|
||||
|
||||
@@ -1040,7 +1042,7 @@ class TracerConcreteWithCompartment : public TracerConcrete<Referent> {
|
||||
// Define specializations for some commonly-used public JSAPI types.
|
||||
// These can use the generic templates above.
|
||||
template<>
|
||||
class Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> {
|
||||
class JS_PUBLIC_API(Concrete<JS::Symbol>) : TracerConcrete<JS::Symbol> {
|
||||
protected:
|
||||
explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) { }
|
||||
|
||||
@@ -1056,7 +1058,7 @@ class Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> {
|
||||
};
|
||||
|
||||
template<>
|
||||
class Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> {
|
||||
class JS_PUBLIC_API(Concrete<JSScript>) : TracerConcreteWithCompartment<JSScript> {
|
||||
protected:
|
||||
explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment<JSScript>(ptr) { }
|
||||
|
||||
@@ -1073,7 +1075,7 @@ class Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> {
|
||||
|
||||
// The JSObject specialization.
|
||||
template<>
|
||||
class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
|
||||
class JS_PUBLIC_API(Concrete<JSObject>) : public TracerConcreteWithCompartment<JSObject> {
|
||||
protected:
|
||||
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
|
||||
|
||||
@@ -1098,7 +1100,7 @@ class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
|
||||
|
||||
// For JSString, we extend the generic template with a 'size' implementation.
|
||||
template<>
|
||||
class Concrete<JSString> : TracerConcrete<JSString> {
|
||||
class JS_PUBLIC_API(Concrete<JSString>) : TracerConcrete<JSString> {
|
||||
protected:
|
||||
explicit Concrete(JSString *ptr) : TracerConcrete<JSString>(ptr) { }
|
||||
|
||||
@@ -1115,7 +1117,7 @@ class Concrete<JSString> : TracerConcrete<JSString> {
|
||||
|
||||
// The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts.
|
||||
template<>
|
||||
class Concrete<void> : public Base {
|
||||
class JS_PUBLIC_API(Concrete<void>) : public Base {
|
||||
const char16_t* typeName() const override;
|
||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
|
||||
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
|
||||
|
||||
@@ -83,7 +83,7 @@ struct Census;
|
||||
class CountBase;
|
||||
|
||||
struct CountDeleter {
|
||||
void operator()(CountBase*);
|
||||
JS_PUBLIC_API(void) operator()(CountBase*);
|
||||
};
|
||||
|
||||
using CountBasePtr = js::UniquePtr<CountBase, CountDeleter>;
|
||||
@@ -203,7 +203,7 @@ struct Census {
|
||||
|
||||
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
|
||||
|
||||
MOZ_MUST_USE bool init();
|
||||
MOZ_MUST_USE JS_PUBLIC_API(bool) init();
|
||||
};
|
||||
|
||||
// A BreadthFirst handler type that conducts a census, using a CountBase to
|
||||
@@ -227,22 +227,23 @@ class CensusHandler {
|
||||
// This class needs to retain no per-node data.
|
||||
class NodeData { };
|
||||
|
||||
MOZ_MUST_USE bool operator() (BreadthFirst<CensusHandler>& traversal,
|
||||
Node origin, const Edge& edge,
|
||||
NodeData* referentData, bool first);
|
||||
MOZ_MUST_USE JS_PUBLIC_API(bool) operator() (BreadthFirst<CensusHandler>& traversal,
|
||||
Node origin, const Edge& edge,
|
||||
NodeData* referentData, bool first);
|
||||
};
|
||||
|
||||
using CensusTraversal = BreadthFirst<CensusHandler>;
|
||||
|
||||
// Examine the census options supplied by the API consumer, and (among other
|
||||
// things) use that to build a CountType tree.
|
||||
MOZ_MUST_USE bool ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
|
||||
CountTypePtr& outResult);
|
||||
MOZ_MUST_USE JS_PUBLIC_API(bool) ParseCensusOptions(JSContext* cx,
|
||||
Census& census, HandleObject options,
|
||||
CountTypePtr& outResult);
|
||||
|
||||
// Parse the breakdown language (as described in
|
||||
// js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
|
||||
// is returned on error and is reported to the cx.
|
||||
CountTypePtr ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
|
||||
JS_PUBLIC_API(CountTypePtr) ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
|
||||
|
||||
|
||||
} // namespace ubi
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ static inline bool ShouldFailWithOOM() { return false; }
|
||||
namespace js {
|
||||
|
||||
/* Disable OOM testing in sections which are not OOM safe. */
|
||||
struct MOZ_RAII AutoEnterOOMUnsafeRegion
|
||||
struct MOZ_RAII JS_PUBLIC_DATA(AutoEnterOOMUnsafeRegion)
|
||||
{
|
||||
MOZ_NORETURN MOZ_COLD void crash(const char* reason);
|
||||
MOZ_NORETURN MOZ_COLD void crash(size_t size, const char* reason);
|
||||
|
||||
+15
-5
@@ -166,13 +166,13 @@ endif # GNU_CC
|
||||
endif
|
||||
endif
|
||||
|
||||
SCRIPTS = $(JS_CONFIG_NAME)
|
||||
|
||||
$(LIBRARY_NAME).pc: js.pc
|
||||
cp $^ $@
|
||||
|
||||
# Install versioned file, for parallel installability in Linux distributions
|
||||
install:: $(LIBRARY_NAME).pc
|
||||
$(SYSINSTALL) $^ $(DESTDIR)$(libdir)/pkgconfig
|
||||
cp $^ $(JS_LIBRARY_NAME).pc
|
||||
$(SYSINSTALL) $(JS_LIBRARY_NAME).pc $(DESTDIR)$(libdir)/pkgconfig
|
||||
|
||||
install:: js-config.h
|
||||
$(SYSINSTALL) $^ $(DESTDIR)$(includedir)
|
||||
@@ -208,9 +208,13 @@ install::
|
||||
# END SpiderMonkey header installation
|
||||
#############################################
|
||||
|
||||
install:: $(SCRIPTS)
|
||||
$(SYSINSTALL) $^ $(DESTDIR)$(bindir)
|
||||
# Install versioned script, for parallel installability in Linux distributions
|
||||
install:: js-config
|
||||
cp $^ js$(MOZJS_MAJOR_VERSION)-config
|
||||
$(SYSINSTALL) js$(MOZJS_MAJOR_VERSION)-config $(DESTDIR)$(bindir)
|
||||
|
||||
# Use install_name_tool to set the install_name properly for standalone
|
||||
# installed libraries on macOS
|
||||
install:: $(REAL_LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
|
||||
ifneq (,$(REAL_LIBRARY))
|
||||
$(SYSINSTALL) $(REAL_LIBRARY) $(DESTDIR)$(libdir)
|
||||
@@ -218,9 +222,14 @@ ifneq (,$(REAL_LIBRARY))
|
||||
endif
|
||||
ifneq (,$(SHARED_LIBRARY))
|
||||
$(SYSINSTALL) $(SHARED_LIBRARY) $(DESTDIR)$(libdir)
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
install_name_tool -id $(abspath $(libdir)/$(SHARED_LIBRARY)) $(DESTDIR)$(libdir)/$(SHARED_LIBRARY)
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(IMPORT_LIBRARY))
|
||||
ifneq ($(IMPORT_LIBRARY),$(SHARED_LIBRARY))
|
||||
$(SYSINSTALL) $(IMPORT_LIBRARY) $(DESTDIR)$(libdir)
|
||||
endif
|
||||
endif
|
||||
$(MAKE) -C shell install
|
||||
|
||||
@@ -246,6 +255,7 @@ source-package:
|
||||
DIST=$(DIST) \
|
||||
MKDIR=$(MKDIR) \
|
||||
TAR=$(TAR) \
|
||||
AUTOCONF=$(AUTOCONF) \
|
||||
MOZJS_MAJOR_VERSION=$(MOZJS_MAJOR_VERSION) \
|
||||
MOZJS_MINOR_VERSION=$(MOZJS_MINOR_VERSION) \
|
||||
MOZJS_PATCH_VERSION=$(MOZJS_PATCH_VERSION) \
|
||||
|
||||
+15
-6
@@ -180,12 +180,21 @@ MovableCellHasher<T>::match(const Key& k, const Lookup& l)
|
||||
return zone->getUniqueIdInfallible(k) == zone->getUniqueIdInfallible(l);
|
||||
}
|
||||
|
||||
template struct MovableCellHasher<JSObject*>;
|
||||
template struct MovableCellHasher<GlobalObject*>;
|
||||
template struct MovableCellHasher<SavedFrame*>;
|
||||
template struct MovableCellHasher<EnvironmentObject*>;
|
||||
template struct MovableCellHasher<WasmInstanceObject*>;
|
||||
template struct MovableCellHasher<JSScript*>;
|
||||
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
|
||||
template struct JS_PUBLIC_API(MovableCellHasher<JSObject*>);
|
||||
template struct JS_PUBLIC_API(MovableCellHasher<GlobalObject*>);
|
||||
template struct JS_PUBLIC_API(MovableCellHasher<SavedFrame*>);
|
||||
template struct JS_PUBLIC_API(MovableCellHasher<EnvironmentObject*>);
|
||||
template struct JS_PUBLIC_API(MovableCellHasher<WasmInstanceObject*>);
|
||||
template struct JS_PUBLIC_API(MovableCellHasher<JSScript*>);
|
||||
|
||||
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
|
||||
} // namespace js
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ MemProfiler::GetGCHeapProfiler(JSRuntime* runtime)
|
||||
return runtime->gc.mMemProfiler.mGCHeapProfiler;
|
||||
}
|
||||
|
||||
MemProfiler*
|
||||
JS_FRIEND_API(MemProfiler*)
|
||||
MemProfiler::GetMemProfiler(JSContext* context)
|
||||
{
|
||||
return &context->gc.mMemProfiler;
|
||||
}
|
||||
|
||||
void
|
||||
JS_FRIEND_API(void)
|
||||
MemProfiler::start(GCHeapProfiler* aGCHeapProfiler)
|
||||
{
|
||||
ReleaseAllJITCode(mRuntime->defaultFreeOp());
|
||||
@@ -41,7 +41,7 @@ MemProfiler::start(GCHeapProfiler* aGCHeapProfiler)
|
||||
sActiveProfilerCount++;
|
||||
}
|
||||
|
||||
void
|
||||
JS_FRIEND_API(void)
|
||||
MemProfiler::stop()
|
||||
{
|
||||
sActiveProfilerCount--;
|
||||
|
||||
@@ -1637,7 +1637,7 @@ JS::ForEachProfiledFrameOp::FrameHandle::FrameHandle(JSRuntime* rt, js::jit::Jit
|
||||
}
|
||||
}
|
||||
|
||||
JS::ProfilingFrameIterator::FrameKind
|
||||
JS_PUBLIC_API(JS::ProfilingFrameIterator::FrameKind)
|
||||
JS::ForEachProfiledFrameOp::FrameHandle::frameKind() const
|
||||
{
|
||||
if (entry_.isBaseline())
|
||||
|
||||
@@ -1294,7 +1294,7 @@ FrameHandle::updateHasTrackedOptimizations()
|
||||
canonicalAddr_ = (void*)(((uint8_t*) entry_.nativeStartAddr()) + entryOffset);
|
||||
}
|
||||
|
||||
void
|
||||
JS_PUBLIC_API(void)
|
||||
FrameHandle::forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
|
||||
JSScript** scriptOut, jsbytecode** pcOut) const
|
||||
{
|
||||
@@ -1303,7 +1303,7 @@ FrameHandle::forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
|
||||
entry_.youngestFrameLocationAtAddr(rt_, addr_, scriptOut, pcOut);
|
||||
}
|
||||
|
||||
void
|
||||
JS_PUBLIC_API(void)
|
||||
FrameHandle::forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const
|
||||
{
|
||||
MOZ_ASSERT(optsIndex_.isSome());
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@ includedir=@includedir@
|
||||
Name: SpiderMonkey @MOZILLA_VERSION@
|
||||
Description: The Mozilla library for JavaScript
|
||||
Version: @MOZILLA_VERSION@
|
||||
Requires.private: @NSPR_PKGCONF_CHECK@
|
||||
@PKGCONF_REQUIRES_PRIVATE@
|
||||
Libs: -L${libdir} -l@JS_LIBRARY_NAME@
|
||||
Cflags: -include ${includedir}/@JS_LIBRARY_NAME@/js/RequiredDefines.h -I${includedir}/@JS_LIBRARY_NAME@
|
||||
|
||||
+2
-2
@@ -121,7 +121,7 @@ using JS::ToUint32;
|
||||
#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
|
||||
#endif
|
||||
|
||||
bool
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CallArgs::requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const
|
||||
{
|
||||
if (length() < required) {
|
||||
@@ -3118,7 +3118,7 @@ JS_DefineConstIntegers(JSContext* cx, HandleObject obj, const JSConstIntegerSpec
|
||||
return DefineConstScalar(cx, obj, cis);
|
||||
}
|
||||
|
||||
bool
|
||||
JS_PUBLIC_API(bool)
|
||||
JSPropertySpec::getValue(JSContext* cx, MutableHandleValue vp) const
|
||||
{
|
||||
MOZ_ASSERT(!isAccessor());
|
||||
|
||||
+3
-3
@@ -1962,7 +1962,7 @@ struct JSPropertySpec {
|
||||
bool isAccessor() const {
|
||||
return !(flags & JSPROP_INTERNAL_USE_BIT);
|
||||
}
|
||||
bool getValue(JSContext* cx, JS::MutableHandleValue value) const;
|
||||
JS_PUBLIC_API(bool) getValue(JSContext* cx, JS::MutableHandleValue value) const;
|
||||
|
||||
bool isSelfHosted() const {
|
||||
MOZ_ASSERT(isAccessor());
|
||||
@@ -6271,7 +6271,7 @@ struct MaxFrames
|
||||
* consider self-hosted frames with the given principals as satisfying the stack
|
||||
* capture.
|
||||
*/
|
||||
struct FirstSubsumedFrame
|
||||
struct JS_PUBLIC_API(FirstSubsumedFrame)
|
||||
{
|
||||
JSContext* cx;
|
||||
JSPrincipals* principals;
|
||||
@@ -6492,7 +6492,7 @@ class AutoStopwatch;
|
||||
* provide a concrete implementation of this class, as well as the
|
||||
* relevant callbacks (see below).
|
||||
*/
|
||||
struct PerformanceGroup {
|
||||
struct JS_PUBLIC_API(PerformanceGroup) {
|
||||
PerformanceGroup();
|
||||
|
||||
// The current iteration of the event loop.
|
||||
|
||||
@@ -1284,7 +1284,7 @@ GetErrorMessage(void* userRef, const unsigned errorNumber);
|
||||
* JSString methods and often the code can be rewritten so that only indexes
|
||||
* instead of char pointers are used in parts of the code that can GC.
|
||||
*/
|
||||
class MOZ_STACK_CLASS AutoStableStringChars
|
||||
class MOZ_STACK_CLASS JS_FRIEND_API(AutoStableStringChars)
|
||||
{
|
||||
/*
|
||||
* When copying string char, use this many bytes of inline storage. This is
|
||||
@@ -2910,7 +2910,7 @@ class GCHeapProfiler
|
||||
class MemProfiler
|
||||
{
|
||||
static mozilla::Atomic<uint32_t, mozilla::Relaxed> sActiveProfilerCount;
|
||||
static NativeProfiler* sNativeProfiler;
|
||||
static JS_FRIEND_DATA(NativeProfiler*) sNativeProfiler;
|
||||
|
||||
static GCHeapProfiler* GetGCHeapProfiler(void* addr);
|
||||
static GCHeapProfiler* GetGCHeapProfiler(JSRuntime* runtime);
|
||||
@@ -2925,8 +2925,8 @@ class MemProfiler
|
||||
public:
|
||||
explicit MemProfiler(JSRuntime* aRuntime) : mGCHeapProfiler(nullptr), mRuntime(aRuntime) {}
|
||||
|
||||
void start(GCHeapProfiler* aGCHeapProfiler);
|
||||
void stop();
|
||||
JS_FRIEND_API(void) start(GCHeapProfiler* aGCHeapProfiler);
|
||||
JS_FRIEND_API(void) stop();
|
||||
|
||||
GCHeapProfiler* getGCHeapProfiler() const {
|
||||
return mGCHeapProfiler;
|
||||
@@ -2936,7 +2936,7 @@ class MemProfiler
|
||||
return sActiveProfilerCount > 0;
|
||||
}
|
||||
|
||||
static MemProfiler* GetMemProfiler(JSContext* context);
|
||||
static JS_FRIEND_API(MemProfiler*) GetMemProfiler(JSContext* context);
|
||||
|
||||
static void SetNativeProfiler(NativeProfiler* aProfiler) {
|
||||
sNativeProfiler = aProfiler;
|
||||
|
||||
@@ -93,6 +93,14 @@
|
||||
#define JS_NO_FASTCALL
|
||||
#endif
|
||||
|
||||
// gcc is buggy and warns on our attempts to JS_PUBLIC_API our
|
||||
// forward-declarations or explicit template instantiations. See
|
||||
// <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50044>. Add a way to detect
|
||||
// that so we can locally disable that warning.
|
||||
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ < 6 || (__GNUC__ == 6 && __GNUC_MINOR__ <= 4))
|
||||
#define JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BEGIN_MACRO
|
||||
** JS_END_MACRO
|
||||
|
||||
+1
-1
@@ -364,7 +364,7 @@ ReportAccessDenied(JSContext* cx);
|
||||
JS_FRIEND_API(bool)
|
||||
IsCrossCompartmentWrapper(JSObject* obj);
|
||||
|
||||
void
|
||||
JS_FRIEND_API(void)
|
||||
NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);
|
||||
|
||||
void
|
||||
|
||||
@@ -7,6 +7,7 @@ set -e
|
||||
|
||||
: ${MKDIR:=mkdir}
|
||||
: ${TAR:=tar}
|
||||
: ${AUTOCONF:=autoconf-2.13}
|
||||
: ${SRCDIR:=$(cd $(dirname $0); pwd 2>/dev/null)}
|
||||
: ${MOZJS_NAME:=mozjs}
|
||||
# The place to gather files to be added to the tarball.
|
||||
@@ -34,6 +35,7 @@ echo "Environment:"
|
||||
echo " MAKE = $MAKE"
|
||||
echo " MKDIR = $MKDIR"
|
||||
echo " TAR = $TAR"
|
||||
echo " AUTOCONF = $AUTOCONF"
|
||||
echo " STAGING = $STAGING"
|
||||
echo " DIST = $DIST"
|
||||
echo " SRCDIR = $SRCDIR"
|
||||
@@ -97,6 +99,12 @@ case $cmd in
|
||||
${MKDIR} -p ${tgtpath}/.cargo
|
||||
cp -pPR ${TOPSRCDIR}/.cargo/config.in ${tgtpath}/.cargo
|
||||
|
||||
# generate configure files to avoid build dependency on autoconf-2.13
|
||||
cp -PR ${TOPSRCDIR}/js/src/configure.in ${tgtpath}/js/src/configure
|
||||
chmod a+x ${tgtpath}/js/src/configure
|
||||
${AUTOCONF} --localdir=${TOPSRCDIR}/js/src \
|
||||
${TOPSRCDIR}/js/src/old-configure.in >${tgtpath}/js/src/old-configure
|
||||
|
||||
# put in js itself
|
||||
cp -pPR ${TOPSRCDIR}/mfbt ${tgtpath}
|
||||
cp -p ${SRCDIR}/../moz.configure ${tgtpath}/js
|
||||
|
||||
@@ -482,7 +482,7 @@ NukeRemovedCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper)
|
||||
MOZ_ASSERT(IsDeadProxyObject(wrapper));
|
||||
}
|
||||
|
||||
void
|
||||
JS_FRIEND_API(void)
|
||||
js::NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper)
|
||||
{
|
||||
JSCompartment* comp = wrapper->compartment();
|
||||
|
||||
@@ -10,5 +10,7 @@ endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# Install versioned binary for parallel installability in Linux distributions
|
||||
install:: $(PROGRAM)
|
||||
$(SYSINSTALL) $^ $(DESTDIR)$(bindir)
|
||||
cp $^ $^$(MOZJS_MAJOR_VERSION)
|
||||
$(SYSINSTALL) $^$(MOZJS_MAJOR_VERSION) $(DESTDIR)$(bindir)
|
||||
|
||||
@@ -483,7 +483,7 @@ SPSBaselineOSRMarker::~SPSBaselineOSRMarker()
|
||||
entry.unsetOSR();
|
||||
}
|
||||
|
||||
JSScript*
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
ProfileEntry::script() const volatile
|
||||
{
|
||||
MOZ_ASSERT(isJs());
|
||||
|
||||
@@ -1702,8 +1702,9 @@ struct MOZ_STACK_CLASS AtomizingMatcher
|
||||
}
|
||||
};
|
||||
|
||||
bool ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFrame& frame,
|
||||
MutableHandleObject outSavedFrameStack)
|
||||
JS_PUBLIC_API(bool)
|
||||
ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFrame& frame,
|
||||
MutableHandleObject outSavedFrameStack)
|
||||
{
|
||||
SavedFrame::AutoLookupVector stackChain(cx);
|
||||
Rooted<JS::ubi::StackFrame> ubiFrame(cx, frame);
|
||||
|
||||
+10
-1
@@ -30,7 +30,16 @@ struct JSCompartment;
|
||||
|
||||
namespace JS {
|
||||
namespace dbg {
|
||||
class AutoEntryMonitor;
|
||||
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
|
||||
class JS_PUBLIC_API(AutoEntryMonitor);
|
||||
|
||||
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
} // namespace dbg
|
||||
} // namespace JS
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ using namespace js;
|
||||
namespace JS {
|
||||
namespace ubi {
|
||||
|
||||
void
|
||||
JS_PUBLIC_API(void)
|
||||
CountDeleter::operator()(CountBase* ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
@@ -29,7 +29,7 @@ CountDeleter::operator()(CountBase* ptr)
|
||||
js_free(ptr);
|
||||
}
|
||||
|
||||
bool
|
||||
JS_PUBLIC_API(bool)
|
||||
Census::init() {
|
||||
AutoLockForExclusiveAccess lock(cx);
|
||||
atomsZone = cx->runtime()->atomsCompartment(lock)->zone();
|
||||
@@ -915,7 +915,7 @@ ByFilename::report(JSContext* cx, CountBase& countBase, MutableHandleValue repor
|
||||
|
||||
/*** Census Handler *******************************************************************************/
|
||||
|
||||
bool
|
||||
JS_PUBLIC_API(bool)
|
||||
CensusHandler::operator() (BreadthFirst<CensusHandler>& traversal,
|
||||
Node origin, const Edge& edge,
|
||||
NodeData* referentData, bool first)
|
||||
@@ -958,7 +958,7 @@ ParseChildBreakdown(JSContext* cx, HandleObject breakdown, PropertyName* prop)
|
||||
return ParseBreakdown(cx, v);
|
||||
}
|
||||
|
||||
CountTypePtr
|
||||
JS_PUBLIC_API(CountTypePtr)
|
||||
ParseBreakdown(JSContext* cx, HandleValue breakdownValue)
|
||||
{
|
||||
if (breakdownValue.isUndefined()) {
|
||||
@@ -1150,7 +1150,7 @@ GetDefaultBreakdown(JSContext* cx)
|
||||
other));
|
||||
}
|
||||
|
||||
bool
|
||||
JS_PUBLIC_API(bool)
|
||||
ParseCensusOptions(JSContext* cx, Census& census, HandleObject options, CountTypePtr& outResult)
|
||||
{
|
||||
RootedValue breakdown(cx, UndefinedValue());
|
||||
|
||||
@@ -2067,10 +2067,10 @@ RecreateLostWaivers(JSContext* cx, const PropertyDescriptor* orig,
|
||||
orig->value.isObject() &&
|
||||
WrapperFactory::HasWaiveXrayFlag(&orig->value.toObject());
|
||||
bool getterWasWaived =
|
||||
(orig->attrs & JSPROP_GETTER) &&
|
||||
(orig->attrs & JSPROP_GETTER) && orig->getter &&
|
||||
WrapperFactory::HasWaiveXrayFlag(JS_FUNC_TO_DATA_PTR(JSObject*, orig->getter));
|
||||
bool setterWasWaived =
|
||||
(orig->attrs & JSPROP_SETTER) &&
|
||||
(orig->attrs & JSPROP_SETTER) && orig->setter &&
|
||||
WrapperFactory::HasWaiveXrayFlag(JS_FUNC_TO_DATA_PTR(JSObject*, orig->setter));
|
||||
|
||||
// Recreate waivers. Note that for value, we need an extra UncheckedUnwrap
|
||||
|
||||
@@ -239,6 +239,15 @@ base64_result_t base64_encode(unsigned char *src, int src_bytes, unsigned char *
|
||||
return BASE64_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned char base64_decode_get_raw(unsigned char index)
|
||||
{
|
||||
/* only have 128 values, MSB must not be set! */
|
||||
if (index >= 128) {
|
||||
return INVALID_CHAR;
|
||||
}
|
||||
return base64_to_raw_table[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* base64_decode
|
||||
*
|
||||
@@ -280,8 +289,8 @@ base64_result_t base64_decode(unsigned char *src, int src_bytes, unsigned char *
|
||||
for (i=0; i<src_bytes; i++) {
|
||||
cindex = src[i];
|
||||
|
||||
if ((cindex & 0x80) || /* only have 128 values, MSB must not be set! */
|
||||
((val = base64_to_raw_table[cindex]) == INVALID_CHAR)) {
|
||||
val = base64_decode_get_raw(cindex);
|
||||
if (val == INVALID_CHAR) {
|
||||
/* Invalid base64 character */
|
||||
return BASE64_BAD_DATA;
|
||||
}
|
||||
@@ -296,7 +305,7 @@ base64_result_t base64_decode(unsigned char *src, int src_bytes, unsigned char *
|
||||
pad_count++;
|
||||
if (++i<src_bytes) {
|
||||
/* can have up to 2 pad chars */
|
||||
if (base64_to_raw_table[src[i]] != PADDING) {
|
||||
if (base64_decode_get_raw(src[i]) != PADDING) {
|
||||
return BASE64_BAD_PADDING;
|
||||
}
|
||||
|
||||
@@ -340,7 +349,7 @@ base64_result_t base64_decode(unsigned char *src, int src_bytes, unsigned char *
|
||||
*/
|
||||
if ((val & 0x0F) ||
|
||||
(i+1>=src_bytes) ||
|
||||
(base64_to_raw_table[src[i+1]] != PADDING)) {
|
||||
(base64_decode_get_raw(src[i+1]) != PADDING)) {
|
||||
return BASE64_BUFFER_OVERRUN;
|
||||
}
|
||||
}
|
||||
@@ -363,7 +372,7 @@ base64_result_t base64_decode(unsigned char *src, int src_bytes, unsigned char *
|
||||
*/
|
||||
if ((val & 0x03) ||
|
||||
(i+1>=src_bytes) ||
|
||||
(base64_to_raw_table[src[i+1]] != PADDING)) {
|
||||
(base64_decode_get_raw(src[i+1]) != PADDING)) {
|
||||
return BASE64_BUFFER_OVERRUN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "mozilla/Vector.h"
|
||||
#include <string.h>
|
||||
|
||||
// Undo potential #include <windows.h> damage to be able to use std::min.
|
||||
#undef min
|
||||
|
||||
// BufferList represents a sequence of buffers of data. A BufferList can choose
|
||||
// to own its buffers or not. The class handles writing to the buffers,
|
||||
// iterating over them, and reading data out. Unlike SegmentedVector, the
|
||||
|
||||
@@ -84,6 +84,44 @@ IsWindowsBuildOrLater(uint32_t aBuild)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsWindows10BuildOrLater(uint32_t aBuild)
|
||||
{
|
||||
static uint32_t minBuild = 0;
|
||||
static uint32_t maxBuild = UINT32_MAX;
|
||||
|
||||
if (minBuild >= aBuild) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aBuild >= maxBuild) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OSVERSIONINFOEX info;
|
||||
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
info.dwMajorVersion = 10;
|
||||
info.dwBuildNumber = aBuild;
|
||||
|
||||
DWORDLONG conditionMask = 0;
|
||||
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
|
||||
|
||||
if (VerifyVersionInfo(&info, VER_MAJORVERSION | VER_MINORVERSION |
|
||||
VER_BUILDNUMBER | VER_SERVICEPACKMAJOR |
|
||||
VER_SERVICEPACKMINOR, conditionMask)) {
|
||||
minBuild = aBuild;
|
||||
return true;
|
||||
}
|
||||
|
||||
maxBuild = aBuild;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0//defined(_M_X64) || defined(_M_AMD64)
|
||||
// We support only Win7 or later on Win64.
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
@@ -183,6 +221,12 @@ IsWin10OrLater()
|
||||
return IsWindowsVersionOrLater(0x0a000000ul);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin10CreatorsUpdateOrLater()
|
||||
{
|
||||
return IsWindows10BuildOrLater(15063);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsNotWin7PreRTM()
|
||||
{
|
||||
@@ -190,6 +234,41 @@ IsNotWin7PreRTM()
|
||||
IsWindowsBuildOrLater(7600);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWin7AndPre2000Compatible() {
|
||||
/*
|
||||
* See Bug 1279171.
|
||||
* We'd like to avoid using WMF on specific OS version when compatibility
|
||||
* mode is in effect. The purpose of this function is to check if FF runs on
|
||||
* Win7 OS with application compatibility mode being set to 95/98/ME.
|
||||
* Those compatibility mode options (95/98/ME) can only display and
|
||||
* be selected for 32-bit application.
|
||||
* If the compatibility mode is in effect, the GetVersionEx function will
|
||||
* report the OS as it identifies itself, which may not be the OS that is
|
||||
* installed.
|
||||
* Note : 1) We only target for Win7 build number greater than 7600.
|
||||
* 2) GetVersionEx may be altered or unavailable for release after
|
||||
* Win8.1. Set pragma to avoid build warning as error.
|
||||
*/
|
||||
bool isWin7 = IsNotWin7PreRTM() && !IsWin8OrLater();
|
||||
if (!isWin7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OSVERSIONINFOEX info;
|
||||
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
|
||||
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996)
|
||||
bool success = GetVersionEx((LPOSVERSIONINFO) &info);
|
||||
#pragma warning(pop)
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
return info.dwMajorVersion < 5;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_WindowsVersion_h */
|
||||
|
||||
@@ -336,10 +336,10 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
|
||||
|
||||
// Watch out for the jar:foo.zip!/ (aDir is empty) top-level special case!
|
||||
nsZipItem *item = nullptr;
|
||||
const char *entry = PromiseFlatCString(aEntryName).get();
|
||||
if (*entry) {
|
||||
const nsCString& entry = PromiseFlatCString(aEntryName);
|
||||
if (*entry.get()) {
|
||||
// First check if item exists in jar
|
||||
item = mZip->GetItem(entry);
|
||||
item = mZip->GetItem(entry.get());
|
||||
if (!item) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
|
||||
}
|
||||
nsJARInputStream* jis = new nsJARInputStream();
|
||||
@@ -348,7 +348,7 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (!item || item->IsDirectory()) {
|
||||
rv = jis->InitDirectory(this, aJarDirSpec, entry);
|
||||
rv = jis->InitDirectory(this, aJarDirSpec, entry.get());
|
||||
} else {
|
||||
rv = jis->InitFile(this, item);
|
||||
}
|
||||
|
||||
@@ -275,6 +275,14 @@ static const char contentSandboxRules[] =
|
||||
" (if (= macosMinorVersion 9)\n"
|
||||
" (allow mach-lookup (global-name \"com.apple.xpcd\")))\n"
|
||||
"\n"
|
||||
" (if (>= macosMinorVersion 13)\n"
|
||||
" (allow mach-lookup\n"
|
||||
" ; bug 1376163\n"
|
||||
" (global-name \"com.apple.audio.AudioComponentRegistrar\")\n"
|
||||
" ; bug 1392988\n"
|
||||
" (xpc-service-name \"com.apple.coremedia.videodecoder\")\n"
|
||||
" (xpc-service-name \"com.apple.coremedia.videoencoder\")))\n"
|
||||
"\n"
|
||||
" (allow iokit-open\n"
|
||||
" (iokit-user-client-class \"IOHIDParamUserClient\")\n"
|
||||
" (iokit-user-client-class \"IOAudioControlUserClient\")\n"
|
||||
|
||||
@@ -60,8 +60,19 @@ function connect_background() {
|
||||
});
|
||||
}
|
||||
function connect_contentScript(testType) {
|
||||
let isUnloading = false;
|
||||
addEventListener("pagehide", () => { isUnloading = true; }, {once: true});
|
||||
|
||||
let port = browser.runtime.connect({name: "port from frame"});
|
||||
port.onMessage.addListener(msg => {
|
||||
// The background page sends a reply as soon as we call runtime.connect().
|
||||
// It is possible that the reply reaches this frame before the
|
||||
// window.close() request has been processed.
|
||||
if (!isUnloading) {
|
||||
browser.test.log(`Ignorting unexpected reply ("${msg}") because the page is not being unloaded.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// The frame has been removed, so we should not get a reply.
|
||||
browser.test.fail(`Unexpected reply: ${msg}`);
|
||||
});
|
||||
|
||||
@@ -190,7 +190,7 @@ ifndef WGET
|
||||
endif
|
||||
$(NSINSTALL) -D $(ABS_DIST)/$(PKG_PATH)
|
||||
(cd $(ABS_DIST)/$(PKG_PATH) && \
|
||||
$(WGET) --no-cache -nv --no-iri -N -O $(PACKAGE) '$(EN_US_BINARY_URL)/$(EN_US_PACKAGE_NAME)')
|
||||
$(WGET) --no-cache -nv --no-iri -N -O '$(notdir $(PACKAGE))' '$(EN_US_BINARY_URL)/$(EN_US_PACKAGE_NAME)')
|
||||
@echo 'Downloaded $(EN_US_BINARY_URL)/$(EN_US_PACKAGE_NAME) to $(ABS_DIST)/$(PKG_PATH)/$(PACKAGE)'
|
||||
ifdef RETRIEVE_WINDOWS_INSTALLER
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
|
||||
@@ -54,11 +54,11 @@ HexStrToInt(NSString* str)
|
||||
|
||||
- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle
|
||||
{
|
||||
[mColorPanel setTitle:aTitle];
|
||||
[mColorPanel setColor:aInitialColor];
|
||||
[mColorPanel setTarget:self];
|
||||
[mColorPanel setAction:@selector(colorChanged:)];
|
||||
[mColorPanel setDelegate:self];
|
||||
[mColorPanel setTitle:aTitle];
|
||||
[mColorPanel setColor:aInitialColor];
|
||||
[mColorPanel makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
@@ -80,11 +80,9 @@ HexStrToInt(NSString* str)
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if ([mColorPanel delegate] == self) {
|
||||
[mColorPanel setTarget:nil];
|
||||
[mColorPanel setAction:nil];
|
||||
[mColorPanel setDelegate:nil];
|
||||
}
|
||||
[mColorPanel setTarget:nil];
|
||||
[mColorPanel setAction:nil];
|
||||
[mColorPanel setDelegate:nil];
|
||||
|
||||
mColorPanel = nil;
|
||||
mColorPicker = nullptr;
|
||||
|
||||
@@ -214,7 +214,8 @@ nsClipboard::SetData(nsITransferable *aTransferable,
|
||||
GtkTargetEntry *gtkTargets = gtk_target_table_new_from_list(list, &numTargets);
|
||||
|
||||
// Set getcallback and request to store data after an application exit
|
||||
if (gtk_clipboard_set_with_data(gtkClipboard, gtkTargets, numTargets,
|
||||
if (gtkTargets &&
|
||||
gtk_clipboard_set_with_data(gtkClipboard, gtkTargets, numTargets,
|
||||
clipboard_get_cb, clipboard_clear_cb, this))
|
||||
{
|
||||
// We managed to set-up the clipboard so update internal state
|
||||
|
||||
@@ -2517,7 +2517,8 @@ NativeKey::HandleCharMessage(const MSG& aCharMsg,
|
||||
*aEventDispatched = false;
|
||||
}
|
||||
|
||||
if (IsCharOrSysCharMessage(mMsg) && IsAnotherInstanceRemovingCharMessage()) {
|
||||
if ((IsCharOrSysCharMessage(mMsg) || IsEnterKeyPressCharMessage(mMsg)) &&
|
||||
IsAnotherInstanceRemovingCharMessage()) {
|
||||
MOZ_LOG(sNativeKeyLogger, LogLevel::Warning,
|
||||
("%p NativeKey::HandleCharMessage(), WARNING, does nothing because "
|
||||
"the message should be handled in another instance removing this "
|
||||
@@ -2546,7 +2547,9 @@ NativeKey::HandleCharMessage(const MSG& aCharMsg,
|
||||
// When a control key is inputted by a key, it should be handled without
|
||||
// WM_*CHAR messages at receiving WM_*KEYDOWN message. So, when we receive
|
||||
// WM_*CHAR message directly, we see a control character here.
|
||||
if (IsControlCharMessage(aCharMsg)) {
|
||||
// Note that when the char is '\r', it means that the char message should
|
||||
// cause "Enter" keypress event for inserting a line break.
|
||||
if (IsControlCharMessage(aCharMsg) && !IsEnterKeyPressCharMessage(aCharMsg)) {
|
||||
// In this case, we don't need to dispatch eKeyPress event because:
|
||||
// 1. We're the only browser which dispatches "keypress" event for
|
||||
// non-printable characters (Although, both Chrome and Edge dispatch
|
||||
@@ -2573,7 +2576,11 @@ NativeKey::HandleCharMessage(const MSG& aCharMsg,
|
||||
|
||||
// First, handle normal text input or non-printable key case here.
|
||||
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
|
||||
keypressEvent.mCharCode = static_cast<uint32_t>(aCharMsg.wParam);
|
||||
if (IsEnterKeyPressCharMessage(aCharMsg)) {
|
||||
keypressEvent.mKeyCode = NS_VK_RETURN;
|
||||
} else {
|
||||
keypressEvent.mCharCode = static_cast<uint32_t>(aCharMsg.wParam);
|
||||
}
|
||||
nsresult rv = mDispatcher->BeginNativeInputTransaction();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
|
||||
|
||||
@@ -531,6 +531,10 @@ private:
|
||||
return aMSG.message == WM_CHAR &&
|
||||
!IsControlChar(static_cast<char16_t>(aMSG.wParam));
|
||||
}
|
||||
bool IsEnterKeyPressCharMessage(const MSG& aMSG) const
|
||||
{
|
||||
return aMSG.message == WM_CHAR && aMSG.wParam == '\r';
|
||||
}
|
||||
bool IsPrintableCharOrSysCharMessage(const MSG& aMSG) const
|
||||
{
|
||||
return IsCharOrSysCharMessage(aMSG) &&
|
||||
|
||||
@@ -2122,6 +2122,18 @@ TSFTextStore::GetSelection(ULONG ulIndex,
|
||||
|
||||
Selection& selectionForTSF = SelectionForTSFRef();
|
||||
if (selectionForTSF.IsDirty()) {
|
||||
if (DoNotReturnErrorFromGetSelection()) {
|
||||
AutoSetTemporarySelection temprarySetter(selectionForTSF);
|
||||
*pSelection = selectionForTSF.ACP();
|
||||
*pcFetched = 1;
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("0x%p TSFTextStore::GetSelection() returns fake selection range "
|
||||
"for avoiding a crash in TSF, "
|
||||
"acpStart=%d, acpEnd=%d (length=%d), reverted=%s",
|
||||
this, selectionForTSF.StartOffset(), selectionForTSF.EndOffset(),
|
||||
selectionForTSF.Length(), GetBoolName(selectionForTSF.IsReversed())));
|
||||
return S_OK;
|
||||
}
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Error,
|
||||
("0x%p TSFTextStore::GetSelection() FAILED due to "
|
||||
"SelectionForTSFRef() failure", this));
|
||||
@@ -2130,10 +2142,26 @@ TSFTextStore::GetSelection(ULONG ulIndex,
|
||||
*pSelection = selectionForTSF.ACP();
|
||||
*pcFetched = 1;
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Info,
|
||||
("0x%p TSFTextStore::GetSelection() succeeded", this));
|
||||
("0x%p TSFTextStore::GetSelection() succeeded, "
|
||||
"acpStart=%d, acpEnd=%d (length=%d), reverted=%s",
|
||||
this, selectionForTSF.StartOffset(), selectionForTSF.EndOffset(),
|
||||
selectionForTSF.Length(), GetBoolName(selectionForTSF.IsReversed())));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
TSFTextStore::DoNotReturnErrorFromGetSelection()
|
||||
{
|
||||
// There is a crash bug of TSF if we return error from GetSelection().
|
||||
// That was introduced in Anniversary Update (build 14393, see bug 1312302)
|
||||
// TODO: We should avoid to run this hack on fixed builds. When we get
|
||||
// exact build number, we should get back here.
|
||||
static bool sTSFMayCrashIfGetSelectionReturnsError =
|
||||
IsWindows10BuildOrLater(14393);
|
||||
return sTSFMayCrashIfGetSelectionReturnsError;
|
||||
}
|
||||
|
||||
bool
|
||||
TSFTextStore::IsComposingInContent() const
|
||||
{
|
||||
@@ -4861,14 +4889,7 @@ TSFTextStore::CreateAndSetFocus(nsWindowBase* aFocusedWidget,
|
||||
|
||||
HRESULT hr;
|
||||
RefPtr<ITfThreadMgr> threadMgr = sThreadMgr;
|
||||
{
|
||||
// Windows 10's softwware keyboard requires that SetSelection must be
|
||||
// always successful into SetFocus. If returning error, it might crash
|
||||
// into TextInputFramework.dll.
|
||||
AutoSetTemporarySelection setSelection(textStore->SelectionForTSFRef());
|
||||
|
||||
hr = threadMgr->SetFocus(newDocMgr);
|
||||
}
|
||||
hr = threadMgr->SetFocus(newDocMgr);
|
||||
|
||||
if (NS_WARN_IF(FAILED(hr))) {
|
||||
MOZ_LOG(sTextStoreLog, LogLevel::Error,
|
||||
|
||||
@@ -253,6 +253,11 @@ public:
|
||||
*/
|
||||
static bool IsMSJapaneseIMEActive();
|
||||
|
||||
/**
|
||||
* Returns true if TSF may crash if GetSelection() returns E_FAIL.
|
||||
*/
|
||||
static bool DoNotReturnErrorFromGetSelection();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Returns true when keyboard layout has IME (TIP).
|
||||
static bool CurrentKeyboardLayoutHasIME();
|
||||
|
||||
+38
-84
@@ -1883,111 +1883,65 @@ WinUtils::GetMaxTouchPoints()
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct REPARSE_DATA_BUFFER {
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
USHORT Reserved;
|
||||
union {
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
ULONG Flags;
|
||||
WCHAR PathBuffer[1];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} MountPointReparseBuffer;
|
||||
struct {
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
#pragma pack(pop)
|
||||
typedef DWORD (WINAPI * GetFinalPathNameByHandlePtr)(HANDLE hFile,
|
||||
LPTSTR lpszFilePath,
|
||||
DWORD cchFilePath,
|
||||
DWORD dwFlags);
|
||||
|
||||
/* static */
|
||||
bool
|
||||
WinUtils::ResolveMovedUsersFolder(std::wstring& aPath)
|
||||
WinUtils::ResolveJunctionPointsAndSymLinks(std::wstring& aPath)
|
||||
{
|
||||
wchar_t* usersPath;
|
||||
if (FAILED(WinUtils::SHGetKnownFolderPath(FOLDERID_UserProfiles, 0, nullptr,
|
||||
&usersPath))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure usersPath gets freed properly.
|
||||
UniquePtr<wchar_t, CoTaskMemFreePolicy> autoFreePath(usersPath);
|
||||
|
||||
// Is aPath in Users folder?
|
||||
size_t usersLen = wcslen(usersPath);
|
||||
if (_wcsnicmp(aPath.c_str(), usersPath, usersLen) != 0 ||
|
||||
aPath[usersLen] != L'\\') {
|
||||
// Users folder was introduced with Vista.
|
||||
if (!IsVistaOrLater()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD attributes = ::GetFileAttributesW(usersPath);
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||
wchar_t path[MAX_PATH] = { 0 };
|
||||
|
||||
nsAutoHandle handle(
|
||||
::CreateFileW(aPath.c_str(),
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
nullptr));
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Junction points are implemented as reparse points, is the Users folder one?
|
||||
if (!(attributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
return true;
|
||||
// GetFinalPathNameByHandleW is a Vista and later API. Since ESR builds with
|
||||
// XP support still, we need to load the function manually.
|
||||
GetFinalPathNameByHandlePtr getFinalPathNameFnPtr = nullptr;
|
||||
HMODULE kernel32Dll = ::GetModuleHandleW(L"Kernel32");
|
||||
if (kernel32Dll) {
|
||||
getFinalPathNameFnPtr = (GetFinalPathNameByHandlePtr)
|
||||
::GetProcAddress(kernel32Dll, "GetFinalPathNameByHandleW");
|
||||
}
|
||||
|
||||
// Get the reparse point data.
|
||||
nsAutoHandle usersHandle(
|
||||
::CreateFileW(usersPath, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
nullptr));
|
||||
|
||||
char maxReparseBuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE] = {0};
|
||||
REPARSE_DATA_BUFFER* reparseBuf = (REPARSE_DATA_BUFFER*)maxReparseBuf;
|
||||
DWORD bytesReturned = 0;
|
||||
if (!::DeviceIoControl(usersHandle, FSCTL_GET_REPARSE_POINT, nullptr, 0,
|
||||
reparseBuf, MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
|
||||
&bytesReturned, nullptr)) {
|
||||
if (!getFinalPathNameFnPtr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if the reparse point is a junction point.
|
||||
if (reparseBuf->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The offset and length are in bytes. Length doesn't include null.
|
||||
wchar_t* substituteName = reparseBuf->MountPointReparseBuffer.PathBuffer +
|
||||
reparseBuf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
|
||||
std::wstring::size_type substituteLen =
|
||||
reparseBuf->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
|
||||
|
||||
// If the substitute path starts with the NT namespace then remove it.
|
||||
if (wcsncmp(substituteName, kNTPrefix, kNTPrefixLen) == 0) {
|
||||
substituteName += kNTPrefixLen;
|
||||
substituteLen -= kNTPrefixLen;
|
||||
}
|
||||
|
||||
// Check that what remains looks like a drive letter path.
|
||||
if (substituteName[1] != L':' || substituteName[2] != L'\\') {
|
||||
DWORD pathLen = getFinalPathNameFnPtr(
|
||||
handle, path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
if (pathLen == 0 || pathLen >= MAX_PATH) {
|
||||
return false;
|
||||
}
|
||||
aPath = path;
|
||||
|
||||
// The documentation for SHGetKnownFolderPath says that it doesn't return a
|
||||
// trailing backslash. The REPARSE_DATA_BUFFER path doesn't seem to have one
|
||||
// either, but the documentation doesn't mention it, so let's make sure.
|
||||
if (substituteName[substituteLen - 1] == L'\\') {
|
||||
--substituteLen;
|
||||
// GetFinalPathNameByHandle sticks a '\\?\' in front of the path,
|
||||
// but that confuses some APIs so strip it off. It will also put
|
||||
// '\\?\UNC\' in front of network paths, we convert that to '\\'.
|
||||
if (aPath.compare(0, 7, L"\\\\?\\UNC") == 0) {
|
||||
aPath.erase(2, 6);
|
||||
} else if (aPath.compare(0, 4, L"\\\\?\\") == 0) {
|
||||
aPath.erase(0, 4);
|
||||
}
|
||||
|
||||
aPath.replace(0, usersLen, substituteName, substituteLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -467,16 +467,16 @@ public:
|
||||
static uint32_t GetMaxTouchPoints();
|
||||
|
||||
/**
|
||||
* Detect if path is within the Users folder and Users is actually a junction
|
||||
* point to another folder.
|
||||
* If this is detected it will change the path to the actual path.
|
||||
* Fully resolves a path to its final path name. So if path contains
|
||||
* junction points or symlinks to other folders, we'll resolve the path
|
||||
* fully to the actual path that the links target.
|
||||
*
|
||||
* @param aPath path to be resolved.
|
||||
* @return true if successful, including if nothing needs to be changed.
|
||||
* false if something failed or aPath does not exist, aPath will
|
||||
* remain unchanged.
|
||||
*/
|
||||
static bool ResolveMovedUsersFolder(std::wstring& aPath);
|
||||
static bool ResolveJunctionPointsAndSymLinks(std::wstring& aPath);
|
||||
|
||||
/**
|
||||
* dwmapi.dll function typedefs and declarations
|
||||
|
||||
Reference in New Issue
Block a user