зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
e196689816
|
@ -182,8 +182,8 @@
|
|||
<key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/>
|
||||
<key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
|
||||
|
||||
<key keycode="VK_BACK" command="cmd_handleBackspace"/>
|
||||
<key keycode="VK_BACK" command="cmd_handleShiftBackspace" modifiers="shift"/>
|
||||
<key keycode="VK_BACK" command="cmd_handleBackspace" reserved="false"/>
|
||||
<key keycode="VK_BACK" command="cmd_handleShiftBackspace" modifiers="shift" reserved="false"/>
|
||||
#ifndef XP_MACOSX
|
||||
<key id="goBackKb" keycode="VK_LEFT" command="Browser:Back" modifiers="alt"/>
|
||||
<key id="goForwardKb" keycode="VK_RIGHT" command="Browser:Forward" modifiers="alt"/>
|
||||
|
|
|
@ -117,3 +117,43 @@ if (!navigator.platform.includes("Mac")) {
|
|||
BrowserTestUtils.removeTab(tab1);
|
||||
});
|
||||
}
|
||||
|
||||
// There is a <key> element for Backspace with reserved="false", so make sure that it is not
|
||||
// treated as a blocked shortcut key.
|
||||
add_task(async function test_backspace() {
|
||||
await new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({"set": [["permissions.default.shortcuts", 2]]}, resolve);
|
||||
});
|
||||
|
||||
// The input field is autofocused. If this test fails, backspace can go back
|
||||
// in history so cancel the beforeunload event and adjust the field to make the test fail.
|
||||
const uri = "data:text/html,<body onbeforeunload='document.getElementById(\"field\").value = \"failed\";'>" +
|
||||
"<input id='field' value='something'></body>";
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri);
|
||||
|
||||
await ContentTask.spawn(tab.linkedBrowser, { }, async function() {
|
||||
content.document.getElementById("field").focus();
|
||||
|
||||
// Add a promise that resolves when the backspace key gets received
|
||||
// so we can ensure the key gets received before checking the result.
|
||||
content.keysPromise = new Promise(resolve => {
|
||||
content.addEventListener("keyup", event => {
|
||||
if (event.code == "Backspace") {
|
||||
resolve(content.document.getElementById("field").value);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Move the caret so backspace will delete the first character.
|
||||
EventUtils.synthesizeKey("KEY_ArrowRight", {});
|
||||
EventUtils.synthesizeKey("KEY_Backspace", {});
|
||||
|
||||
let fieldValue = await ContentTask.spawn(tab.linkedBrowser, { }, async function() {
|
||||
return content.keysPromise;
|
||||
});
|
||||
is(fieldValue, "omething", "backspace not prevented");
|
||||
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
|
|
|
@ -704,6 +704,7 @@ skip-if = (os == "win" && ccov) # Bug 1424154
|
|||
[browser_dbg-expressions-error.js]
|
||||
[browser_dbg-iframes.js]
|
||||
[browser_dbg-inline-cache.js]
|
||||
skip-if = ccov && os == 'win' # Bug 1443132
|
||||
[browser_dbg-inspector-integration.js]
|
||||
[browser_dbg-keyboard-navigation.js]
|
||||
[browser_dbg-keyboard-shortcuts.js]
|
||||
|
|
|
@ -64,7 +64,7 @@ ReverbConvolver::ReverbConvolver(const float* impulseResponseData,
|
|||
m_accumulationBuffer(impulseResponseLength + WEBAUDIO_BLOCK_SIZE),
|
||||
m_inputBuffer(InputBufferSize),
|
||||
m_backgroundThread("ConvolverWorker"),
|
||||
m_backgroundThreadCondition(&m_backgroundThreadLock),
|
||||
m_backgroundThreadMonitor("ConvolverMonitor"),
|
||||
m_useBackgroundThreads(useBackgroundThreads),
|
||||
m_wantsToExit(false),
|
||||
m_moreInputBuffered(false) {
|
||||
|
@ -166,9 +166,9 @@ ReverbConvolver::~ReverbConvolver() {
|
|||
|
||||
// Wake up thread so it can return
|
||||
{
|
||||
AutoLock locker(m_backgroundThreadLock);
|
||||
MonitorAutoLock locker(m_backgroundThreadMonitor);
|
||||
m_moreInputBuffered = true;
|
||||
m_backgroundThreadCondition.Signal();
|
||||
m_backgroundThreadMonitor.Notify();
|
||||
}
|
||||
|
||||
m_backgroundThread.Stop();
|
||||
|
@ -199,8 +199,7 @@ size_t ReverbConvolver::sizeOfIncludingThis(
|
|||
|
||||
// Possible future measurements:
|
||||
// - m_backgroundThread
|
||||
// - m_backgroundThreadLock
|
||||
// - m_backgroundThreadCondition
|
||||
// - m_backgroundThreadMonitor
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
@ -209,9 +208,9 @@ void ReverbConvolver::backgroundThreadEntry() {
|
|||
// Wait for realtime thread to give us more input
|
||||
m_moreInputBuffered = false;
|
||||
{
|
||||
AutoLock locker(m_backgroundThreadLock);
|
||||
MonitorAutoLock locker(m_backgroundThreadMonitor);
|
||||
while (!m_moreInputBuffered && !m_wantsToExit)
|
||||
m_backgroundThreadCondition.Wait();
|
||||
m_backgroundThreadMonitor.Wait();
|
||||
}
|
||||
|
||||
// Process all of the stages until their read indices reach the input
|
||||
|
@ -251,17 +250,17 @@ void ReverbConvolver::process(const float* sourceChannelData,
|
|||
|
||||
// Now that we've buffered more input, wake up our background thread.
|
||||
|
||||
// Not using a MutexLocker looks strange, but we use a tryLock() instead
|
||||
// Not using a MonitorAutoLock looks strange, but we use a TryLock() instead
|
||||
// because this is run on the real-time thread where it is a disaster for the
|
||||
// lock to be contended (causes audio glitching). It's OK if we fail to
|
||||
// signal from time to time, since we'll get to it the next time we're called.
|
||||
// We're called repeatedly and frequently (around every 3ms). The background
|
||||
// thread is processing well into the future and has a considerable amount of
|
||||
// leeway here...
|
||||
if (m_backgroundThreadLock.Try()) {
|
||||
if (m_backgroundThreadMonitor.TryLock()) {
|
||||
m_moreInputBuffered = true;
|
||||
m_backgroundThreadCondition.Signal();
|
||||
m_backgroundThreadLock.Release();
|
||||
m_backgroundThreadMonitor.Notify();
|
||||
m_backgroundThreadMonitor.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,10 @@
|
|||
#include "ReverbInputBuffer.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
#include "base/condition_variable.h"
|
||||
#include "base/lock.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
namespace WebCore {
|
||||
|
@ -80,8 +79,7 @@ class ReverbConvolver {
|
|||
|
||||
// Background thread and synchronization
|
||||
base::Thread m_backgroundThread;
|
||||
Lock m_backgroundThreadLock;
|
||||
ConditionVariable m_backgroundThreadCondition;
|
||||
mozilla::Monitor m_backgroundThreadMonitor;
|
||||
bool m_useBackgroundThreads;
|
||||
bool m_wantsToExit;
|
||||
bool m_moreInputBuffered;
|
||||
|
|
|
@ -15,12 +15,15 @@ namespace base {
|
|||
// thread-safe access, since it will only be modified in testing.
|
||||
static AtExitManager* g_top_manager = NULL;
|
||||
|
||||
AtExitManager::AtExitManager() : next_manager_(NULL) {
|
||||
AtExitManager::AtExitManager() : lock_("AtExitManager"),
|
||||
next_manager_(NULL) {
|
||||
DCHECK(!g_top_manager);
|
||||
g_top_manager = this;
|
||||
}
|
||||
|
||||
AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
|
||||
AtExitManager::AtExitManager(bool shadow) : lock_("AtExitManager"),
|
||||
next_manager_(g_top_manager)
|
||||
{
|
||||
DCHECK(shadow || !g_top_manager);
|
||||
g_top_manager = this;
|
||||
}
|
||||
|
@ -45,7 +48,7 @@ void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
|
|||
|
||||
DCHECK(func);
|
||||
|
||||
AutoLock lock(g_top_manager->lock_);
|
||||
mozilla::MutexAutoLock lock(g_top_manager->lock_);
|
||||
g_top_manager->stack_.push(CallbackAndParam(func, param));
|
||||
}
|
||||
|
||||
|
@ -56,7 +59,7 @@ void AtExitManager::ProcessCallbacksNow() {
|
|||
return;
|
||||
}
|
||||
|
||||
AutoLock lock(g_top_manager->lock_);
|
||||
mozilla::MutexAutoLock lock(g_top_manager->lock_);
|
||||
|
||||
while (!g_top_manager->stack_.empty()) {
|
||||
CallbackAndParam callback_and_param = g_top_manager->stack_.top();
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
#include <stack>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/lock.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
|
@ -63,7 +64,7 @@ class AtExitManager {
|
|||
void* param_;
|
||||
};
|
||||
|
||||
Lock lock_;
|
||||
mozilla::Mutex lock_;
|
||||
std::stack<CallbackAndParam> stack_;
|
||||
AtExitManager* next_manager_; // Stack of managers to allow shadowing.
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ namespace base {
|
|||
#define DVLOG(x) CHROMIUM_LOG(ERROR)
|
||||
#define CHECK_GT DCHECK_GT
|
||||
#define CHECK_LT DCHECK_LT
|
||||
typedef ::Lock Lock;
|
||||
typedef ::AutoLock AutoLock;
|
||||
|
||||
// Static table of checksums for all possible 8 bit bytes.
|
||||
const uint32_t Histogram::kCrcTable[256] = {
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include <string>
|
||||
|
||||
#include "base/time.h"
|
||||
#include "base/lock.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ MessageLoop::MessageLoop(Type type, nsIEventTarget* aEventTarget)
|
|||
id_(++message_loop_id_seq),
|
||||
nestable_tasks_allowed_(true),
|
||||
exception_restoration_(false),
|
||||
incoming_queue_lock_("MessageLoop Incoming Queue Lock"),
|
||||
state_(NULL),
|
||||
run_depth_base_(1),
|
||||
shutting_down_(false),
|
||||
|
@ -400,7 +401,7 @@ void MessageLoop::PostTask_Helper(already_AddRefed<nsIRunnable> task,
|
|||
|
||||
RefPtr<base::MessagePump> pump;
|
||||
{
|
||||
AutoLock locked(incoming_queue_lock_);
|
||||
mozilla::MutexAutoLock locked(incoming_queue_lock_);
|
||||
incoming_queue_.push(std::move(pending_task));
|
||||
pump = pump_;
|
||||
}
|
||||
|
@ -478,7 +479,7 @@ void MessageLoop::ReloadWorkQueue() {
|
|||
|
||||
// Acquire all we can from the inter-thread queue with one lock acquisition.
|
||||
{
|
||||
AutoLock lock(incoming_queue_lock_);
|
||||
mozilla::MutexAutoLock lock(incoming_queue_lock_);
|
||||
if (incoming_queue_.empty()) return;
|
||||
std::swap(incoming_queue_, work_queue_);
|
||||
DCHECK(incoming_queue_.empty());
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "base/lock.h"
|
||||
#include "base/message_pump.h"
|
||||
#include "base/observer_list.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// We need this to declare base::MessagePumpWin::Dispatcher, which we should
|
||||
// really just eliminate.
|
||||
|
@ -423,7 +424,7 @@ class MessageLoop : public base::MessagePump::Delegate {
|
|||
// will be handled by the TimerManager.
|
||||
TaskQueue incoming_queue_;
|
||||
// Protect access to incoming_queue_.
|
||||
Lock incoming_queue_lock_;
|
||||
mozilla::Mutex incoming_queue_lock_;
|
||||
|
||||
RunState* state_;
|
||||
int run_depth_base_;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <list>
|
||||
|
||||
#include "base/lock.h"
|
||||
#include "base/message_pump.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/scoped_handle.h"
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
#include <mmsystem.h>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/lock.h"
|
||||
#include "base/logging.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
||||
using base::Time;
|
||||
using base::TimeDelta;
|
||||
|
@ -216,10 +216,8 @@ DWORD (*tick_function)(void) = &timeGetTimeWrapper;
|
|||
// 49 days.
|
||||
class NowSingleton {
|
||||
public:
|
||||
NowSingleton() : rollover_(TimeDelta::FromMilliseconds(0)), last_seen_(0) {}
|
||||
|
||||
TimeDelta Now() {
|
||||
AutoLock locked(lock_);
|
||||
mozilla::StaticMutexAutoLock locked(lock_);
|
||||
// We should hold the lock while calling tick_function to make sure that
|
||||
// we keep our last_seen_ stay correctly in sync.
|
||||
DWORD now = tick_function();
|
||||
|
@ -231,12 +229,28 @@ class NowSingleton {
|
|||
}
|
||||
|
||||
static NowSingleton& instance() {
|
||||
static NowSingleton now;
|
||||
// This setup is a little gross: the `now` instance lives until libxul is
|
||||
// unloaded, but leak checking runs prior to that, and would see a Mutex
|
||||
// instance contained in NowSingleton as still live. Said instance would
|
||||
// be reported as a leak...but it's not, really. To avoid that, we need
|
||||
// to use StaticMutex (which is not leak-checked), but StaticMutex can't
|
||||
// be a member variable. So we have to have this separate variable and
|
||||
// pass it into the NowSingleton constructor.
|
||||
static mozilla::StaticMutex mutex;
|
||||
static NowSingleton now(mutex);
|
||||
return now;
|
||||
}
|
||||
|
||||
private:
|
||||
Lock lock_; // To protected last_seen_ and rollover_.
|
||||
explicit NowSingleton(mozilla::StaticMutex& aMutex)
|
||||
: lock_(aMutex)
|
||||
, rollover_(TimeDelta::FromMilliseconds(0))
|
||||
, last_seen_(0)
|
||||
{
|
||||
}
|
||||
~NowSingleton() = default;
|
||||
|
||||
mozilla::StaticMutex& lock_; // To protected last_seen_ and rollover_.
|
||||
TimeDelta rollover_; // Accumulation of time lost due to rollover.
|
||||
DWORD last_seen_; // The last timeGetTime value we saw, to detect rollover.
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "base/command_line.h"
|
||||
#include "base/eintr_wrapper.h"
|
||||
#include "base/lock.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/process_util.h"
|
||||
#include "base/string_util.h"
|
||||
|
@ -33,6 +32,7 @@
|
|||
#include "chrome/common/file_descriptor_set_posix.h"
|
||||
#include "chrome/common/ipc_message_utils.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#ifdef FUZZING
|
||||
|
@ -108,7 +108,7 @@ class PipeMap {
|
|||
public:
|
||||
// Lookup a given channel id. Return -1 if not found.
|
||||
int Lookup(const std::string& channel_id) {
|
||||
AutoLock locked(lock_);
|
||||
mozilla::StaticMutexAutoLock locked(lock_);
|
||||
|
||||
ChannelToFDMap::const_iterator i = map_.find(channel_id);
|
||||
if (i == map_.end()) return -1;
|
||||
|
@ -118,7 +118,7 @@ class PipeMap {
|
|||
// Remove the mapping for the given channel id. No error is signaled if the
|
||||
// channel_id doesn't exist
|
||||
void Remove(const std::string& channel_id) {
|
||||
AutoLock locked(lock_);
|
||||
mozilla::StaticMutexAutoLock locked(lock_);
|
||||
|
||||
ChannelToFDMap::iterator i = map_.find(channel_id);
|
||||
if (i != map_.end()) map_.erase(i);
|
||||
|
@ -127,7 +127,7 @@ class PipeMap {
|
|||
// Insert a mapping from @channel_id to @fd. It's a fatal error to insert a
|
||||
// mapping if one already exists for the given channel_id
|
||||
void Insert(const std::string& channel_id, int fd) {
|
||||
AutoLock locked(lock_);
|
||||
mozilla::StaticMutexAutoLock locked(lock_);
|
||||
DCHECK(fd != -1);
|
||||
|
||||
ChannelToFDMap::const_iterator i = map_.find(channel_id);
|
||||
|
@ -137,15 +137,25 @@ class PipeMap {
|
|||
}
|
||||
|
||||
static PipeMap& instance() {
|
||||
static PipeMap map;
|
||||
// This setup is a little gross: the `map` instance lives until libxul is
|
||||
// unloaded, but leak checking runs prior to that, and would see a Mutex
|
||||
// instance contained in PipeMap as still live. Said instance would be
|
||||
// reported as a leak...but it's not, really. To avoid that, we need to
|
||||
// use StaticMutex (which is not leak-checked), but StaticMutex can't be
|
||||
// a member variable. So we have to have this separate variable and pass
|
||||
// it into the PipeMap constructor.
|
||||
static mozilla::StaticMutex mutex;
|
||||
static PipeMap map(mutex);
|
||||
return map;
|
||||
}
|
||||
|
||||
private:
|
||||
PipeMap() = default;
|
||||
explicit PipeMap(mozilla::StaticMutex& aMutex)
|
||||
: lock_(aMutex)
|
||||
{}
|
||||
~PipeMap() = default;
|
||||
|
||||
Lock lock_;
|
||||
mozilla::StaticMutex& lock_;
|
||||
typedef std::map<std::string, int> ChannelToFDMap;
|
||||
ChannelToFDMap map_;
|
||||
};
|
||||
|
|
|
@ -106,11 +106,9 @@ struct JSPropertySpec {
|
|||
|
||||
private:
|
||||
void checkAccessorsAreNative() const {
|
||||
MOZ_ASSERT(accessors.getter.native.op);
|
||||
// We may not have a setter at all. So all we can assert here, for the
|
||||
// native case is that if we have a jitinfo for the setter then we have
|
||||
// a setter op too. This is good enough to make sure we don't have a
|
||||
// SelfHostedWrapper for the setter.
|
||||
// We may have a getter or a setter or both. And whichever ones we have
|
||||
// should not have a SelfHostedWrapper for the accessor.
|
||||
MOZ_ASSERT_IF(accessors.getter.native.info, accessors.getter.native.op);
|
||||
MOZ_ASSERT_IF(accessors.setter.native.info, accessors.setter.native.op);
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,10 @@ class FakeSocketTransportProvider : public nsISocketTransport {
|
|||
MOZ_ASSERT(false);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD SetLinger(bool aPolarity, int16_t aTimeout) override {
|
||||
MOZ_ASSERT(false);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD SetReuseAddrPort(bool reuseAddrPort) override {
|
||||
MOZ_ASSERT(false);
|
||||
return NS_OK;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "CSFLog.h"
|
||||
#include "base/histogram.h"
|
||||
#include "timecard.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
|
|
@ -42,7 +42,9 @@ DeviceInfoIos::DeviceInfoIos() {
|
|||
this->Init();
|
||||
}
|
||||
|
||||
DeviceInfoIos::~DeviceInfoIos() {}
|
||||
DeviceInfoIos::~DeviceInfoIos() {
|
||||
[_captureInfo registerOwner:nil];
|
||||
}
|
||||
|
||||
int32_t DeviceInfoIos::Init() {
|
||||
_captureInfo = [[DeviceInfoIosObjC alloc] init];
|
||||
|
|
|
@ -127,8 +127,9 @@ inline void mozilla::detail::MutexImpl::mutexLock() {
|
|||
"mozilla::detail::MutexImpl::mutexLock: pthread_mutex_lock failed");
|
||||
}
|
||||
|
||||
#ifdef XP_DARWIN
|
||||
inline bool mozilla::detail::MutexImpl::mutexTryLock() {
|
||||
bool mozilla::detail::MutexImpl::tryLock() { return mutexTryLock(); }
|
||||
|
||||
bool mozilla::detail::MutexImpl::mutexTryLock() {
|
||||
int result = pthread_mutex_trylock(&platformData()->ptMutex);
|
||||
if (result == 0) {
|
||||
return true;
|
||||
|
@ -142,7 +143,6 @@ inline bool mozilla::detail::MutexImpl::mutexTryLock() {
|
|||
result,
|
||||
"mozilla::detail::MutexImpl::mutexTryLock: pthread_mutex_trylock failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
void mozilla::detail::MutexImpl::lock() {
|
||||
#ifndef XP_DARWIN
|
||||
|
|
|
@ -22,6 +22,12 @@ void mozilla::detail::MutexImpl::lock() {
|
|||
AcquireSRWLockExclusive(&platformData()->lock);
|
||||
}
|
||||
|
||||
bool mozilla::detail::MutexImpl::tryLock() { return mutexTryLock(); }
|
||||
|
||||
bool mozilla::detail::MutexImpl::mutexTryLock() {
|
||||
return !!TryAcquireSRWLockExclusive(&platformData()->lock);
|
||||
}
|
||||
|
||||
void mozilla::detail::MutexImpl::unlock() {
|
||||
ReleaseSRWLockExclusive(&platformData()->lock);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ class MutexImpl {
|
|||
protected:
|
||||
MFBT_API void lock();
|
||||
MFBT_API void unlock();
|
||||
// We have a separate, forwarding API so internal uses don't have to go
|
||||
// through the PLT.
|
||||
MFBT_API bool tryLock();
|
||||
|
||||
private:
|
||||
MutexImpl(const MutexImpl&) = delete;
|
||||
|
@ -42,9 +45,7 @@ class MutexImpl {
|
|||
bool operator==(const MutexImpl& rhs) = delete;
|
||||
|
||||
void mutexLock();
|
||||
#ifdef XP_DARWIN
|
||||
bool mutexTryLock();
|
||||
#endif
|
||||
|
||||
PlatformData* platformData();
|
||||
|
||||
|
|
|
@ -124,6 +124,13 @@ interface nsISocketTransport : nsITransport
|
|||
unsigned long getTimeout(in unsigned long aType);
|
||||
void setTimeout(in unsigned long aType, in unsigned long aValue);
|
||||
|
||||
/**
|
||||
* Sets the SO_LINGER option with the specified values for the l_onoff and
|
||||
* l_linger parameters. This applies PR_SockOpt_Linger before PR_Close and
|
||||
* can be used with a timeout of zero to send an RST packet when closing.
|
||||
*/
|
||||
void setLinger(in boolean aPolarity, in short aTimeout);
|
||||
|
||||
/**
|
||||
* True to set addr and port reuse socket options.
|
||||
*/
|
||||
|
|
|
@ -717,6 +717,8 @@ nsSocketTransport::nsSocketTransport()
|
|||
mSocketTransportService(gSocketTransportService),
|
||||
mInput(this),
|
||||
mOutput(this),
|
||||
mLingerPolarity(false),
|
||||
mLingerTimeout(0),
|
||||
mQoSBits(0x00),
|
||||
mKeepaliveEnabled(false),
|
||||
mKeepaliveIdleTimeS(-1),
|
||||
|
@ -1978,7 +1980,8 @@ class ThunkPRClose : public Runnable {
|
|||
PRFileDesc *mFD;
|
||||
};
|
||||
|
||||
void STS_PRCloseOnSocketTransport(PRFileDesc *fd) {
|
||||
void STS_PRCloseOnSocketTransport(PRFileDesc *fd, bool lingerPolarity,
|
||||
int16_t lingerTimeout) {
|
||||
if (gSocketTransportService) {
|
||||
// Can't PR_Close() a socket off STS thread. Thunk it to STS to die
|
||||
gSocketTransportService->Dispatch(new ThunkPRClose(fd), NS_DISPATCH_NORMAL);
|
||||
|
@ -1999,13 +2002,22 @@ void nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd) {
|
|||
gSocketTransportService->MaxTimeForPrClosePref())) {
|
||||
// If shutdown last to long, let the socket leak and do not close it.
|
||||
SOCKET_LOG(("Intentional leak"));
|
||||
} else if (OnSocketThread()) {
|
||||
SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
|
||||
CloseSocket(
|
||||
mFD, mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase());
|
||||
} else {
|
||||
// Can't PR_Close() a socket off STS thread. Thunk it to STS to die
|
||||
STS_PRCloseOnSocketTransport(mFD);
|
||||
if (mLingerPolarity || mLingerTimeout) {
|
||||
PRSocketOptionData socket_linger;
|
||||
socket_linger.option = PR_SockOpt_Linger;
|
||||
socket_linger.value.linger.polarity = mLingerPolarity;
|
||||
socket_linger.value.linger.linger = mLingerTimeout;
|
||||
PR_SetSocketOption(mFD, &socket_linger);
|
||||
}
|
||||
if (OnSocketThread()) {
|
||||
SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
|
||||
CloseSocket(
|
||||
mFD, mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase());
|
||||
} else {
|
||||
// Can't PR_Close() a socket off STS thread. Thunk it to STS to die
|
||||
STS_PRCloseOnSocketTransport(mFD, mLingerPolarity, mLingerTimeout);
|
||||
}
|
||||
}
|
||||
mFD = nullptr;
|
||||
}
|
||||
|
@ -2756,6 +2768,16 @@ nsSocketTransport::SetReuseAddrPort(bool reuseAddrPort) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::SetLinger(bool aPolarity, int16_t aTimeout) {
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
mLingerPolarity = aPolarity;
|
||||
mLingerTimeout = aTimeout;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::SetQoSBits(uint8_t aQoSBits) {
|
||||
// Don't do any checking here of bits. Why? Because as of RFC-4594
|
||||
|
|
|
@ -398,6 +398,10 @@ class nsSocketTransport final : public nsASocketHandler,
|
|||
// socket timeouts are not protected by any lock.
|
||||
uint16_t mTimeouts[2];
|
||||
|
||||
// linger options to use when closing
|
||||
bool mLingerPolarity;
|
||||
int16_t mLingerTimeout;
|
||||
|
||||
// QoS setting for socket
|
||||
uint8_t mQoSBits;
|
||||
|
||||
|
|
|
@ -596,7 +596,6 @@ size_t CacheIOThread::SizeOfExcludingThis(
|
|||
MonitorAutoLock lock(const_cast<CacheIOThread*>(this)->mMonitor);
|
||||
|
||||
size_t n = 0;
|
||||
n += mallocSizeOf(mThread);
|
||||
for (const auto& event : mEventQueue) {
|
||||
n += event.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
// Events referenced by the queues are arbitrary objects we cannot be sure
|
||||
|
|
|
@ -1889,6 +1889,11 @@ SocketTransportShim::SetReuseAddrPort(bool aReuseAddrPort) {
|
|||
return mWrapped->SetReuseAddrPort(aReuseAddrPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SocketTransportShim::SetLinger(bool aPolarity, int16_t aTimeout) {
|
||||
return mWrapped->SetLinger(aPolarity, aTimeout);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SocketTransportShim::GetQoSBits(uint8_t *aQoSBits) {
|
||||
return mWrapped->GetQoSBits(aQoSBits);
|
||||
|
|
|
@ -398,7 +398,7 @@ nsHttpServer.prototype =
|
|||
|
||||
try {
|
||||
var conn = new Connection(input, output, this, socket.port, trans.port,
|
||||
connectionNumber);
|
||||
connectionNumber, trans);
|
||||
var reader = new RequestReader(conn);
|
||||
|
||||
// XXX add request timeout functionality here!
|
||||
|
@ -1067,7 +1067,8 @@ ServerIdentity.prototype =
|
|||
* @param number : uint
|
||||
* a serial number used to uniquely identify this connection
|
||||
*/
|
||||
function Connection(input, output, server, port, outgoingPort, number) {
|
||||
function Connection(input, output, server, port, outgoingPort, number,
|
||||
transport) {
|
||||
dumpn("*** opening new connection " + number + " on port " + outgoingPort);
|
||||
|
||||
/** Stream of incoming data. */
|
||||
|
@ -1088,6 +1089,9 @@ function Connection(input, output, server, port, outgoingPort, number) {
|
|||
/** The serial number of this connection. */
|
||||
this.number = number;
|
||||
|
||||
/** Reference to the underlying transport. */
|
||||
this.transport = transport;
|
||||
|
||||
/**
|
||||
* The request for which a response is being generated, null if the
|
||||
* incoming request has not been fully received or if it had errors.
|
||||
|
@ -3559,10 +3563,19 @@ Response.prototype =
|
|||
* @param e : Error
|
||||
* the exception which precipitated this abort, or null if no such exception
|
||||
* was generated
|
||||
* @param truncateConnection : Boolean
|
||||
* ensures that we truncate the connection using an RST packet, so the
|
||||
* client testing code is aware that an error occurred, otherwise it may
|
||||
* consider the response as valid.
|
||||
*/
|
||||
abort(e) {
|
||||
abort(e, truncateConnection = false) {
|
||||
dumpn("*** abort(<" + e + ">)");
|
||||
|
||||
if (truncateConnection) {
|
||||
dumpn("*** truncate connection");
|
||||
this._connection.transport.setLinger(true, 0);
|
||||
}
|
||||
|
||||
// This response will be ended by the processor if one was created.
|
||||
var copier = this._asyncCopier;
|
||||
if (copier) {
|
||||
|
|
|
@ -2212,12 +2212,17 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
|
|||
|
||||
# Find a D3D compiler DLL in a Windows SDK.
|
||||
MOZ_D3DCOMPILER_VISTA_DLL=
|
||||
case "$MOZ_WINSDK_MAXVER" in
|
||||
0x0603*|0x0A00*)
|
||||
if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
|
||||
MOZ_D3DCOMPILER_VISTA_DLL=d3dcompiler_47.dll
|
||||
AC_MSG_RESULT([Found D3D compiler in Windows SDK.])
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([Assuming D3D compiler will be in fxc2.])
|
||||
else
|
||||
case "$MOZ_WINSDK_MAXVER" in
|
||||
0x0603*|0x0A00*)
|
||||
MOZ_D3DCOMPILER_VISTA_DLL=d3dcompiler_47.dll
|
||||
AC_MSG_RESULT([Found D3D compiler in Windows SDK.])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_D3DCOMPILER_VISTA_DLL"; then
|
||||
# We have a name, now track down the path.
|
||||
|
@ -2235,13 +2240,20 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
|
|||
MOZ_D3DCOMPILER_VISTA_DLL_PATH=
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([Windows SDK not found.])
|
||||
MOZ_D3DCOMPILER_VISTA_DLL_PATH="$(dirname $FXC)/$MOZ_D3DCOMPILER_VISTA_DLL"
|
||||
if test -f "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
|
||||
AC_MSG_RESULT([Found MOZ_D3DCOMPILER_VISTA_DLL_PATH: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
|
||||
else
|
||||
AC_MSG_RESULT([MOZ_D3DCOMPILER_VISTA_DLL_PATH doesn't exist: $MOZ_D3DCOMPILER_VISTA_DLL_PATH])
|
||||
AC_MSG_ERROR([fxc2 or "$MOZ_D3DCOMPILER_VISTA_DLL" seem to be missing from the expected location.])
|
||||
MOZ_D3DCOMPILER_VISTA_DLL_PATH=
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if test "$OS_ARCH" = "$HOST_OS_ARCH"; then
|
||||
AC_MSG_ERROR([Couldn't find Windows SDK 8.1 or higher needed for ANGLE.])
|
||||
else
|
||||
AC_MSG_RESULT([Windows SDK not needed for ANGLE in Linux MinGW build.])
|
||||
AC_MSG_ERROR([We should need "$MOZ_D3DCOMPILER_VISTA_DLL" for ANGLE in Linux MinGW build, but we didn't look for it.])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -2263,10 +2275,8 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
|
|||
AC_MSG_RESULT([Found d3dcompiler DLL for Vista+: $MOZ_D3DCOMPILER_VISTA_DLL])
|
||||
fi
|
||||
|
||||
if test -z "$CROSS_COMPILE"; then
|
||||
if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
|
||||
AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
|
||||
fi
|
||||
if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
|
||||
AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
|
||||
fi
|
||||
fi # MOZ_ANGLE_RENDERER
|
||||
|
||||
|
|
|
@ -72,14 +72,12 @@ capture.element = function(node, highlights = []) {
|
|||
* The canvas element where the viewport has been painted on.
|
||||
*/
|
||||
capture.viewport = function(win, highlights = []) {
|
||||
let rootNode = win.document.documentElement;
|
||||
|
||||
return capture.canvas(
|
||||
win,
|
||||
win.pageXOffset,
|
||||
win.pageYOffset,
|
||||
rootNode.clientWidth,
|
||||
rootNode.clientHeight,
|
||||
win.innerWidth,
|
||||
win.innerHeight,
|
||||
{highlights});
|
||||
};
|
||||
|
||||
|
|
|
@ -67,10 +67,7 @@ class ScreenCaptureTestCase(MarionetteTestCase):
|
|||
|
||||
@property
|
||||
def viewport_dimensions(self):
|
||||
return self.marionette.execute_script("""
|
||||
return [arguments[0].clientWidth,
|
||||
arguments[0].clientHeight];
|
||||
""", script_args=[self.document_element])
|
||||
return self.marionette.execute_script("return [window.innerWidth, window.innerHeight];")
|
||||
|
||||
def assert_png(self, screenshot):
|
||||
"""Test that screenshot is a Base64 encoded PNG file."""
|
||||
|
|
|
@ -1,6 +1,2 @@
|
|||
def document_dimensions(session):
|
||||
return tuple(session.execute_script("""
|
||||
let devicePixelRatio = window.devicePixelRatio;
|
||||
let rect = document.documentElement.getBoundingClientRect();
|
||||
return [Math.floor(rect.width * devicePixelRatio), Math.floor(rect.height * devicePixelRatio)];
|
||||
"""))
|
||||
return tuple(session.execute_script("return [window.innerWidth, window.innerHeight];"))
|
||||
|
|
|
@ -1451,6 +1451,51 @@ add_task(async function test_error_source_partial() {
|
|||
Assert.equal(download.target.size, 0);
|
||||
});
|
||||
|
||||
/**
|
||||
* Ensures a download error is reported when an RST packet is received.
|
||||
*/
|
||||
add_task(async function test_error_source_netreset() {
|
||||
if (AppConstants.platform == "win") {
|
||||
return;
|
||||
}
|
||||
|
||||
let download;
|
||||
try {
|
||||
if (!gUseLegacySaver) {
|
||||
// When testing DownloadCopySaver, we want to check that the promise
|
||||
// returned by the "start" method is rejected.
|
||||
download = await promiseNewDownload(httpUrl("netreset.txt"));
|
||||
|
||||
Assert.ok(download.error === null);
|
||||
|
||||
await download.start();
|
||||
} else {
|
||||
// When testing DownloadLegacySaver, we cannot be sure whether we are
|
||||
// testing the promise returned by the "start" method or we are testing
|
||||
// the "error" property checked by promiseDownloadStopped. This happens
|
||||
// because we don't have control over when the download is started.
|
||||
download = await promiseStartLegacyDownload(httpUrl("netreset.txt"));
|
||||
await promiseDownloadStopped(download);
|
||||
}
|
||||
do_throw("The download should have failed.");
|
||||
} catch (ex) {
|
||||
if (!(ex instanceof Downloads.Error) || !ex.becauseSourceFailed) {
|
||||
throw ex;
|
||||
}
|
||||
// A specific error object is thrown when reading from the source fails.
|
||||
}
|
||||
|
||||
// Check the properties now that the download stopped.
|
||||
Assert.ok(download.stopped);
|
||||
Assert.ok(!download.canceled);
|
||||
Assert.ok(download.error !== null);
|
||||
Assert.ok(download.error.becauseSourceFailed);
|
||||
Assert.ok(!download.error.becauseTargetFailed);
|
||||
Assert.equal(download.error.result, Cr.NS_ERROR_NET_RESET);
|
||||
|
||||
Assert.equal(false, await OS.File.exists(download.target.path));
|
||||
});
|
||||
|
||||
/**
|
||||
* Ensures download error details are reported on local writing failures.
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
// Globals
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Integration.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
|
@ -718,6 +719,20 @@ add_task(function test_common_initialize() {
|
|||
"Blocked by Windows Parental Controls");
|
||||
});
|
||||
|
||||
// This URL sends some data followed by an RST packet
|
||||
gHttpServer.registerPathHandler("/netreset.txt",
|
||||
function(aRequest, aResponse) {
|
||||
info("Starting response that will be aborted.");
|
||||
aResponse.processAsync();
|
||||
aResponse.setHeader("Content-Type", "text/plain", false);
|
||||
aResponse.write(TEST_DATA_SHORT);
|
||||
promiseExecuteSoon().then(() => {
|
||||
aResponse.abort(null, true);
|
||||
aResponse.finish();
|
||||
info("Aborting response with network reset.");
|
||||
}).then(null, Cu.reportError);
|
||||
});
|
||||
|
||||
// During unit tests, most of the functions that require profile access or
|
||||
// operating system features will be disabled. Individual tests may override
|
||||
// them again to check for specific behaviors.
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
* Tests for the "DownloadPaths.jsm" JavaScript module.
|
||||
*/
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
function testSanitize(leafName, expectedLeafName) {
|
||||
Assert.equal(DownloadPaths.sanitize(leafName), expectedLeafName);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,133 @@
|
|||
<field name="scrollBox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "class", "popup-internal-box");
|
||||
</field>
|
||||
|
||||
<field name="AUTOSCROLL_INTERVAL">25</field>
|
||||
<field name="NOT_DRAGGING">0</field>
|
||||
<field name="DRAG_OVER_BUTTON">-1</field>
|
||||
<field name="DRAG_OVER_POPUP">1</field>
|
||||
|
||||
<field name="_draggingState">this.NOT_DRAGGING</field>
|
||||
<field name="_scrollTimer">0</field>
|
||||
|
||||
<method name="_enableDragScrolling">
|
||||
<!-- when overItem is true, drag started over menuitem; when false, drag
|
||||
started while the popup was opening.
|
||||
-->
|
||||
<parameter name="overItem"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this._draggingState) {
|
||||
this.setCaptureAlways();
|
||||
this._draggingState = overItem ? this.DRAG_OVER_POPUP : this.DRAG_OVER_BUTTON;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_clearScrollTimer">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._scrollTimer) {
|
||||
this.ownerGlobal.clearInterval(this._scrollTimer);
|
||||
this._scrollTimer = 0;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<constructor><![CDATA[
|
||||
// Enable the drag-to-scroll events only in menulist popups.
|
||||
if (!this.parentNode || this.parentNode.localName != "menulist") {
|
||||
return;
|
||||
}
|
||||
|
||||
// XBL bindings might be constructed more than once.
|
||||
if (this.eventListenersAdded) {
|
||||
return;
|
||||
}
|
||||
this.eventListenersAdded = true;
|
||||
|
||||
this.addEventListener("popupshown", () => {
|
||||
// Enable drag scrolling even when the mouse wasn't used. The
|
||||
// mousemove handler will remove it if the mouse isn't down.
|
||||
this._enableDragScrolling(false);
|
||||
});
|
||||
|
||||
this.addEventListener("popuphidden", () => {
|
||||
this._draggingState = this.NOT_DRAGGING;
|
||||
this._clearScrollTimer();
|
||||
this.releaseCapture();
|
||||
});
|
||||
|
||||
this.addEventListener("mousedown", event => {
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.state == "open" &&
|
||||
(event.target.localName == "menuitem" ||
|
||||
event.target.localName == "menu" ||
|
||||
event.target.localName == "menucaption")) {
|
||||
this._enableDragScrolling(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.addEventListener("mouseup", event => {
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._draggingState = this.NOT_DRAGGING;
|
||||
this._clearScrollTimer();
|
||||
});
|
||||
|
||||
this.addEventListener("mousemove", event => {
|
||||
if (!this._draggingState) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._clearScrollTimer();
|
||||
|
||||
// If the user released the mouse before the popup opens, we will
|
||||
// still be capturing, so check that the button is still pressed. If
|
||||
// not, release the capture and do nothing else. This also handles if
|
||||
// the dropdown was opened via the keyboard.
|
||||
if (!(event.buttons & 1)) {
|
||||
this._draggingState = this.NOT_DRAGGING;
|
||||
this.releaseCapture();
|
||||
return;
|
||||
}
|
||||
|
||||
// If dragging outside the top or bottom edge of the popup, but within
|
||||
// the popup area horizontally, scroll the list in that direction. The
|
||||
// _draggingState flag is used to ensure that scrolling does not start
|
||||
// until the mouse has moved over the popup first, preventing
|
||||
// scrolling while over the dropdown button.
|
||||
let popupRect = this.getOuterScreenRect();
|
||||
if (event.screenX >= popupRect.left &&
|
||||
event.screenX <= popupRect.right) {
|
||||
if (this._draggingState == this.DRAG_OVER_BUTTON) {
|
||||
if (event.screenY > popupRect.top &&
|
||||
event.screenY < popupRect.bottom) {
|
||||
this._draggingState = this.DRAG_OVER_POPUP;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._draggingState == this.DRAG_OVER_POPUP &&
|
||||
(event.screenY <= popupRect.top ||
|
||||
event.screenY >= popupRect.bottom)) {
|
||||
let scrollAmount = event.screenY <= popupRect.top ? -1 : 1;
|
||||
this.scrollBox.scrollByIndex(scrollAmount, true);
|
||||
|
||||
let win = this.ownerGlobal;
|
||||
this._scrollTimer = win.setInterval(() => {
|
||||
this.scrollBox.scrollByIndex(scrollAmount, true);
|
||||
}, this.AUTOSCROLL_INTERVAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
]]></constructor>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
|
@ -262,124 +389,4 @@
|
|||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup">
|
||||
<content>
|
||||
<xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
|
||||
smoothscroll="false">
|
||||
<children/>
|
||||
</xul:arrowscrollbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="AUTOSCROLL_INTERVAL">25</field>
|
||||
<field name="NOT_DRAGGING">0</field>
|
||||
<field name="DRAG_OVER_BUTTON">-1</field>
|
||||
<field name="DRAG_OVER_POPUP">1</field>
|
||||
|
||||
<field name="_draggingState">this.NOT_DRAGGING</field>
|
||||
<field name="_scrollTimer">0</field>
|
||||
|
||||
<method name="enableDragScrolling">
|
||||
<!-- when overItem is true, drag started over menuitem; when false, drag
|
||||
started while the popup was opening.
|
||||
-->
|
||||
<parameter name="overItem"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this._draggingState) {
|
||||
this.setCaptureAlways();
|
||||
this._draggingState = overItem ? this.DRAG_OVER_POPUP : this.DRAG_OVER_BUTTON;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="_clearScrollTimer">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._scrollTimer) {
|
||||
this.ownerGlobal.clearInterval(this._scrollTimer);
|
||||
this._scrollTimer = 0;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
<handlers>
|
||||
<handler event="popupshown">
|
||||
// Enable drag scrolling even when the mouse wasn't used. The mousemove
|
||||
// handler will remove it if the mouse isn't down.
|
||||
this.enableDragScrolling(false);
|
||||
</handler>
|
||||
|
||||
<handler event="popuphidden">
|
||||
<![CDATA[
|
||||
this._draggingState = this.NOT_DRAGGING;
|
||||
this._clearScrollTimer();
|
||||
this.releaseCapture();
|
||||
]]>
|
||||
</handler>
|
||||
|
||||
<handler event="mousedown" button="0">
|
||||
<![CDATA[
|
||||
if (this.state == "open" &&
|
||||
(event.target.localName == "menuitem" ||
|
||||
event.target.localName == "menu" ||
|
||||
event.target.localName == "menucaption")) {
|
||||
this.enableDragScrolling(true);
|
||||
}
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="mouseup" button="0">
|
||||
<![CDATA[
|
||||
this._draggingState = this.NOT_DRAGGING;
|
||||
this._clearScrollTimer();
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="mousemove">
|
||||
<![CDATA[
|
||||
if (!this._draggingState) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._clearScrollTimer();
|
||||
|
||||
// If the user released the mouse before the popup opens, we will
|
||||
// still be capturing, so check that the button is still pressed. If
|
||||
// not, release the capture and do nothing else. This also handles if
|
||||
// the dropdown was opened via the keyboard.
|
||||
if (!(event.buttons & 1)) {
|
||||
this._draggingState = this.NOT_DRAGGING;
|
||||
this.releaseCapture();
|
||||
return;
|
||||
}
|
||||
|
||||
// If dragging outside the top or bottom edge of the popup, but within
|
||||
// the popup area horizontally, scroll the list in that direction. The
|
||||
// _draggingState flag is used to ensure that scrolling does not start
|
||||
// until the mouse has moved over the popup first, preventing scrolling
|
||||
// while over the dropdown button.
|
||||
let popupRect = this.getOuterScreenRect();
|
||||
if (event.screenX >= popupRect.left && event.screenX <= popupRect.right) {
|
||||
if (this._draggingState == this.DRAG_OVER_BUTTON) {
|
||||
if (event.screenY > popupRect.top && event.screenY < popupRect.bottom) {
|
||||
this._draggingState = this.DRAG_OVER_POPUP;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._draggingState == this.DRAG_OVER_POPUP &&
|
||||
(event.screenY <= popupRect.top || event.screenY >= popupRect.bottom)) {
|
||||
let scrollAmount = event.screenY <= popupRect.top ? -1 : 1;
|
||||
this.scrollBox.scrollByIndex(scrollAmount, true);
|
||||
|
||||
let win = this.ownerGlobal;
|
||||
this._scrollTimer = win.setInterval(() => {
|
||||
this.scrollBox.scrollByIndex(scrollAmount, true);
|
||||
}, this.AUTOSCROLL_INTERVAL);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
|
|
@ -1293,6 +1293,7 @@ set_config('MOZ_LAYOUT_DEBUGGER', depends_if('--enable-layout-debugger')(lambda
|
|||
with only_when(compile_environment):
|
||||
fxc = check_prog('FXC', ('fxc.exe', 'fxc2.exe'), when=depends(target)
|
||||
(lambda t: t.kernel == 'WINNT'))
|
||||
add_old_configure_assignment('FXC', fxc)
|
||||
wine = check_prog('WINE', ['wine'], when=depends(target, host)
|
||||
(lambda t, h: t.kernel == 'WINNT' and h.kernel == 'Linux'))
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@ interface nsIUpdatePatch : nsISupports
|
|||
* "complete" A complete patch containing all of the replacement files
|
||||
* to update to the new version
|
||||
*/
|
||||
attribute AString type;
|
||||
readonly attribute AString type;
|
||||
|
||||
/**
|
||||
* The URL this patch was being downloaded from
|
||||
*/
|
||||
attribute AString URL;
|
||||
readonly attribute AString URL;
|
||||
|
||||
/**
|
||||
* The final URL this patch was being downloaded from
|
||||
|
@ -43,7 +43,7 @@ interface nsIUpdatePatch : nsISupports
|
|||
/**
|
||||
* The size of this file, in bytes.
|
||||
*/
|
||||
attribute unsigned long size;
|
||||
readonly attribute unsigned long size;
|
||||
|
||||
/**
|
||||
* The state of this patch
|
||||
|
@ -92,28 +92,28 @@ interface nsIUpdate : nsISupports
|
|||
* "major" A major new version of the Application
|
||||
* "minor" A minor update to the Application (e.g. security update)
|
||||
*/
|
||||
attribute AString type;
|
||||
readonly attribute AString type;
|
||||
|
||||
/**
|
||||
* The name of the update, or "<Application Name> <Update Version>"
|
||||
*/
|
||||
attribute AString name;
|
||||
readonly attribute AString name;
|
||||
|
||||
/**
|
||||
* The string to display in the user interface for the version. If you want
|
||||
* a real version number use appVersion.
|
||||
*/
|
||||
attribute AString displayVersion;
|
||||
readonly attribute AString displayVersion;
|
||||
|
||||
/**
|
||||
* The Application version of this update.
|
||||
*/
|
||||
attribute AString appVersion;
|
||||
readonly attribute AString appVersion;
|
||||
|
||||
/**
|
||||
* The Application version prior to the application being updated.
|
||||
*/
|
||||
attribute AString previousAppVersion;
|
||||
readonly attribute AString previousAppVersion;
|
||||
|
||||
/**
|
||||
* The Build ID of this update. Used to determine a particular build, down
|
||||
|
@ -121,7 +121,7 @@ interface nsIUpdate : nsISupports
|
|||
* to differentiate between several nightly builds with the same |version|
|
||||
* for example.
|
||||
*/
|
||||
attribute AString buildID;
|
||||
readonly attribute AString buildID;
|
||||
|
||||
/**
|
||||
* The URL to a page which offers details about the content of this
|
||||
|
@ -129,22 +129,22 @@ interface nsIUpdate : nsISupports
|
|||
* that summarizes the differences between this update and the previous,
|
||||
* which also links to the release notes.
|
||||
*/
|
||||
attribute AString detailsURL;
|
||||
readonly attribute AString detailsURL;
|
||||
|
||||
/**
|
||||
* The URL to the Update Service that supplied this update.
|
||||
*/
|
||||
attribute AString serviceURL;
|
||||
readonly attribute AString serviceURL;
|
||||
|
||||
/**
|
||||
* The channel used to retrieve this update from the Update Service.
|
||||
*/
|
||||
attribute AString channel;
|
||||
readonly attribute AString channel;
|
||||
|
||||
/**
|
||||
* Whether the update is no longer supported on this system.
|
||||
*/
|
||||
attribute boolean unsupported;
|
||||
readonly attribute boolean unsupported;
|
||||
|
||||
/**
|
||||
* Allows overriding the default amount of time in seconds before prompting the
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
|
||||
/* ::::: XBL bindings ::::: */
|
||||
|
||||
menulist > menupopup {
|
||||
-moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
|
||||
}
|
||||
|
||||
@media (-moz-menubar-drag) {
|
||||
toolbar[type="menubar"] {
|
||||
-moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
|
||||
|
|
|
@ -11,12 +11,6 @@
|
|||
|
||||
%include ../../shared/global.inc.css
|
||||
|
||||
/* ::::: XBL bindings ::::: */
|
||||
|
||||
menulist > menupopup {
|
||||
-moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
|
||||
}
|
||||
|
||||
/* ::::: Variables ::::: */
|
||||
:root {
|
||||
--arrowpanel-padding: 16px;
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
|
||||
%include ../../shared/global.inc.css
|
||||
|
||||
/* ::::: XBL bindings ::::: */
|
||||
|
||||
menulist > menupopup {
|
||||
-moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
|
||||
}
|
||||
|
||||
/* ::::: Variables ::::: */
|
||||
:root {
|
||||
--arrowpanel-padding: 10px;
|
||||
|
|
|
@ -349,6 +349,16 @@ void OffTheBooksMutex::Lock() {
|
|||
Acquire();
|
||||
}
|
||||
|
||||
bool OffTheBooksMutex::TryLock() {
|
||||
CheckAcquire();
|
||||
bool locked = this->tryLock();
|
||||
if (locked) {
|
||||
mOwningThread = PR_GetCurrentThread();
|
||||
Acquire();
|
||||
}
|
||||
return locked;
|
||||
}
|
||||
|
||||
void OffTheBooksMutex::Unlock() {
|
||||
Release();
|
||||
mOwningThread = nullptr;
|
||||
|
|
|
@ -30,6 +30,7 @@ class Monitor {
|
|||
~Monitor() {}
|
||||
|
||||
void Lock() { mMutex.Lock(); }
|
||||
bool TryLock() { return mMutex.TryLock(); }
|
||||
void Unlock() { mMutex.Unlock(); }
|
||||
|
||||
void Wait() { mCondVar.Wait(); }
|
||||
|
|
|
@ -65,6 +65,11 @@ class OffTheBooksMutex : public detail::MutexImpl, BlockingResourceBase {
|
|||
**/
|
||||
void Lock() { this->lock(); }
|
||||
|
||||
/**
|
||||
* Try to lock this mutex, returning true if we were successful.
|
||||
**/
|
||||
bool TryLock() { return this->tryLock(); }
|
||||
|
||||
/**
|
||||
* Unlock this mutex.
|
||||
**/
|
||||
|
@ -89,6 +94,7 @@ class OffTheBooksMutex : public detail::MutexImpl, BlockingResourceBase {
|
|||
|
||||
#else
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
void AssertCurrentThreadOwns() const;
|
||||
|
|
Загрузка…
Ссылка в новой задаче