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:
2018-06-20 22:38:38 +08:00
parent 96244ab710
commit 3a4eb9ff7e
77 changed files with 914 additions and 476 deletions
+2
View File
@@ -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++;
}
+1 -1
View File
@@ -144,7 +144,7 @@ XULTreeAccessible::Value(nsString& aValue)
void
XULTreeAccessible::Shutdown()
{
if (!mDoc->IsDefunct()) {
if (mDoc && !mDoc->IsDefunct()) {
UnbindCacheEntriesFromDocument(mAccessibleCache);
}
+1 -1
View File
@@ -277,7 +277,7 @@ NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
void
XULTreeGridRowAccessible::Shutdown()
{
if (!mDoc->IsDefunct()) {
if (mDoc && !mDoc->IsDefunct()) {
UnbindCacheEntriesFromDocument(mAccessibleCache);
}
+6 -5
View File
@@ -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
+19 -14
View File
@@ -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):
+29
View File
@@ -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>
+1
View File
@@ -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
+9 -1
View File
@@ -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>
+36 -2
View File
@@ -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
+4
View File
@@ -95,6 +95,10 @@ private:
nsresult mErrorResult;
RefPtr<TaskQueue> mTaskQueue;
nsCOMPtr<nsISupports> mPendingParent;
nsCString mPendingContentType;
RefPtr<MutableBlobStorageCallback> mPendingCallback;
};
} // namespace dom
+1 -2
View File
@@ -5802,8 +5802,7 @@ bool HTMLMediaElement::CanActivateAutoplay()
bool hasData =
(mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
(mSrcStream && mSrcStream->Active()) ||
mMediaSource;
(mSrcStream && mSrcStream->Active());
return hasData;
}
+13
View File
@@ -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>
+1
View File
@@ -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
+5 -3
View File
@@ -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);
}
+9 -2
View File
@@ -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.
+2 -2
View File
@@ -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));
}
+2
View File
@@ -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>
+11 -1
View File
@@ -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);
+11
View File
@@ -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
View File
@@ -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;
+5
View File
@@ -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^
+1 -1
View File
@@ -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>
+16 -34
View File
@@ -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;
}
+3 -3
View File
@@ -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;
+1 -1
View File
@@ -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 },
+9 -4
View File
@@ -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;
+5 -1
View File
@@ -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);
+8 -8
View File
@@ -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) {
+16
View File
@@ -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",
+1 -1
View File
@@ -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
View File
@@ -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_;
+1 -1
View File
@@ -18,7 +18,7 @@
#include "js/StructuredClone.h"
namespace js {
struct PerformanceGroup;
struct JS_PUBLIC_API(PerformanceGroup);
} // namespace js
struct JSPrincipals {
+7 -4
View File
@@ -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.
+1 -1
View File
@@ -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);
+2 -1
View File
@@ -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
View File
@@ -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;
+9 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+3 -3
View File
@@ -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--;
+1 -1
View File
@@ -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())
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+5 -5
View File
@@ -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;
+8
View File
@@ -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
View File
@@ -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
+8
View File
@@ -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
+1 -1
View File
@@ -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();
+3 -1
View File
@@ -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)
+1 -1
View File
@@ -483,7 +483,7 @@ SPSBaselineOSRMarker::~SPSBaselineOSRMarker()
entry.unsetOSR();
}
JSScript*
JS_PUBLIC_API(JSScript*)
ProfileEntry::script() const volatile
{
MOZ_ASSERT(isJs());
+3 -2
View File
@@ -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
View File
@@ -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
+5 -5
View File
@@ -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());
+2 -2
View File
@@ -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;
}
}
+3
View File
@@ -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
+79
View File
@@ -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 */
+4 -4
View File
@@ -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);
}
+8
View File
@@ -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}`);
});
+1 -1
View File
@@ -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)
+5 -7
View File
@@ -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;
+2 -1
View File
@@ -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
+10 -3
View File
@@ -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,
+4
View File
@@ -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) &&
+30 -9
View File
@@ -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,
+5
View File
@@ -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
View File
@@ -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;
}
+4 -4
View File
@@ -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