diff --git a/dom/file/MutableBlobStorage.cpp b/dom/file/MutableBlobStorage.cpp
index 4ba8a5102..43f43b52d 100644
--- a/dom/file/MutableBlobStorage.cpp
+++ b/dom/file/MutableBlobStorage.cpp
@@ -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;
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 = 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 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 =
+ new LastRunnable(this, mPendingParent, mPendingContentType,
+ mPendingCallback);
+ DispatchToIOThread(runnable.forget());
+
+ mPendingParent = nullptr;
+ mPendingCallback = nullptr;
+ }
}
void
diff --git a/dom/file/MutableBlobStorage.h b/dom/file/MutableBlobStorage.h
index 5af8a682c..fad391b16 100644
--- a/dom/file/MutableBlobStorage.h
+++ b/dom/file/MutableBlobStorage.h
@@ -95,6 +95,10 @@ private:
nsresult mErrorResult;
RefPtr mTaskQueue;
+
+ nsCOMPtr mPendingParent;
+ nsCString mPendingContentType;
+ RefPtr mPendingCallback;
};
} // namespace dom
diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index 31fab8af1..4d94c54b9 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -5802,8 +5802,7 @@ bool HTMLMediaElement::CanActivateAutoplay()
bool hasData =
(mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
- (mSrcStream && mSrcStream->Active()) ||
- mMediaSource;
+ (mSrcStream && mSrcStream->Active());
return hasData;
}
diff --git a/dom/html/crashtests/1386905.html b/dom/html/crashtests/1386905.html
new file mode 100644
index 000000000..6ecc59e23
--- /dev/null
+++ b/dom/html/crashtests/1386905.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/dom/html/crashtests/crashtests.list b/dom/html/crashtests/crashtests.list
index 757276d59..11d0ea840 100644
--- a/dom/html/crashtests/crashtests.list
+++ b/dom/html/crashtests/crashtests.list
@@ -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
diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp
index af34fdfc6..b7467c77a 100644
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1751,6 +1751,8 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
}
mBoundFrame = nullptr;
+ // Clear mRootNode so that we don't unexpectedly notify below.
+ nsCOMPtr 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);
}
diff --git a/dom/media/gmp/GMPProcessParent.cpp b/dom/media/gmp/GMPProcessParent.cpp
index 0bf0d925f..d0bcd2fae 100644
--- a/dom/media/gmp/GMPProcessParent.cpp
+++ b/dom/media/gmp/GMPProcessParent.cpp
@@ -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.
diff --git a/dom/media/mediasource/MediaSourceDecoder.cpp b/dom/media/mediasource/MediaSourceDecoder.cpp
index 9bc740ac5..774bed868 100644
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -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));
}
diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini
index 4ed672c65..e3b3aa8ea 100644
--- a/dom/media/mediasource/test/mochitest.ini
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -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]
diff --git a/dom/media/mediasource/test/test_PlayEventsAutoPlaying.html b/dom/media/mediasource/test/test_PlayEventsAutoPlaying.html
new file mode 100644
index 000000000..492677b5c
--- /dev/null
+++ b/dom/media/mediasource/test/test_PlayEventsAutoPlaying.html
@@ -0,0 +1,74 @@
+
+
+
+ MSE: basic functionality
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp
index 44b586945..507c7291c 100644
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -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 remote = new dom::RemoteDecoderModule(m);
StartupPDM(remote);
diff --git a/dom/media/platforms/wmf/WMFUtils.cpp b/dom/media/platforms/wmf/WMFUtils.cpp
index ff6bb4da5..3d9de7d02 100644
--- a/dom/media/platforms/wmf/WMFUtils.cpp
+++ b/dom/media/platforms/wmf/WMFUtils.cpp
@@ -12,6 +12,7 @@
#include "nsThreadUtils.h"
#include "nsWindowsHelpers.h"
#include "mozilla/CheckedInt.h"
+#include "mozilla/WindowsVersion.h"
#include "VideoUtils.h"
#include
#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;
diff --git a/dom/plugins/ipc/PluginUtilsWin.cpp b/dom/plugins/ipc/PluginUtilsWin.cpp
index 688f82443..b6fad4a0d 100644
--- a/dom/plugins/ipc/PluginUtilsWin.cpp
+++ b/dom/plugins/ipc/PluginUtilsWin.cpp
@@ -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
-#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
+#include "PluginUtilsWin.h"
+#include "PluginModuleParent.h"
+#include "mozilla/StaticMutex.h"
+
+namespace mozilla {
+namespace plugins {
+namespace PluginUtilsWin {
+
typedef nsTHashtable> 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 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
diff --git a/dom/security/test/csp/file_sandbox_13.html b/dom/security/test/csp/file_sandbox_13.html
new file mode 100644
index 000000000..e4672ed05
--- /dev/null
+++ b/dom/security/test/csp/file_sandbox_13.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ I am sandboxed but with only inline "allow-scripts"
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/security/test/csp/file_sandbox_allow_scripts.html b/dom/security/test/csp/file_sandbox_allow_scripts.html
new file mode 100644
index 000000000..faab9f0fc
--- /dev/null
+++ b/dom/security/test/csp/file_sandbox_allow_scripts.html
@@ -0,0 +1,12 @@
+
+
+
+
+ Bug 1396320: Fix CSP sandbox regression for allow-scripts
+
+
+
+
+
diff --git a/dom/security/test/csp/file_sandbox_allow_scripts.html^headers^ b/dom/security/test/csp/file_sandbox_allow_scripts.html^headers^
new file mode 100644
index 000000000..4705ce9de
--- /dev/null
+++ b/dom/security/test/csp/file_sandbox_allow_scripts.html^headers^
@@ -0,0 +1 @@
+Content-Security-Policy: sandbox allow-scripts;
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini
index 163a19a17..3b310ccfc 100644
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -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^
diff --git a/dom/security/test/csp/test_sandbox.html b/dom/security/test/csp/test_sandbox.html
index 3a60be304..97d5275d2 100644
--- a/dom/security/test/csp/test_sandbox.html
+++ b/dom/security/test/csp/test_sandbox.html
@@ -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
},
diff --git a/dom/security/test/csp/test_sandbox_allow_scripts.html b/dom/security/test/csp/test_sandbox_allow_scripts.html
new file mode 100644
index 000000000..10acaae43
--- /dev/null
+++ b/dom/security/test/csp/test_sandbox_allow_scripts.html
@@ -0,0 +1,31 @@
+
+
+
+ Bug 1396320: Fix CSP sandbox regression for allow-scripts
+
+
+
+
+
+
+
+
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
index 4c14d5741..4080a3d33 100644
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -275,6 +275,10 @@ HTMLEditor::Init(nsIDOMDocument* aDoc,
nsCOMPtr 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 rootElement;
nsCOMPtr 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 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
@@ -3234,8 +3220,9 @@ HTMLEditor::DoContentInserted(nsIDocument* aDocument,
nsCOMPtr 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 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 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 root;
- rv = GetRootElement(getter_AddRefs(root));
- if (NS_FAILED(rv) || !mRootElement) {
+ UpdateRootElement();
+ if (!mRootElement) {
return;
}
diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h
index b8b69678a..850ca2146 100644
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -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;
diff --git a/extensions/auth/nsAuthFactory.cpp b/extensions/auth/nsAuthFactory.cpp
index d026a900b..3d2008225 100644
--- a/extensions/auth/nsAuthFactory.cpp
+++ b/extensions/auth/nsAuthFactory.cpp
@@ -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 },
diff --git a/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp b/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
index cf56299a1..cfde89ffc 100644
--- a/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
+++ b/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
@@ -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;
diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm
index f0cf98ad2..c8d7c1564 100644
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -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);
diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp
index b04fc314d..dea730a6e 100644
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -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) {
diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
index 6a978f8c3..07e54040a 100644
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -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 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",
diff --git a/js/public/CallArgs.h b/js/public/CallArgs.h
index d527b5603..a7774309a 100644
--- a/js/public/CallArgs.h
+++ b/js/public/CallArgs.h
@@ -300,7 +300,7 @@ class MOZ_STACK_CLASS CallArgs : public detail::CallArgsBase(lineOrPcOffset);
diff --git a/js/public/StructuredClone.h b/js/public/StructuredClone.h
index 9d4002c50..0e30bc3f2 100644
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -211,7 +211,8 @@ namespace js
};
}
-class MOZ_NON_MEMMOVABLE JSStructuredCloneData : public mozilla::BufferList
+class MOZ_NON_MEMMOVABLE JS_PUBLIC_API(JSStructuredCloneData) :
+ public mozilla::BufferList
{
typedef js::SystemAllocPolicy AllocPolicy;
typedef mozilla::BufferList BufferList;
diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h
index c8742f33f..7332f198f 100644
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -193,7 +193,7 @@ using Vector = mozilla::Vector;
// 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 {
+class JS_PUBLIC_API(AtomOrTwoByteChars) : public Variant {
using Base = Variant;
public:
@@ -466,8 +466,10 @@ class ConcreteStackFrame : 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& noGC;
public:
@@ -1001,7 +1003,7 @@ class MOZ_STACK_CLASS RootList {
/*** Concrete classes for ubi::Node referent types ************************************************/
template<>
-class Concrete : public Base {
+class JS_PUBLIC_API(Concrete) : public Base {
protected:
explicit Concrete(RootList* ptr) : Base(ptr) { }
RootList& get() const { return *static_cast(ptr); }
@@ -1018,7 +1020,7 @@ class Concrete : public Base {
// A reusable ubi::Concrete specialization base class for types supported by
// JS::TraceChildren.
template
-class TracerConcrete : public Base {
+class JS_PUBLIC_API(TracerConcrete) : public Base {
js::UniquePtr 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
-class TracerConcreteWithCompartment : public TracerConcrete {
+class JS_PUBLIC_API(TracerConcreteWithCompartment) : public TracerConcrete {
typedef TracerConcrete TracerBase;
JSCompartment* compartment() const override;
@@ -1040,7 +1042,7 @@ class TracerConcreteWithCompartment : public TracerConcrete {
// Define specializations for some commonly-used public JSAPI types.
// These can use the generic templates above.
template<>
-class Concrete : TracerConcrete {
+class JS_PUBLIC_API(Concrete) : TracerConcrete {
protected:
explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) { }
@@ -1056,7 +1058,7 @@ class Concrete : TracerConcrete {
};
template<>
-class Concrete : TracerConcreteWithCompartment {
+class JS_PUBLIC_API(Concrete) : TracerConcreteWithCompartment {
protected:
explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment(ptr) { }
@@ -1073,7 +1075,7 @@ class Concrete : TracerConcreteWithCompartment {
// The JSObject specialization.
template<>
-class Concrete : public TracerConcreteWithCompartment {
+class JS_PUBLIC_API(Concrete) : public TracerConcreteWithCompartment {
protected:
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
@@ -1098,7 +1100,7 @@ class Concrete : public TracerConcreteWithCompartment {
// For JSString, we extend the generic template with a 'size' implementation.
template<>
-class Concrete : TracerConcrete {
+class JS_PUBLIC_API(Concrete) : TracerConcrete {
protected:
explicit Concrete(JSString *ptr) : TracerConcrete(ptr) { }
@@ -1115,7 +1117,7 @@ class Concrete : TracerConcrete {
// The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts.
template<>
-class Concrete : public Base {
+class JS_PUBLIC_API(Concrete) : public Base {
const char16_t* typeName() const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
js::UniquePtr edges(JSContext* cx, bool wantNames) const override;
diff --git a/js/public/UbiNodeCensus.h b/js/public/UbiNodeCensus.h
index c0859ec56..8c7990886 100644
--- a/js/public/UbiNodeCensus.h
+++ b/js/public/UbiNodeCensus.h
@@ -83,7 +83,7 @@ struct Census;
class CountBase;
struct CountDeleter {
- void operator()(CountBase*);
+ JS_PUBLIC_API(void) operator()(CountBase*);
};
using CountBasePtr = js::UniquePtr;
@@ -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& traversal,
- Node origin, const Edge& edge,
- NodeData* referentData, bool first);
+ MOZ_MUST_USE JS_PUBLIC_API(bool) operator() (BreadthFirst& traversal,
+ Node origin, const Edge& edge,
+ NodeData* referentData, bool first);
};
using CensusTraversal = BreadthFirst;
// 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
diff --git a/js/public/Utility.h b/js/public/Utility.h
index 249260610..8f7dc1254 100644
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -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);
diff --git a/js/src/Makefile.in b/js/src/Makefile.in
index fde813867..9df0ac3ba 100644
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -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) \
diff --git a/js/src/gc/Barrier.cpp b/js/src/gc/Barrier.cpp
index fd8455eb8..fefebc8fe 100644
--- a/js/src/gc/Barrier.cpp
+++ b/js/src/gc/Barrier.cpp
@@ -180,12 +180,21 @@ MovableCellHasher::match(const Key& k, const Lookup& l)
return zone->getUniqueIdInfallible(k) == zone->getUniqueIdInfallible(l);
}
-template struct MovableCellHasher;
-template struct MovableCellHasher;
-template struct MovableCellHasher;
-template struct MovableCellHasher;
-template struct MovableCellHasher;
-template struct MovableCellHasher;
+#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);
+template struct JS_PUBLIC_API(MovableCellHasher);
+template struct JS_PUBLIC_API(MovableCellHasher);
+template struct JS_PUBLIC_API(MovableCellHasher);
+template struct JS_PUBLIC_API(MovableCellHasher);
+template struct JS_PUBLIC_API(MovableCellHasher);
+
+#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
+#pragma GCC diagnostic pop
+#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
} // namespace js
diff --git a/js/src/gc/MemoryProfiler.cpp b/js/src/gc/MemoryProfiler.cpp
index 8825bb650..a061f9303 100644
--- a/js/src/gc/MemoryProfiler.cpp
+++ b/js/src/gc/MemoryProfiler.cpp
@@ -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--;
diff --git a/js/src/jit/JitcodeMap.cpp b/js/src/jit/JitcodeMap.cpp
index 3650da896..b20c615a8 100644
--- a/js/src/jit/JitcodeMap.cpp
+++ b/js/src/jit/JitcodeMap.cpp
@@ -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())
diff --git a/js/src/jit/OptimizationTracking.cpp b/js/src/jit/OptimizationTracking.cpp
index 013e39dda..910619a76 100644
--- a/js/src/jit/OptimizationTracking.cpp
+++ b/js/src/jit/OptimizationTracking.cpp
@@ -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());
diff --git a/js/src/js.pc.in b/js/src/js.pc.in
index 1efea3342..2eae393a6 100644
--- a/js/src/js.pc.in
+++ b/js/src/js.pc.in
@@ -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@
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index fda46f9f1..e2be19a3c 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -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());
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index e0d910148..154a80d05 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -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.
diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h
index a39ead3de..b29894162 100644
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -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 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;
diff --git a/js/src/jstypes.h b/js/src/jstypes.h
index 2a96dc3ed..0ae8a4bde 100644
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -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
+// . 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
diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h
index 218b6ed90..d6a977589 100644
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -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
diff --git a/js/src/make-source-package.sh b/js/src/make-source-package.sh
index 192144c62..f4131b98f 100644
--- a/js/src/make-source-package.sh
+++ b/js/src/make-source-package.sh
@@ -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
diff --git a/js/src/proxy/CrossCompartmentWrapper.cpp b/js/src/proxy/CrossCompartmentWrapper.cpp
index 5ccd61eb6..b16c35a46 100644
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -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();
diff --git a/js/src/shell/Makefile.in b/js/src/shell/Makefile.in
index ebe7992c3..ebc58cfc7 100644
--- a/js/src/shell/Makefile.in
+++ b/js/src/shell/Makefile.in
@@ -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)
diff --git a/js/src/vm/SPSProfiler.cpp b/js/src/vm/SPSProfiler.cpp
index 80c2aff03..8ba04fea9 100644
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -483,7 +483,7 @@ SPSBaselineOSRMarker::~SPSBaselineOSRMarker()
entry.unsetOSR();
}
-JSScript*
+JS_PUBLIC_API(JSScript*)
ProfileEntry::script() const volatile
{
MOZ_ASSERT(isJs());
diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp
index 1f0c541b2..1b78cb1be 100644
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -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 ubiFrame(cx, frame);
diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h
index f2cf4646c..af75834ed 100644
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -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
diff --git a/js/src/vm/UbiNodeCensus.cpp b/js/src/vm/UbiNodeCensus.cpp
index 4836bfecf..e2c56c666 100644
--- a/js/src/vm/UbiNodeCensus.cpp
+++ b/js/src/vm/UbiNodeCensus.cpp
@@ -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& 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());
diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp
index 08e73f5f4..17b5e0f8d 100644
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -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
diff --git a/media/webrtc/signaling/src/sdp/sipcc/sdp_base64.c b/media/webrtc/signaling/src/sdp/sipcc/sdp_base64.c
index 0cef82166..80f1eb52d 100644
--- a/media/webrtc/signaling/src/sdp/sipcc/sdp_base64.c
+++ b/media/webrtc/signaling/src/sdp/sipcc/sdp_base64.c
@@ -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) ||
- (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;
}
}
diff --git a/mfbt/BufferList.h b/mfbt/BufferList.h
index 42aea12db..26b335957 100644
--- a/mfbt/BufferList.h
+++ b/mfbt/BufferList.h
@@ -16,6 +16,9 @@
#include "mozilla/Vector.h"
#include
+// Undo potential #include 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
diff --git a/mfbt/WindowsVersion.h b/mfbt/WindowsVersion.h
index 5fa30c5c1..4a73fb3ff 100644
--- a/mfbt/WindowsVersion.h
+++ b/mfbt/WindowsVersion.h
@@ -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 */
diff --git a/modules/libjar/nsJAR.cpp b/modules/libjar/nsJAR.cpp
index b6524a0d9..2bed0e59d 100644
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -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);
}
diff --git a/security/sandbox/mac/Sandbox.mm b/security/sandbox/mac/Sandbox.mm
index b90c5a553..59b8e1dbc 100644
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -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"
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_unload_frame.html b/toolkit/components/extensions/test/mochitest/test_ext_unload_frame.html
index bc94b25d8..5572de281 100644
--- a/toolkit/components/extensions/test/mochitest/test_ext_unload_frame.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_unload_frame.html
@@ -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}`);
});
diff --git a/toolkit/locales/l10n.mk b/toolkit/locales/l10n.mk
index 48d086fcd..ecc5de3bd 100644
--- a/toolkit/locales/l10n.mk
+++ b/toolkit/locales/l10n.mk
@@ -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)
diff --git a/widget/cocoa/nsColorPicker.mm b/widget/cocoa/nsColorPicker.mm
index 1fdaa03a2..263ea349b 100644
--- a/widget/cocoa/nsColorPicker.mm
+++ b/widget/cocoa/nsColorPicker.mm
@@ -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;
diff --git a/widget/gtk/nsClipboard.cpp b/widget/gtk/nsClipboard.cpp
index 053ae970e..eecae3e88 100644
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -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
diff --git a/widget/windows/KeyboardLayout.cpp b/widget/windows/KeyboardLayout.cpp
index 2f06d55d9..58e7bfe60 100644
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -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(aCharMsg.wParam);
+ if (IsEnterKeyPressCharMessage(aCharMsg)) {
+ keypressEvent.mKeyCode = NS_VK_RETURN;
+ } else {
+ keypressEvent.mCharCode = static_cast(aCharMsg.wParam);
+ }
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
MOZ_LOG(sNativeKeyLogger, LogLevel::Error,
diff --git a/widget/windows/KeyboardLayout.h b/widget/windows/KeyboardLayout.h
index 70aacc80e..ba0d2d2d0 100644
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -531,6 +531,10 @@ private:
return aMSG.message == WM_CHAR &&
!IsControlChar(static_cast(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) &&
diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp
index 2731e1eaf..3049aa32f 100644
--- a/widget/windows/TSFTextStore.cpp
+++ b/widget/windows/TSFTextStore.cpp
@@ -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 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,
diff --git a/widget/windows/TSFTextStore.h b/widget/windows/TSFTextStore.h
index 08896ef36..d41dff0e4 100644
--- a/widget/windows/TSFTextStore.h
+++ b/widget/windows/TSFTextStore.h
@@ -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();
diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp
index f30a83248..d3592e810 100644
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -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 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;
}
diff --git a/widget/windows/WinUtils.h b/widget/windows/WinUtils.h
index b35c0c1c8..5dc298661 100644
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -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