Merge inbound to central, a=merge

MozReview-Commit-ID: 1SvQU51m5qC
This commit is contained in:
Wes Kocher 2017-06-20 17:58:46 -07:00
Родитель 714606a814 dde8de6908
Коммит 586bef635e
493 изменённых файлов: 5279 добавлений и 2128 удалений

Просмотреть файл

@ -141,7 +141,7 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eOpenCloseAction,
eNoLiveAttr,
kGenericAccType,
states::COLLAPSED | states::HASPOPUP | states::VERTICAL,
states::COLLAPSED | states::HASPOPUP,
eARIAAutoComplete,
eARIAReadonly,
eARIAOrientation
@ -788,8 +788,7 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eClickAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckedMixed
kNoReqStates
},
{ // menuitemcheckbox
&nsGkAtoms::menuitemcheckbox,
@ -800,7 +799,8 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableMixed
eARIACheckableMixed,
eARIAReadonly
},
{ // menuitemradio
&nsGkAtoms::menuitemradio,
@ -811,7 +811,8 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableBool
eARIACheckableBool,
eARIAReadonly
},
{ // navigation
&nsGkAtoms::navigation,
@ -896,7 +897,8 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAOrientation
eARIAOrientation,
eARIAReadonly
},
{ // region
&nsGkAtoms::region,
@ -1029,7 +1031,8 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableBool
eARIACheckableBool,
eARIAReadonly
},
{ // tab
&nsGkAtoms::tab,
@ -1149,7 +1152,7 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eNoAction,
eNoLiveAttr,
eSelect | eTable,
states::VERTICAL,
kNoReqStates,
eARIAReadonlyOrEditable,
eARIAMultiSelectable,
eFocusableUntilDisabled,

Просмотреть файл

@ -64,7 +64,7 @@ private:
Atomic<uint32_t> mRefCnt;
Mutex mMutex; // Protects mSerializer
REFIID mTargetUnkIid;
const IID mTargetUnkIid;
mscom::InterceptorTargetPtr<IUnknown> mTargetUnk; // Constant, main thread only
UniquePtr<mscom::StructToStream> mSerializer;
};

Просмотреть файл

@ -30,7 +30,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
testAttrs("autocomplete", {"autocomplete" : "true"}, true);
testAttrs("checkbox", {"checkable" : "true"}, true);
testAttrs("checkedCheckbox", {"checkable" : "true"}, true);
testAttrs("checkedMenuitem", {"checkable" : "true"}, true);
testAbsentAttrs("checkedMenuitem", {"checkable" : "true"}, true);
testAttrs("checkedMenuitemCheckbox", {"checkable" : "true"}, true);
testAttrs("checkedMenuitemRadio", {"checkable" : "true"}, true);
testAttrs("checkedOption", {"checkable" : "true"}, true);
testAttrs("checkedRadio", {"checkable" : "true"}, true);
testAttrs("checkedTreeitem", {"checkable" : "true"}, true);
@ -205,6 +207,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
<div id="checkbox" role="checkbox"></div>
<div id="checkedCheckbox" role="checkbox" aria-checked="true"></div>
<div id="checkedMenuitem" role="menuitem" aria-checked="true"></div>
<div id="checkedMenuitemCheckbox" role="menuitemcheckbox" aria-checked="true"></div>
<div id="checkedMenuitemRadio" role="menuitemradio" aria-checked="true"></div>
<div id="checkedOption" role="option" aria-checked="true"></div>
<div id="checkedRadio" role="radio" aria-checked="true"></div>
<div id="checkedTreeitem" role="treeitem" aria-checked="true"></div>

Просмотреть файл

