зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to autoland. a=merge
--HG-- rename : accessible/tests/browser/browser_caching_attributes.js => accessible/tests/browser/e10s/browser_caching_attributes.js rename : accessible/tests/browser/browser_caching_description.js => accessible/tests/browser/e10s/browser_caching_description.js rename : accessible/tests/browser/browser_caching_name.js => accessible/tests/browser/e10s/browser_caching_name.js rename : accessible/tests/browser/browser_caching_relations.js => accessible/tests/browser/e10s/browser_caching_relations.js rename : accessible/tests/browser/browser_caching_states.js => accessible/tests/browser/e10s/browser_caching_states.js rename : accessible/tests/browser/browser_caching_value.js => accessible/tests/browser/e10s/browser_caching_value.js rename : accessible/tests/browser/browser_events_caretmove.js => accessible/tests/browser/e10s/browser_events_caretmove.js rename : accessible/tests/browser/browser_events_hide.js => accessible/tests/browser/e10s/browser_events_hide.js rename : accessible/tests/browser/browser_events_show.js => accessible/tests/browser/e10s/browser_events_show.js rename : accessible/tests/browser/browser_events_statechange.js => accessible/tests/browser/e10s/browser_events_statechange.js rename : accessible/tests/browser/browser_events_textchange.js => accessible/tests/browser/e10s/browser_events_textchange.js rename : accessible/tests/browser/browser_treeupdate_ariadialog.js => accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js rename : accessible/tests/browser/browser_treeupdate_ariaowns.js => accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js rename : accessible/tests/browser/browser_treeupdate_canvas.js => accessible/tests/browser/e10s/browser_treeupdate_canvas.js rename : accessible/tests/browser/browser_treeupdate_cssoverflow.js => accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js rename : accessible/tests/browser/browser_treeupdate_doc.js => accessible/tests/browser/e10s/browser_treeupdate_doc.js rename : accessible/tests/browser/browser_treeupdate_gencontent.js => accessible/tests/browser/e10s/browser_treeupdate_gencontent.js rename : accessible/tests/browser/browser_treeupdate_hidden.js => accessible/tests/browser/e10s/browser_treeupdate_hidden.js rename : accessible/tests/browser/browser_treeupdate_imagemap.js => accessible/tests/browser/e10s/browser_treeupdate_imagemap.js rename : accessible/tests/browser/browser_treeupdate_list.js => accessible/tests/browser/e10s/browser_treeupdate_list.js rename : accessible/tests/browser/browser_treeupdate_list_editabledoc.js => accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js rename : accessible/tests/browser/browser_treeupdate_listener.js => accessible/tests/browser/e10s/browser_treeupdate_listener.js rename : accessible/tests/browser/browser_treeupdate_optgroup.js => accessible/tests/browser/e10s/browser_treeupdate_optgroup.js rename : accessible/tests/browser/browser_treeupdate_removal.js => accessible/tests/browser/e10s/browser_treeupdate_removal.js rename : accessible/tests/browser/browser_treeupdate_table.js => accessible/tests/browser/e10s/browser_treeupdate_table.js rename : accessible/tests/browser/browser_treeupdate_textleaf.js => accessible/tests/browser/e10s/browser_treeupdate_textleaf.js rename : accessible/tests/browser/browser_treeupdate_visibility.js => accessible/tests/browser/e10s/browser_treeupdate_visibility.js rename : accessible/tests/browser/browser_treeupdate_whitespace.js => accessible/tests/browser/e10s/browser_treeupdate_whitespace.js rename : accessible/tests/browser/doc_treeupdate_ariadialog.html => accessible/tests/browser/e10s/doc_treeupdate_ariadialog.html rename : accessible/tests/browser/doc_treeupdate_ariaowns.html => accessible/tests/browser/e10s/doc_treeupdate_ariaowns.html rename : accessible/tests/browser/doc_treeupdate_imagemap.html => accessible/tests/browser/e10s/doc_treeupdate_imagemap.html rename : accessible/tests/browser/doc_treeupdate_removal.xhtml => accessible/tests/browser/e10s/doc_treeupdate_removal.xhtml rename : accessible/tests/browser/doc_treeupdate_visibility.html => accessible/tests/browser/e10s/doc_treeupdate_visibility.html rename : accessible/tests/browser/doc_treeupdate_whitespace.html => accessible/tests/browser/e10s/doc_treeupdate_whitespace.html rename : accessible/tests/browser/events.js => accessible/tests/browser/e10s/events.js rename : browser/components/extensions/test/browser/browser_ext_pageAction_context.js => browser/components/extensions/test/browser/browser_ext_pageAction_title.js rename : browser/components/extensions/test/browser/browser_ext_pageAction_context.js => browser/components/extensions/test/browser/head_pageAction.js rename : dom/events/test/pointerevents/pointerevent_element_haspointercapture.html => dom/events/test/pointerevents/pointerevent_element_haspointercapture-manual.html rename : dom/events/test/pointerevents/test_pointerevent_element_haspointercapture.html => dom/events/test/pointerevents/test_pointerevent_element_haspointercapture-manual.html rename : gfx/thebes/DeviceManagerD3D11.cpp => gfx/thebes/DeviceManagerDx.cpp rename : gfx/thebes/DeviceManagerD3D11.h => gfx/thebes/DeviceManagerDx.h rename : media/webrtc/trunk/tools/gyp/test/compiler-override/compiler.gyp => media/webrtc/trunk/tools/gyp/test/compiler-override/compiler-exe.gyp rename : media/webrtc/trunk/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings => media/webrtc/trunk/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist-error.strings rename : media/webrtc/trunk/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings => media/webrtc/trunk/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist-error.strings rename : media/webrtc/trunk/tools/gyp/test/mac/gyptest-postbuild-static-library.gyp => media/webrtc/trunk/tools/gyp/test/mac/gyptest-postbuild-static-library.py rename : media/webrtc/trunk/tools/gyp/test/rules/src/subdir4/asm-function.asm => media/webrtc/trunk/tools/gyp/test/rules/src/subdir4/asm-function.assem rename : mfbt/unused.h => mfbt/Unused.h rename : testing/web-platform/tests/pointerevents/pointerevent_element_haspointercapture.html => testing/web-platform/tests/pointerevents/pointerevent_element_haspointercapture-manual.html extra : rebase_source : a3de7d91a61df9b14fe07a89f5b0184a067549cf
This commit is contained in:
Коммит
e5adfbffe6
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1294803's backout needed a clobber to fix SM builds
|
||||
Bug 1297276 - renaming a file with a different case needed a clobber on case insensitive filesystem
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AccessibleNode.h"
|
||||
#include "mozilla/dom/AccessibleNodeBinding.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "DocAccessible.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(AccessibleNode)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AccessibleNode)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AccessibleNode)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AccessibleNode)
|
||||
|
||||
AccessibleNode::AccessibleNode(nsINode* aNode) : mDOMNode(aNode)
|
||||
{
|
||||
DocAccessible* doc =
|
||||
GetOrCreateAccService()->GetDocAccessible(mDOMNode->OwnerDoc());
|
||||
if (doc) {
|
||||
mIntl = doc->GetAccessible(mDOMNode);
|
||||
}
|
||||
}
|
||||
|
||||
AccessibleNode::~AccessibleNode()
|
||||
{
|
||||
}
|
||||
|
||||
/* virtual */ JSObject*
|
||||
AccessibleNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AccessibleNodeBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
/* virtual */ ParentObject
|
||||
AccessibleNode::GetParentObject() const
|
||||
{
|
||||
return mDOMNode->GetParentObject();
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleNode::GetRole(nsAString& aRole)
|
||||
{
|
||||
if (mIntl) {
|
||||
GetOrCreateAccService()->GetStringRole(mIntl->Role(), aRole);
|
||||
return;
|
||||
}
|
||||
|
||||
aRole.AssignLiteral("unknown");
|
||||
}
|
||||
|
||||
nsINode*
|
||||
AccessibleNode::GetDOMNode()
|
||||
{
|
||||
return mDOMNode;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 A11Y_AOM_ACCESSIBLENODE_H
|
||||
#define A11Y_AOM_ACCESSIBLENODE_H
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
class nsINode;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace a11y {
|
||||
class Accessible;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
struct ParentObject;
|
||||
|
||||
class AccessibleNode : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit AccessibleNode(nsINode* aNode);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS;
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AccessibleNode);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override final;
|
||||
virtual dom::ParentObject GetParentObject() const final;
|
||||
|
||||
void GetRole(nsAString& aRole);
|
||||
nsINode* GetDOMNode();
|
||||
|
||||
protected:
|
||||
AccessibleNode(const AccessibleNode& aCopy) = delete;
|
||||
AccessibleNode& operator=(const AccessibleNode& aCopy) = delete;
|
||||
virtual ~AccessibleNode();
|
||||
|
||||
RefPtr<a11y::Accessible> mIntl;
|
||||
RefPtr<nsINode> mDOMNode;
|
||||
};
|
||||
|
||||
} // dom
|
||||
} // mozilla
|
||||
|
||||
|
||||
#endif // A11Y_JSAPI_ACCESSIBLENODE
|
|
@ -0,0 +1,38 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'AccessibleNode.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AccessibleNode.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/base',
|
||||
'/accessible/generic',
|
||||
]
|
||||
|
||||
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/atk',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/windows/ia2',
|
||||
'/accessible/windows/msaa',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/mac',
|
||||
]
|
||||
else:
|
||||
LOCAL_INCLUDES += [
|
||||
'/accessible/other',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
|
@ -105,16 +105,18 @@ LogDocShellState(nsIDocument* aDocumentNode)
|
|||
nsCOMPtr<nsIDocShell> docShell = aDocumentNode->GetDocShell();
|
||||
uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
|
||||
docShell->GetBusyFlags(&busyFlags);
|
||||
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE)
|
||||
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) {
|
||||
printf("'none'");
|
||||
if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY)
|
||||
}
|
||||
if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) {
|
||||
printf("'busy'");
|
||||
if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD)
|
||||
}
|
||||
if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) {
|
||||
printf(", 'before page load'");
|
||||
if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)
|
||||
}
|
||||
if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) {
|
||||
printf(", 'page loading'");
|
||||
|
||||
printf("[failed]");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2D.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "mozilla/a11y/Role.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "RelationType.h"
|
||||
#include "xpcAccessibleDocument.h"
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "mozilla/a11y/DocManager.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/a11y/Platform.h"
|
||||
#include "RelationType.h"
|
||||
#include "mozilla/a11y/Role.h"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "mozilla/a11y/DocManager.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/a11y/Platform.h"
|
||||
#include "RelationType.h"
|
||||
#include "mozilla/a11y/Role.h"
|
||||
|
|
|
@ -15,11 +15,22 @@ elif toolkit == 'cocoa':
|
|||
else:
|
||||
DIRS += ['other']
|
||||
|
||||
DIRS += ['base', 'generic', 'html', 'interfaces', 'ipc', 'jsat', 'xpcom']
|
||||
DIRS += [ 'aom',
|
||||
'base',
|
||||
'generic',
|
||||
'html',
|
||||
'interfaces',
|
||||
'ipc',
|
||||
'jsat',
|
||||
'xpcom'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_XUL']:
|
||||
DIRS += ['xul']
|
||||
|
||||
TEST_DIRS += ['tests/mochitest']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'tests/browser/browser.ini',
|
||||
'tests/browser/e10s/browser.ini'
|
||||
]
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
// Content scripts have global 'content' object
|
||||
"content": true,
|
||||
|
||||
"add_task": true,
|
||||
|
||||
// Defined in accessible/tests/mochitest/ common.js, name.js, states.js
|
||||
"prettyName": true,
|
||||
"statesToString": true,
|
||||
|
@ -22,13 +24,21 @@
|
|||
"isAccessible": true,
|
||||
"getAccessibleDOMNodeID": true,
|
||||
|
||||
// Defined for all accessibility browser tests.
|
||||
// Defined for all top level accessibility browser tests.
|
||||
"setE10sPrefs": true,
|
||||
"unsetE10sPrefs": true,
|
||||
"initPromise": true,
|
||||
"shutdownPromise": true,
|
||||
"forceGC": true,
|
||||
|
||||
// Defined for all e10s accessibility browser tests.
|
||||
"addAccessibleTask": true,
|
||||
"BrowserTestUtils": true,
|
||||
"ContentTask": true,
|
||||
"gBrowser": true,
|
||||
"isDefunct": true,
|
||||
"loadScripts": true,
|
||||
"loadFrameScripts": true,
|
||||
"Logger": true,
|
||||
"MOCHITESTS_DIR": true,
|
||||
"waitForEvent": true,
|
||||
|
@ -36,7 +46,7 @@
|
|||
"invokeSetAttribute": true,
|
||||
"invokeSetStyle": true,
|
||||
"invokeFocus": true,
|
||||
"findAccessibleChildByID": true
|
||||
"findAccessibleChildByID": true,
|
||||
},
|
||||
"rules": {
|
||||
"mozilla/mark-test-function-used": 1,
|
||||
|
@ -68,7 +78,7 @@
|
|||
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
|
||||
"linebreak-style": 0,
|
||||
"max-depth": 0,
|
||||
"max-nested-callbacks": [2, 3],
|
||||
"max-nested-callbacks": [2, 4],
|
||||
"max-params": 0,
|
||||
"max-statements": 0,
|
||||
"new-cap": [2, {"capIsNew": false}],
|
||||
|
|
|
@ -1,52 +1,9 @@
|
|||
[DEFAULT]
|
||||
skip-if = (e10s && os == 'win') # Bug 1269369: Document loaded event does not fire in Windows
|
||||
|
||||
support-files =
|
||||
events.js
|
||||
head.js
|
||||
doc_treeupdate_ariadialog.html
|
||||
doc_treeupdate_ariaowns.html
|
||||
doc_treeupdate_imagemap.html
|
||||
doc_treeupdate_removal.xhtml
|
||||
doc_treeupdate_visibility.html
|
||||
doc_treeupdate_whitespace.html
|
||||
!/accessible/tests/mochitest/*.js
|
||||
!/accessible/tests/mochitest/letters.gif
|
||||
!/accessible/tests/mochitest/moz.png
|
||||
shared-head.js
|
||||
|
||||
# Caching tests
|
||||
[browser_caching_attributes.js]
|
||||
[browser_caching_description.js]
|
||||
[browser_caching_name.js]
|
||||
skip-if = e10s
|
||||
[browser_caching_relations.js]
|
||||
[browser_caching_states.js]
|
||||
[browser_caching_value.js]
|
||||
|
||||
# Events tests
|
||||
[browser_events_caretmove.js]
|
||||
[browser_events_hide.js]
|
||||
[browser_events_show.js]
|
||||
[browser_events_statechange.js]
|
||||
[browser_events_textchange.js]
|
||||
|
||||
# Tree update tests
|
||||
[browser_treeupdate_ariadialog.js]
|
||||
[browser_treeupdate_ariaowns.js]
|
||||
skip-if = e10s
|
||||
[browser_treeupdate_canvas.js]
|
||||
[browser_treeupdate_cssoverflow.js]
|
||||
[browser_treeupdate_doc.js]
|
||||
[browser_treeupdate_gencontent.js]
|
||||
[browser_treeupdate_hidden.js]
|
||||
[browser_treeupdate_imagemap.js]
|
||||
skip-if = e10s
|
||||
[browser_treeupdate_list.js]
|
||||
[browser_treeupdate_list_editabledoc.js]
|
||||
[browser_treeupdate_listener.js]
|
||||
[browser_treeupdate_optgroup.js]
|
||||
[browser_treeupdate_removal.js]
|
||||
[browser_treeupdate_table.js]
|
||||
[browser_treeupdate_textleaf.js]
|
||||
[browser_treeupdate_visibility.js]
|
||||
[browser_treeupdate_whitespace.js]
|
||||
skip-if = true # Failing due to incorrect index of test container children on document load.
|
||||
[browser_shutdown_multi_reference.js]
|
||||
[browser_shutdown_scope_lifecycle.js]
|
||||
[browser_shutdown_start_restart.js]
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* () {
|
||||
info('Creating a service');
|
||||
// Create a11y service.
|
||||
let a11yInit = initPromise();
|
||||
let accService1 = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
yield a11yInit;
|
||||
ok(accService1, 'Service initialized');
|
||||
|
||||
// Add another reference to a11y service. This will not trigger
|
||||
// 'a11y-init-or-shutdown' event
|
||||
let accService2 = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
ok(accService2, 'Service initialized');
|
||||
|
||||
info('Removing all service references');
|
||||
let canShutdown = false;
|
||||
// This promise will resolve only if canShutdonw flag is set to true. If
|
||||
// 'a11y-init-or-shutdown' event with '0' flag comes before it can be shut
|
||||
// down, the promise will reject.
|
||||
let a11yShutdown = new Promise((resolve, reject) =>
|
||||
shutdownPromise().then(flag => canShutdown ?
|
||||
resolve() : reject('Accessible service was shut down incorrectly')));
|
||||
// Remove first a11y service reference.
|
||||
accService1 = null;
|
||||
ok(!accService1, 'Service is removed');
|
||||
// Force garbage collection that should not trigger shutdown because there is
|
||||
// another reference.
|
||||
forceGC();
|
||||
|
||||
// Have some breathing room when removing a11y service references.
|
||||
yield new Promise(resolve => executeSoon(resolve));
|
||||
|
||||
// Now allow a11y service to shutdown.
|
||||
canShutdown = true;
|
||||
// Remove last a11y service reference.
|
||||
accService2 = null;
|
||||
ok(!accService2, 'Service is removed');
|
||||
// Force garbage collection that should trigger shutdown.
|
||||
forceGC();
|
||||
yield a11yShutdown;
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* testScopeLifecycle() {
|
||||
// Create a11y service inside of the function scope. Its reference should be
|
||||
// released once the anonimous function is called.
|
||||
let a11yInitThenShutdown = initPromise().then(shutdownPromise);
|
||||
|
||||
(function() {
|
||||
let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
ok(accService, 'Service initialized');
|
||||
})();
|
||||
|
||||
// Force garbage collection that should trigger shutdown.
|
||||
forceGC();
|
||||
yield a11yInitThenShutdown;
|
||||
});
|
|
@ -0,0 +1,41 @@
|
|||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(function* testStartAndRestart() {
|
||||
info('Creating a service');
|
||||
// Create a11y service.
|
||||
let a11yInit = initPromise();
|
||||
let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
yield a11yInit;
|
||||
ok(accService, 'Service initialized');
|
||||
|
||||
info('Removing a service');
|
||||
// Remove the only reference to an a11y service.
|
||||
let a11yShutdown = shutdownPromise();
|
||||
accService = null;
|
||||
ok(!accService, 'Service is removed');
|
||||
// Force garbage collection that should trigger shutdown.
|
||||
forceGC();
|
||||
yield a11yShutdown;
|
||||
|
||||
info('Recreating a service');
|
||||
// Re-create a11y service.
|
||||
a11yInit = initPromise();
|
||||
accService = Cc['@mozilla.org/accessibilityService;1'].getService(
|
||||
Ci.nsIAccessibilityService);
|
||||
yield a11yInit;
|
||||
ok(accService, 'Service initialized again');
|
||||
|
||||
info('Removing a service again');
|
||||
// Remove the only reference to an a11y service again.
|
||||
a11yShutdown = shutdownPromise();
|
||||
accService = null;
|
||||
ok(!accService, 'Service is removed again');
|
||||
// Force garbage collection that should trigger shutdown.
|
||||
forceGC();
|
||||
yield a11yShutdown;
|
||||
});
|
|
@ -0,0 +1,53 @@
|
|||
[DEFAULT]
|
||||
skip-if = (e10s && os == 'win') # Bug 1269369: Document loaded event does not fire in Windows
|
||||
support-files =
|
||||
events.js
|
||||
head.js
|
||||
doc_treeupdate_ariadialog.html
|
||||
doc_treeupdate_ariaowns.html
|
||||
doc_treeupdate_imagemap.html
|
||||
doc_treeupdate_removal.xhtml
|
||||
doc_treeupdate_visibility.html
|
||||
doc_treeupdate_whitespace.html
|
||||
!/accessible/tests/browser/shared-head.js
|
||||
!/accessible/tests/mochitest/*.js
|
||||
!/accessible/tests/mochitest/letters.gif
|
||||
!/accessible/tests/mochitest/moz.png
|
||||
|
||||
# Caching tests
|
||||
[browser_caching_attributes.js]
|
||||
[browser_caching_description.js]
|
||||
[browser_caching_name.js]
|
||||
skip-if = e10s
|
||||
[browser_caching_relations.js]
|
||||
[browser_caching_states.js]
|
||||
[browser_caching_value.js]
|
||||
|
||||
# Events tests
|
||||
[browser_events_caretmove.js]
|
||||
[browser_events_hide.js]
|
||||
[browser_events_show.js]
|
||||
[browser_events_statechange.js]
|
||||
[browser_events_textchange.js]
|
||||
|
||||
# Tree update tests
|
||||
[browser_treeupdate_ariadialog.js]
|
||||
[browser_treeupdate_ariaowns.js]
|
||||
skip-if = e10s
|
||||
[browser_treeupdate_canvas.js]
|
||||
[browser_treeupdate_cssoverflow.js]
|
||||
[browser_treeupdate_doc.js]
|
||||
[browser_treeupdate_gencontent.js]
|
||||
[browser_treeupdate_hidden.js]
|
||||
[browser_treeupdate_imagemap.js]
|
||||
skip-if = e10s
|
||||
[browser_treeupdate_list.js]
|
||||
[browser_treeupdate_list_editabledoc.js]
|
||||
[browser_treeupdate_listener.js]
|
||||
[browser_treeupdate_optgroup.js]
|
||||
[browser_treeupdate_removal.js]
|
||||
[browser_treeupdate_table.js]
|
||||
[browser_treeupdate_textleaf.js]
|
||||
[browser_treeupdate_visibility.js]
|
||||
[browser_treeupdate_whitespace.js]
|
||||
skip-if = true # Failing due to incorrect index of test container children on document load.
|
|
@ -0,0 +1,84 @@
|
|||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
/* global EVENT_DOCUMENT_LOAD_COMPLETE, CURRENT_CONTENT_DIR, loadFrameScripts */
|
||||
|
||||
/* exported addAccessibleTask */
|
||||
|
||||
// Load the shared-head file first.
|
||||
Services.scriptloader.loadSubScript(
|
||||
'chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js',
|
||||
this);
|
||||
|
||||
/**
|
||||
* A wrapper around browser test add_task that triggers an accessible test task
|
||||
* as a new browser test task with given document, data URL or markup snippet.
|
||||
* @param {String} doc URL (relative to current directory) or
|
||||
* data URL or markup snippet that is used
|
||||
* to test content with
|
||||
* @param {Function|Function*} task a generator or a function with tests to
|
||||
* run
|
||||
*/
|
||||
function addAccessibleTask(doc, task) {
|
||||
add_task(function*() {
|
||||
let url;
|
||||
if (doc.includes('doc_')) {
|
||||
url = `${CURRENT_CONTENT_DIR}e10s/${doc}`;
|
||||
} else {
|
||||
// Assume it's a markup snippet.
|
||||
url = `data:text/html,
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Test</title>
|
||||
</head>
|
||||
<body id="body">${doc}</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
let observers = Services.obs.enumerateObservers('accessible-event');
|
||||
while (observers.hasMoreElements()) {
|
||||
Services.obs.removeObserver(
|
||||
observers.getNext().QueryInterface(Ci.nsIObserver),
|
||||
'accessible-event');
|
||||
}
|
||||
});
|
||||
|
||||
let onDocLoad = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, 'body');
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: url
|
||||
}, function*(browser) {
|
||||
registerCleanupFunction(() => {
|
||||
if (browser) {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (tab && !tab.closing && tab.linkedBrowser) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
yield SimpleTest.promiseFocus(browser);
|
||||
|
||||
loadFrameScripts(browser,
|
||||
'let { document, window, navigator } = content;',
|
||||
{ name: 'common.js', dir: MOCHITESTS_DIR });
|
||||
|
||||
Logger.log(
|
||||
`e10s enabled: ${Services.appinfo.browserTabsRemoteAutostart}`);
|
||||
Logger.log(`Actually remote browser: ${browser.isRemoteBrowser}`);
|
||||
|
||||
let event = yield onDocLoad;
|
||||
yield task(browser, event.accessible);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Loading and common.js from accessible/tests/mochitest/ for all tests, as
|
||||
// well as events.js.
|
||||
loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR }, 'e10s/events.js');
|
|
@ -4,300 +4,113 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
/* global EVENT_DOCUMENT_LOAD_COMPLETE */
|
||||
|
||||
/* exported Logger, MOCHITESTS_DIR, isDefunct, addAccessibleTask,
|
||||
invokeSetAttribute, invokeFocus, invokeSetStyle,
|
||||
findAccessibleChildByID, getAccessibleDOMNodeID */
|
||||
|
||||
const { interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
/* exported initPromise, shutdownPromise,
|
||||
setE10sPrefs, unsetE10sPrefs, forceGC */
|
||||
|
||||
/**
|
||||
* Current browser test directory path used to load subscripts.
|
||||
* Set e10s related preferences in the test environment.
|
||||
* @return {Promise} promise that resolves when preferences are set.
|
||||
*/
|
||||
const CURRENT_DIR =
|
||||
'chrome://mochitests/content/browser/accessible/tests/browser/';
|
||||
/**
|
||||
* A11y mochitest directory where we find common files used in both browser and
|
||||
* plain tests.
|
||||
*/
|
||||
const MOCHITESTS_DIR =
|
||||
'chrome://mochitests/content/a11y/accessible/tests/mochitest/';
|
||||
/**
|
||||
* A base URL for test files used in content.
|
||||
*/
|
||||
const CURRENT_CONTENT_DIR =
|
||||
'http://example.com/browser/accessible/tests/browser/';
|
||||
|
||||
/**
|
||||
* Used to dump debug information.
|
||||
*/
|
||||
let Logger = {
|
||||
/**
|
||||
* Set up this variable to dump log messages into console.
|
||||
*/
|
||||
dumpToConsole: false,
|
||||
|
||||
/**
|
||||
* Set up this variable to dump log messages into error console.
|
||||
*/
|
||||
dumpToAppConsole: false,
|
||||
|
||||
/**
|
||||
* Return true if dump is enabled.
|
||||
*/
|
||||
get enabled() {
|
||||
return this.dumpToConsole || this.dumpToAppConsole;
|
||||
},
|
||||
|
||||
/**
|
||||
* Dump information into console if applicable.
|
||||
*/
|
||||
log(msg) {
|
||||
if (this.enabled) {
|
||||
this.logToConsole(msg);
|
||||
this.logToAppConsole(msg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Log message to console.
|
||||
*/
|
||||
logToConsole(msg) {
|
||||
if (this.dumpToConsole) {
|
||||
dump(`\n${msg}\n`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Log message to error console.
|
||||
*/
|
||||
logToAppConsole(msg) {
|
||||
if (this.dumpToAppConsole) {
|
||||
Services.console.logStringMessage(`${msg}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if an accessible object has a defunct test.
|
||||
* @param {nsIAccessible} accessible object to test defunct state for
|
||||
* @return {Boolean} flag indicating defunct state
|
||||
*/
|
||||
function isDefunct(accessible) {
|
||||
let defunct = false;
|
||||
try {
|
||||
let extState = {};
|
||||
accessible.getState({}, extState);
|
||||
defunct = extState.value & Ci.nsIAccessibleStates.EXT_STATE_DEFUNCT;
|
||||
} catch (x) {
|
||||
defunct = true;
|
||||
} finally {
|
||||
if (defunct) {
|
||||
Logger.log(`Defunct accessible: ${prettyName(accessible)}`);
|
||||
}
|
||||
}
|
||||
return defunct;
|
||||
function setE10sPrefs() {
|
||||
return new Promise(resolve =>
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
['browser.tabs.remote.autostart', true],
|
||||
['browser.tabs.remote.force-enable', true],
|
||||
['extensions.e10sBlocksEnabling', false]
|
||||
]
|
||||
}, resolve));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously set or remove content element's attribute (in content process
|
||||
* if e10s is enabled).
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @param {String} id content element id
|
||||
* @param {String} attr attribute name
|
||||
* @param {String?} value optional attribute value, if not present, remove
|
||||
* attribute
|
||||
* @return {Promise} promise indicating that attribute is set/removed
|
||||
* Unset e10s related preferences in the test environment.
|
||||
* @return {Promise} promise that resolves when preferences are unset.
|
||||
*/
|
||||
function invokeSetAttribute(browser, id, attr, value) {
|
||||
if (value) {
|
||||
Logger.log(`Setting ${attr} attribute to ${value} for node with id: ${id}`);
|
||||
} else {
|
||||
Logger.log(`Removing ${attr} attribute from node with id: ${id}`);
|
||||
}
|
||||
return ContentTask.spawn(browser, { id, attr, value },
|
||||
({ id, attr, value }) => {
|
||||
let elm = content.document.getElementById(id);
|
||||
if (value) {
|
||||
elm.setAttribute(attr, value);
|
||||
} else {
|
||||
elm.removeAttribute(attr);
|
||||
}
|
||||
});
|
||||
function unsetE10sPrefs() {
|
||||
return new Promise(resolve => {
|
||||
SpecialPowers.popPrefEnv(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously set or remove content element's style (in content process if
|
||||
* e10s is enabled).
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @param {String} id content element id
|
||||
* @param {String} aStyle style property name
|
||||
* @param {String?} aValue optional style property value, if not present,
|
||||
* remove style
|
||||
* @return {Promise} promise indicating that style is set/removed
|
||||
*/
|
||||
function invokeSetStyle(browser, id, style, value) {
|
||||
if (value) {
|
||||
Logger.log(`Setting ${style} style to ${value} for node with id: ${id}`);
|
||||
} else {
|
||||
Logger.log(`Removing ${style} style from node with id: ${id}`);
|
||||
}
|
||||
return ContentTask.spawn(browser, { id, style, value },
|
||||
({ id, style, value }) => {
|
||||
let elm = content.document.getElementById(id);
|
||||
if (value) {
|
||||
elm.style[style] = value;
|
||||
} else {
|
||||
delete elm.style[style];
|
||||
}
|
||||
});
|
||||
}
|
||||
// Load the shared-head file first.
|
||||
Services.scriptloader.loadSubScript(
|
||||
'chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js',
|
||||
this);
|
||||
|
||||
/**
|
||||
* Asynchronously set focus on a content element (in content process if e10s is
|
||||
* enabled).
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @param {String} id content element id
|
||||
* @return {Promise} promise indicating that focus is set
|
||||
* Returns a promise that resolves when 'a11y-init-or-shutdown' event is fired.
|
||||
* @return {Promise} event promise evaluating to event's data
|
||||
*/
|
||||
function invokeFocus(browser, id) {
|
||||
Logger.log(`Setting focus on a node with id: ${id}`);
|
||||
return ContentTask.spawn(browser, id, id => {
|
||||
let elm = content.document.getElementById(id);
|
||||
if (elm instanceof Ci.nsIDOMNSEditableElement && elm.editor ||
|
||||
elm instanceof Ci.nsIDOMXULTextBoxElement) {
|
||||
elm.selectionStart = elm.selectionEnd = elm.value.length;
|
||||
}
|
||||
elm.focus();
|
||||
function a11yInitOrShutdownPromise() {
|
||||
return new Promise(resolve => {
|
||||
let observe = (subject, topic, data) => {
|
||||
Services.obs.removeObserver(observe, 'a11y-init-or-shutdown');
|
||||
resolve(data);
|
||||
};
|
||||
Services.obs.addObserver(observe, 'a11y-init-or-shutdown', false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the accessible tree starting from a given accessible as a root and
|
||||
* looks for an accessible that matches based on its DOMNode id.
|
||||
* @param {nsIAccessible} accessible root accessible
|
||||
* @param {String} id id to look up accessible for
|
||||
* @return {nsIAccessible?} found accessible if any
|
||||
* Returns a promise that resolves when 'a11y-init-or-shutdown' event is fired
|
||||
* in content.
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @return {Promise} event promise evaluating to event's data
|
||||
*/
|
||||
function findAccessibleChildByID(accessible, id) {
|
||||
if (getAccessibleDOMNodeID(accessible) === id) {
|
||||
return accessible;
|
||||
}
|
||||
for (let i = 0; i < accessible.children.length; ++i) {
|
||||
let found = findAccessibleChildByID(accessible.getChildAt(i), id);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
function contentA11yInitOrShutdownPromise(browser) {
|
||||
return ContentTask.spawn(browser, {}, a11yInitOrShutdownPromise);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a list of scripts into the test
|
||||
* @param {Array} scripts a list of scripts to load
|
||||
* A helper function that maps 'a11y-init-or-shutdown' event to a promise that
|
||||
* resovles or rejects depending on whether accessibility service is expected to
|
||||
* be initialized or shut down.
|
||||
*/
|
||||
function loadScripts(...scripts) {
|
||||
for (let script of scripts) {
|
||||
let path = typeof script === 'string' ? `${CURRENT_DIR}${script}` :
|
||||
`${script.dir}${script.name}`;
|
||||
Services.scriptloader.loadSubScript(path, this);
|
||||
}
|
||||
function promiseOK(promise, expected) {
|
||||
return promise.then(flag =>
|
||||
flag === expected ? Promise.resolve() : Promise.reject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a list of frame scripts into test's content.
|
||||
* @param {Object} browser browser element that content belongs to
|
||||
* @param {Array} scripts a list of scripts to load into content
|
||||
* Checks and returns a promise that resolves when accessibility service is
|
||||
* initialized with the correct flag.
|
||||
* @param {?Object} contentBrowser optinal remove browser object that indicates
|
||||
* that accessibility service is expected to be
|
||||
* initialized in content process.
|
||||
* @return {Promise} promise that resolves when the accessibility
|
||||
* service initialized correctly.
|
||||
*/
|
||||
function loadFrameScripts(browser, ...scripts) {
|
||||
let mm = browser.messageManager;
|
||||
for (let script of scripts) {
|
||||
let frameScript;
|
||||
if (typeof script === 'string') {
|
||||
if (script.includes('.js')) {
|
||||
// If script string includes a .js extention, assume it is a script
|
||||
// path.
|
||||
frameScript = `${CURRENT_DIR}${script}`;
|
||||
} else {
|
||||
// Otherwise it is a serealized script.
|
||||
frameScript = `data:,${script}`;
|
||||
}
|
||||
} else {
|
||||
// Script is a object that has { dir, name } format.
|
||||
frameScript = `${script.dir}${script.name}`;
|
||||
}
|
||||
mm.loadFrameScript(frameScript, false, true);
|
||||
}
|
||||
function initPromise(contentBrowser) {
|
||||
let a11yInitPromise = contentBrowser ?
|
||||
contentA11yInitOrShutdownPromise(contentBrowser) :
|
||||
a11yInitOrShutdownPromise();
|
||||
return promiseOK(a11yInitPromise, '1').then(
|
||||
() => ok(true, 'Service initialized correctly'),
|
||||
() => ok(false, 'Service shutdown incorrectly'));
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around browser test add_task that triggers an accessible test task
|
||||
* as a new browser test task with given document, data URL or markup snippet.
|
||||
* @param {String} doc URL (relative to current directory) or
|
||||
* data URL or markup snippet that is used
|
||||
* to test content with
|
||||
* @param {Function|Function*} task a generator or a function with tests to
|
||||
* run
|
||||
* Checks and returns a promise that resolves when accessibility service is
|
||||
* shut down with the correct flag.
|
||||
* @param {?Object} contentBrowser optinal remove browser object that indicates
|
||||
* that accessibility service is expected to be
|
||||
* shut down in content process.
|
||||
* @return {Promise} promise that resolves when the accessibility
|
||||
* service shuts down correctly.
|
||||
*/
|
||||
function addAccessibleTask(doc, task) {
|
||||
add_task(function*() {
|
||||
let url;
|
||||
if (doc.includes('doc_')) {
|
||||
url = `${CURRENT_CONTENT_DIR}${doc}`;
|
||||
} else {
|
||||
// Assume it's a markup snippet.
|
||||
url = `data:text/html,
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Accessibility Test</title>
|
||||
</head>
|
||||
<body id="body">${doc}</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
let observers = Services.obs.enumerateObservers('accessible-event');
|
||||
while (observers.hasMoreElements()) {
|
||||
Services.obs.removeObserver(
|
||||
observers.getNext().QueryInterface(Ci.nsIObserver),
|
||||
'accessible-event');
|
||||
}
|
||||
});
|
||||
|
||||
let onDocLoad = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, 'body');
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: url
|
||||
}, function*(browser) {
|
||||
registerCleanupFunction(() => {
|
||||
if (browser) {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (tab && !tab.closing && tab.linkedBrowser) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
yield SimpleTest.promiseFocus(browser);
|
||||
|
||||
loadFrameScripts(browser,
|
||||
'let { document, window, navigator } = content;',
|
||||
{ name: 'common.js', dir: MOCHITESTS_DIR });
|
||||
|
||||
Logger.log(
|
||||
`e10s enabled: ${Services.appinfo.browserTabsRemoteAutostart}`);
|
||||
Logger.log(`Actually remote browser: ${browser.isRemoteBrowser}`);
|
||||
|
||||
let event = yield onDocLoad;
|
||||
yield task(browser, event.accessible);
|
||||
});
|
||||
});
|
||||
function shutdownPromise(contentBrowser) {
|
||||
let a11yShutdownPromise = contentBrowser ?
|
||||
contentA11yInitOrShutdownPromise(contentBrowser) :
|
||||
a11yInitOrShutdownPromise();
|
||||
return promiseOK(a11yShutdownPromise, '0').then(
|
||||
() => ok(true, 'Service shutdown correctly'),
|
||||
() => ok(false, 'Service initialized incorrectly'));
|
||||
}
|
||||
|
||||
// Loading and common.js from accessible/tests/mochitest/ for all tests, as well
|
||||
// as events.js.
|
||||
loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR }, 'events.js');
|
||||
/**
|
||||
* Force garbage collection.
|
||||
*/
|
||||
function forceGC() {
|
||||
Cu.forceCC();
|
||||
Cu.forceGC();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
/* exported Logger, MOCHITESTS_DIR, isDefunct, invokeSetAttribute, invokeFocus,
|
||||
invokeSetStyle, findAccessibleChildByID, getAccessibleDOMNodeID,
|
||||
CURRENT_CONTENT_DIR, loadScripts, loadFrameScripts, Cc, Cu */
|
||||
|
||||
const { interfaces: Ci, utils: Cu, classes: Cc } = Components;
|
||||
|
||||
/**
|
||||
* Current browser test directory path used to load subscripts.
|
||||
*/
|
||||
const CURRENT_DIR =
|
||||
'chrome://mochitests/content/browser/accessible/tests/browser/';
|
||||
/**
|
||||
* A11y mochitest directory where we find common files used in both browser and
|
||||
* plain tests.
|
||||
*/
|
||||
const MOCHITESTS_DIR =
|
||||
'chrome://mochitests/content/a11y/accessible/tests/mochitest/';
|
||||
/**
|
||||
* A base URL for test files used in content.
|
||||
*/
|
||||
const CURRENT_CONTENT_DIR =
|
||||
'http://example.com/browser/accessible/tests/browser/';
|
||||
|
||||
/**
|
||||
* Used to dump debug information.
|
||||
*/
|
||||
let Logger = {
|
||||
/**
|
||||
* Set up this variable to dump log messages into console.
|
||||
*/
|
||||
dumpToConsole: false,
|
||||
|
||||
/**
|
||||
* Set up this variable to dump log messages into error console.
|
||||
*/
|
||||
dumpToAppConsole: false,
|
||||
|
||||
/**
|
||||
* Return true if dump is enabled.
|
||||
*/
|
||||
get enabled() {
|
||||
return this.dumpToConsole || this.dumpToAppConsole;
|
||||
},
|
||||
|
||||
/**
|
||||
* Dump information into console if applicable.
|
||||
*/
|
||||
log(msg) {
|
||||
if (this.enabled) {
|
||||
this.logToConsole(msg);
|
||||
this.logToAppConsole(msg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Log message to console.
|
||||
*/
|
||||
logToConsole(msg) {
|
||||
if (this.dumpToConsole) {
|
||||
dump(`\n${msg}\n`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Log message to error console.
|
||||
*/
|
||||
logToAppConsole(msg) {
|
||||
if (this.dumpToAppConsole) {
|
||||
Services.console.logStringMessage(`${msg}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if an accessible object has a defunct test.
|
||||
* @param {nsIAccessible} accessible object to test defunct state for
|
||||
* @return {Boolean} flag indicating defunct state
|
||||
*/
|
||||
function isDefunct(accessible) {
|
||||
let defunct = false;
|
||||
try {
|
||||
let extState = {};
|
||||
accessible.getState({}, extState);
|
||||
defunct = extState.value & Ci.nsIAccessibleStates.EXT_STATE_DEFUNCT;
|
||||
} catch (x) {
|
||||
defunct = true;
|
||||
} finally {
|
||||
if (defunct) {
|
||||
Logger.log(`Defunct accessible: ${prettyName(accessible)}`);
|
||||
}
|
||||
}
|
||||
return defunct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously set or remove content element's attribute (in content process
|
||||
* if e10s is enabled).
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @param {String} id content element id
|
||||
* @param {String} attr attribute name
|
||||
* @param {String?} value optional attribute value, if not present, remove
|
||||
* attribute
|
||||
* @return {Promise} promise indicating that attribute is set/removed
|
||||
*/
|
||||
function invokeSetAttribute(browser, id, attr, value) {
|
||||
if (value) {
|
||||
Logger.log(`Setting ${attr} attribute to ${value} for node with id: ${id}`);
|
||||
} else {
|
||||
Logger.log(`Removing ${attr} attribute from node with id: ${id}`);
|
||||
}
|
||||
return ContentTask.spawn(browser, { id, attr, value },
|
||||
({ id, attr, value }) => {
|
||||
let elm = content.document.getElementById(id);
|
||||
if (value) {
|
||||
elm.setAttribute(attr, value);
|
||||
} else {
|
||||
elm.removeAttribute(attr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously set or remove content element's style (in content process if
|
||||
* e10s is enabled).
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @param {String} id content element id
|
||||
* @param {String} aStyle style property name
|
||||
* @param {String?} aValue optional style property value, if not present,
|
||||
* remove style
|
||||
* @return {Promise} promise indicating that style is set/removed
|
||||
*/
|
||||
function invokeSetStyle(browser, id, style, value) {
|
||||
if (value) {
|
||||
Logger.log(`Setting ${style} style to ${value} for node with id: ${id}`);
|
||||
} else {
|
||||
Logger.log(`Removing ${style} style from node with id: ${id}`);
|
||||
}
|
||||
return ContentTask.spawn(browser, { id, style, value },
|
||||
({ id, style, value }) => {
|
||||
let elm = content.document.getElementById(id);
|
||||
if (value) {
|
||||
elm.style[style] = value;
|
||||
} else {
|
||||
delete elm.style[style];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously set focus on a content element (in content process if e10s is
|
||||
* enabled).
|
||||
* @param {Object} browser current "tabbrowser" element
|
||||
* @param {String} id content element id
|
||||
* @return {Promise} promise indicating that focus is set
|
||||
*/
|
||||
function invokeFocus(browser, id) {
|
||||
Logger.log(`Setting focus on a node with id: ${id}`);
|
||||
return ContentTask.spawn(browser, id, id => {
|
||||
let elm = content.document.getElementById(id);
|
||||
if (elm instanceof Ci.nsIDOMNSEditableElement && elm.editor ||
|
||||
elm instanceof Ci.nsIDOMXULTextBoxElement) {
|
||||
elm.selectionStart = elm.selectionEnd = elm.value.length;
|
||||
}
|
||||
elm.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the accessible tree starting from a given accessible as a root and
|
||||
* looks for an accessible that matches based on its DOMNode id.
|
||||
* @param {nsIAccessible} accessible root accessible
|
||||
* @param {String} id id to look up accessible for
|
||||
* @return {nsIAccessible?} found accessible if any
|
||||
*/
|
||||
function findAccessibleChildByID(accessible, id) {
|
||||
if (getAccessibleDOMNodeID(accessible) === id) {
|
||||
return accessible;
|
||||
}
|
||||
for (let i = 0; i < accessible.children.length; ++i) {
|
||||
let found = findAccessibleChildByID(accessible.getChildAt(i), id);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a list of scripts into the test
|
||||
* @param {Array} scripts a list of scripts to load
|
||||
*/
|
||||
function loadScripts(...scripts) {
|
||||
for (let script of scripts) {
|
||||
let path = typeof script === 'string' ? `${CURRENT_DIR}${script}` :
|
||||
`${script.dir}${script.name}`;
|
||||
Services.scriptloader.loadSubScript(path, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a list of frame scripts into test's content.
|
||||
* @param {Object} browser browser element that content belongs to
|
||||
* @param {Array} scripts a list of scripts to load into content
|
||||
*/
|
||||
function loadFrameScripts(browser, ...scripts) {
|
||||
let mm = browser.messageManager;
|
||||
for (let script of scripts) {
|
||||
let frameScript;
|
||||
if (typeof script === 'string') {
|
||||
if (script.includes('.js')) {
|
||||
// If script string includes a .js extention, assume it is a script
|
||||
// path.
|
||||
frameScript = `${CURRENT_DIR}${script}`;
|
||||
} else {
|
||||
// Otherwise it is a serealized script.
|
||||
frameScript = `data:,${script}`;
|
||||
}
|
||||
} else {
|
||||
// Script is a object that has { dir, name } format.
|
||||
frameScript = `${script.dir}${script.name}`;
|
||||
}
|
||||
mm.loadFrameScript(frameScript, false, true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
[DEFAULT]
|
||||
|
||||
[test_general.html]
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Accessibility API: generic</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const finish = SimpleTest.finish.bind(SimpleTest);
|
||||
enablePref()
|
||||
.then(createIframe)
|
||||
.then(checkImplementation)
|
||||
.catch(err => {
|
||||
dump(`${err}: ${err.stack}`);
|
||||
finish();
|
||||
});
|
||||
|
||||
function enablePref() {
|
||||
const ops = {
|
||||
"set": [
|
||||
[ "accessibility.AOM.enabled", true ],
|
||||
],
|
||||
};
|
||||
return SpecialPowers.pushPrefEnv(ops);
|
||||
}
|
||||
|
||||
// WebIDL conditional annotations for an interface are evaluated once per
|
||||
// global, so we need to create an iframe to see the effects of calling
|
||||
// enablePref().
|
||||
function createIframe() {
|
||||
return new Promise((resolve) => {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.src = "about:blank";
|
||||
iframe.onload = () => resolve(iframe.contentDocument);
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
// Check that the WebIDL is as expected.
|
||||
function checkImplementation(ifrDoc) {
|
||||
let anode = ifrDoc.accessibleNode;
|
||||
ok(anode, "DOM document has accessible node");
|
||||
|
||||
is(anode.role, 'document', 'correct role of a document accessible node');
|
||||
is(anode.DOMNode, ifrDoc, 'correct DOM Node of a document accessible node');
|
||||
|
||||
finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
|
@ -7,6 +7,7 @@
|
|||
A11Y_MANIFESTS += [
|
||||
'a11y.ini',
|
||||
'actions/a11y.ini',
|
||||
'aom/a11y.ini',
|
||||
'attributes/a11y.ini',
|
||||
'bounds/a11y.ini',
|
||||
'editabletext/a11y.ini',
|
||||
|
|
|
@ -618,7 +618,6 @@ pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 0);
|
|||
pref("javascript.options.mem.gc_low_frequency_heap_growth", 120);
|
||||
pref("javascript.options.mem.high_water_mark", 6);
|
||||
pref("javascript.options.mem.gc_allocation_threshold_mb", 1);
|
||||
pref("javascript.options.mem.gc_decommit_threshold_mb", 1);
|
||||
pref("javascript.options.mem.gc_min_empty_chunk_count", 1);
|
||||
pref("javascript.options.mem.gc_max_empty_chunk_count", 2);
|
||||
|
||||
|
|
|
@ -762,6 +762,7 @@ html|*#fullscreen-exit-button {
|
|||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.blocked-permission-icon:not([showing]),
|
||||
.notification-anchor-icon:not([showing]) {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -692,19 +692,19 @@
|
|||
onclick="PageProxyClickHandler(event);"/>
|
||||
<image id="sharing-icon" mousethrough="always"/>
|
||||
<box id="blocked-permissions-container" align="center" tooltiptext="">
|
||||
<image data-permission-id="geo" class="notification-anchor-icon geo-icon blocked" role="button"
|
||||
<image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button"
|
||||
aria-label="&urlbar.geolocationNotificationAnchor.label;"/>
|
||||
<image data-permission-id="desktop-notification" class="notification-anchor-icon desktop-notification-icon blocked" role="button"
|
||||
<image data-permission-id="desktop-notification" class="blocked-permission-icon desktop-notification-icon" role="button"
|
||||
aria-label="&urlbar.webNotsNotificationAnchor3.label;"/>
|
||||
<image data-permission-id="camera" class="notification-anchor-icon camera-icon blocked" role="button"
|
||||
<image data-permission-id="camera" class="blocked-permission-icon camera-icon" role="button"
|
||||
aria-label="&urlbar.webRTCShareDevicesNotificationAnchor.label;"/>
|
||||
<image data-permission-id="indexedDB" class="notification-anchor-icon indexedDB-icon blocked" role="button"
|
||||
<image data-permission-id="indexedDB" class="blocked-permission-icon indexedDB-icon" role="button"
|
||||
aria-label="&urlbar.indexedDBNotificationAnchor.label;"/>
|
||||
<image data-permission-id="microphone" class="notification-anchor-icon microphone-icon blocked" role="button"
|
||||
<image data-permission-id="microphone" class="blocked-permission-icon microphone-icon" role="button"
|
||||
aria-label="&urlbar.webRTCShareMicrophoneNotificationAnchor.label;"/>
|
||||
<image data-permission-id="screen" class="notification-anchor-icon screen-icon blocked" role="button"
|
||||
<image data-permission-id="screen" class="blocked-permission-icon screen-icon" role="button"
|
||||
aria-label="&urlbar.webRTCShareScreenNotificationAnchor.label;"/>
|
||||
<image data-permission-id="pointerLock" class="notification-anchor-icon pointerLock-icon blocked" role="button"
|
||||
<image data-permission-id="pointerLock" class="blocked-permission-icon pointerLock-icon" role="button"
|
||||
aria-label="&urlbar.pointerLockNotificationAnchor.label;"/>
|
||||
</box>
|
||||
<box id="notification-popup-box"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
}
|
||||
|
||||
.tab-close-button[pinned],
|
||||
.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([visuallyselected="true"]),
|
||||
.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([selected="true"]),
|
||||
.tab-icon-image:not([src]):not([pinned]):not([crashed])[selected],
|
||||
.tab-icon-image:not([src]):not([pinned]):not([crashed]):not([sharing]),
|
||||
.tab-icon-image[busy],
|
||||
|
|
|
@ -6245,44 +6245,44 @@
|
|||
|
||||
<content context="tabContextMenu">
|
||||
<xul:stack class="tab-stack" flex="1">
|
||||
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,fadein"
|
||||
<xul:hbox xbl:inherits="pinned,selected=visuallyselected,fadein"
|
||||
class="tab-background">
|
||||
<xul:hbox xbl:inherits="pinned,selected,visuallyselected"
|
||||
<xul:hbox xbl:inherits="pinned,selected=visuallyselected"
|
||||
class="tab-background-start"/>
|
||||
<xul:hbox xbl:inherits="pinned,selected,visuallyselected"
|
||||
<xul:hbox xbl:inherits="pinned,selected=visuallyselected"
|
||||
class="tab-background-middle"/>
|
||||
<xul:hbox xbl:inherits="pinned,selected,visuallyselected"
|
||||
<xul:hbox xbl:inherits="pinned,selected=visuallyselected"
|
||||
class="tab-background-end"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,titlechanged,attention"
|
||||
<xul:hbox xbl:inherits="pinned,selected=visuallyselected,titlechanged,attention"
|
||||
class="tab-content" align="center">
|
||||
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected,visuallyselected"
|
||||
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected=visuallyselected"
|
||||
class="tab-throbber"
|
||||
role="presentation"
|
||||
layer="true" />
|
||||
<xul:image xbl:inherits="src=image,fadein,pinned,selected,visuallyselected,busy,crashed,sharing"
|
||||
<xul:image xbl:inherits="src=image,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
|
||||
anonid="tab-icon-image"
|
||||
class="tab-icon-image"
|
||||
validate="never"
|
||||
role="presentation"/>
|
||||
<xul:image xbl:inherits="sharing,selected"
|
||||
<xul:image xbl:inherits="sharing,selected=visuallyselected"
|
||||
anonid="sharing-icon"
|
||||
class="tab-sharing-icon-overlay"
|
||||
role="presentation"/>
|
||||
<xul:image xbl:inherits="crashed,busy,soundplaying,pinned,muted,visuallyselected"
|
||||
<xul:image xbl:inherits="crashed,busy,soundplaying,pinned,muted,selected=visuallyselected"
|
||||
anonid="overlay-icon"
|
||||
class="tab-icon-overlay"
|
||||
role="presentation"/>
|
||||
<xul:label flex="1"
|
||||
xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected,visuallyselected,attention"
|
||||
xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected=visuallyselected,attention"
|
||||
class="tab-text tab-label"
|
||||
role="presentation"/>
|
||||
<xul:image xbl:inherits="soundplaying,pinned,muted,visuallyselected"
|
||||
<xul:image xbl:inherits="soundplaying,pinned,muted,selected=visuallyselected"
|
||||
anonid="soundplaying-icon"
|
||||
class="tab-icon-sound"
|
||||
role="presentation"/>
|
||||
<xul:toolbarbutton anonid="close-button"
|
||||
xbl:inherits="fadein,pinned,selected,visuallyselected"
|
||||
xbl:inherits="fadein,pinned,selected=visuallyselected"
|
||||
class="tab-close-button close-icon"/>
|
||||
</xul:hbox>
|
||||
</xul:stack>
|
||||
|
|
|
@ -186,8 +186,6 @@ add_task(function* testPermissionIcons() {
|
|||
|
||||
let geoIcon = gIdentityHandler._identityBox.querySelector("[data-permission-id='geo']");
|
||||
ok(geoIcon.hasAttribute("showing"), "blocked permission icon is shown");
|
||||
ok(geoIcon.classList.contains("blocked"),
|
||||
"blocked permission icon is shown as blocked");
|
||||
|
||||
let cameraIcon = gIdentityHandler._identityBox.querySelector("[data-permission-id='camera']");
|
||||
ok(!cameraIcon.hasAttribute("showing"),
|
||||
|
|
|
@ -42,7 +42,7 @@ var gTests = [
|
|||
|
||||
// After selecting a new tab, check the attribute is still there,
|
||||
// and the icon is now visible.
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
yield BrowserTestUtils.switchTab(gBrowser, gBrowser.addTab());
|
||||
is(gBrowser.selectedTab.getAttribute("sharing"), "",
|
||||
"the new tab doesn't have the 'sharing' attribute");
|
||||
is(tab.getAttribute("sharing"), aSharing,
|
||||
|
@ -51,7 +51,7 @@ var gTests = [
|
|||
"the animated sharing icon of the tab is now visible");
|
||||
|
||||
// Ensure the icon disappears when selecting the tab.
|
||||
gBrowser.removeCurrentTab();
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
ok(tab.selected, "the tab with ongoing sharing is selected again");
|
||||
is(window.getComputedStyle(icon).display, "none",
|
||||
"the animated sharing icon is gone after selecting the tab again");
|
||||
|
|
|
@ -25,3 +25,4 @@ tags = openwindow
|
|||
[browser_blobUrl.js]
|
||||
[browser_middleClick.js]
|
||||
[browser_imageCache.js]
|
||||
[browser_count_and_remove.js]
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/ContextualIdentityService.jsm");
|
||||
|
||||
function openTabInUserContext(userContextId) {
|
||||
let tab = gBrowser.addTab("about:blank", {userContextId});
|
||||
gBrowser.selectedTab = tab;
|
||||
}
|
||||
|
||||
add_task(function* setup() {
|
||||
// make sure userContext is enabled.
|
||||
yield SpecialPowers.pushPrefEnv({"set": [
|
||||
["privacy.userContext.enabled", true]
|
||||
]});
|
||||
});
|
||||
|
||||
add_task(function* test() {
|
||||
is(ContextualIdentityService.countContainerTabs(), 0, "0 container tabs by default.");
|
||||
|
||||
openTabInUserContext(1);
|
||||
is(ContextualIdentityService.countContainerTabs(), 1, "1 container tab created");
|
||||
|
||||
openTabInUserContext(1);
|
||||
is(ContextualIdentityService.countContainerTabs(), 2, "2 container tab created");
|
||||
|
||||
openTabInUserContext(2);
|
||||
is(ContextualIdentityService.countContainerTabs(), 3, "3 container tab created");
|
||||
|
||||
ContextualIdentityService.closeAllContainerTabs();
|
||||
is(ContextualIdentityService.countContainerTabs(), 0, "0 container tab at the end.");
|
||||
});
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
head_pageAction.js
|
||||
context.html
|
||||
ctxmenu-image.png
|
||||
context_tabs_onUpdated_page.html
|
||||
|
@ -44,6 +45,7 @@ tags = webextensions
|
|||
[browser_ext_pageAction_popup.js]
|
||||
[browser_ext_pageAction_popup_resize.js]
|
||||
[browser_ext_pageAction_simple.js]
|
||||
[browser_ext_pageAction_title.js]
|
||||
[browser_ext_popup_api_injection.js]
|
||||
[browser_ext_popup_background.js]
|
||||
[browser_ext_popup_corners.js]
|
||||
|
|
|
@ -2,160 +2,10 @@
|
|||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
function* runTests(options) {
|
||||
function background(getTests) {
|
||||
let tabs;
|
||||
let tests;
|
||||
/* global runTests */
|
||||
|
||||
// Gets the current details of the page action, and returns a
|
||||
// promise that resolves to an object containing them.
|
||||
function getDetails() {
|
||||
return new Promise(resolve => {
|
||||
return browser.tabs.query({active: true, currentWindow: true}, resolve);
|
||||
}).then(([tab]) => {
|
||||
let tabId = tab.id;
|
||||
browser.test.log(`Get details: tab={id: ${tabId}, url: ${JSON.stringify(tab.url)}}`);
|
||||
return Promise.all([
|
||||
browser.pageAction.getTitle({tabId}),
|
||||
browser.pageAction.getPopup({tabId})]);
|
||||
}).then(details => {
|
||||
return Promise.resolve({title: details[0],
|
||||
popup: details[1]});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Runs the next test in the `tests` array, checks the results,
|
||||
// and passes control back to the outer test scope.
|
||||
function nextTest() {
|
||||
let test = tests.shift();
|
||||
|
||||
test(expecting => {
|
||||
function finish() {
|
||||
// Check that the actual icon has the expected values, then
|
||||
// run the next test.
|
||||
browser.test.sendMessage("nextTest", expecting, tests.length);
|
||||
}
|
||||
|
||||
if (expecting) {
|
||||
// Check that the API returns the expected values, and then
|
||||
// run the next test.
|
||||
getDetails().then(details => {
|
||||
browser.test.assertEq(expecting.title, details.title,
|
||||
"expected value from getTitle");
|
||||
|
||||
browser.test.assertEq(expecting.popup, details.popup,
|
||||
"expected value from getPopup");
|
||||
|
||||
finish();
|
||||
});
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
tabs = [];
|
||||
tests = getTests(tabs);
|
||||
|
||||
browser.tabs.query({active: true, currentWindow: true}, resultTabs => {
|
||||
tabs[0] = resultTabs[0].id;
|
||||
|
||||
nextTest();
|
||||
});
|
||||
}
|
||||
|
||||
browser.test.onMessage.addListener((msg) => {
|
||||
if (msg == "runTests") {
|
||||
runTests();
|
||||
} else if (msg == "runNextTest") {
|
||||
nextTest();
|
||||
} else {
|
||||
browser.test.fail(`Unexpected message: ${msg}`);
|
||||
}
|
||||
});
|
||||
|
||||
runTests();
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: options.manifest,
|
||||
|
||||
files: options.files || {},
|
||||
|
||||
background: `(${background})(${options.getTests})`,
|
||||
});
|
||||
|
||||
let pageActionId;
|
||||
let currentWindow = window;
|
||||
let windows = [];
|
||||
|
||||
function checkDetails(details) {
|
||||
let image = currentWindow.document.getElementById(pageActionId);
|
||||
if (details == null) {
|
||||
ok(image == null || image.hidden, "image is hidden");
|
||||
} else {
|
||||
ok(image, "image exists");
|
||||
|
||||
is(getListStyleImage(image), details.icon, "icon URL is correct");
|
||||
|
||||
let title = details.title || options.manifest.name;
|
||||
is(image.getAttribute("tooltiptext"), title, "image title is correct");
|
||||
is(image.getAttribute("aria-label"), title, "image aria-label is correct");
|
||||
// TODO: Popup URL.
|
||||
}
|
||||
}
|
||||
|
||||
let testNewWindows = 1;
|
||||
|
||||
let awaitFinish = new Promise(resolve => {
|
||||
extension.onMessage("nextTest", (expecting, testsRemaining) => {
|
||||
if (!pageActionId) {
|
||||
pageActionId = `${makeWidgetId(extension.id)}-page-action`;
|
||||
}
|
||||
|
||||
checkDetails(expecting);
|
||||
|
||||
if (testsRemaining) {
|
||||
extension.sendMessage("runNextTest");
|
||||
} else if (testNewWindows) {
|
||||
testNewWindows--;
|
||||
|
||||
BrowserTestUtils.openNewBrowserWindow().then(window => {
|
||||
windows.push(window);
|
||||
currentWindow = window;
|
||||
return focusWindow(window);
|
||||
}).then(() => {
|
||||
extension.sendMessage("runTests");
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({set: [["general.useragent.locale", "es-ES"]]});
|
||||
|
||||
yield extension.startup();
|
||||
|
||||
yield awaitFinish;
|
||||
|
||||
yield extension.unload();
|
||||
|
||||
yield SpecialPowers.popPrefEnv();
|
||||
|
||||
let node = document.getElementById(pageActionId);
|
||||
is(node, null, "pageAction image removed from document");
|
||||
|
||||
currentWindow = null;
|
||||
for (let win of windows.splice(0)) {
|
||||
node = win.document.getElementById(pageActionId);
|
||||
is(node, null, "pageAction image removed from second document");
|
||||
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
}
|
||||
}
|
||||
Services.scriptloader.loadSubScript(new URL("head_pageAction.js", gTestPath).href,
|
||||
this);
|
||||
|
||||
add_task(function* testTabSwitchContext() {
|
||||
yield runTests({
|
||||
|
@ -329,55 +179,3 @@ add_task(function* testTabSwitchContext() {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* testDefaultTitle() {
|
||||
yield runTests({
|
||||
manifest: {
|
||||
"name": "Foo Extension",
|
||||
|
||||
"page_action": {
|
||||
"default_icon": "icon.png",
|
||||
},
|
||||
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
files: {
|
||||
"icon.png": imageBuffer,
|
||||
},
|
||||
|
||||
getTests(tabs) {
|
||||
let details = [
|
||||
{"title": "Foo Extension",
|
||||
"popup": "",
|
||||
"icon": browser.runtime.getURL("icon.png")},
|
||||
{"title": "Foo Title",
|
||||
"popup": "",
|
||||
"icon": browser.runtime.getURL("icon.png")},
|
||||
];
|
||||
|
||||
return [
|
||||
expect => {
|
||||
browser.test.log("Initial state. No icon visible.");
|
||||
expect(null);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Show the icon on the first tab, expect extension title as default title.");
|
||||
browser.pageAction.show(tabs[0]).then(() => {
|
||||
expect(details[0]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Change the title. Expect new title.");
|
||||
browser.pageAction.setTitle({tabId: tabs[0], title: "Foo Title"});
|
||||
expect(details[1]);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Clear the title. Expect extension title.");
|
||||
browser.pageAction.setTitle({tabId: tabs[0], title: ""});
|
||||
expect(details[0]);
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
/* global runTests */
|
||||
|
||||
Services.scriptloader.loadSubScript(new URL("head_pageAction.js", gTestPath).href,
|
||||
this);
|
||||
|
||||
add_task(function* testTabSwitchContext() {
|
||||
yield runTests({
|
||||
manifest: {
|
||||
"name": "Foo Extension",
|
||||
|
||||
"page_action": {
|
||||
"default_icon": "default.png",
|
||||
"default_popup": "__MSG_popup__",
|
||||
"default_title": "Default __MSG_title__ \u263a",
|
||||
},
|
||||
|
||||
"default_locale": "en",
|
||||
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
"files": {
|
||||
"_locales/en/messages.json": {
|
||||
"popup": {
|
||||
"message": "default.html",
|
||||
"description": "Popup",
|
||||
},
|
||||
|
||||
"title": {
|
||||
"message": "Title",
|
||||
"description": "Title",
|
||||
},
|
||||
},
|
||||
|
||||
"_locales/es_ES/messages.json": {
|
||||
"popup": {
|
||||
"message": "default.html",
|
||||
"description": "Popup",
|
||||
},
|
||||
|
||||
"title": {
|
||||
"message": "T\u00edtulo",
|
||||
"description": "Title",
|
||||
},
|
||||
},
|
||||
|
||||
"default.png": imageBuffer,
|
||||
"1.png": imageBuffer,
|
||||
"2.png": imageBuffer,
|
||||
},
|
||||
|
||||
getTests(tabs) {
|
||||
let details = [
|
||||
{"icon": browser.runtime.getURL("default.png"),
|
||||
"popup": browser.runtime.getURL("default.html"),
|
||||
"title": "Default T\u00edtulo \u263a"},
|
||||
{"icon": browser.runtime.getURL("1.png"),
|
||||
"popup": browser.runtime.getURL("default.html"),
|
||||
"title": "Default T\u00edtulo \u263a"},
|
||||
{"icon": browser.runtime.getURL("2.png"),
|
||||
"popup": browser.runtime.getURL("2.html"),
|
||||
"title": "Title 2"},
|
||||
{"icon": browser.runtime.getURL("2.png"),
|
||||
"popup": browser.runtime.getURL("2.html"),
|
||||
"title": "Default T\u00edtulo \u263a"},
|
||||
];
|
||||
|
||||
let promiseTabLoad = details => {
|
||||
return new Promise(resolve => {
|
||||
browser.tabs.onUpdated.addListener(function listener(tabId, changed) {
|
||||
if (tabId == details.id && changed.url == details.url) {
|
||||
browser.tabs.onUpdated.removeListener(listener);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return [
|
||||
expect => {
|
||||
browser.test.log("Initial state. No icon visible.");
|
||||
expect(null);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Show the icon on the first tab, expect default properties.");
|
||||
browser.pageAction.show(tabs[0]).then(() => {
|
||||
expect(details[0]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Change the icon. Expect default properties excluding the icon.");
|
||||
browser.pageAction.setIcon({tabId: tabs[0], path: "1.png"});
|
||||
expect(details[1]);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Create a new tab. No icon visible.");
|
||||
browser.tabs.create({active: true, url: "about:blank?0"}, tab => {
|
||||
tabs.push(tab.id);
|
||||
expect(null);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Await tab load. No icon visible.");
|
||||
expect(null);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Change properties. Expect new properties.");
|
||||
let tabId = tabs[1];
|
||||
browser.pageAction.show(tabId).then(() => {
|
||||
browser.pageAction.setIcon({tabId, path: "2.png"});
|
||||
browser.pageAction.setPopup({tabId, popup: "2.html"});
|
||||
browser.pageAction.setTitle({tabId, title: "Title 2"});
|
||||
|
||||
expect(details[2]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Change the hash. Expect same properties.");
|
||||
|
||||
promiseTabLoad({id: tabs[1], url: "about:blank?0#ref"}).then(() => {
|
||||
expect(details[2]);
|
||||
});
|
||||
|
||||
browser.tabs.update(tabs[1], {url: "about:blank?0#ref"});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Clear the title. Expect default title.");
|
||||
browser.pageAction.setTitle({tabId: tabs[1], title: ""});
|
||||
|
||||
expect(details[3]);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Navigate to a new page. Expect icon hidden.");
|
||||
|
||||
// TODO: This listener should not be necessary, but the |tabs.update|
|
||||
// callback currently fires too early in e10s windows.
|
||||
promiseTabLoad({id: tabs[1], url: "about:blank?1"}).then(() => {
|
||||
expect(null);
|
||||
});
|
||||
|
||||
browser.tabs.update(tabs[1], {url: "about:blank?1"});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Show the icon. Expect default properties again.");
|
||||
browser.pageAction.show(tabs[1]).then(() => {
|
||||
expect(details[0]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Switch back to the first tab. Expect previously set properties.");
|
||||
browser.tabs.update(tabs[0], {active: true}, () => {
|
||||
expect(details[1]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Hide the icon on tab 2. Switch back, expect hidden.");
|
||||
browser.pageAction.hide(tabs[1]).then(() => {
|
||||
browser.tabs.update(tabs[1], {active: true}, () => {
|
||||
expect(null);
|
||||
});
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Switch back to tab 1. Expect previous results again.");
|
||||
browser.tabs.remove(tabs[1], () => {
|
||||
expect(details[1]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Hide the icon. Expect hidden.");
|
||||
browser.pageAction.hide(tabs[0]).then(() => {
|
||||
expect(null);
|
||||
});
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* testDefaultTitle() {
|
||||
yield runTests({
|
||||
manifest: {
|
||||
"name": "Foo Extension",
|
||||
|
||||
"page_action": {
|
||||
"default_icon": "icon.png",
|
||||
},
|
||||
|
||||
"permissions": ["tabs"],
|
||||
},
|
||||
|
||||
files: {
|
||||
"icon.png": imageBuffer,
|
||||
},
|
||||
|
||||
getTests(tabs) {
|
||||
let details = [
|
||||
{"title": "Foo Extension",
|
||||
"popup": "",
|
||||
"icon": browser.runtime.getURL("icon.png")},
|
||||
{"title": "Foo Title",
|
||||
"popup": "",
|
||||
"icon": browser.runtime.getURL("icon.png")},
|
||||
];
|
||||
|
||||
return [
|
||||
expect => {
|
||||
browser.test.log("Initial state. No icon visible.");
|
||||
expect(null);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Show the icon on the first tab, expect extension title as default title.");
|
||||
browser.pageAction.show(tabs[0]).then(() => {
|
||||
expect(details[0]);
|
||||
});
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Change the title. Expect new title.");
|
||||
browser.pageAction.setTitle({tabId: tabs[0], title: "Foo Title"});
|
||||
expect(details[1]);
|
||||
},
|
||||
expect => {
|
||||
browser.test.log("Clear the title. Expect extension title.");
|
||||
browser.pageAction.setTitle({tabId: tabs[0], title: ""});
|
||||
expect(details[0]);
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
});
|
|
@ -31,9 +31,11 @@ add_task(function* testExecuteScript() {
|
|||
return Promise.reject(new Error("Max tries exceeded"));
|
||||
}
|
||||
|
||||
let url = `${URL}?r=${Math.random()}`;
|
||||
|
||||
let loadingPromise = new Promise(resolve => {
|
||||
browser.tabs.onUpdated.addListener(function listener(tabId, changed, tab_) {
|
||||
if (tabId == tab.id && changed.status == "loading" && tab_.url == URL) {
|
||||
if (tabId == tab.id && changed.status == "loading" && tab_.url == url) {
|
||||
browser.tabs.onUpdated.removeListener(listener);
|
||||
resolve();
|
||||
}
|
||||
|
@ -42,7 +44,7 @@ add_task(function* testExecuteScript() {
|
|||
|
||||
// TODO: Test allFrames and frameId.
|
||||
|
||||
return browser.tabs.update({url: URL}).then(() => {
|
||||
return browser.tabs.update({url}).then(() => {
|
||||
return loadingPromise;
|
||||
}).then(() => {
|
||||
return Promise.all([
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
/* exported runTests */
|
||||
/* globals getListStyleImage */
|
||||
|
||||
function* runTests(options) {
|
||||
function background(getTests) {
|
||||
let tabs;
|
||||
let tests;
|
||||
|
||||
// Gets the current details of the page action, and returns a
|
||||
// promise that resolves to an object containing them.
|
||||
function getDetails() {
|
||||
return new Promise(resolve => {
|
||||
return browser.tabs.query({active: true, currentWindow: true}, resolve);
|
||||
}).then(([tab]) => {
|
||||
let tabId = tab.id;
|
||||
browser.test.log(`Get details: tab={id: ${tabId}, url: ${JSON.stringify(tab.url)}}`);
|
||||
return Promise.all([
|
||||
browser.pageAction.getTitle({tabId}),
|
||||
browser.pageAction.getPopup({tabId})]);
|
||||
}).then(details => {
|
||||
return Promise.resolve({title: details[0],
|
||||
popup: details[1]});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Runs the next test in the `tests` array, checks the results,
|
||||
// and passes control back to the outer test scope.
|
||||
function nextTest() {
|
||||
let test = tests.shift();
|
||||
|
||||
test(expecting => {
|
||||
function finish() {
|
||||
// Check that the actual icon has the expected values, then
|
||||
// run the next test.
|
||||
browser.test.sendMessage("nextTest", expecting, tests.length);
|
||||
}
|
||||
|
||||
if (expecting) {
|
||||
// Check that the API returns the expected values, and then
|
||||
// run the next test.
|
||||
getDetails().then(details => {
|
||||
browser.test.assertEq(expecting.title, details.title,
|
||||
"expected value from getTitle");
|
||||
|
||||
browser.test.assertEq(expecting.popup, details.popup,
|
||||
"expected value from getPopup");
|
||||
|
||||
finish();
|
||||
});
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
tabs = [];
|
||||
tests = getTests(tabs);
|
||||
|
||||
browser.tabs.query({active: true, currentWindow: true}, resultTabs => {
|
||||
tabs[0] = resultTabs[0].id;
|
||||
|
||||
nextTest();
|
||||
});
|
||||
}
|
||||
|
||||
browser.test.onMessage.addListener((msg) => {
|
||||
if (msg == "runTests") {
|
||||
runTests();
|
||||
} else if (msg == "runNextTest") {
|
||||
nextTest();
|
||||
} else {
|
||||
browser.test.fail(`Unexpected message: ${msg}`);
|
||||
}
|
||||
});
|
||||
|
||||
runTests();
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: options.manifest,
|
||||
|
||||
files: options.files || {},
|
||||
|
||||
background: `(${background})(${options.getTests})`,
|
||||
});
|
||||
|
||||
let pageActionId;
|
||||
let currentWindow = window;
|
||||
let windows = [];
|
||||
|
||||
function checkDetails(details) {
|
||||
let image = currentWindow.document.getElementById(pageActionId);
|
||||
if (details == null) {
|
||||
ok(image == null || image.hidden, "image is hidden");
|
||||
} else {
|
||||
ok(image, "image exists");
|
||||
|
||||
is(getListStyleImage(image), details.icon, "icon URL is correct");
|
||||
|
||||
let title = details.title || options.manifest.name;
|
||||
is(image.getAttribute("tooltiptext"), title, "image title is correct");
|
||||
is(image.getAttribute("aria-label"), title, "image aria-label is correct");
|
||||
// TODO: Popup URL.
|
||||
}
|
||||
}
|
||||
|
||||
let testNewWindows = 1;
|
||||
|
||||
let awaitFinish = new Promise(resolve => {
|
||||
extension.onMessage("nextTest", (expecting, testsRemaining) => {
|
||||
if (!pageActionId) {
|
||||
pageActionId = `${makeWidgetId(extension.id)}-page-action`;
|
||||
}
|
||||
|
||||
checkDetails(expecting);
|
||||
|
||||
if (testsRemaining) {
|
||||
extension.sendMessage("runNextTest");
|
||||
} else if (testNewWindows) {
|
||||
testNewWindows--;
|
||||
|
||||
BrowserTestUtils.openNewBrowserWindow().then(window => {
|
||||
windows.push(window);
|
||||
currentWindow = window;
|
||||
return focusWindow(window);
|
||||
}).then(() => {
|
||||
extension.sendMessage("runTests");
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({set: [["general.useragent.locale", "es-ES"]]});
|
||||
|
||||
yield extension.startup();
|
||||
|
||||
yield awaitFinish;
|
||||
|
||||
yield extension.unload();
|
||||
|
||||
yield SpecialPowers.popPrefEnv();
|
||||
|
||||
let node = document.getElementById(pageActionId);
|
||||
is(node, null, "pageAction image removed from document");
|
||||
|
||||
currentWindow = null;
|
||||
for (let win of windows.splice(0)) {
|
||||
node = win.document.getElementById(pageActionId);
|
||||
is(node, null, "pageAction image removed from second document");
|
||||
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,8 @@ const kPasswordManagerTopicTypes = new Set([
|
|||
"modifyLogin",
|
||||
]);
|
||||
|
||||
const kSyncTopic = "fxaccounts:onlogin";
|
||||
|
||||
const kNotificationId = "abouthome-automigration-undo";
|
||||
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
|
@ -46,24 +48,28 @@ const AutoMigrate = {
|
|||
},
|
||||
|
||||
maybeInitUndoObserver() {
|
||||
// Check synchronously (NB: canUndo is async) if we really need
|
||||
// to do this:
|
||||
if (!this.getUndoRange()) {
|
||||
if (!this.canUndo()) {
|
||||
return;
|
||||
}
|
||||
// Now register places and password observers:
|
||||
// Now register places, password and sync observers:
|
||||
this.onItemAdded = this.onItemMoved = this.onItemChanged =
|
||||
this.removeUndoOption;
|
||||
this.removeUndoOption.bind(this, this.UNDO_REMOVED_REASON_BOOKMARK_CHANGE);
|
||||
PlacesUtils.addLazyBookmarkObserver(this, true);
|
||||
Services.obs.addObserver(this, kPasswordManagerTopic, true);
|
||||
for (let topic of [kSyncTopic, kPasswordManagerTopic]) {
|
||||
Services.obs.addObserver(this, topic, true);
|
||||
}
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
// As soon as any login gets added or modified, disable undo:
|
||||
// (Note that this ignores logins being removed as that doesn't
|
||||
// impair the 'undo' functionality of the import.)
|
||||
if (kPasswordManagerTopicTypes.has(data)) {
|
||||
this.removeUndoOption();
|
||||
if (topic == kPasswordManagerTopic) {
|
||||
// As soon as any login gets added or modified, disable undo:
|
||||
// (Note that this ignores logins being removed as that doesn't
|
||||
// impair the 'undo' functionality of the import.)
|
||||
if (kPasswordManagerTopicTypes.has(data)) {
|
||||
this.removeUndoOption(this.UNDO_REMOVED_REASON_PASSWORD_CHANGE);
|
||||
}
|
||||
} else if (topic == kSyncTopic) {
|
||||
this.removeUndoOption(this.UNDO_REMOVED_REASON_SYNC_SIGNIN);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -190,24 +196,13 @@ const AutoMigrate = {
|
|||
},
|
||||
|
||||
canUndo() {
|
||||
if (!this.getUndoRange()) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
// Return a promise resolving to false if we're signed into sync, resolve
|
||||
// to true otherwise.
|
||||
let {fxAccounts} = Cu.import("resource://gre/modules/FxAccounts.jsm", {});
|
||||
return fxAccounts.getSignedInUser().then(user => {
|
||||
if (user) {
|
||||
Services.telemetry.getHistogramById("FX_STARTUP_MIGRATION_CANT_UNDO_BECAUSE_SYNC").add(true);
|
||||
}
|
||||
return !user;
|
||||
}, () => Promise.resolve(true));
|
||||
return !!this.getUndoRange();
|
||||
},
|
||||
|
||||
undo: Task.async(function* () {
|
||||
let histogram = Services.telemetry.getHistogramById("FX_STARTUP_MIGRATION_AUTOMATED_IMPORT_UNDO");
|
||||
histogram.add(0);
|
||||
if (!(yield this.canUndo())) {
|
||||
if (!this.canUndo()) {
|
||||
histogram.add(5);
|
||||
throw new Error("Can't undo!");
|
||||
}
|
||||
|
@ -238,19 +233,27 @@ const AutoMigrate = {
|
|||
// ignore failure.
|
||||
}
|
||||
histogram.add(25);
|
||||
this.removeUndoOption();
|
||||
this.removeUndoOption(this.UNDO_REMOVED_REASON_UNDO_USED);
|
||||
histogram.add(30);
|
||||
}),
|
||||
|
||||
removeUndoOption() {
|
||||
removeUndoOption(reason) {
|
||||
// Remove observers, and ensure that exceptions doing so don't break
|
||||
// removing the pref.
|
||||
try {
|
||||
Services.obs.removeObserver(this, kPasswordManagerTopic);
|
||||
} catch (ex) {}
|
||||
for (let topic of [kSyncTopic, kPasswordManagerTopic]) {
|
||||
try {
|
||||
Services.obs.removeObserver(this, topic);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Error removing observer for " + topic + ": " + ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
PlacesUtils.removeLazyBookmarkObserver(this);
|
||||
} catch (ex) {}
|
||||
} catch (ex) {
|
||||
Cu.reportError("Error removing lazy bookmark observer: " + ex);
|
||||
}
|
||||
|
||||
let migrationBrowser = Preferences.get(kAutoMigrateBrowserPref, "unknown");
|
||||
Services.prefs.clearUserPref(kAutoMigrateStartedPref);
|
||||
Services.prefs.clearUserPref(kAutoMigrateFinishedPref);
|
||||
Services.prefs.clearUserPref(kAutoMigrateBrowserPref);
|
||||
|
@ -268,6 +271,9 @@ const AutoMigrate = {
|
|||
}
|
||||
}
|
||||
}
|
||||
let histogram =
|
||||
Services.telemetry.getKeyedHistogramById("FX_STARTUP_MIGRATION_UNDO_REASON");
|
||||
histogram.add(migrationBrowser, reason);
|
||||
},
|
||||
|
||||
getBrowserUsedForMigration() {
|
||||
|
@ -279,54 +285,53 @@ const AutoMigrate = {
|
|||
},
|
||||
|
||||
maybeShowUndoNotification(target) {
|
||||
this.canUndo().then(canUndo => {
|
||||
// The tab might have navigated since we requested the undo state:
|
||||
if (!canUndo || target.currentURI.spec != "about:home") {
|
||||
return;
|
||||
}
|
||||
let win = target.ownerGlobal;
|
||||
let notificationBox = win.gBrowser.getNotificationBox(target);
|
||||
if (!notificationBox || notificationBox.getNotificationWithValue("abouthome-automigration-undo")) {
|
||||
return;
|
||||
}
|
||||
// The tab might have navigated since we requested the undo state:
|
||||
if (!this.canUndo() || target.currentURI.spec != "about:home") {
|
||||
return;
|
||||
}
|
||||
|
||||
// At this stage we're committed to show the prompt - unless we shouldn't,
|
||||
// in which case we remove the undo prefs (which will cause canUndo() to
|
||||
// return false from now on.):
|
||||
if (!this.shouldStillShowUndoPrompt()) {
|
||||
this.removeUndoOption();
|
||||
return;
|
||||
}
|
||||
let win = target.ownerGlobal;
|
||||
let notificationBox = win.gBrowser.getNotificationBox(target);
|
||||
if (!notificationBox || notificationBox.getNotificationWithValue("abouthome-automigration-undo")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let browserName = this.getBrowserUsedForMigration();
|
||||
let message;
|
||||
if (browserName) {
|
||||
message = MigrationUtils.getLocalizedString("automigration.undo.message",
|
||||
[browserName]);
|
||||
} else {
|
||||
message = MigrationUtils.getLocalizedString("automigration.undo.unknownBrowserMessage");
|
||||
}
|
||||
// At this stage we're committed to show the prompt - unless we shouldn't,
|
||||
// in which case we remove the undo prefs (which will cause canUndo() to
|
||||
// return false from now on.):
|
||||
if (!this.shouldStillShowUndoPrompt()) {
|
||||
this.removeUndoOption(this.UNDO_REMOVED_REASON_OFFER_EXPIRED);
|
||||
return;
|
||||
}
|
||||
|
||||
let buttons = [
|
||||
{
|
||||
label: MigrationUtils.getLocalizedString("automigration.undo.keep.label"),
|
||||
accessKey: MigrationUtils.getLocalizedString("automigration.undo.keep.accesskey"),
|
||||
callback: () => {
|
||||
this.removeUndoOption();
|
||||
},
|
||||
let browserName = this.getBrowserUsedForMigration();
|
||||
let message;
|
||||
if (browserName) {
|
||||
message = MigrationUtils.getLocalizedString("automigration.undo.message",
|
||||
[browserName]);
|
||||
} else {
|
||||
message = MigrationUtils.getLocalizedString("automigration.undo.unknownBrowserMessage");
|
||||
}
|
||||
|
||||
let buttons = [
|
||||
{
|
||||
label: MigrationUtils.getLocalizedString("automigration.undo.keep.label"),
|
||||
accessKey: MigrationUtils.getLocalizedString("automigration.undo.keep.accesskey"),
|
||||
callback: () => {
|
||||
this.removeUndoOption(this.UNDO_REMOVED_REASON_OFFER_REJECTED);
|
||||
},
|
||||
{
|
||||
label: MigrationUtils.getLocalizedString("automigration.undo.dontkeep.label"),
|
||||
accessKey: MigrationUtils.getLocalizedString("automigration.undo.dontkeep.accesskey"),
|
||||
callback: () => {
|
||||
this.undo();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: MigrationUtils.getLocalizedString("automigration.undo.dontkeep.label"),
|
||||
accessKey: MigrationUtils.getLocalizedString("automigration.undo.dontkeep.accesskey"),
|
||||
callback: () => {
|
||||
this.undo();
|
||||
},
|
||||
];
|
||||
notificationBox.appendNotification(
|
||||
message, kNotificationId, null, notificationBox.PRIORITY_INFO_HIGH, buttons
|
||||
);
|
||||
});
|
||||
},
|
||||
];
|
||||
notificationBox.appendNotification(
|
||||
message, kNotificationId, null, notificationBox.PRIORITY_INFO_HIGH, buttons
|
||||
);
|
||||
},
|
||||
|
||||
shouldStillShowUndoPrompt() {
|
||||
|
@ -350,6 +355,13 @@ const AutoMigrate = {
|
|||
return true;
|
||||
},
|
||||
|
||||
UNDO_REMOVED_REASON_UNDO_USED: 0,
|
||||
UNDO_REMOVED_REASON_SYNC_SIGNIN: 1,
|
||||
UNDO_REMOVED_REASON_PASSWORD_CHANGE: 2,
|
||||
UNDO_REMOVED_REASON_BOOKMARK_CHANGE: 3,
|
||||
UNDO_REMOVED_REASON_OFFER_EXPIRED: 4,
|
||||
UNDO_REMOVED_REASON_OFFER_REJECTED: 5,
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI(
|
||||
[Ci.nsIObserver, Ci.nsINavBookmarkObserver, Ci.nsISupportsWeakReference]
|
||||
),
|
||||
|
|
|
@ -165,7 +165,7 @@ add_task(function* checkUndoPreconditions() {
|
|||
"Should have set start time pref");
|
||||
Assert.ok(Preferences.has("browser.migrate.automigrate.finished"),
|
||||
"Should have set finish time pref");
|
||||
Assert.ok((yield AutoMigrate.canUndo()), "Should be able to undo migration");
|
||||
Assert.ok(AutoMigrate.canUndo(), "Should be able to undo migration");
|
||||
|
||||
let [beginRange, endRange] = AutoMigrate.getUndoRange();
|
||||
let stringRange = `beginRange: ${beginRange}; endRange: ${endRange}`;
|
||||
|
@ -226,7 +226,7 @@ add_task(function* checkUndoRemoval() {
|
|||
Preferences.set("browser.migrate.automigrate.finished", endTime);
|
||||
|
||||
// Verify that we can undo, then undo:
|
||||
Assert.ok(yield AutoMigrate.canUndo(), "Should be possible to undo migration");
|
||||
Assert.ok(AutoMigrate.canUndo(), "Should be possible to undo migration");
|
||||
yield AutoMigrate.undo();
|
||||
|
||||
// Check that the undo removed the history visits:
|
||||
|
@ -259,17 +259,17 @@ add_task(function* checkUndoDisablingByBookmarksAndPasswords() {
|
|||
Services.prefs.setCharPref("browser.migrate.automigrate.finished", endTime);
|
||||
AutoMigrate.maybeInitUndoObserver();
|
||||
|
||||
ok((yield AutoMigrate.canUndo()), "Should be able to undo.");
|
||||
ok(AutoMigrate.canUndo(), "Should be able to undo.");
|
||||
|
||||
// Insert a login and check that that disabled undo.
|
||||
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||
login.init("www.mozilla.org", "http://www.mozilla.org", null, "user", "pass", "userEl", "passEl");
|
||||
Services.logins.addLogin(login);
|
||||
|
||||
ok(!(yield AutoMigrate.canUndo()), "Should no longer be able to undo.");
|
||||
ok(!AutoMigrate.canUndo(), "Should no longer be able to undo.");
|
||||
Services.prefs.setCharPref("browser.migrate.automigrate.started", startTime);
|
||||
Services.prefs.setCharPref("browser.migrate.automigrate.finished", endTime);
|
||||
ok((yield AutoMigrate.canUndo()), "Should be able to undo.");
|
||||
ok(AutoMigrate.canUndo(), "Should be able to undo.");
|
||||
AutoMigrate.maybeInitUndoObserver();
|
||||
|
||||
// Insert a bookmark and check that that disabled undo.
|
||||
|
@ -278,7 +278,7 @@ add_task(function* checkUndoDisablingByBookmarksAndPasswords() {
|
|||
url: "http://www.example.org/",
|
||||
title: "Some example bookmark",
|
||||
});
|
||||
ok(!(yield AutoMigrate.canUndo()), "Should no longer be able to undo.");
|
||||
ok(!AutoMigrate.canUndo(), "Should no longer be able to undo.");
|
||||
|
||||
try {
|
||||
Services.logins.removeAllLogins();
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm");
|
||||
Components.utils.import("resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
|
||||
"resource://gre/modules/ContextualIdentityService.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
var gPrivacyPane = {
|
||||
|
||||
|
@ -65,6 +71,45 @@ var gPrivacyPane = {
|
|||
link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
|
||||
|
||||
document.getElementById("browserContainersbox").hidden = false;
|
||||
|
||||
document.getElementById("browserContainersCheckbox").checked =
|
||||
Services.prefs.getBoolPref("privacy.userContext.enabled");
|
||||
},
|
||||
|
||||
_checkBrowserContainers: function(event) {
|
||||
let checkbox = document.getElementById("browserContainersCheckbox");
|
||||
if (checkbox.checked) {
|
||||
Services.prefs.setBoolPref("privacy.userContext.enabled", true);
|
||||
return;
|
||||
}
|
||||
|
||||
let count = ContextualIdentityService.countContainerTabs();
|
||||
if (count == 0) {
|
||||
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
|
||||
return;
|
||||
}
|
||||
|
||||
let bundlePreferences = document.getElementById("bundlePreferences");
|
||||
|
||||
let title = bundlePreferences.getString("disableContainersAlertTitle");
|
||||
let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg"))
|
||||
.replace("#S", count)
|
||||
let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton"))
|
||||
.replace("#S", count)
|
||||
let cancelButton = bundlePreferences.getString("disableContainersButton2");
|
||||
|
||||
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
|
||||
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
|
||||
|
||||
let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
|
||||
okButton, cancelButton, null, null, {});
|
||||
if (rv == 0) {
|
||||
ContextualIdentityService.closeAllContainerTabs();
|
||||
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
|
||||
return;
|
||||
}
|
||||
|
||||
checkbox.checked = true;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -131,6 +176,8 @@ var gPrivacyPane = {
|
|||
gPrivacyPane.showBlockLists);
|
||||
setEventListener("changeBlockListPBM", "command",
|
||||
gPrivacyPane.showBlockLists);
|
||||
setEventListener("browserContainersCheckbox", "command",
|
||||
gPrivacyPane._checkBrowserContainers);
|
||||
},
|
||||
|
||||
// TRACKING PROTECTION MODE
|
||||
|
|
|
@ -73,12 +73,6 @@
|
|||
<preference id="browser.privatebrowsing.autostart"
|
||||
name="browser.privatebrowsing.autostart"
|
||||
type="bool"/>
|
||||
|
||||
<!-- Containers -->
|
||||
<preference id="privacy.userContext.enabled"
|
||||
name="privacy.userContext.enabled"
|
||||
type="bool"/>
|
||||
|
||||
</preferences>
|
||||
|
||||
<hbox id="header-privacy"
|
||||
|
@ -298,7 +292,6 @@
|
|||
</label></caption>
|
||||
<checkbox id="browserContainersCheckbox"
|
||||
label="&browserContainersEnabled.label;"
|
||||
accesskey="&browserContainersEnabled.accesskey;"
|
||||
preference="privacy.userContext.enabled"/>
|
||||
accesskey="&browserContainersEnabled.accesskey;" />
|
||||
</vbox>
|
||||
</groupbox>
|
||||
|
|
|
@ -175,3 +175,8 @@ revertNoRestartButton=Revert
|
|||
|
||||
restartNow=Restart Now
|
||||
restartLater=Restart Later
|
||||
|
||||
disableContainersAlertTitle=Close All Container Tabs?
|
||||
disableContainersMsg=If you disable Container Tabs now, #S container tab will be closed. Are you sure you want to disable Container Tabs?;If you disable Containers Tabs now, #S container tabs will be closed. Are you sure you want to disable Containers Tabs?
|
||||
disableContainersOkButton=Close #S Container Tab;Close #S Container Tabs
|
||||
disableContainersButton2=Keep enabled
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
*/
|
||||
|
||||
/* Lightweight theme on tabs */
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
|
||||
background-attachment: scroll, fixed;
|
||||
background-color: transparent;
|
||||
background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
|
||||
|
@ -20,7 +20,7 @@
|
|||
background-repeat: repeat-x, no-repeat;
|
||||
}
|
||||
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-attachment: scroll, scroll, fixed;
|
||||
background-color: transparent;
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
|
||||
|
|
|
@ -1592,12 +1592,12 @@ html|span.ac-emphasize-text-url {
|
|||
}
|
||||
|
||||
/* Tab close button */
|
||||
.tab-close-button:not([visuallyselected]):not(:hover) {
|
||||
.tab-close-button:not([selected]):not(:hover) {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 64, 16, 48);
|
||||
}
|
||||
|
||||
.tab-close-button:not(:hover):-moz-lwtheme-brighttext,
|
||||
#TabsToolbar[brighttext] .tab-close-button:not([visuallyselected]):not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-close-button:not([selected]):not(:hover) {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
:root[devtoolstheme="dark"] .findbar-closebutton:not(:hover),
|
||||
:root[devtoolstheme="dark"] #sidebar-header > .close-icon:not(:hover),
|
||||
.tab-close-button[visuallyselected]:not(:hover) {
|
||||
.tab-close-button[selected]:not(:hover) {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
*/
|
||||
|
||||
/* Lightweight theme on tabs */
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
|
||||
background-attachment: scroll, fixed;
|
||||
background-color: transparent;
|
||||
background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
|
||||
|
@ -19,7 +19,7 @@
|
|||
background-repeat: repeat-x, no-repeat;
|
||||
}
|
||||
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-attachment: scroll, scroll, fixed;
|
||||
background-color: transparent;
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
|
||||
|
@ -30,7 +30,7 @@
|
|||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
|
||||
@fgTabTextureLWT@;/*,
|
||||
lwtHeader;*/
|
||||
|
|
|
@ -2480,30 +2480,30 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
url(chrome://browser/skin/tabbrowser/tab-background-start.png);
|
||||
}
|
||||
|
||||
.tab-background-middle[visuallyselected=true]:-moz-window-inactive {
|
||||
.tab-background-middle[selected=true]:-moz-window-inactive {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-active-middle-inactive.png),
|
||||
@fgTabTextureYosemiteInactive@,
|
||||
none;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-start[selected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[selected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-stroke-start-inactive.png);
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-end[selected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[selected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-stroke-end-inactive.png);
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-end[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
.tab-background-start[selected=true]:-moz-window-inactive:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-end[selected=true]:-moz-window-inactive:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-selected-start-inactive.svg);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-start[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
.tab-background-end[selected=true]:-moz-window-inactive:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-start[selected=true]:-moz-window-inactive:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-selected-end-inactive.svg);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
@ -2527,25 +2527,25 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-middle[visuallyselected=true]:-moz-window-inactive {
|
||||
.tab-background-middle[selected=true]:-moz-window-inactive {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-active-middle-inactive@2x.png),
|
||||
@fgTabTextureYosemiteInactive@,
|
||||
none;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-start[selected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[selected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-stroke-start-inactive@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[visuallyselected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-end[selected=true]:-moz-window-inactive:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[selected=true]:-moz-window-inactive:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/yosemite/tab-stroke-end-inactive@2x.png);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tabbrowser-tab:not(:hover) > .tab-stack > .tab-content > .tab-icon-image:not([visuallyselected="true"]) {
|
||||
.tabbrowser-tab:not(:hover) > .tab-stack > .tab-content > .tab-icon-image:not([selected="true"]) {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
|
@ -2557,7 +2557,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
opacity: 0.9999;
|
||||
}
|
||||
|
||||
.tab-label:not([visuallyselected="true"]) {
|
||||
.tab-label:not([selected="true"]) {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
|
@ -2649,12 +2649,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([visuallyselected=true]):not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([selected=true]):not(:hover) {
|
||||
-moz-image-region: rect(0, 64px, 16px, 48px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([visuallyselected=true]):not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([selected=true]):not(:hover) {
|
||||
-moz-image-region: rect(0, 128px, 32px, 96px);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,12 +108,12 @@
|
|||
:root[devtoolstheme="dark"] .findbar-closebutton:not(:hover),
|
||||
/* Tab styling - make sure to use an inverted icon for the selected tab
|
||||
(brighttext only covers the unselected tabs) */
|
||||
.tab-close-button[visuallyselected=true]:not(:hover) {
|
||||
.tab-close-button[selected=true]:not(:hover) {
|
||||
-moz-image-region: rect(0, 64px, 16px, 48px);
|
||||
}
|
||||
@media (min-resolution: 2dppx) {
|
||||
:root[devtoolstheme="dark"] .findbar-closebutton:not(:hover),
|
||||
.tab-close-button[visuallyselected=true]:not(:hover) {
|
||||
.tab-close-button[selected=true]:not(:hover) {
|
||||
-moz-image-region: rect(0, 128px, 32px, 96px);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@
|
|||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-top: 1px solid #ccc;
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
padding: 8px 20px;
|
||||
color: ButtonText;
|
||||
background-color: transparent;
|
||||
|
|
|
@ -118,17 +118,17 @@
|
|||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]::after,
|
||||
.tab-background-start[visuallyselected=true]::before,
|
||||
.tab-background-start[selected=true]::after,
|
||||
.tab-background-start[selected=true]::before,
|
||||
.tab-background-start,
|
||||
.tab-background-end,
|
||||
.tab-background-end[visuallyselected=true]::after,
|
||||
.tab-background-end[visuallyselected=true]::before {
|
||||
.tab-background-end[selected=true]::after,
|
||||
.tab-background-end[selected=true]::before {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]::after,
|
||||
.tab-background-end[visuallyselected=true]::after {
|
||||
.tab-background-start[selected=true]::after,
|
||||
.tab-background-end[selected=true]::after {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
/* End override @tabCurveHalfWidth@ and @tabCurveWidth@ */
|
||||
|
@ -256,14 +256,14 @@ window:not([chromehidden~="toolbar"]) #urlbar-wrapper {
|
|||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:-moz-any([image], [pinned]) > .tab-stack > .tab-content[attention]:not([visuallyselected="true"]),
|
||||
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([visuallyselected="true"]) {
|
||||
.tabbrowser-tab:-moz-any([image], [pinned]) > .tab-stack > .tab-content[attention]:not([selected="true"]),
|
||||
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([selected="true"]) {
|
||||
background-image: var(--pinned-tab-glow);
|
||||
background-position: center;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[image] > .tab-stack > .tab-content[attention]:not([pinned]):not([visuallyselected="true"]) {
|
||||
.tabbrowser-tab[image] > .tab-stack > .tab-content[attention]:not([pinned]):not([selected="true"]) {
|
||||
background-position: left bottom var(--tab-toolbar-navbar-overlap);
|
||||
background-size: 34px 100%;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,17 @@
|
|||
padding-inline-end: 5px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon,
|
||||
.blocked-permission-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-inline-start: 2px;
|
||||
}
|
||||
|
||||
/* This class can be used alone or in combination with the class defining the
|
||||
type of icon displayed. This rule must be defined before the others in order
|
||||
for its list-style-image to be overridden. */
|
||||
.notification-anchor-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-inline-start: 2px;
|
||||
%ifdef MOZ_WIDGET_GTK
|
||||
list-style-image: url(moz-icon://stock/gtk-dialog-info?size=16);
|
||||
%else
|
||||
|
@ -76,7 +80,7 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification);
|
||||
}
|
||||
|
||||
.desktop-notification-icon.blocked {
|
||||
.desktop-notification-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification-blocked);
|
||||
}
|
||||
|
||||
|
@ -90,7 +94,7 @@
|
|||
%endif
|
||||
}
|
||||
|
||||
.geo-icon.blocked {
|
||||
.geo-icon.blocked-permission-icon {
|
||||
%ifdef XP_MACOSX
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#geo-osx-blocked);
|
||||
%elif defined(MOZ_WIDGET_GTK)
|
||||
|
@ -115,7 +119,7 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons.svg#indexedDB);
|
||||
}
|
||||
|
||||
.indexedDB-icon.blocked {
|
||||
.indexedDB-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#indexedDB-blocked);
|
||||
}
|
||||
|
||||
|
@ -137,7 +141,7 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons.svg#camera);
|
||||
}
|
||||
|
||||
.camera-icon.blocked {
|
||||
.camera-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#camera-blocked);
|
||||
}
|
||||
|
||||
|
@ -145,7 +149,7 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons.svg#microphone);
|
||||
}
|
||||
|
||||
.microphone-icon.blocked {
|
||||
.microphone-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#microphone-blocked);
|
||||
}
|
||||
|
||||
|
@ -158,7 +162,7 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons.svg#screen);
|
||||
}
|
||||
|
||||
.screen-icon.blocked {
|
||||
.screen-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#screen-blocked);
|
||||
}
|
||||
|
||||
|
@ -167,7 +171,7 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons.svg#pointerLock);
|
||||
}
|
||||
|
||||
.pointerLock-icon.blocked {
|
||||
.pointerLock-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons.svg#pointerLock-blocked);
|
||||
}
|
||||
|
||||
|
|
|
@ -161,13 +161,13 @@
|
|||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-muted");
|
||||
}
|
||||
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying]:not([visuallyselected]):not(:hover),
|
||||
.tab-icon-overlay[soundplaying][visuallyselected]:-moz-lwtheme-brighttext:not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
|
||||
.tab-icon-overlay[soundplaying][selected]:-moz-lwtheme-brighttext:not(:hover) {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white");
|
||||
}
|
||||
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[muted]:not([crashed]):not([visuallyselected]):not(:hover),
|
||||
.tab-icon-overlay[muted][visuallyselected]:-moz-lwtheme-brighttext:not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
|
||||
.tab-icon-overlay[muted][selected]:-moz-lwtheme-brighttext:not(:hover) {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-muted");
|
||||
}
|
||||
|
||||
|
@ -272,12 +272,12 @@
|
|||
transition: opacity 150ms ease;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]::after,
|
||||
.tab-background-start[visuallyselected=true]::before,
|
||||
.tab-background-start[selected=true]::after,
|
||||
.tab-background-start[selected=true]::before,
|
||||
.tab-background-start,
|
||||
.tab-background-end,
|
||||
.tab-background-end[visuallyselected=true]::after,
|
||||
.tab-background-end[visuallyselected=true]::before {
|
||||
.tab-background-end[selected=true]::after,
|
||||
.tab-background-end[selected=true]::before {
|
||||
min-height: var(--tab-min-height);
|
||||
width: @tabCurveWidth@;
|
||||
}
|
||||
|
@ -298,8 +298,8 @@
|
|||
*/
|
||||
|
||||
|
||||
.tab-background-start[visuallyselected=true]::after,
|
||||
.tab-background-end[visuallyselected=true]::after {
|
||||
.tab-background-start[selected=true]::after,
|
||||
.tab-background-end[selected=true]::after {
|
||||
/* position ::after on top of its parent */
|
||||
margin-inline-start: -@tabCurveWidth@;
|
||||
background-size: 100% 100%;
|
||||
|
@ -308,47 +308,47 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]::before,
|
||||
.tab-background-end[visuallyselected=true]::before {
|
||||
.tab-background-start[selected=true]::before,
|
||||
.tab-background-end[selected=true]::before {
|
||||
/* all ::before pseudo elements */
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-selected-start.svg);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-selected-end.svg);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
/* For lightweight themes, clip the header image on start, middle, and end. */
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
|
||||
clip-path: url(chrome://browser/content/browser.xul#tab-curve-clip-path-start);
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
|
||||
clip-path: url(chrome://browser/content/browser.xul#tab-curve-clip-path-end);
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-start.png);
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-end.png);
|
||||
}
|
||||
|
||||
.tab-background-middle[visuallyselected=true] {
|
||||
.tab-background-middle[selected=true] {
|
||||
background-clip: padding-box, padding-box, content-box;
|
||||
background-color: @fgTabBackgroundColor@;
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
|
||||
|
@ -363,7 +363,7 @@
|
|||
|
||||
/* Selected tab lightweight theme styles.
|
||||
See browser-lightweightTheme.css for information about run-time changes to LWT styles. */
|
||||
.tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
.tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-color: transparent;
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
|
||||
@fgTabTextureLWT@;/*,
|
||||
|
@ -373,21 +373,21 @@
|
|||
}
|
||||
|
||||
/* These LWT styles are normally overridden by browser-lightweightTheme.css */
|
||||
.tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
|
||||
.tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
|
||||
.tab-background-start[selected=true]:-moz-lwtheme::before,
|
||||
.tab-background-end[selected=true]:-moz-lwtheme::before {
|
||||
background-image: @fgTabTextureLWT@;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
|
||||
.tab-background-end[visuallyselected=true]:-moz-lwtheme::before,
|
||||
.tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
.tab-background-start[selected=true]:-moz-lwtheme::before,
|
||||
.tab-background-end[selected=true]:-moz-lwtheme::before,
|
||||
.tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* End selected tab */
|
||||
|
||||
/* new tab button border and gradient on hover */
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([visuallyselected=true]),
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
|
||||
.tabs-newtab-button:hover {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-middle.png),
|
||||
|
@ -419,20 +419,20 @@
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:-moz-any([image], [pinned]) > .tab-stack > .tab-content[attention]:not([visuallyselected="true"]),
|
||||
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([visuallyselected="true"]) {
|
||||
.tabbrowser-tab:-moz-any([image], [pinned]) > .tab-stack > .tab-content[attention]:not([selected="true"]),
|
||||
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([selected="true"]) {
|
||||
background-image: radial-gradient(farthest-corner at center bottom, rgb(255,255,255) 3%, rgba(186,221,251,0.75) 20%, rgba(127,179,255,0.25) 40%, transparent 70%);
|
||||
background-position: center bottom var(--tab-toolbar-navbar-overlap);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 85% 100%;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[image] > .tab-stack > .tab-content[attention]:not([pinned]):not([visuallyselected="true"]) {
|
||||
.tabbrowser-tab[image] > .tab-stack > .tab-content[attention]:not([pinned]):not([selected="true"]) {
|
||||
background-position: left bottom var(--tab-toolbar-navbar-overlap);
|
||||
background-size: 34px 100%;
|
||||
}
|
||||
|
||||
.tab-label[attention]:not([visuallyselected="true"]) {
|
||||
.tab-label[attention]:not([selected="true"]) {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -456,8 +456,8 @@
|
|||
|
||||
/* Also show separators beside the selected tab when dragging it. */
|
||||
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[beforeselected]:not([last-visible-tab])::after,
|
||||
.tabbrowser-tab:not([visuallyselected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
|
||||
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
|
||||
.tabbrowser-tab:not([selected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
|
||||
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([selected]):not([beforehovered]):not(:hover)::after {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
}
|
||||
|
@ -477,26 +477,26 @@
|
|||
url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([visuallyselected=true]),
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
|
||||
.tabs-newtab-button:hover {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-middle[visuallyselected=true] {
|
||||
.tab-background-middle[selected=true] {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
|
||||
@fgTabTexture@,
|
||||
none;
|
||||
}
|
||||
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-start@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl)::after {
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-end@2x.png);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
background-color: @customToolbarColor@;
|
||||
}
|
||||
|
||||
.tab-background-middle[visuallyselected=true]:not(:-moz-lwtheme) {
|
||||
.tab-background-middle[selected=true]:not(:-moz-lwtheme) {
|
||||
background-color: @customToolbarColor@;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
*/
|
||||
|
||||
/* Lightweight theme on tabs */
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
|
||||
background-attachment: scroll, fixed;
|
||||
background-color: transparent;
|
||||
background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
|
||||
|
@ -20,7 +20,7 @@
|
|||
background-repeat: repeat-x, no-repeat;
|
||||
}
|
||||
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-attachment: scroll, scroll, fixed;
|
||||
background-color: transparent;
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
|
||||
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
|
||||
@fgTabTextureLWT@;/*,
|
||||
lwtHeader;*/
|
||||
|
|
|
@ -2063,8 +2063,8 @@ html|span.ac-emphasize-text-url {
|
|||
@media not all and (-moz-os-version: windows-win7) {
|
||||
@media not all and (-moz-os-version: windows-win8) {
|
||||
@media (-moz-windows-default-theme) {
|
||||
.tab-background-end[visuallyselected=true]::after,
|
||||
.tab-background-start[visuallyselected=true]::after {
|
||||
.tab-background-end[selected=true]::after,
|
||||
.tab-background-start[selected=true]::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
|
@ -2089,14 +2089,14 @@ html|span.ac-emphasize-text-url {
|
|||
/* Invert the unhovered close tab icons on bright-text tabs */
|
||||
@media not all and (min-resolution: 1.1dppx) {
|
||||
.tab-close-button:-moz-lwtheme-brighttext,
|
||||
#TabsToolbar[brighttext] .tab-close-button:not([visuallyselected="true"]) {
|
||||
#TabsToolbar[brighttext] .tab-close-button:not([selected="true"]) {
|
||||
list-style-image: url("chrome://global/skin/icons/close-inverted.png");
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.tab-close-button:-moz-lwtheme-brighttext,
|
||||
#TabsToolbar[brighttext] .tab-close-button:not([visuallyselected="true"]) {
|
||||
#TabsToolbar[brighttext] .tab-close-button:not([selected="true"]) {
|
||||
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,14 +104,14 @@
|
|||
:root[devtoolstheme="dark"] #sidebar-header > .close-icon,
|
||||
/* Tab styling - make sure to use an inverted icon for the selected tab
|
||||
(brighttext only covers the unselected tabs) */
|
||||
.tab-close-button[visuallyselected=true] {
|
||||
.tab-close-button[selected=true] {
|
||||
list-style-image: url("chrome://global/skin/icons/close-inverted.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
:root[devtoolstheme="dark"] .findbar-closebutton,
|
||||
:root[devtoolstheme="dark"] #sidebar-header > .close-icon,
|
||||
.tab-close-button[visuallyselected=true] {
|
||||
.tab-close-button[selected=true] {
|
||||
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,26 +2,6 @@ dnl This Source Code Form is subject to the terms of the Mozilla Public
|
|||
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
AC_DEFUN([MOZ_CONFIG_FFI], [
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(system-ffi,
|
||||
[ --enable-system-ffi Use system libffi (located with pkgconfig)],
|
||||
MOZ_SYSTEM_FFI=1 )
|
||||
|
||||
if test -n "$MOZ_SYSTEM_FFI"; then
|
||||
# Vanilla libffi 3.0.9 needs a few patches from upcoming version 3.0.10
|
||||
# for non-GCC compilers.
|
||||
if test -z "$GNU_CC"; then
|
||||
PKG_CHECK_MODULES(MOZ_FFI, libffi > 3.0.9)
|
||||
else
|
||||
PKG_CHECK_MODULES(MOZ_FFI, libffi >= 3.0.9)
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_SYSTEM_FFI)
|
||||
|
||||
])
|
||||
|
||||
AC_DEFUN([MOZ_SUBCONFIGURE_FFI], [
|
||||
if test "$MOZ_BUILD_APP" != js -o -n "$JS_STANDALONE"; then
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
js_option('--with-system-ffi',
|
||||
help='Use system libffi (located with pkgconfig)')
|
||||
|
||||
use_system_ffi = depends_if('--with-system-ffi')(lambda _: True)
|
||||
|
||||
system_ffi = pkg_check_modules('MOZ_FFI', 'libffi > 3.0.9',
|
||||
when=use_system_ffi)
|
||||
|
||||
set_config('MOZ_SYSTEM_FFI', system_ffi)
|
||||
add_old_configure_assignment('MOZ_SYSTEM_FFI', system_ffi)
|
|
@ -169,7 +169,6 @@ def old_configure_options(*options):
|
|||
'--enable-cookies',
|
||||
'--enable-cpp-rtti',
|
||||
'--enable-crashreporter',
|
||||
'--enable-ctypes',
|
||||
'--enable-dbus',
|
||||
'--enable-debug-js-modules',
|
||||
'--enable-directshow',
|
||||
|
@ -232,7 +231,6 @@ def old_configure_options(*options):
|
|||
'--enable-synth-pico',
|
||||
'--enable-system-cairo',
|
||||
'--enable-system-extension-dirs',
|
||||
'--enable-system-ffi',
|
||||
'--enable-system-pixman',
|
||||
'--enable-system-sqlite',
|
||||
'--enable-tasktracer',
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "DomainPolicy.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIMessageManager.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "nsXPCOMCIDInternal.h"
|
||||
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "nsICommandLine.h"
|
||||
#include "nsILocaleService.h"
|
||||
|
|
73
configure.py
73
configure.py
|
@ -5,17 +5,19 @@
|
|||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import codecs
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from collections import Iterable
|
||||
import textwrap
|
||||
|
||||
|
||||
base_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
|
||||
from mozbuild.configure import ConfigureSandbox
|
||||
from mozbuild.util import (
|
||||
indented_repr,
|
||||
encode,
|
||||
)
|
||||
|
||||
|
||||
def main(argv):
|
||||
|
@ -60,49 +62,27 @@ def config_status(config):
|
|||
print("Creating config.status", file=sys.stderr)
|
||||
encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
|
||||
with codecs.open('config.status', 'w', encoding) as fh:
|
||||
fh.write('#!%s\n' % config['PYTHON'])
|
||||
fh.write('# coding=%s\n' % encoding)
|
||||
# Because we're serializing as JSON but reading as python, the values
|
||||
# for True, False and None are true, false and null, which don't exist.
|
||||
# Define them.
|
||||
fh.write('true, false, null = True, False, None\n')
|
||||
fh.write(textwrap.dedent('''\
|
||||
#!%(python)s
|
||||
# coding=%(encoding)s
|
||||
from __future__ import unicode_literals
|
||||
from mozbuild.util import encode
|
||||
encoding = '%(encoding)s'
|
||||
''') % {'python': config['PYTHON'], 'encoding': encoding})
|
||||
# A lot of the build backend code is currently expecting byte
|
||||
# strings and breaks in subtle ways with unicode strings. (bug 1296508)
|
||||
for k, v in sanitized_config.iteritems():
|
||||
fh.write('%s = ' % k)
|
||||
json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False)
|
||||
fh.write('\n')
|
||||
fh.write('%s = encode(%s, encoding)\n' % (k, indented_repr(v)))
|
||||
fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
|
||||
"'non_global_defines', 'substs', 'mozconfig']")
|
||||
|
||||
if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
|
||||
fh.write('''
|
||||
if __name__ == '__main__':
|
||||
args = dict([(name, globals()[name]) for name in __all__])
|
||||
from mozbuild.config_status import config_status
|
||||
config_status(**args)
|
||||
''')
|
||||
|
||||
# Running config.status standalone uses byte literals for all the config,
|
||||
# instead of the unicode literals we have in sanitized_config right now.
|
||||
# Some values in sanitized_config also have more complex types, such as
|
||||
# EnumString, which using when calling config_status would currently break
|
||||
# the build, as well as making it inconsistent with re-running
|
||||
# config.status. Fortunately, EnumString derives from unicode, so it's
|
||||
# covered by converting unicode strings.
|
||||
# Moreover, a lot of the build backend code is currently expecting byte
|
||||
# strings and breaks in subtle ways with unicode strings.
|
||||
def encode(v):
|
||||
if isinstance(v, dict):
|
||||
return {
|
||||
encode(k): encode(val)
|
||||
for k, val in v.iteritems()
|
||||
}
|
||||
if isinstance(v, str):
|
||||
return v
|
||||
if isinstance(v, unicode):
|
||||
return v.encode(encoding)
|
||||
if isinstance(v, Iterable):
|
||||
return [encode(i) for i in v]
|
||||
return v
|
||||
fh.write(textwrap.dedent('''
|
||||
if __name__ == '__main__':
|
||||
from mozbuild.config_status import config_status
|
||||
args = dict([(name, globals()[name]) for name in __all__])
|
||||
config_status(**args)
|
||||
'''))
|
||||
|
||||
# Other things than us are going to run this file, so we need to give it
|
||||
# executable permissions.
|
||||
|
@ -110,7 +90,16 @@ if __name__ == '__main__':
|
|||
if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
|
||||
os.environ[b'WRITE_MOZINFO'] = b'1'
|
||||
from mozbuild.config_status import config_status
|
||||
return config_status(args=[], **encode(sanitized_config))
|
||||
|
||||
# Some values in sanitized_config also have more complex types, such as
|
||||
# EnumString, which using when calling config_status would currently
|
||||
# break the build, as well as making it inconsistent with re-running
|
||||
# config.status. Fortunately, EnumString derives from unicode, so it's
|
||||
# covered by converting unicode strings.
|
||||
|
||||
# A lot of the build backend code is currently expecting byte strings
|
||||
# and breaks in subtle ways with unicode strings.
|
||||
return config_status(args=[], **encode(sanitized_config, encoding))
|
||||
return 0
|
||||
|
||||
|
||||
|
|
|
@ -362,9 +362,7 @@ var SnapshotsListView = Heritage.extend(WidgetMethods, {
|
|||
}
|
||||
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: NetUtil.newURI(fp.file),
|
||||
loadingNode: window.document,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER});
|
||||
uri: NetUtil.newURI(fp.file), loadUsingSystemPrincipal: true});
|
||||
channel.contentType = "text/plain";
|
||||
|
||||
NetUtil.asyncFetch(channel, (inputStream, status) => {
|
||||
|
|
|
@ -34,13 +34,16 @@ function SourceMapService(target) {
|
|||
target.on("source-updated", this._onSourceUpdated);
|
||||
target.on("navigate", this.reset);
|
||||
target.on("will-navigate", this.reset);
|
||||
target.on("close", this.destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the store containing the cached promised locations
|
||||
*/
|
||||
SourceMapService.prototype.reset = function () {
|
||||
// Guard to prevent clearing the store when it is not initialized yet.
|
||||
if (!this._locationStore) {
|
||||
return;
|
||||
}
|
||||
this._locationStore.clear();
|
||||
this._isNotSourceMapped.clear();
|
||||
};
|
||||
|
@ -84,9 +87,10 @@ SourceMapService.prototype.unsubscribe = function (location, callback) {
|
|||
// Check to see if the store exists before attempting to clear a location
|
||||
// Sometimes un-subscribe happens during the destruction cascades and this
|
||||
// condition is to protect against that. Could be looked into in the future.
|
||||
if (this._locationStore) {
|
||||
this._locationStore.clearByURL(location.url);
|
||||
if (!this._locationStore) {
|
||||
return;
|
||||
}
|
||||
this._locationStore.clearByURL(location.url);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,8 @@ const {EyeDropper, HighlighterEnvironment} = require("devtools/server/actors/hig
|
|||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
|
||||
const windowEyeDroppers = new WeakMap();
|
||||
|
||||
exports.items = [{
|
||||
item: "command",
|
||||
runAt: "client",
|
||||
|
@ -48,9 +50,28 @@ exports.items = [{
|
|||
name: "frommenu",
|
||||
type: "boolean",
|
||||
hidden: true
|
||||
}, {
|
||||
name: "hide",
|
||||
type: "boolean",
|
||||
hidden: true
|
||||
}]
|
||||
}],
|
||||
exec: function (args, context) {
|
||||
exec: function* (args, context) {
|
||||
if (args.hide) {
|
||||
context.updateExec("eyedropper_server_hide").catch(e => console.error(e));
|
||||
return;
|
||||
}
|
||||
|
||||
// If the inspector is already picking a color from the page, cancel it.
|
||||
let target = context.environment.target;
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
if (toolbox) {
|
||||
let inspector = toolbox.getPanel("inspector");
|
||||
if (inspector) {
|
||||
yield inspector.hideEyeDropper();
|
||||
}
|
||||
}
|
||||
|
||||
let telemetry = new Telemetry();
|
||||
telemetry.toolOpened(args.frommenu ? "menueyedropper" : "eyedropper");
|
||||
context.updateExec("eyedropper_server").catch(e => console.error(e));
|
||||
|
@ -61,15 +82,33 @@ exports.items = [{
|
|||
name: "eyedropper_server",
|
||||
hidden: true,
|
||||
exec: function (args, {environment}) {
|
||||
let env = new HighlighterEnvironment();
|
||||
env.initFromWindow(environment.window);
|
||||
let eyeDropper = new EyeDropper(env);
|
||||
let eyeDropper = windowEyeDroppers.get(environment.window);
|
||||
|
||||
if (!eyeDropper) {
|
||||
let env = new HighlighterEnvironment();
|
||||
env.initFromWindow(environment.window);
|
||||
|
||||
eyeDropper = new EyeDropper(env);
|
||||
eyeDropper.once("hidden", () => {
|
||||
eyeDropper.destroy();
|
||||
env.destroy();
|
||||
windowEyeDroppers.delete(environment.window);
|
||||
});
|
||||
|
||||
windowEyeDroppers.set(environment.window, eyeDropper);
|
||||
}
|
||||
|
||||
eyeDropper.show(environment.document.documentElement, {copyOnSelect: true});
|
||||
|
||||
eyeDropper.once("hidden", () => {
|
||||
eyeDropper.destroy();
|
||||
env.destroy();
|
||||
});
|
||||
}
|
||||
}, {
|
||||
item: "command",
|
||||
runAt: "server",
|
||||
name: "eyedropper_server_hide",
|
||||
hidden: true,
|
||||
exec: function (args, {environment}) {
|
||||
let eyeDropper = windowEyeDroppers.get(environment.window);
|
||||
if (eyeDropper) {
|
||||
eyeDropper.hide();
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
|
|
@ -1304,7 +1304,7 @@ InspectorPanel.prototype = {
|
|||
this.telemetry.toolOpened("toolbareyedropper");
|
||||
this.eyeDropperButton.setAttribute("checked", "true");
|
||||
this.startEyeDropperListeners();
|
||||
return this.inspector.pickColorFromPage({copyOnSelect: true})
|
||||
return this.inspector.pickColorFromPage(this.toolbox, {copyOnSelect: true})
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче