Bug 1169290 - Add navigator.webdriver attribute. r?bz,maja_zf
This patch adds an enumerable, configurable, readonly attribute
"webdriver" to the Navigator object. The attribute is true when the
-marionette flag has been passed to Firefox or the marionette.enabled
preference is true. Otherwise it is false.
The definition of the interface is found in the WebDriver standard:
https://w3c.github.io/webdriver/webdriver-spec.html#interface
The navigator.webdriver attribute is meant as an indication to web
authors that a document is visited by WebDriver. It is important
to stress that it is not meant as a fool-proof way to detect that
a website is being visited by a browser automation tool, but as a
tool for web documents to take alternate code paths.
MozReview-Commit-ID: D3qXVKqZG
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1882,10 +1882,17 @@ CredentialsContainer*
Navigator::Credentials()
{
if (!mCredentials) {
mCredentials = new CredentialsContainer(GetWindow());
}
return mCredentials;
}
+/* static */
+bool
+Navigator::Webdriver()
+{
+ return Preferences::GetBool("marionette.enabled", false);
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -196,16 +196,18 @@ public:
uint64_t aInnerWindowID,
const nsAString& aCallID,
ErrorResult& aRv);
already_AddRefed<ServiceWorkerContainer> ServiceWorker();
mozilla::dom::CredentialsContainer* Credentials();
+ static bool Webdriver();
+
void GetLanguages(nsTArray<nsString>& aLanguages);
StorageManager* Storage();
static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
// WebIDL helper methods
static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -10,16 +10,17 @@
* http://www.w3.org/TR/battery-status/#navigatorbattery-interface
* http://www.w3.org/TR/vibration/#vibration-interface
* http://www.w3.org/2012/sysapps/runtime/#extension-to-the-navigator-interface-1
* https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension
* http://www.w3.org/TR/beacon/#sec-beacon-method
* https://html.spec.whatwg.org/#navigatorconcurrenthardware
* http://wicg.github.io/netinfo/#extensions-to-the-navigator-interface
* https://w3c.github.io/webappsec-credential-management/#framework-credential-management
+ * https://w3c.github.io/webdriver/webdriver-spec.html#interface
*
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
* Opera Software ASA. You are granted a license to use, reproduce
* and create derivative works of this document.
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
[HeaderFile="Navigator.h"]
@@ -28,16 +29,17 @@ interface Navigator {
};
Navigator implements NavigatorID;
Navigator implements NavigatorLanguage;
Navigator implements NavigatorOnLine;
Navigator implements NavigatorContentUtils;
Navigator implements NavigatorStorageUtils;
Navigator implements NavigatorConcurrentHardware;
Navigator implements NavigatorStorage;
+Navigator implements NavigatorAutomationInformation;
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorID {
// WebKit/Blink/Trident/Presto support this (hardcoded "Mozilla").
[Constant, Cached, Throws]
readonly attribute DOMString appCodeName; // constant "Mozilla"
[Constant, Cached, NeedsCallerType]
readonly attribute DOMString appName;
@@ -303,8 +305,14 @@ interface NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};
// https://w3c.github.io/webappsec-credential-management/#framework-credential-management
partial interface Navigator {
[Pref="security.webauth.webauthn", SecureContext, SameObject]
readonly attribute CredentialsContainer credentials;
};
+
+// https://w3c.github.io/webdriver/webdriver-spec.html#interface
+[NoInterfaceObject]
+interface NavigatorAutomationInformation {
+ readonly attribute boolean webdriver;
+};
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -592244,29 +592244,29 @@
"d589b53f0096893600e696b43ec19ca84e5ee2ab",
"wdspec"
],
"webdriver/tests/actions/key_shortcuts.py": [
"dbe27dd0b1625169fc8cc2055f8fb49d5a4a78d2",
"wdspec"
],
"webdriver/tests/actions/modifier_click.py": [
- "56df38086ef05cd8bff1437038efb598ab63f1e3",
+ "88a384182fdd9df1515b9d8cfda8f56aed138ec7",
"wdspec"
],
"webdriver/tests/actions/mouse.py": [
- "2fb4c47335f144a2dd6f16db4c20239116f20fed",
+ "edad7693fcd01b418821942edb870191db64ea41",
"wdspec"
],
"webdriver/tests/actions/mouse_dblclick.py": [
- "932b053eef5e052d53ab2007540428d68b758ad4",
+ "f6afcb8c0fa017d58a9fcdd3cc474e0c8fd52db5",
"wdspec"
],
"webdriver/tests/actions/pointer_origin.py": [
- "da2a9f21018582c8cd52d206d172841f71fd19f3",
+ "a9a99d58daec7719ee53ed758f566ccceb582f65",
"wdspec"
],
"webdriver/tests/actions/sequence.py": [
"d43caf0f8607a76c3baed7806664b686bde21fda",
"wdspec"
],
"webdriver/tests/actions/special_keys.py": [
"64eb2401664b71d68f7b53e236a947eec6d651cc",
@@ -592276,25 +592276,25 @@
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
"webdriver/tests/actions/support/keys.py": [
"528ab8473914c14f9671d89b8a888d30162714ec",
"support"
],
"webdriver/tests/actions/support/mouse.py": [
- "208a1c4fbc0d5c542d17de7f6474d477ce1feb45",
+ "bc7da107e5b897105dfa7405aa57cba7355854dc",
"support"
],
"webdriver/tests/actions/support/refine.py": [
"0d244bffe67ef57be68aad99f1cbc7440ff80e27",
"support"
],
"webdriver/tests/actions/support/test_actions_wdspec.html": [
- "34f99c46ac9c52e5902477c26a3d16a89a29235a",
+ "95203777fcc012ab64465287737a89a4ba2c31dc",
"support"
],
"webdriver/tests/conftest.py": [
"c812269d034c9ca1b8c4f136dd5d0cea52f4d0f0",
"support"
],
"webdriver/tests/contexts/json_serialize_windowproxy.py": [
"d29c82c48b3bd1e2b07c40798a774eb77d6178a5",
@@ -592412,17 +592412,17 @@
"7d0a8199890afb97894c363af7ef342b5ed5cef3",
"wdspec"
],
"webdriver/tests/interaction/send_keys_content_editable.py": [
"9c071e60e1203cf31120f20874b5f38ba41dacc3",
"wdspec"
],
"webdriver/tests/interface.html": [
- "6625887cfa7f461dc428c11861fce71c47bef57d",
+ "f7b2c45ff8b1b5790dd390fbe2ab997766f5d9a8",
"testharness"
],
"webdriver/tests/minimize_window.py": [
"ac1df5462702ac368ffa92cc12cfb5e34df226ac",
"wdspec"
],
"webdriver/tests/navigation/current_url.py": [
"828e40301838c99aa2978733bbce3db3acc185a0",
deleted file mode 100644
--- a/testing/web-platform/meta/webdriver/tests/interface.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[interface.html]
- [Navigator interface: attribute webdriver]
- expected: FAIL
-
- [Navigator interface: navigator must inherit property "webdriver" with the proper type (0)]
- expected: FAIL
-
- [Navigator interface: navigator must inherit property "webdriver" with the proper type]
- expected: FAIL
-
--- a/testing/web-platform/tests/webdriver/tests/interface.html
+++ b/testing/web-platform/tests/webdriver/tests/interface.html
@@ -1,38 +1,49 @@
-<!DOCTYPE html>
-<body>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
+<!doctype html>
+<meta charset=utf-8>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
<script src=/resources/WebIDLParser.js></script>
<script src=/resources/idlharness.js></script>
+
<script type=text/plain class=untested>
[Exposed=Window]
interface Navigator {
// objects implementing this interface also implement the interfaces given below
};
</script>
+
<script type=text/plain>
Navigator includes NavigatorAutomationInformation;
interface mixin NavigatorAutomationInformation {
- readonly attribute boolean webdriver;
- // always returns true
+ readonly attribute boolean webdriver;
};
</script>
+
<script>
"use strict";
-if ("webdriver" in navigator) {
- test(() => assert_true(navigator.webdriver), "navigator.webdriver is always true");
- var idlArray = new IdlArray();
- [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
- if (node.className == "untested") {
- idlArray.add_untested_idls(node.textContent);
- } else {
- idlArray.add_idls(node.textContent);
- }
- });
- idlArray.test();
-} else {
- done();
+test(() => assert_idl_attribute(navigator, "webdriver"), "navigator.webdriver is present");
+
+// When test is run in automation navigator.webdriver is likely to
+// be true because WebDriver controls the browser instance. To that
+// extent, this test is a bit special. It should also be possible to
+// run the test manually, when WebDriver is not active, and so either
+// true/false outcome is OK.
+if (navigator.webdriver) {
+ test(() => assert_true(navigator.webdriver), "navigator.webdriver is true when webdriver-active is set");
+} else {
+ test(() => assert_false(navigator.webdriver), "navigator.webdriver is false when webdriver-active is not set");
}
+
+var idls = new IdlArray();
+for (let node of [...document.scripts].filter(({type}) => type == "text/plain")) {
+ if (node.className == "untested") {
+ idls.add_untested_idls(node.textContent);
+ } else {
+ idls.add_idls(node.textContent);
+ }
+};
+idls.test();
</script>