@ -223,7 +223,7 @@
testStates("aria_navigation_anchor", STATE_SELECTABLE);
// aria-orientation
testStates("aria_combobox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
testStates("aria_combobox", 0, 0, 0, EXT_STATE_HORIZONTAL | EXT_STATE_VERTICAL);
testStates("aria_hcombobox", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
testStates("aria_vcombobox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
testStates("aria_listbox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
@ -256,7 +256,7 @@
testStates("aria_tree", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
testStates("aria_htree", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
testStates("aria_vtree", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
testStates("aria_treegrid", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
testStates("aria_treegrid", 0, 0, 0, EXT_STATE_HORIZONTAL | EXT_STATE_VERTICAL);
testStates("aria_htreegrid", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
testStates("aria_vtreegrid", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);

Просмотреть файл

@ -96,13 +96,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
testStates("option_checked_undefined", 0, 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("option_checked_absent", 0, 0, STATE_CHECKABLE | STATE_CHECKED);
// test (menuitem) checkable and checked states
testStates("menuitem_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (menuitem) checkable and checked states, which are unsupported on this role
testStates("menuitem_checked_true", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_false", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_absent", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
// test (menuitemcheckbox) checkable and checked states
testStates("menuitemcheckbox_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemcheckbox_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemcheckbox_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemcheckbox_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemcheckbox_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (menuitemcheckbox) readonly states
testStates("menuitemcheckbox_readonly_true", STATE_READONLY);
testStates("menuitemcheckbox_readonly_false", 0, 0, STATE_READONLY);
testStates("menuitemcheckbox_readonly_empty", 0, 0, STATE_READONLY);
testStates("menuitemcheckbox_readonly_undefined", 0, 0, STATE_READONLY);
testStates("menuitemcheckbox_readonly_absent", 0, 0, STATE_READONLY);
// test (menuitemradio) checkable and checked states
testStates("menuitemradio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
@ -110,6 +124,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
testStates("menuitemradio_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (menuitemradio) readonly states
testStates("menuitemradio_readonly_true", STATE_READONLY);
testStates("menuitemradio_readonly_false", 0, 0, STATE_READONLY);
testStates("menuitemradio_readonly_empty", 0, 0, STATE_READONLY);
testStates("menuitemradio_readonly_undefined", 0, 0, STATE_READONLY);
testStates("menuitemradio_readonly_absent", 0, 0, STATE_READONLY);
// test (radio) checkable and checked states
testStates("radio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
@ -117,6 +138,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
testStates("radio_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (radiogroup) readonly states
testStates("radiogroup_readonly_true", STATE_READONLY);
testStates("radiogroup_readonly_false", 0, 0, STATE_READONLY);
testStates("radiogroup_readonly_empty", 0, 0, STATE_READONLY);
testStates("radiogroup_readonly_undefined", 0, 0, STATE_READONLY);
testStates("radiogroup_readonly_absent", 0, 0, STATE_READONLY);
// test (switch) readonly states
testStates("switch_readonly_true", STATE_READONLY);
testStates("switch_readonly_false", 0, 0, STATE_READONLY);
testStates("switch_readonly_empty", 0, 0, STATE_READONLY);
testStates("switch_readonly_undefined", 0, 0, STATE_READONLY);
testStates("switch_readonly_absent", 0, 0, STATE_READONLY);
// test (textbox) multiline states
testStates("textbox_multiline_true", 0, EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_false", 0, EXT_STATE_SINGLE_LINE);
@ -260,11 +295,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
</div>
<div role="menu">
<div id="menuitem_checked_true" role="menuitem" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitem_checked_false" role="menuitem" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitem_checked_empty" role="menuitem" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_undefined" role="menuitem" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_absent" role="menuitem">This menuitem has <emph>no</emph> aria-checked attribute and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_true" role="menuitem" aria-checked="true">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_false" role="menuitem" aria-checked="false">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_empty" role="menuitem" aria-checked="">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_undefined" role="menuitem" aria-checked="undefined">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_absent" role="menuitem">Generic menuitems don't support aria-checked.</div>
<div id="menuitemcheckbox_checked_true" role="menuitemcheckbox" aria-checked="true">This menuitemcheckbox has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitemcheckbox_checked_false" role="menuitemcheckbox" aria-checked="false">This menuitemcheckbox has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitemcheckbox_checked_empty" role="menuitemcheckbox" aria-checked="">This menuitemcheckbox has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemcheckbox_checked_undefined" role="menuitemcheckbox" aria-checked="undefined">This menuitemcheckbox has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemcheckbox_checked_absent" role="menuitemcheckbox">This menuitemcheckbox has <emph>no</emph> aria-checked attribute and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemcheckbox_readonly_true" role="menuitemcheckbox" aria-readonly="true">This menuitemcheckbox has aria-readonly="true" and should get STATE_READONLY.</div>
<div id="menuitemcheckbox_readonly_false" role="menuitemcheckbox" aria-readonly="false">This menuitemcheckbox has aria-readonly="false" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemcheckbox_readonly_empty" role="menuitemcheckbox" aria-readonly="">This menuitemcheckbox has aria-readonly="" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemcheckbox_readonly_undefined" role="menuitemcheckbox" aria-readonly="undefined">This menuitemcheckbox has aria-readonly="undefined" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemcheckbox_readonly_absent" role="menuitemcheckbox">This menuitemcheckbox has <emph>no</emph> aria-readonly attribute and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemradio_checked_true" role="menuitemradio" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitemradio_checked_false" role="menuitemradio" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
@ -273,12 +320,45 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
<div id="menuitemradio_checked_absent" role="menuitemradio">This menuitem has <emph>no</emph> aria-checked attribute but should get STATE_CHECKABLE.</div>
</div>
<div id="menuitemradio_readonly_true" role="menuitemradio" aria-readonly="true">This menuitemradio has aria-readonly="true" and should get STATE_READONLY.</div>
<div id="menuitemradio_readonly_false" role="menuitemradio" aria-readonly="false">This menuitemradio has aria-readonly="false" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemradio_readonly_empty" role="menuitemradio" aria-readonly="">This menuitemradio has aria-readonly="" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemradio_readonly_undefined" role="menuitemradio" aria-readonly="undefined">This menuitemradio has aria-readonly="undefined" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemradio_readonly_absent" role="menuitemradio">This menuitemradio has <emph>no</emph> aria-readonly attribute and should <emph>not</emph> get STATE_READONLY.</div>
<div id="radio_checked_true" role="radio" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_CHECKED.</div>
<div id="radio_checked_false" role="radio" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="radio_checked_empty" role="radio" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="radio_checked_undefined" role="radio" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="radio_checked_absent" role="radio">This menuitem has <emph>no</emph> aria-checked attribute but should get STATE_CHECKABLE.</div>
<div id="radiogroup_readonly_true" role="radiogroup" aria-readonly="true">
<div role="radio">yes</div>
<div role="radio">no</div>
</div>
<div id="radiogroup_readonly_false" role="radiogroup" aria-readonly="false">
<div role="radio">yes</div>
<div role="radio">no</div>
</div>
<div id="radiogroup_readonly_empty" role="radiogroup" aria-readonly="">
<div role="radio">yes</div>
<div role="radio">no</div>
</div>
<div id="radiogroup_readonly_undefined" role="radiogroup" aria-readonly="undefined">
<div role="radio">yes</div>
<div role="radio">no</div>
</div>
<div id="radiogroup_readonly_absent" role="radiogroup">
<div role="radio">yes</div>
<div role="radio">no</div>
</div>
<div id="switch_readonly_true" role="switch" aria-readonly="true">This switch has aria-readonly="true" and should get STATE_READONLY.</div>
<div id="switch_readonly_false" role="switch" aria-readonly="false">This switch has aria-readonly="false" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="switch_readonly_empty" role="switch" aria-readonly="">This switch has aria-readonly="" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="switch_readonly_undefined" role="switch" aria-readonly="undefined">This switch has aria-readonly="undefined" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="switch_readonly_absent" role="switch">This switch has <emph>no</emph> aria-readonly attribute and should <emph>not</emph> get STATE_READONLY.</div>
<div id="textbox_readonly_true" role="textbox" aria-readonly="true"></div>
<div id="textbox_readonly_false" role="textbox" aria-readonly="false"></div>
<div id="textbox_readonly_empty" role="textbox" aria-readonly=""></div>

Просмотреть файл

@ -0,0 +1,832 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "LazyInstantiator.h"
#include "MainThreadUtils.h"
#include "mozilla/a11y/Accessible.h"
#include "mozilla/Assertions.h"
#include "mozilla/mscom/MainThreadRuntime.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/Registration.h"
#include "mozilla/UniquePtr.h"
#include "nsAccessibilityService.h"
#include "nsWindowsHelpers.h"
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsXPCOM.h"
#include "RootAccessibleWrap.h"
#include "WinUtils.h"
#if defined(MOZ_TELEMETRY_REPORTING)
#include "mozilla/Telemetry.h"
#endif // defined(MOZ_TELEMETRY_REPORTING)
#include <oaidl.h>
#if !defined(STATE_SYSTEM_NORMAL)
#define STATE_SYSTEM_NORMAL (0)
#endif // !defined(STATE_SYSTEM_NORMAL)
/**
* Because our wrapped accessible is cycle-collected, we can't safely AddRef()
* or Release() ourselves off the main thread. This template specialization
* forces NewRunnableMethod() to use STAUniquePtr instead of RefPtr for managing
* a runnable's lifetime. Once the runnable has completed, the STAUniquePtr will
* post a runnable to the main thread to release ourselves from there.
*/
template<>
struct nsRunnableMethodReceiver<mozilla::a11y::LazyInstantiator, true>
{
mozilla::mscom::STAUniquePtr<mozilla::a11y::LazyInstantiator> mObj;
explicit nsRunnableMethodReceiver(mozilla::a11y::LazyInstantiator* aObj)
: mObj(aObj)
{
MOZ_ASSERT(NS_IsMainThread());
// STAUniquePtr does not implicitly AddRef(), so we must explicitly do so
// here.
aObj->AddRef();
}
~nsRunnableMethodReceiver() { Revoke(); }
mozilla::a11y::LazyInstantiator* Get() const { return mObj.get(); }
void Revoke() { mObj = nullptr; }
};
namespace mozilla {
namespace a11y {
static const wchar_t kLazyInstantiatorProp[] = L"mozilla::a11y::LazyInstantiator";
/* static */
already_AddRefed<IAccessible>
LazyInstantiator::GetRootAccessible(HWND aHwnd)
{
// There must only be one LazyInstantiator per HWND.
// To track this, we set the kLazyInstantiatorProp on the HWND with a pointer
// to an existing instance. We only create a new LazyInstatiator if that prop
// has not already been set.
LazyInstantiator* existingInstantiator =
reinterpret_cast<LazyInstantiator*>(::GetProp(aHwnd, kLazyInstantiatorProp));
RefPtr<IAccessible> result;
if (existingInstantiator) {
// Temporarily disable blind aggregation until we know that we have been
// marshaled. See EnableBlindAggregation for more information.
existingInstantiator->mAllowBlindAggregation = false;
result = existingInstantiator;
return result.forget();
}
// At this time we only want to check whether the acc service is running; We
// don't actually want to create the acc service yet.
if (!GetAccService()) {
// a11y is not running yet, there are no existing LazyInstantiators for this
// HWND, so create a new one and return it as a surrogate for the root
// accessible.
result = new LazyInstantiator(aHwnd);
return result.forget();
}
// a11y is running, so we just resolve the real root accessible.
a11y::Accessible* rootAcc = widget::WinUtils::GetRootAccessibleForHWND(aHwnd);
if (!rootAcc || !rootAcc->IsRoot()) {
return nullptr;
}
// Subtle: rootAcc might still be wrapped by a LazyInstantiator, but we
// don't need LazyInstantiator's capabilities anymore (since a11y is already
// running). We can bypass LazyInstantiator by retrieving the internal
// unknown (which is not wrapped by the LazyInstantiator) and then querying
// that for IID_IAccessible.
a11y::RootAccessibleWrap* rootWrap =
static_cast<a11y::RootAccessibleWrap*>(rootAcc);
RefPtr<IUnknown> punk(rootWrap->GetInternalUnknown());
MOZ_ASSERT(punk);
if (!punk) {
return nullptr;
}
punk->QueryInterface(IID_IAccessible, getter_AddRefs(result));
return result.forget();
}
/**
* When marshaling an interface, COM makes a whole bunch of QueryInterface
* calls to determine what kind of marshaling the interface supports. We need
* to handle those queries without instantiating a11y, so we temporarily
* disable passing through of QueryInterface calls to a11y. Once we know that
* COM is finished marshaling, we call EnableBlindAggregation to re-enable
* QueryInterface passthrough.
*/
/* static */
void
LazyInstantiator::EnableBlindAggregation(HWND aHwnd)
{
LazyInstantiator* existingInstantiator =
reinterpret_cast<LazyInstantiator*>(::GetProp(aHwnd, kLazyInstantiatorProp));
if (!existingInstantiator) {
return;
}
existingInstantiator->mAllowBlindAggregation = true;
}
LazyInstantiator::LazyInstantiator(HWND aHwnd)
: mHwnd(aHwnd)
, mAllowBlindAggregation(false)
, mWeakRootAccWrap(nullptr)
, mWeakAccessible(nullptr)
, mWeakDispatch(nullptr)
{
MOZ_ASSERT(aHwnd);
// Assign ourselves as the designated LazyInstantiator for aHwnd
DebugOnly<BOOL> setPropOk = ::SetProp(aHwnd, kLazyInstantiatorProp,
reinterpret_cast<HANDLE>(this));
MOZ_ASSERT(setPropOk);
}
LazyInstantiator::~LazyInstantiator()
{
if (mRealRootUnk) {
// Disconnect ourselves from the root accessible.
RefPtr<IUnknown> dummy(mWeakRootAccWrap->Aggregate(nullptr));
}
ClearProp();
}
void
LazyInstantiator::ClearProp()
{
// Remove ourselves as the designated LazyInstantiator for mHwnd
DebugOnly<HANDLE> removedProp = ::RemoveProp(mHwnd, kLazyInstantiatorProp);
MOZ_ASSERT(!removedProp ||
reinterpret_cast<LazyInstantiator*>(removedProp.value) == this);
}
/**
* Given the remote client's thread ID, resolve its execuatable image name.
*/
bool
LazyInstantiator::GetClientExecutableName(const DWORD aClientTid,
nsIFile** aOutClientExe)
{
nsAutoHandle callingThread(::OpenThread(THREAD_QUERY_LIMITED_INFORMATION,
FALSE, aClientTid));
if (!callingThread) {
return false;
}
DWORD callingPid = ::GetProcessIdOfThread(callingThread);
nsAutoHandle callingProcess(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
FALSE, callingPid));
if (!callingProcess) {
return false;
}
DWORD bufLen = MAX_PATH;
UniquePtr<wchar_t[]> buf;
while (true) {
buf = MakeUnique<wchar_t[]>(bufLen);
if (::QueryFullProcessImageName(callingProcess, 0, buf.get(), &bufLen)) {
break;
}
DWORD lastError = ::GetLastError();
MOZ_ASSERT(lastError == ERROR_INSUFFICIENT_BUFFER);
if (lastError != ERROR_INSUFFICIENT_BUFFER) {
return false;
}
bufLen *= 2;
}
nsCOMPtr<nsIFile> file;
nsresult rv = NS_NewLocalFile(nsDependentString(buf.get(), bufLen), false,
getter_AddRefs(file));
if (NS_FAILED(rv)) {
return false;
}
file.forget(aOutClientExe);
return NS_SUCCEEDED(rv);
}
/**
* Given a remote client's thread ID, determine whether we should proceed with
* a11y instantiation. This is where telemetry should be gathered and any
* potential blocking of unwanted a11y clients should occur.
*
* @return true if we should instantiate a11y
*/
bool
LazyInstantiator::ShouldInstantiate(const DWORD aClientTid)
{
if (!aClientTid) {
// aClientTid == 0 implies that this is either an in-process call, or else
// we failed to retrieve information about the remote caller.
// We should always default to instantiating a11y in this case.
return true;
}
nsCOMPtr<nsIFile> clientExe;
GetClientExecutableName(aClientTid, getter_AddRefs(clientExe));
// Blocklist checks should go here. return false if we should not instantiate.
/*
if (ClientShouldBeBlocked(clientExe)) {
return false;
}
*/
#if defined(MOZ_TELEMETRY_REPORTING)
if (!mTelemetryThread) {
// Call GatherTelemetry on a background thread because it does I/O on
// the executable file to retrieve version information.
nsCOMPtr<nsIRunnable> runnable(
NewRunnableMethod<nsCOMPtr<nsIFile>>(this,
&LazyInstantiator::GatherTelemetry,
clientExe));
NS_NewThread(getter_AddRefs(mTelemetryThread), runnable);
}
#endif // defined(MOZ_TELEMETRY_REPORTING)
return true;
}
#if defined(MOZ_TELEMETRY_REPORTING)
/**
* Appends version information in the format "|a.b.c.d".
* If there is no version information, we append nothing.
*/
void
LazyInstantiator::AppendVersionInfo(nsIFile* aClientExe,
nsAString& aStrToAppend)
{
MOZ_ASSERT(!NS_IsMainThread());
nsAutoString fullPath;
nsresult rv = aClientExe->GetPath(fullPath);
if (NS_FAILED(rv)) {
return;
}
DWORD verInfoSize = ::GetFileVersionInfoSize(fullPath.get(), nullptr);
if (!verInfoSize) {
return;
}
auto verInfoBuf = MakeUnique<BYTE[]>(verInfoSize);
if (!::GetFileVersionInfo(fullPath.get(), 0, verInfoSize, verInfoBuf.get())) {
return;
}
VS_FIXEDFILEINFO* fixedInfo = nullptr;
UINT fixedInfoLen = 0;
if (!::VerQueryValue(verInfoBuf.get(), L"\\", (LPVOID*) &fixedInfo,
&fixedInfoLen)) {
return;
}
uint32_t major = HIWORD(fixedInfo->dwFileVersionMS);
uint32_t minor = LOWORD(fixedInfo->dwFileVersionMS);
uint32_t patch = HIWORD(fixedInfo->dwFileVersionLS);
uint32_t build = LOWORD(fixedInfo->dwFileVersionLS);
aStrToAppend.AppendLiteral(u"|");
NS_NAMED_LITERAL_STRING(dot, ".");
aStrToAppend.AppendInt(major);
aStrToAppend.Append(dot);
aStrToAppend.AppendInt(minor);
aStrToAppend.Append(dot);
aStrToAppend.AppendInt(patch);
aStrToAppend.Append(dot);
aStrToAppend.AppendInt(build);
}
void
LazyInstantiator::GatherTelemetry(nsIFile* aClientExe)
{
MOZ_ASSERT(!NS_IsMainThread());
nsAutoString value;
nsresult rv = aClientExe->GetLeafName(value);
if (NS_SUCCEEDED(rv)) {
AppendVersionInfo(aClientExe, value);
}
// Now that we've (possibly) obtained version info, send the resulting
// string back to the main thread to accumulate in telemetry.
NS_DispatchToMainThread(NewNonOwningRunnableMethod<nsString>(this,
&LazyInstantiator::AccumulateTelemetry, value));
}
void
LazyInstantiator::AccumulateTelemetry(const nsString& aValue)
{
MOZ_ASSERT(NS_IsMainThread());
if (!aValue.IsEmpty()) {
Telemetry::ScalarSet(Telemetry::ScalarID::A11Y_INSTANTIATORS, aValue);
}
mTelemetryThread->Shutdown();
mTelemetryThread = nullptr;
}
#endif // defined(MOZ_TELEMETRY_REPORTING)
RootAccessibleWrap*
LazyInstantiator::ResolveRootAccWrap()
{
Accessible* acc = widget::WinUtils::GetRootAccessibleForHWND(mHwnd);
if (!acc || !acc->IsRoot()) {
return nullptr;
}
return static_cast<RootAccessibleWrap*>(acc);
}
/**
* With COM aggregation, the aggregated inner object usually delegates its
* reference counting to the outer object. In other words, we would expect
* mRealRootUnk to delegate its AddRef() and Release() to this LazyInstantiator.
*
* This scheme will not work in our case because the RootAccessibleWrap is
* cycle-collected!
*
* Instead, once a LazyInstantiator aggregates a RootAccessibleWrap, we transfer
* our strong references into mRealRootUnk. Any future calls to AddRef or
* Release now operate on mRealRootUnk instead of our intrinsic reference
* count. This is a bit strange, but it is the only way for these objects to
* share their reference count in a way that is safe for cycle collection.
*
* How do we know when it is safe to destroy ourselves? In
* LazyInstantiator::Release, we examine the result of mRealRootUnk->Release().
* If mRealRootUnk's resulting refcount is 1, then we know that the only
* remaining reference to mRealRootUnk is the mRealRootUnk reference itself (and
* thus nobody else holds references to either this or mRealRootUnk). Therefore
* we may now delete ourselves.
*/
void
LazyInstantiator::TransplantRefCnt()
{
MOZ_ASSERT(mRefCnt > 0);
MOZ_ASSERT(mRealRootUnk);
while (mRefCnt > 0) {
mRealRootUnk.get()->AddRef();
--mRefCnt;
}
}
HRESULT
LazyInstantiator::MaybeResolveRoot()
{
MOZ_ASSERT(NS_IsMainThread());
if (mWeakAccessible) {
return S_OK;
}
if (GetAccService() ||
ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) {
mWeakRootAccWrap = ResolveRootAccWrap();
if (!mWeakRootAccWrap) {
return E_POINTER;
}
// Wrap ourselves around the root accessible wrap
mRealRootUnk = mWeakRootAccWrap->Aggregate(static_cast<IAccessible*>(this));
if (!mRealRootUnk) {
return E_FAIL;
}
// Move our strong references into the root accessible (see the comments
// above TransplantRefCnt for explanation).
TransplantRefCnt();
// Now obtain mWeakAccessible which we use to forward our incoming calls
// to the real accesssible.
HRESULT hr = mRealRootUnk->QueryInterface(IID_IAccessible,
(void**) &mWeakAccessible);
if (FAILED(hr)) {
return hr;
}
// mWeakAccessible is weak, so don't hold a strong ref
mWeakAccessible->Release();
// Now that a11y is running, we don't need to remain registered with our
// HWND anymore.
ClearProp();
return S_OK;
}
// If we don't want a real root, let's resolve a fake one.
const WPARAM flags = 0xFFFFFFFFUL;
// Synthesize a WM_GETOBJECT request to obtain a system-implemented
// IAccessible object from DefWindowProc
LRESULT lresult = ::DefWindowProc(mHwnd, WM_GETOBJECT, flags,
static_cast<LPARAM>(OBJID_CLIENT));
HRESULT hr = ObjectFromLresult(lresult, IID_IAccessible, flags,
getter_AddRefs(mRealRootUnk));
if (FAILED(hr)) {
return hr;
}
if (!mRealRootUnk) {
return E_NOTIMPL;
}
hr = mRealRootUnk->QueryInterface(IID_IAccessible,
(void**) &mWeakAccessible);
if (FAILED(hr)) {
return hr;
}
// mWeakAccessible is weak, so don't hold a strong ref
mWeakAccessible->Release();
return S_OK;
}
#define RESOLVE_ROOT \
{ \
HRESULT hr = MaybeResolveRoot(); \
if (FAILED(hr)) { \
return hr; \
} \
}
IMPL_IUNKNOWN_QUERY_HEAD(LazyInstantiator)
IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, IAccessible)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessible)
IMPL_IUNKNOWN_QUERY_IFACE(IDispatch)
IMPL_IUNKNOWN_QUERY_IFACE(IServiceProvider)
// See EnableBlindAggregation for comments.
if (!mAllowBlindAggregation) {
return E_NOINTERFACE;
}
// If the client queries for an interface that LazyInstantiator does not
// intrinsically support, then we must resolve the root accessible and pass
// on the QueryInterface call to mRealRootUnk.
RESOLVE_ROOT
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mRealRootUnk)
ULONG
LazyInstantiator::AddRef()
{
// Always delegate refcounting to mRealRootUnk when it exists
if (mRealRootUnk) {
return mRealRootUnk.get()->AddRef();
}
return ++mRefCnt;
}
ULONG
LazyInstantiator::Release()
{
ULONG result;
// Always delegate refcounting to mRealRootUnk when it exists
if (mRealRootUnk) {
result = mRealRootUnk.get()->Release();
if (result == 1) {
// mRealRootUnk is the only strong reference left, so nothing else holds
// a strong reference to us. Drop result to zero so that we destroy
// ourselves (See the comments above LazyInstantiator::TransplantRefCnt
// for more info).
--result;
}
} else {
result = --mRefCnt;
}
if (!result) {
delete this;
}
return result;
}
/**
* Create a standard IDispatch implementation. mStdDispatch will translate any
* IDispatch::Invoke calls into real IAccessible calls.
*/
HRESULT
LazyInstantiator::ResolveDispatch()
{
if (mWeakDispatch) {
return S_OK;
}
// The IAccessible typelib is embedded in oleacc.dll's resources.
auto typelib = mscom::RegisterTypelib(L"oleacc.dll",
mscom::RegistrationFlags::eUseSystemDirectory);
if (!typelib) {
return E_UNEXPECTED;
}
// Extract IAccessible's type info
RefPtr<ITypeInfo> accTypeInfo;
HRESULT hr = typelib->GetTypeInfoForGuid(IID_IAccessible,
getter_AddRefs(accTypeInfo));
if (FAILED(hr)) {
return hr;
}
// Now create the standard IDispatch for IAccessible
hr = ::CreateStdDispatch(static_cast<IAccessible*>(this),
static_cast<IAccessible*>(this),
accTypeInfo, getter_AddRefs(mStdDispatch));
if (FAILED(hr)) {
return hr;
}
hr = mStdDispatch->QueryInterface(IID_IDispatch, (void**)&mWeakDispatch);
if (FAILED(hr)) {
return hr;
}
// WEAK reference
mWeakDispatch->Release();
return S_OK;
}
#define RESOLVE_IDISPATCH \
{ \
HRESULT hr = ResolveDispatch(); \
if (FAILED(hr)) { \
return hr; \
} \
}
/**
* The remaining methods implement IDispatch, IAccessible, and IServiceProvider,
* lazily resolving the real a11y objects and passing the call through.
*/
HRESULT
LazyInstantiator::GetTypeInfoCount(UINT* pctinfo)
{
RESOLVE_IDISPATCH;
return mWeakDispatch->GetTypeInfoCount(pctinfo);
}
HRESULT
LazyInstantiator::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
RESOLVE_IDISPATCH;
return mWeakDispatch->GetTypeInfo(iTInfo, lcid, ppTInfo);
}
HRESULT
LazyInstantiator::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId)
{
RESOLVE_IDISPATCH;
return mWeakDispatch->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
}
HRESULT
LazyInstantiator::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
UINT* puArgErr)
{
RESOLVE_IDISPATCH;
return mWeakDispatch->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams,
pVarResult, pExcepInfo, puArgErr);
}
HRESULT
LazyInstantiator::get_accParent(IDispatch **ppdispParent)
{
RESOLVE_ROOT;
return mWeakAccessible->get_accParent(ppdispParent);
}
HRESULT
LazyInstantiator::get_accChildCount(long *pcountChildren)
{
if (!pcountChildren) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accChildCount(pcountChildren);
}
HRESULT
LazyInstantiator::get_accChild(VARIANT varChild, IDispatch **ppdispChild)
{
if (!ppdispChild) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accChild(varChild, ppdispChild);
}
HRESULT
LazyInstantiator::get_accName(VARIANT varChild, BSTR *pszName)
{
if (!pszName) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accName(varChild, pszName);
}
HRESULT
LazyInstantiator::get_accValue(VARIANT varChild, BSTR *pszValue)
{
if (!pszValue) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accValue(varChild, pszValue);
}
HRESULT
LazyInstantiator::get_accDescription(VARIANT varChild, BSTR *pszDescription)
{
if (!pszDescription) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accDescription(varChild, pszDescription);
}
HRESULT
LazyInstantiator::get_accRole(VARIANT varChild, VARIANT *pvarRole)
{
if (!pvarRole) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accRole(varChild, pvarRole);
}
HRESULT
LazyInstantiator::get_accState(VARIANT varChild, VARIANT *pvarState)
{
if (!pvarState) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accState(varChild, pvarState);
}
HRESULT
LazyInstantiator::get_accHelp(VARIANT varChild, BSTR *pszHelp)
{
return E_NOTIMPL;
}
HRESULT
LazyInstantiator::get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild,
long *pidTopic)
{
return E_NOTIMPL;
}
HRESULT
LazyInstantiator::get_accKeyboardShortcut(VARIANT varChild,
BSTR *pszKeyboardShortcut)
{
if (!pszKeyboardShortcut) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
}
HRESULT
LazyInstantiator::get_accFocus(VARIANT *pvarChild)
{
if (!pvarChild) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accFocus(pvarChild);
}
HRESULT
LazyInstantiator::get_accSelection(VARIANT *pvarChildren)
{
if (!pvarChildren) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accSelection(pvarChildren);
}
HRESULT
LazyInstantiator::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
{
if (!pszDefaultAction) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->get_accDefaultAction(varChild, pszDefaultAction);
}
HRESULT
LazyInstantiator::accSelect(long flagsSelect, VARIANT varChild)
{
RESOLVE_ROOT;
return mWeakAccessible->accSelect(flagsSelect, varChild);
}
HRESULT
LazyInstantiator::accLocation(long *pxLeft, long *pyTop, long *pcxWidth,
long *pcyHeight, VARIANT varChild)
{
RESOLVE_ROOT;
return mWeakAccessible->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild);
}
HRESULT
LazyInstantiator::accNavigate(long navDir, VARIANT varStart,
VARIANT *pvarEndUpAt)
{
return E_NOTIMPL;
}
HRESULT
LazyInstantiator::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
{
if (!pvarChild) {
return E_INVALIDARG;
}
RESOLVE_ROOT;
return mWeakAccessible->accHitTest(xLeft, yTop, pvarChild);
}
HRESULT
LazyInstantiator::accDoDefaultAction(VARIANT varChild)
{
RESOLVE_ROOT;
return mWeakAccessible->accDoDefaultAction(varChild);
}
HRESULT
LazyInstantiator::put_accName(VARIANT varChild, BSTR szName)
{
return E_NOTIMPL;
}
HRESULT
LazyInstantiator::put_accValue(VARIANT varChild, BSTR szValue)
{
return E_NOTIMPL;
}
HRESULT
LazyInstantiator::QueryService(REFGUID aServiceId, REFIID aServiceIid,
void** aOutInterface)
{
if (!aOutInterface) {
return E_INVALIDARG;
}
*aOutInterface = nullptr;
RESOLVE_ROOT;
RefPtr<IServiceProvider> servProv;
HRESULT hr = mRealRootUnk->QueryInterface(IID_IServiceProvider,
getter_AddRefs(servProv));
if (FAILED(hr)) {
return hr;
}
return servProv->QueryService(aServiceId, aServiceIid, aOutInterface);
}
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,133 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_a11y_LazyInstantiator_h
#define mozilla_a11y_LazyInstantiator_h
#include "IUnknownImpl.h"
#include "mozilla/RefPtr.h"
#include "nsString.h"
#if defined(MOZ_TELEMETRY_REPORTING)
#include "nsThreadUtils.h"
#endif // defined(MOZ_TELEMETRY_REPORTING)
#include <oleacc.h>
class nsIFile;
namespace mozilla {
namespace a11y {
class RootAccessibleWrap;
/**
* LazyInstantiator is an IAccessible that initially acts as a placeholder.
* The a11y service is not actually started until two conditions are met:
*
* (1) A method is called on the LazyInstantiator that would require a11y
* services in order to fulfill; and
* (2) LazyInstantiator::ShouldInstantiate returns true.
*/
class LazyInstantiator final : public IAccessible
, public IServiceProvider
{
public:
static already_AddRefed<IAccessible> GetRootAccessible(HWND aHwnd);
static void EnableBlindAggregation(HWND aHwnd);
// IUnknown
STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) override;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) override;
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId) override;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
// IAccessible
STDMETHODIMP get_accParent(IDispatch **ppdispParent) override;
STDMETHODIMP get_accChildCount(long *pcountChildren) override;
STDMETHODIMP get_accChild(VARIANT varChild, IDispatch **ppdispChild) override;
STDMETHODIMP get_accName(VARIANT varChild, BSTR *pszName) override;
STDMETHODIMP get_accValue(VARIANT varChild, BSTR *pszValue) override;
STDMETHODIMP get_accDescription(VARIANT varChild, BSTR *pszDescription) override;
STDMETHODIMP get_accRole(VARIANT varChild, VARIANT *pvarRole) override;
STDMETHODIMP get_accState(VARIANT varChild, VARIANT *pvarState) override;
STDMETHODIMP get_accHelp(VARIANT varChild, BSTR *pszHelp) override;
STDMETHODIMP get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic) override;
STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut) override;
STDMETHODIMP get_accFocus(VARIANT *pvarChild) override;
STDMETHODIMP get_accSelection(VARIANT *pvarChildren) override;
STDMETHODIMP get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction) override;
STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override;
STDMETHODIMP accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild) override;
STDMETHODIMP accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt) override;
STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT *pvarChild) override;
STDMETHODIMP accDoDefaultAction(VARIANT varChild) override;
STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override;
STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override;
// IServiceProvider
STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aServiceIid, void** aOutInterface) override;
private:
explicit LazyInstantiator(HWND aHwnd);
~LazyInstantiator();
bool ShouldInstantiate(const DWORD aClientTid);
bool GetClientExecutableName(const DWORD aClientTid, nsIFile** aOutClientExe);
#if defined(MOZ_TELEMETRY_REPORTING)
void AppendVersionInfo(nsIFile* aClientExe, nsAString& aStrToAppend);
void GatherTelemetry(nsIFile* aClientExe);
void AccumulateTelemetry(const nsString& aValue);
#endif // defined(MOZ_TELEMETRY_REPORTING)
/**
* @return S_OK if we have a valid mRealRoot to invoke methods on
*/
HRESULT MaybeResolveRoot();
/**
* @return S_OK if we have a valid mWeakDispatch to invoke methods on
*/
HRESULT ResolveDispatch();
RootAccessibleWrap* ResolveRootAccWrap();
void TransplantRefCnt();
void ClearProp();
private:
mozilla::a11y::AutoRefCnt mRefCnt;
HWND mHwnd;
bool mAllowBlindAggregation;
RefPtr<IUnknown> mRealRootUnk;
RefPtr<IUnknown> mStdDispatch;
/**
* mWeakRootAccWrap, mWeakAccessible and mWeakDispatch are weak because they
* are interfaces that come from objects that we aggregate. Aggregated object
* interfaces share refcount methods with ours, so if we were to hold strong
* references to them, we would be holding strong references to ourselves,
* creating a cycle.
*/
RootAccessibleWrap* mWeakRootAccWrap;
IAccessible* mWeakAccessible;
IDispatch* mWeakDispatch;
#if defined(MOZ_TELEMETRY_REPORTING)
nsCOMPtr<nsIThread> mTelemetryThread;
#endif // defined(MOZ_TELEMETRY_REPORTING)
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_LazyInstantiator_h

Просмотреть файл

@ -14,9 +14,10 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// Constructor/destructor
RootAccessibleWrap::
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
RootAccessible(aDocument, aPresShell)
RootAccessibleWrap::RootAccessibleWrap(nsIDocument* aDocument,
nsIPresShell* aPresShell)
: RootAccessible(aDocument, aPresShell)
, mOuter(&mInternalUnknown)
{
}
@ -24,6 +25,62 @@ RootAccessibleWrap::~RootAccessibleWrap()
{
}
////////////////////////////////////////////////////////////////////////////////
// Aggregated IUnknown
HRESULT
RootAccessibleWrap::InternalQueryInterface(REFIID aIid, void** aOutInterface)
{
if (!aOutInterface) {
return E_INVALIDARG;
}
// InternalQueryInterface should always return its internal unknown
// when queried for IID_IUnknown...
if (aIid == IID_IUnknown) {
RefPtr<IUnknown> punk(&mInternalUnknown);
punk.forget(aOutInterface);
return S_OK;
}
// ...Otherwise we pass through to the base COM implementation of
// QueryInterface which is provided by DocAccessibleWrap.
return DocAccessibleWrap::QueryInterface(aIid, aOutInterface);
}
ULONG
RootAccessibleWrap::InternalAddRef()
{
return DocAccessible::AddRef();
}
ULONG
RootAccessibleWrap::InternalRelease()
{
return DocAccessible::Release();
}
already_AddRefed<IUnknown>
RootAccessibleWrap::Aggregate(IUnknown* aOuter)
{
MOZ_ASSERT(mOuter && (mOuter == &mInternalUnknown || mOuter == aOuter || !aOuter));
if (!aOuter) {
// If there is no aOuter then we should always set mOuter to
// mInternalUnknown. This is standard COM aggregation stuff.
mOuter = &mInternalUnknown;
return nullptr;
}
mOuter = aOuter;
return GetInternalUnknown();
}
already_AddRefed<IUnknown>
RootAccessibleWrap::GetInternalUnknown()
{
RefPtr<IUnknown> result(&mInternalUnknown);
return result.forget();
}
////////////////////////////////////////////////////////////////////////////////
// RootAccessible

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef mozilla_a11y_RootAccessibleWrap_h__
#define mozilla_a11y_RootAccessibleWrap_h__
#include "mozilla/mscom/Aggregation.h"
#include "RootAccessible.h"
namespace mozilla {
@ -19,6 +20,29 @@ public:
// RootAccessible
virtual void DocumentActivated(DocAccessible* aDocument);
/**
* This method enables a RootAccessibleWrap to be wrapped by a
* LazyInstantiator.
*
* @param aOuter The IUnknown of the object that is wrapping this
* RootAccessibleWrap, or nullptr to unwrap the aOuter from
* a previous call.
* @return This objects own IUnknown (as opposed to aOuter's IUnknown).
*/
already_AddRefed<IUnknown> Aggregate(IUnknown* aOuter);
/**
* @return This object's own IUnknown, as opposed to its wrapper's IUnknown
* which is what would be returned by QueryInterface(IID_IUnknown).
*/
already_AddRefed<IUnknown> GetInternalUnknown();
private:
// DECLARE_AGGREGATABLE declares the internal IUnknown methods as well as
// mInternalUnknown.
DECLARE_AGGREGATABLE(RootAccessibleWrap);
IUnknown* mOuter;
};
} // namespace a11y

Просмотреть файл

@ -13,6 +13,7 @@ EXPORTS.mozilla.a11y += [
'Compatibility.h',
'HyperTextAccessibleWrap.h',
'IDSet.h',
'LazyInstantiator.h',
'MsaaIdGenerator.h',
'nsWinUtils.h',
]
@ -37,8 +38,10 @@ UNIFIED_SOURCES += [
'TextLeafAccessibleWrap.cpp',
]
# This file cannot be built in unified mode because it includes ISimpleDOMNode_i.c.
SOURCES += [
# This file cannot be built in unified mode because it redefines _WIN32_WINNT
'LazyInstantiator.cpp',
# This file cannot be built in unified mode because it includes ISimpleDOMNode_i.c.
'ServiceProvider.cpp',
]

Просмотреть файл

@ -70,7 +70,7 @@ function startup(reason, options) {
// Run the addon even in case of error (best effort approach)
require('../l10n/loader').
load(rootURI).
then(null, function failure(error) {
catch(function failure(error) {
if (!isNative)
console.info("Error while loading localization: " + error.message);
}).
@ -81,7 +81,7 @@ function startup(reason, options) {
return ready;
}).then(function() {
run(options);
}).then(null, console.exception);
}).catch(console.exception);
return void 0; // otherwise we raise a warning, see bug 910304
});
}

Просмотреть файл

@ -15,7 +15,7 @@ lazyRequire(this, "../core/promise", "resolve");
function parseJsonURI(uri) {
return readURI(uri).
then(JSON.parse).
then(null, function (error) {
catch(function (error) {
throw Error("Failed to parse locale file:\n" + uri + "\n" + error);
});
}

Просмотреть файл

@ -43,7 +43,7 @@ exports.testDebugger = function(assert, done) {
then(_ => { assert.pass('closeConnection called') }).
then(_ => { tab.close() }).
then(done).
then(null, aError => {
catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
}

Просмотреть файл

@ -50,7 +50,7 @@ exports.testDebugger = function(assert, done) {
then(_ => { assert.pass('closeConnection called') }).
then(_ => { tab.close() }).
then(done).
then(null, aError => {
catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
}

Просмотреть файл

@ -66,7 +66,7 @@ exports.testBookmarksCreateFail = function (assert, done) {
group: bmsrv.unfiledBookmarksFolder
}];
all(items.map(function (item) {
return send('sdk-places-bookmarks-create', item).then(null, function (reason) {
return send('sdk-places-bookmarks-create', item).catch(function (reason) {
assert.ok(reason, 'bookmark create should fail');
});
})).then(done);

Просмотреть файл

@ -233,14 +233,14 @@ exports["test PWPB Selection Listener"] = function(assert, done) {
closeWindow(window).
then(loader.unload).
then(done).
then(null, assert.fail);
catch(assert.fail);
});
});
return window;
}).
then(selectContentFirstDiv).
then(dispatchSelectionEvent).
then(null, assert.fail);
catch(assert.fail);
};
exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
@ -263,14 +263,14 @@ exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
closeWindow(window).
then(loader.unload).
then(done).
then(null, assert.fail);
catch(assert.fail);
});
});
return window;
}).
then(selectTextarea).
then(dispatchOnSelectEvent).
then(null, assert.fail);
catch(assert.fail);
};
exports["test PWPB Single DOM Selection"] = function(assert, done) {
@ -304,7 +304,7 @@ exports["test PWPB Single DOM Selection"] = function(assert, done) {
"One iterable selection");
return closeWindow(window);
}).then(loader.unload).then(done).then(null, assert.fail);
}).then(loader.unload).then(done).catch(assert.fail);
}
exports["test PWPB Textarea Selection"] = function(assert, done) {
@ -340,7 +340,7 @@ exports["test PWPB Textarea Selection"] = function(assert, done) {
"One iterable selection");
return closeWindow(window);
}).then(loader.unload).then(done).then(null, assert.fail);
}).then(loader.unload).then(done).catch(assert.fail);
};
exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done) {
@ -380,7 +380,7 @@ exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done)
"Two iterable selections");
return closeWindow(window);
}).then(loader.unload).then(done).then(null, assert.fail);
}).then(loader.unload).then(done).catch(assert.fail);
};
exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
@ -417,7 +417,7 @@ exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
"One iterable selection");
return closeWindow(window);
}).then(loader.unload).then(done).then(null, assert.fail);
}).then(loader.unload).then(done).catch(assert.fail);
};
// If the platform doesn't support the PBPW, we're replacing PBPW tests

Просмотреть файл

@ -40,7 +40,7 @@ exports.testSideBarIsInNewPrivateWindows = function(assert, done) {
assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
return close(window);
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
}
// Disabled in order to land other fixes, see bug 910647 for further details.
@ -142,8 +142,8 @@ exports.testDestroyEdgeCaseBugWithPrivateWindow = function(assert, done) {
sidebar.show();
assert.pass('showing the sidebar');
}).then(null, assert.fail);
}).then(null, assert.fail);
}).catch(assert.fail);
}).catch(assert.fail);
}
exports.testShowInPrivateWindow = function(assert, done) {
@ -188,12 +188,12 @@ exports.testShowInPrivateWindow = function(assert, done) {
null,
'the menuitem on the old window dne');
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
},
function bad() {
assert.fail('a successful show should not happen here..');
});
}).then(null, assert.fail);
}).catch(assert.fail);
}
// If the module doesn't support the app we're being run in, require() will

Просмотреть файл

@ -18,10 +18,10 @@ exports.testOpenTabWithPrivateActiveWindowNoIsPrivateOption = function(assert, d
url: 'about:blank',
onOpen: function(tab) {
assert.ok(isPrivate(tab), 'new tab is private');
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
})
}).then(null, assert.fail);
}).catch(assert.fail);
}
exports.testOpenTabWithNonPrivateActiveWindowNoIsPrivateOption = function(assert, done) {
@ -34,10 +34,10 @@ exports.testOpenTabWithNonPrivateActiveWindowNoIsPrivateOption = function(assert
url: 'about:blank',
onOpen: function(tab) {
assert.equal(isPrivate(tab), false, 'new tab is not private');
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
})
}).then(null, assert.fail);
}).catch(assert.fail);
}
exports.testOpenTabWithPrivateActiveWindowWithIsPrivateOptionTrue = function(assert, done) {
@ -51,10 +51,10 @@ exports.testOpenTabWithPrivateActiveWindowWithIsPrivateOptionTrue = function(ass
isPrivate: true,
onOpen: function(tab) {
assert.ok(isPrivate(tab), 'new tab is private');
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
})
}).then(null, assert.fail);
}).catch(assert.fail);
}
exports.testOpenTabWithNonPrivateActiveWindowWithIsPrivateOptionFalse = function(assert, done) {
@ -68,8 +68,8 @@ exports.testOpenTabWithNonPrivateActiveWindowWithIsPrivateOptionFalse = function
isPrivate: false,
onOpen: function(tab) {
assert.equal(isPrivate(tab), false, 'new tab is not private');
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
})
}).then(null, assert.fail);
}).catch(assert.fail);
}

Просмотреть файл

@ -74,7 +74,7 @@ exports.testWindowTrackerIgnoresPrivateWindows = function(assert, done) {
return close(window);
});
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
// Test setting activeWIndow and onFocus for private windows
@ -146,7 +146,7 @@ exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, don
assert.strictEqual(winUtils.activeWindow, browserWindow,
"Correct active window when pb mode is supported [4]");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
];
@ -236,5 +236,5 @@ exports.testWindowIteratorPrivateDefault = function(assert, done) {
assert.equal(windows(null, { includePrivate: true }).length, 2);
return close(window);
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
};

Просмотреть файл

@ -75,7 +75,7 @@ exports.testBrowserWindowCreationOnActivate = function(assert, done) {
open().then(function(window) {
assert.ok(gotActivate, "Received activate event");
return close(window);
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
}
// TEST: tab unloader
@ -176,7 +176,7 @@ exports.testTabPropertiesInNewWindow = function(assert, done) {
let count = 0;
function onReadyOrLoad (tab) {
if (count++) {
close(getOwnerWindow(viewFor(tab))).then(done).then(null, assert.fail);
close(getOwnerWindow(viewFor(tab))).then(done).catch(assert.fail);
}
}
@ -269,7 +269,7 @@ exports.testTabContentTypeAndReload = function(assert, done) {
}
else {
assert.equal(tab.contentType, "text/xml");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
}
});
@ -294,7 +294,7 @@ exports.testTabsIteratorAndLength = function(assert, done) {
assert.equal(count, startCount + 3, "iterated tab count matches");
assert.equal(startCount + 3, tabs.length, "iterated tab count matches length property");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
});
});
@ -311,7 +311,7 @@ exports.testTabLocation = function(assert, done) {
return;
tabs.removeListener('ready', onReady);
assert.pass("tab.load() loaded the correct url");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
});
tabs.open({
@ -365,10 +365,10 @@ exports.testTabMove = function(assert, done) {
assert.equal(tab.index, 1, "tab index before move matches");
tab.index = 0;
assert.equal(tab.index, 0, "tab index after move matches");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
exports.testIgnoreClosing = function*(assert) {
@ -481,7 +481,7 @@ exports.testOpenInNewWindow = function(assert, done) {
assert.equal(tabs.activeTab.url, url, "URL of activeTab matches");
return close(newWindow).then(done);
}).then(null, assert.fail);
}).catch(assert.fail);
}
});
@ -502,7 +502,7 @@ exports.testOpenInNewWindowOnOpen = function(assert, done) {
assert.equal(windows().length, startWindowCount + 1, "a new window was opened");
assert.equal(getMostRecentBrowserWindow(), newWindow, "new window is active");
close(newWindow).then(done).then(null, assert.fail);
close(newWindow).then(done).catch(assert.fail);
});
}
});
@ -525,11 +525,11 @@ exports.testTabsEvent_onOpen = function(assert, done) {
assert.equal(++eventCount, 2, "both listeners notified");
tabs.removeListener('open', listener1);
tabs.removeListener('open', listener2);
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
});
tabs.open(url);
}).then(null, assert.fail);
}).catch(assert.fail);
};
// TEST: onClose event handler
@ -621,7 +621,7 @@ exports.testTabsEvent_onCloseWindow = function(assert, done) {
onOpen: testCasePossiblyLoaded,
onClose: endTest
});
}).then(null, assert.fail);
}).catch(assert.fail);
}
// TEST: onReady event handler
@ -645,7 +645,7 @@ exports.testTabsEvent_onReady = function(assert, done) {
});
tabs.open(url);
}).then(null, assert.fail);
}).catch(assert.fail);
};
// TEST: onActivate event handler
@ -665,11 +665,11 @@ exports.testTabsEvent_onActivate = function(assert, done) {
assert.equal(++eventCount, 2, "both listeners notified");
tabs.removeListener('activate', listener1);
tabs.removeListener('activate', listener2);
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
});
tabs.open(url);
}).then(null, assert.fail);
}).catch(assert.fail);
};
// onDeactivate event handler
@ -726,11 +726,11 @@ exports.testTabsEvent_pinning = function(assert, done) {
tabs.on('unpinned', function onUnpinned(tab) {
tabs.removeListener('unpinned', onUnpinned);
assert.ok(!tab.isPinned, "notified tab is not pinned");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
});
tabs.open(url);
}).then(null, assert.fail);
}).catch(assert.fail);
};
// TEST: per-tab event handlers
@ -840,9 +840,9 @@ exports.testAttachOnMultipleDocuments = function (assert, done) {
assert.pass("Got all detach events");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
}).then(null, assert.fail);
}).catch(assert.fail);
}
@ -866,12 +866,12 @@ exports.testAttachWrappers = function (assert, done) {
onMessage: function (msg) {
assert.equal(msg, true, "Worker has wrapped objects ("+count+")");
if (count++ == 1)
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
});
}
});
}).then(null, assert.fail);
}).catch(assert.fail);
}
/*
@ -931,7 +931,7 @@ exports['test window focus changes active tab'] = function(assert, done) {
return close(win2).then(function() {
assert.pass('window 2 was closed');
return close(win1);
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
}
});
@ -948,7 +948,7 @@ exports['test ready event on new window tab'] = function(assert, done) {
if (tab.url === uri) {
require("sdk/tabs").removeListener("ready", onReady);
assert.pass("ready event was emitted");
close(window).then(done).then(null, assert.fail);
close(window).then(done).catch(assert.fail);
}
});

Просмотреть файл

@ -16,7 +16,7 @@ exports.testReady = function(assert, done) {
loader.unload();
done();
}).then(null, assert.fail);
}).catch(assert.fail);
}
require('sdk/test').run(exports);

Просмотреть файл

@ -66,7 +66,7 @@ exports.testExecOptionsEnvironment = function (assert, done) {
'receives environment option');
done();
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
exports.testExecOptionsTimeout = function (assert, done) {
@ -104,7 +104,7 @@ exports.testExecOptionsTimeout = function (assert, done) {
child.off('close', closeHandler);
done();
}
}).then(null, assert.fail);
}).catch(assert.fail);
};
exports.testExecFileCallbackSuccess = function (assert, done) {
@ -116,7 +116,7 @@ exports.testExecFileCallbackSuccess = function (assert, done) {
assert.equal(stdout.trim(), '--myargs -j -s'.trim(), 'passes in correct arguments');
done();
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
exports.testExecFileCallbackError = function (assert, done) {
@ -143,7 +143,7 @@ exports.testExecFileOptionsEnvironment = function (assert, done) {
'receives environment option');
done();
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
exports.testExecFileOptionsTimeout = function (assert, done) {
@ -181,7 +181,7 @@ exports.testExecFileOptionsTimeout = function (assert, done) {
child.off('close', closeHandler);
done();
}
}).then(null, assert.fail);
}).catch(assert.fail);
};
/**
@ -204,7 +204,7 @@ exports.testExecFileOptionsMaxBufferLargeStdOut = function (assert, done) {
});
stdoutChild.on('exit', exitHandler);
stdoutChild.on('close', closeHandler);
}).then(null, assert.fail);
}).catch(assert.fail);
function exitHandler (code, signal) {
assert.equal(code, null, 'Exit code is null in exit handler');
@ -239,7 +239,7 @@ exports.testExecFileOptionsMaxBufferLargeStdOErr = function (assert, done) {
});
stderrChild.on('exit', exitHandler);
stderrChild.on('close', closeHandler);
}).then(null, assert.fail);
}).catch(assert.fail);
function exitHandler (code, signal) {
assert.equal(code, null, 'Exit code is null in exit handler');
@ -280,7 +280,7 @@ exports.testExecFileOptionsMaxBufferSmallStdOut = function (assert, done) {
});
stdoutChild.on('exit', exitHandler);
stdoutChild.on('close', closeHandler);
}).then(null, assert.fail);
}).catch(assert.fail);
function exitHandler (code, signal) {
// Sometimes the buffer limit is hit before the process closes successfully
@ -331,7 +331,7 @@ exports.testExecFileOptionsMaxBufferSmallStdErr = function (assert, done) {
});
stderrChild.on('exit', exitHandler);
stderrChild.on('close', closeHandler);
}).then(null, assert.fail);
}).catch(assert.fail);
function exitHandler (code, signal) {
// Sometimes the buffer limit is hit before the process closes successfully
@ -377,7 +377,7 @@ exports.testChildExecFileKillSignal = function (assert, done) {
assert.equal(err.signal, 'beepbeep', 'correctly used custom killSignal');
done();
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
exports.testChildProperties = function (assert, done) {
@ -508,7 +508,7 @@ exports.testSpawnOptions = function (assert, done) {
envChild.on('close', envClose);
cwdChild.on('close', cwdClose);
}).then(null, assert.fail);
}).catch(assert.fail);
function envClose () {
assert.equal(envStdout.trim(), 'my-value-test', 'spawn correctly passed in ENV');

Просмотреть файл

@ -237,7 +237,7 @@ for (let variant of variants) {
testLoader(program, assert);
unload(loader);
done();
}).then(null, (reason) => console.error(reason));
}).catch((reason) => console.error(reason));
};
exports[`test require#resolve with relative, dependencies (${variant.description})`] = function(assert, done) {
@ -265,7 +265,7 @@ for (let variant of variants) {
unload(loader);
done();
}).then(null, (reason) => console.error(reason));
}).catch((reason) => console.error(reason));
};
}
@ -309,7 +309,7 @@ exports['test JSM loading'] = function (assert, done) {
assert.equal(jsabsolute, 30, 'JS files resolved from full resource:// work');
}).then(done, console.error);
}).then(null, console.error);
}).catch(console.error);
};
function testLoader (program, assert) {
@ -388,7 +388,7 @@ function loadAddon (uri, map) {
}
});
let program = main(loader);
}).then(null, console.error);
}).catch(console.error);
}
require('sdk/test').run(exports);

Просмотреть файл

@ -1021,7 +1021,7 @@ exports['test panel CSS'] = function(assert, done) {
loader.unload();
done();
}).then(null, assert.fail);
}).catch(assert.fail);
}
});

Просмотреть файл

@ -117,12 +117,12 @@ exports['test error recovery with promise'] = function(assert, done) {
let deferred = defer();
deferred.reject('error');
return deferred.promise;
}).then(null, function(actual) {
}).catch(function(actual) {
assert.equal(actual, 'error', 'rejected via promise');
let deferred = defer();
deferred.reject('end');
return deferred.promise;
}).then(null, function(actual) {
}).catch(function(actual) {
assert.equal(actual, 'end', 'rejeced via promise');
done();
});
@ -150,17 +150,17 @@ exports['test chaining'] = function(assert, done) {
deferred.promise.then().then().then(function(actual) {
assert.equal(actual, 2, 'value propagates unchanged');
return actual + 2;
}).then(null, function(reason) {
}).catch(function(reason) {
assert.fail('should not reject');
}).then(function(actual) {
assert.equal(actual, 4, 'value propagates through if not handled');
throw boom;
}).then(function(actual) {
assert.fail('exception must reject promise');
}).then().then(null, function(actual) {
}).then().catch(function(actual) {
assert.equal(actual, boom, 'reason propagates unchanged');
throw brax;
}).then().then(null, function(actual) {
}).then().catch(function(actual) {
assert.equal(actual, brax, 'reason changed becase of exception');
return 'recovery';
}).then(function(actual) {
@ -241,7 +241,7 @@ exports['test errors in promise resolution handlers are propagated'] = function(
throw expected;
}).then(function() {
return undefined;
}).then(null, function(actual) {
}).catch(function(actual) {
assert.equal(actual, expected, 'rejected as expected');
}).then(done, assert.fail);
@ -445,7 +445,7 @@ function testEnvironment ({all, resolve, defer, reject, promised}, assert, done,
}).then(value => {
assert.equal(value, 1000, 'promise#resolve works ' + type);
return reject('testing reject');
}).then(null, reason => {
}).catch(reason => {
assert.equal(reason, 'testing reject', 'promise#reject works ' + type);
let deferred = defer();
setTimeout(() => deferred.resolve('\\m/'), 10);

Просмотреть файл

@ -1205,7 +1205,7 @@ exports['test button checked'] = function(assert, done) {
then(loader.unload).
then(done, assert.fail);
})
}).then(null, assert.fail);
}).catch(assert.fail);
}
exports['test button is checked on window level'] = function(assert, done) {
@ -1267,7 +1267,7 @@ exports['test button is checked on window level'] = function(assert, done) {
then(done, assert.fail);
})
}).
then(null, assert.fail);
catch(assert.fail);
}
});

Просмотреть файл

@ -79,7 +79,7 @@ exports.testWindowTrackerIgnoresPrivateWindows = function(assert, done) {
return close(window);
});
});
}).then(null, assert.fail);
}).catch(assert.fail);
};
// Test setting activeWIndow and onFocus for private windows
@ -142,7 +142,7 @@ exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, don
return close(window);
})
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
};
exports.testActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
@ -182,7 +182,7 @@ exports.testActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
}
return close(window);
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
}
exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
@ -204,7 +204,7 @@ exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
}
return close(window);
}).then(done).then(null, assert.fail);
}).then(done).catch(assert.fail);
};
require("sdk/test").run(exports);

Просмотреть файл

@ -445,7 +445,7 @@ function migrateToDevEdition(urlParams) {
show("remote");
wrapper.init(url, urlParams);
});
}).then(null, error => {
}).catch(error => {
log("Failed to migrate FX Account: " + error);
show("stage", "intro");
// load the remote frame in the background
@ -459,7 +459,7 @@ function migrateToDevEdition(urlParams) {
// Reset the pref after migration.
Services.prefs.setBoolPref("identity.fxaccounts.migrateToDevEdition", false);
return true;
}).then(null, err => {
}).catch(err => {
Cu.reportError("Failed to reset the migrateToDevEdition pref: " + err);
return false;
});

Просмотреть файл

@ -1674,7 +1674,7 @@ var gBrowserInit = {
this.gmpInstallManager = new GMPInstallManager();
// We don't really care about the results, if someone is interested they
// can check the log.
this.gmpInstallManager.simpleCheckAndInstall().then(null, () => {});
this.gmpInstallManager.simpleCheckAndInstall().catch(() => {});
}, {timeout: 1000 * 60});
SessionStore.promiseInitialized.then(() => {

Просмотреть файл

@ -103,9 +103,9 @@ var gSanitizePromptDialog = {
docElt.getButton("cancel").disabled = true;
try {
s.sanitize().then(null, Components.utils.reportError)
s.sanitize().catch(Components.utils.reportError)
.then(() => window.close())
.then(null, Components.utils.reportError);
.catch(Components.utils.reportError);
return false;
} catch (er) {
Components.utils.reportError("Exception during sanitize: " + er);

Просмотреть файл

@ -426,7 +426,7 @@ CustomizeMode.prototype = {
if (!this._wantToBeInCustomizeMode) {
this.exit();
}
})().then(null, e => {
})().catch(e => {
log.error("Error entering customize mode", e);
// We should ensure this has been called, and calling it again doesn't hurt:
window.PanelUI.endBatchUpdate();
@ -596,7 +596,7 @@ CustomizeMode.prototype = {
if (this._wantToBeInCustomizeMode) {
this.enter();
}
})().then(null, e => {
})().catch(e => {
log.error("Error exiting customize mode", e);
if (!gPhotonStructure) {
// We should ensure this has been called, and calling it again doesn't hurt:
@ -866,7 +866,7 @@ CustomizeMode.prototype = {
}
this.visiblePalette.hidden = false;
this.window.gNavToolbox.palette = this._stowedPalette;
})().then(null, log.error);
})().catch(log.error);
},
isCustomizableItem(aNode) {
@ -1072,7 +1072,7 @@ CustomizeMode.prototype = {
this._addDragHandlers(target);
for (let child of target.children) {
if (this.isCustomizableItem(child) && !this.isWrappedToolbarItem(child)) {
await this.deferredWrapToolbarItem(child, CustomizableUI.getPlaceForItem(child)).then(null, log.error);
await this.deferredWrapToolbarItem(child, CustomizableUI.getPlaceForItem(child)).catch(log.error);
}
}
this.areas.add(target);
@ -1149,7 +1149,7 @@ CustomizeMode.prototype = {
this._removeDragHandlers(target);
}
this.areas.clear();
})().then(null, log.error);
})().catch(log.error);
},
_removeExtraToolbarsIfEmpty() {
@ -1205,7 +1205,7 @@ CustomizeMode.prototype = {
if (!this._wantToBeInCustomizeMode) {
this.exit();
}
})().then(null, log.error);
})().catch(log.error);
},
undoReset() {
@ -1229,7 +1229,7 @@ CustomizeMode.prototype = {
this._updateUndoResetButton();
this._updateEmptyPaletteNotice();
this.resetting = false;
})().then(null, log.error);
})().catch(log.error);
},
_onToolbarVisibilityChange(aEvent) {

Просмотреть файл

@ -444,7 +444,7 @@ const PanelUI = {
this._updateQuitTooltip();
this.panel.hidden = false;
this._isReady = true;
})().then(null, Cu.reportError);
})().catch(Cu.reportError);
return this._readyPromise;
},

Просмотреть файл

@ -467,7 +467,7 @@ this.DownloadsCommon = {
.getService(Ci.nsIExternalProtocolService)
.loadUrl(NetUtil.newURI(aFile));
}
}).then(null, Cu.reportError);
}).catch(Cu.reportError);
},
/**
@ -674,7 +674,7 @@ DownloadsDataCtor.prototype = {
if (!this._dataLinkInitialized) {
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
: Downloads.PUBLIC);
promiseList.then(list => list.addView(this)).then(null, Cu.reportError);
promiseList.then(list => list.addView(this)).catch(Cu.reportError);
this._dataLinkInitialized = true;
}
},
@ -708,7 +708,7 @@ DownloadsDataCtor.prototype = {
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
: Downloads.PUBLIC);
promiseList.then(list => list.removeFinished())
.then(null, Cu.reportError);
.catch(Cu.reportError);
let indicatorData = this._isPrivate ? PrivateDownloadsIndicatorData
: DownloadsIndicatorData;
indicatorData.attention = DownloadsCommon.ATTENTION_NONE;

Просмотреть файл

@ -110,7 +110,7 @@ this.DownloadsTaskbar = {
}
this._summary = summary;
return this._summary.addView(this);
}).then(null, Cu.reportError);
}).catch(Cu.reportError);
}
},

Просмотреть файл

@ -1181,7 +1181,7 @@ BrowserGlue.prototype = {
}
// Let's load the contextual identities.
Services.tm.mainThread.idleDispatch(() => {
Services.tm.idleDispatchToMainThread(() => {
ContextualIdentityService.load();
});
@ -1216,7 +1216,7 @@ BrowserGlue.prototype = {
let newProfilePath = newProfile.rootDir.path;
OS.File.removeDir(newProfilePath).then(() => {
return OS.File.makeDir(newProfilePath);
}).then(null, e => {
}).catch(e => {
Cu.reportError("Could not empty profile 'default': " + e);
});
}

Просмотреть файл

@ -1642,7 +1642,7 @@ PlacesToolbar.prototype = {
let dropPoint = this._getDropPoint(aEvent);
if (dropPoint && dropPoint.ip) {
PlacesControllerDragHelper.onDrop(dropPoint.ip, aEvent.dataTransfer)
.then(null, Components.utils.reportError);
.catch(Components.utils.reportError);
aEvent.preventDefault();
}

Просмотреть файл

@ -217,14 +217,14 @@ PlacesController.prototype = {
PlacesUtils.transactionManager.undoTransaction();
return;
}
PlacesTransactions.undo().then(null, Components.utils.reportError);
PlacesTransactions.undo().catch(Components.utils.reportError);
break;
case "cmd_redo":
if (!PlacesUIUtils.useAsyncTransactions) {
PlacesUtils.transactionManager.redoTransaction();
return;
}
PlacesTransactions.redo().then(null, Components.utils.reportError);
PlacesTransactions.redo().catch(Components.utils.reportError);
break;
case "cmd_cut":
case "placesCmd_cut":
@ -236,11 +236,11 @@ PlacesController.prototype = {
break;
case "cmd_paste":
case "placesCmd_paste":
this.paste().then(null, Components.utils.reportError);
this.paste().catch(Components.utils.reportError);
break;
case "cmd_delete":
case "placesCmd_delete":
this.remove("Remove Selection").then(null, Components.utils.reportError);
this.remove("Remove Selection").catch(Components.utils.reportError);
break;
case "placesCmd_deleteDataHost":
var host;
@ -286,7 +286,7 @@ PlacesController.prototype = {
this.reloadSelectedLivemark();
break;
case "placesCmd_sortBy:name":
this.sortFolderByName().then(null, Components.utils.reportError);
this.sortFolderByName().catch(Components.utils.reportError);
break;
case "placesCmd_createBookmark":
let node = this._view.selectedNode;

Просмотреть файл

@ -363,7 +363,7 @@
let dropPoint = this._getDropPoint(event);
if (dropPoint && dropPoint.ip) {
PlacesControllerDragHelper.onDrop(dropPoint.ip, event.dataTransfer)
.then(null, Components.utils.reportError);
.catch(Components.utils.reportError);
event.preventDefault();
}

Просмотреть файл

@ -54,7 +54,7 @@ var gMoveBookmarksDialog = {
await PlacesTransactions.Move({ guid: node.bookmarkGuid,
newParentGuid }).transact();
}
}).then(null, Components.utils.reportError);
}).catch(Components.utils.reportError);
},
newFolder: function MBD_newFolder() {

Просмотреть файл

@ -374,7 +374,7 @@ var PlacesOrganizer = {
if (aResult != Ci.nsIFilePicker.returnCancel && fp.fileURL) {
Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
BookmarkHTMLUtils.importFromURL(fp.fileURL.spec, false)
.then(null, Components.utils.reportError);
.catch(Components.utils.reportError);
}
};
@ -393,7 +393,7 @@ var PlacesOrganizer = {
if (aResult != Ci.nsIFilePicker.returnCancel) {
Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
BookmarkHTMLUtils.exportToFile(fp.file.path)
.then(null, Components.utils.reportError);
.catch(Components.utils.reportError);
}
};

Просмотреть файл

@ -1357,7 +1357,7 @@ PlacesTreeView.prototype = {
let ip = this._getInsertionPoint(aRow, aOrientation);
if (ip) {
PlacesControllerDragHelper.onDrop(ip, aDataTransfer)
.then(null, Components.utils.reportError);
.catch(Components.utils.reportError);
}
PlacesControllerDragHelper.currentDropTarget = null;

Просмотреть файл

@ -78,7 +78,7 @@ function test() {
gDownloadLastDir.cleanupPrivateFile();
aWin.close();
aCallback();
}).then(null, function() { ok(false); });
}).catch(function() { ok(false); });
}
testOnWindow(false, function(win, downloadDir) {

Просмотреть файл

@ -68,9 +68,10 @@ startupRecorder.prototype = {
Services.obs.removeObserver(this, topic);
if (topic == "sessionstore-windows-restored") {
// We use idleDispatch here to record the set of loaded scripts after we
// are fully done with startup and ready to react to user events.
Services.tm.mainThread.idleDispatch(
// We use idleDispatchToMainThread here to record the set of
// loaded scripts after we are fully done with startup and ready
// to react to user events.
Services.tm.idleDispatchToMainThread(
this.record.bind(this, "before handling user events"));
} else {
const topicsToNames = {

Просмотреть файл

@ -653,7 +653,7 @@ this.UITour = {
searchbar.textbox.popup.addEventListener("popupshown", onPopupShown);
searchbar.openSuggestionsPanel();
}
}).then(null, Cu.reportError);
}).catch(Cu.reportError);
break;
}

Просмотреть файл

@ -159,7 +159,7 @@ var tests = [
done();
}, "Highlight should move to the appMenu button");
}, "Highlight should be shown after showHighlight() for fixed panel items");
}).then(null, Components.utils.reportError);
}).catch(Components.utils.reportError);
},
function test_highlight_effect(done) {
function waitForHighlightWithEffect(highlightEl, effect, next, error) {

Просмотреть файл

@ -63,7 +63,7 @@ var tests = [
});
}, "Info should be shown after showInfo() for fixed menu panel items");
});
}).then(null, Components.utils.reportError);
}).catch(Components.utils.reportError);
},
taskify(async function test_bookmarks_menu() {
let bookmarksMenuButton = document.getElementById("bookmarks-menu-button");

Просмотреть файл

@ -26,7 +26,7 @@ function realstartup() {
let branch = "racy-set";
experiments.setExperimentBranch(experiment.id, branch)
.then(null, Cu.reportError);
.catch(Cu.reportError);
}
function shutdown() { }

Просмотреть файл

@ -187,7 +187,7 @@ var AboutHome = {
let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
mm.broadcastAsyncMessage("AboutHome:Update", data);
}
}).then(null, function onError(x) {
}).catch(function onError(x) {
Cu.reportError("Error in AboutHome.sendAboutHomeData: " + x);
});
},

Просмотреть файл

@ -693,11 +693,13 @@ html|span.ac-emphasize-text-url {
}
.ac-type-icon[type=bookmark] {
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star");
list-style-image: url("chrome://browser/skin/bookmark.svg");
-moz-context-properties: fill;
fill: #b2b2b2;
}
.ac-type-icon[type=bookmark][selected][current] {
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star-inverted");
fill: white;
}
.ac-type-icon[type=keyword],
@ -714,12 +716,14 @@ html|span.ac-emphasize-text-url {
.ac-type-icon[type=switchtab],
.ac-type-icon[type=remotetab] {
list-style-image: url("chrome://browser/skin/urlbar-tab.svg#tab");
list-style-image: url("chrome://browser/skin/urlbar-tab.svg");
-moz-context-properties: fill;
fill: #b2b2b2;
}
.ac-type-icon[type=switchtab][selected],
.ac-type-icon[type=remotetab][selected] {
list-style-image: url("chrome://browser/skin/urlbar-tab.svg#tab-inverted");
fill: white;
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {

Просмотреть файл

@ -851,11 +851,13 @@ html|span.ac-emphasize-text-url {
}
.ac-type-icon[type=bookmark] {
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star");
list-style-image: url("chrome://browser/skin/bookmark.svg");
-moz-context-properties: fill;
fill: #b2b2b2;
}
.ac-type-icon[type=bookmark][selected][current] {
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star-inverted");
fill: white;
}
.ac-type-icon[type=keyword],
@ -872,12 +874,14 @@ html|span.ac-emphasize-text-url {
.ac-type-icon[type=switchtab],
.ac-type-icon[type=remotetab] {
list-style-image: url("chrome://browser/skin/urlbar-tab.svg#tab");
list-style-image: url("chrome://browser/skin/urlbar-tab.svg");
-moz-context-properties: fill;
fill: #b2b2b2;
}
.ac-type-icon[type=switchtab][selected],
.ac-type-icon[type=remotetab][selected] {
list-style-image: url("chrome://browser/skin/urlbar-tab.svg#tab-inverted");
fill: white;
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {

Просмотреть файл

@ -218,5 +218,4 @@
skin/classic/browser/compacttheme/loading-inverted.png (../shared/compacttheme/loading-inverted.png)
skin/classic/browser/compacttheme/loading-inverted@2x.png (../shared/compacttheme/loading-inverted@2x.png)
skin/classic/browser/compacttheme/urlbar-history-dropmarker.svg (../shared/compacttheme/urlbar-history-dropmarker.svg)
skin/classic/browser/urlbar-star.svg (../shared/urlbar-star.svg)
skin/classic/browser/urlbar-tab.svg (../shared/urlbar-tab.svg)

Просмотреть файл

@ -1,22 +1,8 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<style>
g:not(:target) { display: none; }
.glyph { fill: #4d4d4d; }
.glyph.translucent { fill-opacity: .15; }
.inverted .glyph { fill: #fff; }
.inverted .glyph.translucent { fill-opacity: .15; }
</style>
<g id="icon">
<path class="glyph" d="M15,14H1a1,1,0,0,1-1-1V12.526H16V13A1,1,0,0,1,15,14ZM1,4A1,1,0,0,1,2,3H14a1,1,0,0,1,1,1v8H1V4Zm1,7H14V4H2v7Z"/>
<rect class="glyph translucent" x="2" y="4" width="12" height="7"/>
</g>
<g id="icon-inverted" class="inverted">
<path class="glyph" d="M15,14H1a1,1,0,0,1-1-1V12.526H16V13A1,1,0,0,1,15,14ZM1,4A1,1,0,0,1,2,3H14a1,1,0,0,1,1,1v8H1V4Zm1,7H14V4H2v7Z"/>
<rect class="glyph translucent" x="2" y="4" width="12" height="7"/>
</g>
<svg xmlns="http://www.w3.org/2000/svg"
width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M15,14H1a1,1,0,0,1-1-1V12.526H16V13A1,1,0,0,1,15,14ZM1,4A1,1,0,0,1,2,3H14a1,1,0,0,1,1,1v8H1V4Zm1,7H14V4H2v7Z"/>
<rect fill="context-fill" fill-opacity="0.15" x="2" y="4" width="12" height="7"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.0 KiB

После

Ширина:  |  Высота:  |  Размер: 535 B

Просмотреть файл

@ -1,22 +1,8 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<style>
g:not(:target) { display: none; }
.glyph { fill: #4d4d4d; }
.glyph.translucent { fill-opacity: .15; }
.inverted .glyph { fill: #fff; }
.inverted .glyph.translucent { fill-opacity: .15; }
</style>
<g id="icon">
<path class="glyph" d="M12,16H4a1,1,0,0,1-1-1V1A1,1,0,0,1,4,0h8a1,1,0,0,1,1,1V15A1,1,0,0,1,12,16Zm-4-.684a0.785,0.785,0,1,0-.785-0.785A0.785,0.785,0,0,0,8,15.316ZM12,2H4V13h8V2Z"/>
<rect class="glyph translucent" x="4" y="2" width="8" height="11"/>
</g>
<g id="icon-inverted" class="inverted">
<path class="glyph" d="M12,16H4a1,1,0,0,1-1-1V1A1,1,0,0,1,4,0h8a1,1,0,0,1,1,1V15A1,1,0,0,1,12,16Zm-4-.684a0.785,0.785,0,1,0-.785-0.785A0.785,0.785,0,0,0,8,15.316ZM12,2H4V13h8V2Z"/>
<rect class="glyph translucent" x="4" y="2" width="8" height="11"/>
</g>
<svg xmlns="http://www.w3.org/2000/svg"
width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M12,16H4a1,1,0,0,1-1-1V1A1,1,0,0,1,4,0h8a1,1,0,0,1,1,1V15A1,1,0,0,1,12,16Zm-4-.684a0.785,0.785,0,1,0-.785-0.785A0.785,0.785,0,0,0,8,15.316ZM12,2H4V13h8V2Z"/>
<rect fill="context-fill" fill-opacity="0.15" x="4" y="2" width="8" height="11"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

После

Ширина:  |  Высота:  |  Размер: 581 B

Просмотреть файл

@ -90,19 +90,23 @@ body {
}
.item.client.device-image-desktop > .item-title-container > .item-icon-container {
background-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon");
background-image: url("chrome://browser/skin/sync-desktopIcon.svg");
-moz-context-properties: fill;
fill: #4d4d4d;
}
.item.client.device-image-desktop.selected:focus > .item-title-container > .item-icon-container {
background-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon-inverted");
fill: white;
}
.item.client.device-image-mobile > .item-title-container > .item-icon-container {
background-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon");
background-image: url("chrome://browser/skin/sync-mobileIcon.svg");
-moz-context-properties: fill;
fill: #4d4d4d;
}
.item.client.device-image-mobile.selected:focus > .item-title-container > .item-icon-container {
background-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon-inverted");
fill: white;
}
.item.tab > .item-title-container > .item-icon-container {

Просмотреть файл

@ -1,20 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<style>
path:not(:target) {
display: none;
}
path {
fill: #b2b2b2;
}
path[id$="-inverted"] {
fill: #fff;
}
</style>
<path id="star" d="M8.7,0.5l2,4.3l4.6,0.7c0.6,0.1,0.9,0.9,0.4,1.4l-3.3,3.4l0.8,4.8c0.1,0.7-0.6,1.2-1.1,0.9L8,13.7l-4.1,2.3 c-0.6,0.3-1.2-0.2-1.1-0.9l0.8-4.8L0.2,6.9C-0.2,6.4,0,5.6,0.7,5.5l4.6-0.7l2-4.3C7.6-0.1,8.4-0.1,8.7,0.5z"/>
<path id="star-inverted" d="M8.7,0.5l2,4.3l4.6,0.7c0.6,0.1,0.9,0.9,0.4,1.4l-3.3,3.4l0.8,4.8c0.1,0.7-0.6,1.2-1.1,0.9L8,13.7l-4.1,2.3 c-0.6,0.3-1.2-0.2-1.1-0.9l0.8-4.8L0.2,6.9C-0.2,6.4,0,5.6,0.7,5.5l4.6-0.7l2-4.3C7.6-0.1,8.4-0.1,8.7,0.5z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1022 B

Просмотреть файл

@ -1,21 +1,7 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<style>
path:not(:target) {
display: none;
}
path {
fill: #b2b2b2;
}
path[id$="-inverted"] {
fill: #fff;
}
</style>
<path id="tab" d="M14,9.5V6c0-1.7-1.3-3-3-3H5C3.3,3,2,4.3,2,6v3.5C2,10.3,1.3,11,0.5,11h0C0.2,11,0,11.2,0,11.5v1 C0,12.8,0.2,13,0.5,13h15c0.3,0,0.5-0.2,0.5-0.5v-1c0-0.3-0.2-0.5-0.5-0.5h0C14.7,11,14,10.3,14,9.5z"/>
<path id="tab-inverted" d="M14,9.5V6c0-1.7-1.3-3-3-3H5C3.3,3,2,4.3,2,6v3.5C2,10.3,1.3,11,0.5,11h0C0.2,11,0,11.2,0,11.5v1 C0,12.8,0.2,13,0.5,13h15c0.3,0,0.5-0.2,0.5-0.5v-1c0-0.3-0.2-0.5-0.5-0.5h0C14.7,11,14,10.3,14,9.5z"/>
<svg xmlns="http://www.w3.org/2000/svg"
width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M14,9.5V6c0-1.7-1.3-3-3-3H5C3.3,3,2,4.3,2,6v3.5C2,10.3,1.3,11,0.5,11h0C0.2,11,0,11.2,0,11.5v1 C0,12.8,0.2,13,0.5,13h15c0.3,0,0.5-0.2,0.5-0.5v-1c0-0.3-0.2-0.5-0.5-0.5h0C14.7,11,14,10.3,14,9.5z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 971 B

После

Ширина:  |  Высота:  |  Размер: 534 B

Просмотреть файл

@ -1077,11 +1077,13 @@ treechildren.searchbar-treebody::-moz-tree-row(selected) {
}
.ac-type-icon[type=bookmark] {
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star");
list-style-image: url("chrome://browser/skin/bookmark.svg");
-moz-context-properties: fill;
fill: #b2b2b2;
}
.ac-type-icon[type=bookmark][selected][current] {
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star-inverted");
fill: white;
}
.ac-type-icon[type=keyword],
@ -1098,12 +1100,14 @@ treechildren.searchbar-treebody::-moz-tree-row(selected) {
.ac-type-icon[type=switchtab],
.ac-type-icon[type=remotetab] {
list-style-image: url("chrome://browser/skin/urlbar-tab.svg#tab");
list-style-image: url("chrome://browser/skin/urlbar-tab.svg");
-moz-context-properties: fill;
fill: #b2b2b2;
}
.ac-type-icon[type=switchtab][selected],
.ac-type-icon[type=remotetab][selected] {
list-style-image: url("chrome://browser/skin/urlbar-tab.svg#tab-inverted");
fill: white;
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {

Просмотреть файл

@ -1,26 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="16" width="16" viewBox="0 0 16 16">
<style>
use:not(:target) {
display: none;
}
use {
fill: MenuText;
}
use[id$="-disabled"] {
fill: GrayText;
}
use[id$="-hover"] {
fill: HighlightText;
}
</style>
<defs>
<path id="arrow-shape" d="m 6,4 0,8 5,-4 z"/>
</defs>
<use id="arrow" xlink:href="#arrow-shape"/>
<use id="arrow-disabled" xlink:href="#arrow-shape"/>
<use id="arrow-hover" xlink:href="#arrow-shape"/>
<svg xmlns="http://www.w3.org/2000/svg"
height="16" width="16" viewBox="0 0 16 16">
<path fill="context-fill" d="m 6,4 0,8 5,-4 z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 828 B

После

Ширина:  |  Высота:  |  Размер: 359 B

Просмотреть файл

@ -111,18 +111,20 @@ toolbarbutton.social-provider-menuitem > .toolbarbutton-icon {
menu.subviewbutton > .menu-right {
-moz-appearance: none;
list-style-image: url(chrome://browser/skin/customizableui/menu-arrow.svg#arrow);
list-style-image: url(chrome://browser/skin/customizableui/menu-arrow.svg);
-moz-context-properties: fill;
fill: MenuText;
/* Reset the rect we inherit from the button: */
-moz-image-region: auto;
}
menu[disabled="true"].subviewbutton > .menu-right {
list-style-image: url(chrome://browser/skin/customizableui/menu-arrow.svg#arrow-disabled);
fill: GrayText;
}
@media (-moz-windows-default-theme: 0) {
menu[_moz-menuactive].subviewbutton > .menu-right {
list-style-image: url(chrome://browser/skin/customizableui/menu-arrow.svg#arrow-hover);
fill: HighlightText;
}
}

Просмотреть файл

@ -50,7 +50,7 @@ CanvasDebuggerPanel.prototype = {
this.emit("ready");
return this;
})
.then(null, function onError(aReason) {
.catch(function onError(aReason) {
DevToolsUtils.reportException("CanvasDebuggerPanel.prototype.open", aReason);
});
},

Просмотреть файл

@ -126,7 +126,7 @@ function ifTestingUnsupported() {
function test() {
let generator = isTestingSupported() ? ifTestingSupported : ifTestingUnsupported;
Task.spawn(generator).then(null, handleError);
Task.spawn(generator).catch(handleError);
}
function createCanvas() {

Просмотреть файл

@ -134,7 +134,7 @@ var { helpers, assert } = (function () {
var loaded = helpers.listenOnce(options.browser, "load", true).then(function (ev) {
var reply = callback.call(null, options);
return Promise.resolve(reply).then(null, function (error) {
return Promise.resolve(reply).catch(function (error) {
ok(false, error);
}).then(function () {
tabbrowser.removeTab(options.tab);
@ -330,7 +330,7 @@ var { helpers, assert } = (function () {
var reply = callback.call(null, innerOptions);
return Promise.resolve(reply).then(null, function (error) {
return Promise.resolve(reply).catch(function (error) {
ok(false, error);
console.error(error);
}).then(function () {

Просмотреть файл

@ -69,7 +69,7 @@ DebuggerPanel.prototype = {
this.emit("ready");
return this;
})
.then(null, function onError(aReason) {
.catch(function onError(aReason) {
DevToolsUtils.reportException("DebuggerPanel.prototype.open", aReason);
});
},

Просмотреть файл

@ -31,7 +31,7 @@ function test() {
.then(() => gClient.close())
.then(uninstallAddon)
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -60,7 +60,7 @@ function test() {
yield disableAutoPrettyPrint();
closeDebuggerAndFinish(gPanel)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
});
});

Просмотреть файл

@ -24,7 +24,7 @@ function test() {
testBlackBoxSource()
.then(testBlackBoxReload)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -28,7 +28,7 @@ function test() {
testBlackBoxSource()
.then(testBlackBoxStack)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -30,7 +30,7 @@ function test() {
.then(testBlackBoxStack)
.then(testBlackBoxSource)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});

Просмотреть файл

@ -29,7 +29,7 @@ function test() {
blackBoxSources()
.then(testBlackBoxStack)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -30,7 +30,7 @@ function test() {
.then(clickStopBlackBoxingButton)
.then(testSourceEditorShownAgain)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -27,7 +27,7 @@ function test() {
waitForCaretAndScopes(gPanel, 21)
.then(testBlackBox)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});

Просмотреть файл

@ -24,7 +24,7 @@ function test() {
testBlackBoxSource()
.then(testBlackBoxReload)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -29,7 +29,7 @@ function test() {
.then(focusCurrentStackFrame)
.then(checkNavigationWhileFocused)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});

Просмотреть файл

@ -33,7 +33,7 @@ function test() {
.then(testBreakOnClick)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -31,7 +31,7 @@ function test() {
.then(testBreakOnClick)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -35,7 +35,7 @@ function test() {
promise.all([gAttached.promise, gNewGlobal.promise, gNewChromeSource.promise])
.then(resumeAndCloseConnection)
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});

Просмотреть файл

@ -22,7 +22,7 @@ function test() {
return testCleanExit();
})
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
}

Просмотреть файл

@ -21,7 +21,7 @@ function test() {
testClosure()
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -33,7 +33,7 @@ function test() {
.then(testDebuggerStatement)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -25,7 +25,7 @@ function test() {
gSources = gDebugger.DebuggerView.Sources;
gContextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest).then(null, info);
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest).catch(info);
callInTab(gTab, "firstCall");
});
@ -50,7 +50,7 @@ function test() {
gEditor.focus();
gEditor.setSelection({ line: 1, ch: 0 }, { line: 1, ch: 10 });
once(gContextMenu, "popupshown").then(testContextMenu).then(null, info);
once(gContextMenu, "popupshown").then(testContextMenu).catch(info);
gContextMenu.openPopup(gEditor.container, "overlap", 0, 0, true, false);
}

Просмотреть файл

@ -30,7 +30,7 @@ function test() {
.then(testSwitch1)
.then(testSwitch2)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});

Просмотреть файл

@ -33,7 +33,7 @@ function test() {
.then(testEventListeners)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -34,7 +34,7 @@ function test() {
.then(testEventListeners)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -34,7 +34,7 @@ function test() {
.then(testEventListeners)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -30,7 +30,7 @@ function test() {
checkIframeSource();
checkIframePause()
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -34,7 +34,7 @@ function test() {
.then(testResumeButton)
.then(testResumeKeyboard)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -26,7 +26,7 @@ function test() {
jumpToFunctionDefinition()
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -32,7 +32,7 @@ function test() {
.then(testRemoveSecondAddon)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -31,7 +31,7 @@ function test() {
.then(testAttachRemovedTab)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -35,7 +35,7 @@ function test() {
.then(testRemoveTab)
.then(() => gClient.close())
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -29,7 +29,7 @@ function test() {
.then(testNavigate)
.then(testDetach)
.then(finish)
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -26,7 +26,7 @@ function test() {
waitForNavigation(gPanel)
.then(testSourcesEmptyText)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -44,7 +44,7 @@ function test() {
"Should have the right property value for |arg|.");
yield resumeDebuggerThenCloseAndFinish(panel);
}).then(null, aError => {
}).catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
}

Просмотреть файл

@ -39,7 +39,7 @@ function test() {
.then(disablePauseOnExceptions)
.then(enableIgnoreCaughtExceptions)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -41,7 +41,7 @@ function test() {
.then(disablePauseOnExceptions)
.then(enableIgnoreCaughtExceptions)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});

Просмотреть файл

@ -44,7 +44,7 @@ function test() {
yield caretMove;
yield resumeDebuggerThenCloseAndFinish(panel);
}).then(null, aError => {
}).catch(aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
}

Просмотреть файл

@ -36,7 +36,7 @@ function test() {
})
.then(testSourceIsPretty)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
.catch(aError => {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
});
});

Просмотреть файл

@ -35,7 +35,7 @@ function test() {
yield close(client);
yield closeDebuggerAndFinish(panel);
}).then(null, error => {
}).catch(error => {
ok(false, "Got an error: " + error.message + "\n" + error.stack);
});
}

Просмотреть файл

@ -38,13 +38,13 @@ function test() {
p.name = "p";
let q = p.then();
q.name = "q";
let r = p.then(null, () => {});
let r = p.catch(() => {});
r.name = "r";
});
yield close(client);
finish();
}).then(null, error => {
}).catch(error => {
ok(false, "Got an error: " + error.message + "\n" + error.stack);
});
}

Просмотреть файл

@ -53,7 +53,7 @@ function test() {
yield close(client);
yield closeDebuggerAndFinish(panel);
}).then(null, error => {
}).catch(error => {
ok(false, "Got an error: " + error.message + "\n" + error.stack);
});
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше