Browse Source

import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1183825 - Hide PushMessageData methods until we support sending push data. r=mt,smaug (c07f6b6c9)
- Bug 1186880 - Performance timing api in workers should output entries if preference is enabled. r=baku (642bd335a)
- Bug 1188091 - Fix the exposure of Push interfaces; r=dougt,bzbarsky,nsm Currently we don't check the dom.push.enabled pref in some cases for some of these interfaces.  This patch unifies how all of these interfaces are exposed to Window, Worker, and ServiceWorker. (dbe4ebfcc)
- Bug 1188062 - Unship Request.context; r=baku (6ca2ebcf6)
- Bug 1162714 - Don't let YCM generate machc. r=ehsan (7c5f36c12)
- Bug 1160897 - Fixing .ycm_extra_conf for Fennec. r=ehsan (22adf0705)
- goanna->gecko (94b69bd6c)
- improve (e87b53162)
- Bug 1147939 - The expression decompiler can't assume that it's called directly from script. (r=bhackett) (4759a5210)
- Bug 1188609 - Remove mirroring support from RokuApp (Toolkit) r=snorp (81a0bb66a)
- Bug 1050749 - Expose BatteryManager via getBattery() returning a Promise. r=bz, r=baku, r=jgraham (67d2dd502)
- Bug 1182347 - Remove nsIPrincipal::cookieJar. r=sicking (855d0e8ce)
- remove double method, probably misspach (3c256c5b4)
- Bug 1182357 - Add an API to mint nsExpandedPrincipals. r=mrbkap (42de17cfd)
- Bug 1172080 - Part 1: Throw when requesting origin for poorly behaved URIs, r=bholley (c8410f3c6)
- Bug 1124126 - Retry database connection for the case of corrupted permissions.sqlite. r=bsmedberg (748e9205a)
pull/8/head
roytam1 6 months ago
parent
commit
9e4ed9857d
  1. 8
      .gitignore
  2. 2
      .lldbinit
  3. 15
      .ycm_extra_conf.py
  4. 3
      browser/app/jar.mn
  5. 2
      browser/app/moz.build
  6. 20
      browser/app/permissions
  7. 3
      browser/app/profile/palemoon.js
  8. 15
      caps/BasePrincipal.cpp
  9. 3
      caps/BasePrincipal.h
  10. 26
      caps/nsIPrincipal.idl
  11. 16
      caps/nsIScriptSecurityManager.idl
  12. 34
      caps/nsPrincipal.cpp
  13. 17
      caps/nsScriptSecurityManager.cpp
  14. 5
      caps/tests/unit/test_origin.js
  15. 9
      dom/base/ChromeUtils.cpp
  16. 5
      dom/base/ChromeUtils.h
  17. 34
      dom/base/Navigator.cpp
  18. 4
      dom/base/Navigator.h
  19. 20
      dom/base/nsContentUtils.cpp
  20. 2
      dom/base/nsContentUtils.h
  21. 20
      dom/base/nsPerformance.cpp
  22. 2
      dom/base/nsPerformance.h
  23. 53
      dom/battery/BatteryManager.cpp
  24. 10
      dom/battery/BatteryManager.h
  25. 6
      dom/battery/test/marionette/manifest.ini
  26. 25
      dom/battery/test/marionette/test_battery_level.js
  27. 17
      dom/battery/test/marionette/test_battery_status_charging.js
  28. 17
      dom/battery/test/marionette/test_battery_status_discharging.js
  29. 15
      dom/battery/test/marionette/test_battery_status_full.js
  30. 15
      dom/battery/test/marionette/test_battery_status_not_charging.js
  31. 15
      dom/battery/test/marionette/test_battery_status_unknown.js
  32. 68
      dom/battery/test/marionette/test_deprecated_battery_level.js
  33. 85
      dom/battery/test/marionette/test_deprecated_battery_status_charging.js
  34. 93
      dom/battery/test/marionette/test_deprecated_battery_status_discharging.js
  35. 87
      dom/battery/test/marionette/test_deprecated_battery_status_full.js
  36. 93
      dom/battery/test/marionette/test_deprecated_battery_status_not_charging.js
  37. 93
      dom/battery/test/marionette/test_deprecated_battery_unknown.js
  38. 6
      dom/battery/test/mochitest.ini
  39. 23
      dom/battery/test/test_battery_basics.html
  40. 33
      dom/battery/test/test_battery_charging.html
  41. 33
      dom/battery/test/test_battery_discharging.html
  42. 32
      dom/battery/test/test_deprecated_battery_basics.html
  43. 20
      dom/fetch/Request.cpp
  44. 3
      dom/fetch/Request.h
  45. 17
      dom/push/PushManager.cpp
  46. 3
      dom/push/PushManager.h
  47. 6
      dom/push/test/worker.js
  48. 3
      dom/tests/mochitest/fetch/fetch_test_framework.js
  49. 1
      dom/tests/mochitest/fetch/mochitest.ini
  50. 19
      dom/tests/mochitest/fetch/test_request_context.html
  51. 9
      dom/webidl/ChromeUtils.webidl
  52. 15
      dom/webidl/Navigator.webidl
  53. 6
      dom/webidl/PushEvent.webidl
  54. 2
      dom/webidl/PushManager.webidl
  55. 15
      dom/webidl/PushMessageData.webidl
  56. 2
      dom/webidl/PushSubscription.webidl
  57. 3
      dom/webidl/Request.webidl
  58. 2
      dom/webidl/ServiceWorkerRegistration.webidl
  59. 10
      dom/workers/Performance.cpp
  60. 2
      dom/workers/Performance.h
  61. 30
      dom/workers/RuntimeService.cpp
  62. 1
      dom/workers/ServiceWorkerEvents.h
  63. 21
      dom/workers/WorkerPrivate.h
  64. 3
      dom/workers/Workers.h
  65. 1
      dom/workers/test/serviceworkers/test_request_context.js
  66. 10
      dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
  67. 4
      dom/workers/test/test_worker_interfaces.js
  68. 41
      extensions/cookie/nsPermissionManager.cpp
  69. 8
      js/src/jit-test/tests/debug/bug1147939.js
  70. 8
      js/src/jsopcode.cpp
  71. 5
      modules/libpref/init/all.js
  72. 52
      testing/web-platform/meta/battery-status/battery-interface-idlharness.html.ini
  73. 35
      testing/web-platform/meta/battery-status/battery-interface.html.ini
  74. 8
      testing/web-platform/meta/battery-status/battery-promise.html.ini
  75. 10
      toolkit/components/telemetry/Histograms.json
  76. 26
      toolkit/devtools/server/tests/unit/test_originAttributesToCookieJar.js
  77. 1
      toolkit/devtools/server/tests/unit/xpcshell.ini
  78. 21
      toolkit/modules/Battery.jsm
  79. 31
      toolkit/modules/BrowserUtils.jsm
  80. 173
      toolkit/modules/secondscreen/RokuApp.jsm
  81. 37
      toolkit/modules/tests/browser/browser_Battery.js

8
.gitignore vendored

@ -10,10 +10,14 @@ TAGS
tags
ID
.DS_Store*
*.pdb
# Vim swap files.
.*.sw[a-z]
# Emacs directory variable files.
**/.dir-locals.el
# User files that may appear at the root
/.mozconfig*
/mozconfig
@ -51,8 +55,8 @@ parser/html/java/javaparser/
.settings/
# Python virtualenv artifacts.
python/psutil/*.so
python/psutil/*.pyd
python/psutil/**/*.so
python/psutil/**/*.pyd
python/psutil/build/
# Ignore chrome.manifest files from the devtools loader

2
.lldbinit

@ -5,7 +5,7 @@
# and in the accompanying Python scripts, see python/lldbutils/README.txt.
# -----------------------------------------------------------------------------
# Import the module that defines complex Goanna debugging commands. This assumes
# Import the module that defines complex Gecko debugging commands. This assumes
# you are either running lldb from the top level source directory, the objdir,
# or the dist/bin directory. (.lldbinit files in the objdir and dist/bin set
# topsrcdir appropriately.)

15
.ycm_extra_conf.py

@ -6,6 +6,10 @@ import imp
import os
from StringIO import StringIO
import shlex
import sys
old_bytecode = sys.dont_write_bytecode
sys.dont_write_bytecode = True
path = os.path.join(os.path.dirname(__file__), 'mach')
@ -15,13 +19,22 @@ if not os.path.exists(path):
path = os.path.join(config.topsrcdir, 'mach')
mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE))
sys.dont_write_bytecode = old_bytecode
def FlagsForFile(filename):
mach = mach_module.get_mach()
out = StringIO()
out.encoding = None
mach.run(['compileflags', filename], stdout=out, stderr=out)
flag_list = shlex.split(out.getvalue())
# This flag is added by Fennec for android build and causes ycmd to fail to parse the file.
# Removing this flag is a workaround until ycmd starts to handle this flag properly.
# https://github.com/Valloric/YouCompleteMe/issues/1490
final_flags = [x for x in flag_list if not x.startswith('-march=armv')]
return {
'flags': shlex.split(out.getvalue()),
'flags': final_flags,
'do_cache': True
}

3
browser/app/jar.mn

@ -0,0 +1,3 @@
browser.jar:
% resource app %
defaults/permissions (permissions)

2
browser/app/moz.build

@ -89,3 +89,5 @@ if CONFIG['MOZ_LINKER']:
if CONFIG['HAVE_CLOCK_MONOTONIC']:
OS_LIBS += CONFIG['REALTIME_LIBS']
JAR_MANIFESTS += ['jar.mn']

20
browser/app/permissions

@ -0,0 +1,20 @@
# This file has default permissions for the permission manager.
# The file-format is strict:
# * matchtype \t type \t permission \t host
# * Only "host" is supported for matchtype
# * type is a string that identifies the type of permission (e.g. "cookie")
# * permission is an integer between 1 and 15
# See nsPermissionManager.cpp for more...
# UITour
host uitour 1 www.mozilla.org
host uitour 1 support.mozilla.org
host uitour 1 about:home
# XPInstall
host install 1 addons.mozilla.org
host install 1 marketplace.firefox.com
# Remote troubleshooting
host remote-troubleshooting 1 input.mozilla.org
host remote-troubleshooting 1 support.mozilla.org

3
browser/app/profile/palemoon.js

@ -392,6 +392,9 @@ pref("browser.search.official", true);
pref("browser.sessionhistory.max_entries", 50);
// Built-in default permissions.
pref("permissions.manager.defaultsUrl", "resource://app/defaults/permissions");
// handle links targeting new windows
// 1=current window/tab, 2=new window, 3=new tab in most recent window
pref("browser.link.open_newwindow", 3);

15
caps/BasePrincipal.cpp

@ -145,12 +145,6 @@ OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin,
return PopulateFromSuffix(Substring(origin, pos));
}
void
OriginAttributes::CookieJar(nsACString& aStr)
{
mozilla::GetJarPrefix(mAppId, mInBrowser, aStr);
}
BasePrincipal::BasePrincipal()
{}
@ -248,7 +242,7 @@ BasePrincipal::GetJarPrefix(nsACString& aJarPrefix)
{
MOZ_ASSERT(AppId() != nsIScriptSecurityManager::UNKNOWN_APP_ID);
mOriginAttributes.CookieJar(aJarPrefix);
mozilla::GetJarPrefix(mOriginAttributes.mAppId, mOriginAttributes.mInBrowser, aJarPrefix);
return NS_OK;
}
@ -268,13 +262,6 @@ BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetCookieJar(nsACString& aCookieJar)
{
mOriginAttributes.CookieJar(aCookieJar);
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetAppStatus(uint16_t* aAppStatus)
{

3
caps/BasePrincipal.h

@ -48,8 +48,6 @@ public:
void CreateSuffix(nsACString& aStr) const;
bool PopulateFromSuffix(const nsACString& aStr);
void CookieJar(nsACString& aStr);
// Populates the attributes from a string like
// |uri!key1=value1&key2=value2| and returns the uri without the suffix.
bool PopulateFromOrigin(const nsACString& aOrigin,
@ -83,7 +81,6 @@ public:
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix) final;
NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
NS_IMETHOD GetCookieJar(nsACString& aCookieJar) final;
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) final;

26
caps/nsIPrincipal.idl

@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(49c2faf0-b6de-4640-8d0f-e0217baa8627)]
[scriptable, builtinclass, uuid(7a9aa074-7565-4567-af2f-9e3704c7af9e)]
interface nsIPrincipal : nsISerializable
{
/**
@ -195,30 +195,6 @@ interface nsIPrincipal : nsISerializable
*/
readonly attribute AUTF8String originSuffix;
/**
* Opaque string token representing the "cookie jar" associated with this
* principal. Cookie jars are intended to be a tag associated with persistent
* data (like cookies, localStorage data, etc) such that all data associated
* with a given cookie jar can be quickly located and (for example) deleted.
* Code from many origins may share a given cookie jar, so callers still need
* to consult .origin (or equivalent) to compartmentalize data - the cookie
* jar should _only_ be used as a tag in the manner described above.
*
* If two principals are in different cookie jars, they must be cross-origin.
* As such, the information making up the cookie jar token must be contained
* in the originAttributes (i.e. cookieJar must be a function of / derivable
* from originAttributes). Long term, the intention is for the cookie jar
* identifier to simply be an origin attribute. But we don't have that
* attribute yet, and we also need to concatenate the appId and inBrowser
* attributes until those go away.
*
* This getter is designed to hide these details from consumers so that they
* don't need to be updated when we swap out the implementation. For that
* reason, callers should treat the string as opaque and not rely on the
* current format.
*/
readonly attribute ACString cookieJar;
/**
* The base domain of the codebase URI to which this principal pertains
* (generally the document URI), handling null principals and

16
caps/nsIScriptSecurityManager.idl

@ -26,7 +26,7 @@ class DomainPolicyClone;
[ptr] native JSObjectPtr(JSObject);
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
[scriptable, uuid(f4c578b8-5bac-4ba1-9582-f1140e09a3b4)]
[scriptable, uuid(50418f5c-b0d8-42c3-ba5d-efffb6927e1c)]
interface nsIScriptSecurityManager : nsISupports
{
/**
@ -201,6 +201,20 @@ interface nsIScriptSecurityManager : nsISupports
[implicit_jscontext]
nsIPrincipal createNullPrincipal(in jsval originAttributes);
/**
* Creates an expanded principal whose capabilities are the union of the
* given principals. An expanded principal has an asymmetric privilege
* relationship with its sub-principals (that is to say, it subsumes the
* sub-principals, but the sub-principals do not subsume it), even if
* there's only one. This presents a legitimate use-case for making an
* expanded principal around a single sub-principal, which we do frequently.
*
* Expanded principals cannot have origin attributes themselves, but rather
* have them through their sub-principals - so we don't accept them here.
*/
nsIPrincipal createExpandedPrincipal([array, size_is(aLength)] in nsIPrincipal aPrincipalArray,
[optional] in unsigned long aLength);
/**
* Returns OK if aSourceURI and target have the same "origin"
* (scheme, host, and port).

34
caps/nsPrincipal.cpp

@ -14,6 +14,7 @@
#include "pratom.h"
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsIStandardURL.h"
#include "nsIURIWithPrincipal.h"
#include "nsJSPrincipals.h"
#include "nsIEffectiveTLDService.h"
@ -127,6 +128,31 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
}
}
// We want the invariant that prinA.origin == prinB.origin i.f.f.
// prinA.equals(prinB). However, this requires that we impose certain constraints
// on the behavior and origin semantics of principals, and in particular, forbid
// creating origin strings for principals whose equality constraints are not
// expressible as strings (i.e. object equality). Moreover, we want to forbid URIs
// containing the magic "^" we use as a separating character for origin
// attributes.
//
// These constraints can generally be achieved by restricting .origin to
// nsIStandardURL-based URIs, but there are a few other URI schemes that we need
// to handle.
bool isBehaved;
if ((NS_SUCCEEDED(origin->SchemeIs("about", &isBehaved)) && isBehaved) ||
(NS_SUCCEEDED(origin->SchemeIs("moz-safe-about", &isBehaved)) && isBehaved) ||
(NS_SUCCEEDED(origin->SchemeIs("indexeddb", &isBehaved)) && isBehaved)) {
rv = origin->GetAsciiSpec(aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
// These URIs could technically contain a '^', but they never should.
if (NS_WARN_IF(aOrigin.FindChar('^', 0) != -1)) {
aOrigin.Truncate();
return NS_ERROR_FAILURE;
}
return NS_OK;
}
int32_t port;
if (NS_SUCCEEDED(rv) && !isChrome) {
rv = origin->GetPort(&port);
@ -144,6 +170,14 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
aOrigin.Append(hostPort);
}
else {
// If we reached this branch, we can only create an origin if we have a nsIStandardURL.
// So, we query to a nsIStandardURL, and fail if we aren't an instance of an nsIStandardURL
// nsIStandardURLs have the good property of escaping the '^' character in their specs,
// which means that we can be sure that the caret character (which is reserved for delimiting
// the end of the spec, and the beginning of the origin attributes) is not present in the
// origin string
nsCOMPtr<nsIStandardURL> standardURL = do_QueryInterface(origin);
NS_ENSURE_TRUE(standardURL, NS_ERROR_FAILURE);
rv = origin->GetAsciiSpec(aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
}

17
caps/nsScriptSecurityManager.cpp

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 et sw=4 tw=80: */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -1077,6 +1077,21 @@ nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttrib
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateExpandedPrincipal(nsIPrincipal** aPrincipalArray, uint32_t aLength,
nsIPrincipal** aResult)
{
nsTArray<nsCOMPtr<nsIPrincipal>> principals;
principals.SetCapacity(aLength);
for (uint32_t i = 0; i < aLength; ++i) {
principals.AppendElement(aPrincipalArray[i]);
}
nsCOMPtr<nsIPrincipal> p = new nsExpandedPrincipal(principals);
p.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
uint32_t aAppId,

5
caps/tests/unit/test_origin.js

@ -20,9 +20,6 @@ function checkCrossOrigin(a, b) {
do_check_false(a.subsumesConsideringDomain(b));
do_check_false(b.subsumes(a));
do_check_false(b.subsumesConsideringDomain(a));
do_check_eq(a.cookieJar === b.cookieJar,
a.originAttributes.appId == b.originAttributes.appId &&
a.originAttributes.inBrowser == b.originAttributes.inBrowser);
}
function checkOriginAttributes(prin, attrs, suffix) {
@ -50,7 +47,7 @@ function run_test() {
var nullPrin = Cu.getObjectPrincipal(new Cu.Sandbox(null));
do_check_true(/^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(nullPrin.origin));
checkOriginAttributes(nullPrin);
var ep = Cu.getObjectPrincipal(new Cu.Sandbox([exampleCom, nullPrin, exampleOrg]));
var ep = ssm.createExpandedPrincipal([exampleCom, nullPrin, exampleOrg]);
checkOriginAttributes(ep);
checkCrossOrigin(exampleCom, exampleOrg);
checkCrossOrigin(exampleOrg, nullPrin);

9
dom/base/ChromeUtils.cpp

@ -10,15 +10,6 @@
namespace mozilla {
namespace dom {
/* static */ void
ChromeUtils::OriginAttributesToCookieJar(GlobalObject& aGlobal,
const OriginAttributesDictionary& aAttrs,
nsCString& aCookieJar)
{
OriginAttributes attrs(aAttrs);
attrs.CookieJar(aCookieJar);
}
/* static */ void
ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,

5
dom/base/ChromeUtils.h

@ -40,11 +40,6 @@ public:
class ChromeUtils : public ThreadSafeChromeUtils
{
public:
static void
OriginAttributesToCookieJar(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,
nsCString& aCookieJar);
static void
OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,

34
dom/base/Navigator.cpp

@ -176,6 +176,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCellBroadcast)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager)
@ -241,6 +242,8 @@ Navigator::Invalidate()
mBatteryManager = nullptr;
}
mBatteryPromise = nullptr;
#ifdef MOZ_B2G_FM
if (mFMRadio) {
mFMRadio->Shutdown();
@ -1385,8 +1388,37 @@ Navigator::GetMozFMRadio(ErrorResult& aRv)
// Navigator::nsINavigatorBattery
//*****************************************************************************
battery::BatteryManager*
Promise*
Navigator::GetBattery(ErrorResult& aRv)
{
if (mBatteryPromise) {
return mBatteryPromise;
}
if (!mWindow || !mWindow->GetDocShell()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
nsRefPtr<Promise> batteryPromise = Promise::Create(go, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
mBatteryPromise = batteryPromise;
if (!mBatteryManager) {
mBatteryManager = new battery::BatteryManager(mWindow);
mBatteryManager->Init();
}
mBatteryPromise->MaybeResolve(mBatteryManager);
return mBatteryPromise;
}
battery::BatteryManager*
Navigator::GetDeprecatedBattery(ErrorResult& aRv)
{
if (!mBatteryManager) {
if (!mWindow) {

4
dom/base/Navigator.h

@ -156,7 +156,8 @@ public:
Permissions* GetPermissions(ErrorResult& aRv);
// The XPCOM GetDoNotTrack is ok
Geolocation* GetGeolocation(ErrorResult& aRv);
battery::BatteryManager* GetBattery(ErrorResult& aRv);
Promise* GetBattery(ErrorResult& aRv);
battery::BatteryManager* GetDeprecatedBattery(ErrorResult& aRv);
static already_AddRefed<Promise> GetDataStores(nsPIDOMWindow* aWindow,
const nsAString& aName,
@ -351,6 +352,7 @@ private:
nsRefPtr<Geolocation> mGeolocation;
nsRefPtr<DesktopNotificationCenter> mNotification;
nsRefPtr<battery::BatteryManager> mBatteryManager;
nsRefPtr<Promise> mBatteryPromise;
#ifdef MOZ_B2G_FM
nsRefPtr<FMRadio> mFMRadio;
#endif

20
dom/base/nsContentUtils.cpp

@ -51,6 +51,7 @@
#include "mozilla/dom/TextDecoder.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
@ -8050,3 +8051,22 @@ nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
net::ReferrerPolicy referrerPolicy = aDoc->GetReferrerPolicy();
return aChannel->SetReferrerWithPolicy(referrerURI, referrerPolicy);
}
// static
bool
nsContentUtils::PushEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.push.enabled", false);
}
using namespace workers;
// Otherwise, check the pref via the WorkerPrivate
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->PushEnabled();
}

2
dom/base/nsContentUtils.h

@ -2489,6 +2489,8 @@ public:
nsIDocument* aDoc,
nsIHttpChannel* aChannel);
static bool PushEnabled(JSContext* aCx, JSObject* aObj);
private:
static bool InitializeEventTable();

20
dom/base/nsPerformance.cpp

@ -744,13 +744,7 @@ nsPerformance::InsertUserEntry(PerformanceEntry* aEntry)
// If we have no URI, just put in "none".
uri.AssignLiteral("none");
}
PERFLOG("Performance Entry: %s|%s|%s|%f|%f|%" PRIu64 "\n",
uri.get(),
NS_ConvertUTF16toUTF8(aEntry->GetEntryType()).get(),
NS_ConvertUTF16toUTF8(aEntry->GetName()).get(),
aEntry->StartTime(),
aEntry->Duration(),
static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC));
PerformanceBase::LogEntry(aEntry, uri);
}
PerformanceBase::InsertUserEntry(aEntry);
@ -979,6 +973,18 @@ PerformanceBase::ClearMeasures(const Optional<nsAString>& aName)
ClearUserEntries(aName, NS_LITERAL_STRING("measure"));
}
void
PerformanceBase::LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const
{
PERFLOG("Performance Entry: %s|%s|%s|%f|%f|%" PRIu64 "\n",
aOwner.BeginReading(),
NS_ConvertUTF16toUTF8(aEntry->GetEntryType()).get(),
NS_ConvertUTF16toUTF8(aEntry->GetName()).get(),
aEntry->StartTime(),
aEntry->Duration(),
static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC));
}
void
PerformanceBase::InsertUserEntry(PerformanceEntry* aEntry)
{

2
dom/base/nsPerformance.h

@ -350,6 +350,8 @@ protected:
return mResourceEntries.Length() >= mResourceTimingBufferSize;
}
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
private:
nsTArray<nsRefPtr<PerformanceEntry>> mUserEntries;
nsTArray<nsRefPtr<PerformanceEntry>> mResourceEntries;

53
dom/battery/BatteryManager.cpp

@ -10,6 +10,7 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Hal.h"
#include "mozilla/dom/BatteryManagerBinding.h"
#include "mozilla/Preferences.h"
#include "nsIDOMClassInfo.h"
/**
@ -56,10 +57,37 @@ BatteryManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return BatteryManagerBinding::Wrap(aCx, this, aGivenProto);
}
bool
BatteryManager::Charging() const
{
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default", false)) {
return true;
}
if (Preferences::GetBool("dom.battery.test.charging", false)) {
return true;
}
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
return false;
}
return mCharging;
}
double
BatteryManager::DischargingTime() const
{
if (mCharging || mRemainingTime == kUnknownRemainingTime) {
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default", false)) {
return std::numeric_limits<double>::infinity();
}
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
return 42.0;
}
if (Charging() || mRemainingTime == kUnknownRemainingTime) {
return std::numeric_limits<double>::infinity();
}
@ -69,13 +97,34 @@ BatteryManager::DischargingTime() const
double
BatteryManager::ChargingTime() const
{
if (!mCharging || mRemainingTime == kUnknownRemainingTime) {
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default", false)) {
return 0.0;
}
if (Preferences::GetBool("dom.battery.test.charging", false)) {
return 42.0;
}
if (!Charging() || mRemainingTime == kUnknownRemainingTime) {
return std::numeric_limits<double>::infinity();
}
return mRemainingTime;
}
double
BatteryManager::Level() const
{
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default")) {
return 1.0;
}
return mLevel;
}
void
BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
{

10
dom/battery/BatteryManager.h

@ -46,19 +46,13 @@ public:
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
bool Charging() const
{
return mCharging;
}
bool Charging() const;
double ChargingTime() const;
double DischargingTime() const;
double Level() const
{
return mLevel;
}
double Level() const;
IMPL_EVENT_HANDLER(chargingchange)
IMPL_EVENT_HANDLER(chargingtimechange)

6
dom/battery/test/marionette/manifest.ini

@ -9,3 +9,9 @@ qemu = true
[test_battery_status_full.js]
[test_battery_status_not_charging.js]
[test_battery_status_unknown.js]
[test_deprecated_battery_level.js]
[test_deprecated_battery_status_charging.js]
[test_deprecated_battery_status_discharging.js]
[test_deprecated_battery_status_full.js]
[test_deprecated_battery_status_not_charging.js]
[test_deprecated_battery_status_unknown.js]

25
dom/battery/test/marionette/test_battery_level.js

@ -3,15 +3,18 @@
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let battery = null;
function verifyInitialState() {
ok(battery, "battery");
is(battery.level, 0.5, "battery.level");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("capacity: 50") !== -1, "power capacity");
setUp();
window.navigator.getBattery().then(function (b) {
battery = b;
ok(battery, "battery");
is(battery.level, 0.5, "battery.level");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("capacity: 50") !== -1, "power capacity");
setUp();
});
});
}
@ -29,10 +32,10 @@ function changeCapacity(capacity, changeExpected, nextFunction) {
log("Changing power capacity to " + capacity);
if (changeExpected) {
battery.onlevelchange = function (event) {
battery.onlevelchange = unexpectedEvent;
is(event.type, "levelchange", "event.type");
is(battery.level, capacity / 100, "battery.level");
nextFunction();
battery.onlevelchange = unexpectedEvent;
is(event.type, "levelchange", "event.type");
is(battery.level, capacity / 100, "battery.level");
nextFunction();
};
runEmulatorCmd("power capacity " + capacity);
}

17
dom/battery/test/marionette/test_battery_status_charging.js

@ -3,17 +3,20 @@
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let battery = null;
let fromStatus = "charging";
let fromCharging = true;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
window.navigator.getBattery().then(function (b) {
battery = b;
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
});
}

17
dom/battery/test/marionette/test_battery_status_discharging.js

@ -3,17 +3,20 @@
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let battery = null;
let fromStatus = "discharging";
let fromCharging = false;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
window.navigator.getBattery().then(function (b) {
battery = b;
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
});
}

15
dom/battery/test/marionette/test_battery_status_full.js

@ -8,12 +8,15 @@ let fromStatus = "full";
let fromCharging = true;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
window.navigator.getBattery().then(function (b) {
battery = b;
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
});
}

15
dom/battery/test/marionette/test_battery_status_not_charging.js

@ -8,12 +8,15 @@ let fromStatus = "not-charging";
let fromCharging = false;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
window.navigator.getBattery().then(function (b) {
battery = b;
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
});
}

15
dom/battery/test/marionette/test_battery_status_unknown.js

@ -8,12 +8,15 @@ let fromStatus = "unknown";
let fromCharging = false;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
window.navigator.getBattery().then(function (b) {
battery = b;
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
});
}

68
dom/battery/test/marionette/test_deprecated_battery_level.js

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
function verifyInitialState() {
ok(battery, "battery");
is(battery.level, 0.5, "battery.level");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("capacity: 50") !== -1, "power capacity");
setUp();
});
}
function unexpectedEvent(event) {
ok(false, "Unexpected " + event.type + " event");
}
function setUp() {
battery.onchargingchange = unexpectedEvent;
battery.onlevelchange = unexpectedEvent;
levelUp();
}
function changeCapacity(capacity, changeExpected, nextFunction) {
log("Changing power capacity to " + capacity);
if (changeExpected) {
battery.onlevelchange = function (event) {
battery.onlevelchange = unexpectedEvent;
is(event.type, "levelchange", "event.type");
is(battery.level, capacity / 100, "battery.level");
nextFunction();
};
runEmulatorCmd("power capacity " + capacity);
}
else {
runEmulatorCmd("power capacity " + capacity, function () {
is(battery.level, capacity / 100, "battery.level");
nextFunction();
});
}
}
function levelUp() {
changeCapacity("90", true, levelDown);
}
function levelDown() {
changeCapacity("10", true, levelSame);
}
function levelSame() {
changeCapacity("10", false, cleanUp);
}
function cleanUp() {
battery.onchargingchange = null;
battery.onlevelchange = function () {
battery.onlevelchange = null;
finish();
};
runEmulatorCmd("power capacity 50");
}
verifyInitialState();

85
dom/battery/test/marionette/test_deprecated_battery_status_charging.js

@ -0,0 +1,85 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let fromStatus = "charging";
let fromCharging = true;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
}
function unexpectedEvent(event) {
ok(false, "Unexpected " + event.type + " event");
}
function setUp() {
battery.onchargingchange = unexpectedEvent;
battery.onlevelchange = unexpectedEvent;
toDischarging();
}
function resetStatus(charging, nextFunction) {
log("Resetting power status to " + fromStatus);
if (charging !== fromCharging) {
battery.onchargingchange = function () {
battery.onchargingchange = unexpectedEvent;
nextFunction();
};
runEmulatorCmd("power status " + fromStatus);
}
else {
runEmulatorCmd("power status " + fromStatus, nextFunction);
}
}
function changeStatus(toStatus, toCharging, nextFunction) {
log("Changing power status to " + toStatus);
if (fromCharging !== toCharging) {
battery.onchargingchange = function (event) {
battery.onchargingchange = unexpectedEvent;
is(event.type, "chargingchange", "event type");
is(battery.charging, toCharging, "battery.charging");
resetStatus(toCharging, nextFunction);
};
runEmulatorCmd("power status " + toStatus);
}
else {
runEmulatorCmd("power status " + toStatus, function () {
is(battery.charging, toCharging, "battery.charging");
resetStatus(toCharging, nextFunction);
});
}
}
function toDischarging() {
changeStatus("discharging", false, toFull);
}
function toFull() {
changeStatus("full", true, toNotCharging);
}
function toNotCharging() {
changeStatus("not-charging", false, toUnknown);
}
function toUnknown() {
changeStatus("unknown", false, cleanUp);
}
function cleanUp() {
battery.onchargingchange = null;
battery.onlevelchange = null;
finish();
}
verifyInitialState();

93
dom/battery/test/marionette/test_deprecated_battery_status_discharging.js

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let fromStatus = "discharging";
let fromCharging = false;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
}
function unexpectedEvent(event) {
ok(false, "Unexpected " + event.type + " event");
}
function setUp() {
battery.onchargingchange = function () {
battery.onchargingchange = unexpectedEvent;
toCharging();
};
battery.onlevelchange = unexpectedEvent;
log("Changing power status to " + fromStatus);
runEmulatorCmd("power status " + fromStatus);
}
function resetStatus(charging, nextFunction) {
log("Resetting power status to " + fromStatus);
if (charging !== fromCharging) {
battery.onchargingchange = function () {
battery.onchargingchange = unexpectedEvent;
nextFunction();
};
runEmulatorCmd("power status " + fromStatus);
}
else {
runEmulatorCmd("power status " + fromStatus, nextFunction);
}
}
function changeStatus(toStatus, toCharging, nextFunction) {
log("Changing power status to " + toStatus);
if (fromCharging !== toCharging) {
battery.onchargingchange = function (event) {
battery.onchargingchange = unexpectedEvent;
is(event.type, "chargingchange", "event type");
is(battery.charging, toCharging, "battery.charging");
resetStatus(toCharging, nextFunction);
};
runEmulatorCmd("power status " + toStatus);
}
else {
runEmulatorCmd("power status " + toStatus, function () {
is(battery.charging, toCharging, "battery.charging");
resetStatus(toCharging, nextFunction);
});
}
}
function toCharging() {
changeStatus("charging", true, toFull);
}
function toFull() {
changeStatus("full", true, toNotCharging);
}
function toNotCharging() {
changeStatus("not-charging", false, toUnknown);
}
function toUnknown() {
changeStatus("unknown", false, cleanUp);
}
function cleanUp() {
battery.onchargingchange = function () {
battery.onchargingchange = null;
finish();
};
battery.onlevelchange = null;
log("Resetting power status to charging");
runEmulatorCmd("power status charging");
}
verifyInitialState();

87
dom/battery/test/marionette/test_deprecated_battery_status_full.js

@ -0,0 +1,87 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let fromStatus = "full";
let fromCharging = true;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
}
function unexpectedEvent(event) {
ok(false, "Unexpected " + event.type + " event");
}
function setUp() {
battery.onchargingchange = unexpectedEvent;
battery.onlevelchange = unexpectedEvent;
log("Changing power status to " + fromStatus);
runEmulatorCmd("power status " + fromStatus, toCharging);
}
function resetStatus(charging, nextFunction) {
log("Resetting power status to " + fromStatus);
if (charging !== fromCharging) {
battery.onchargingchange = function () {
battery.onchargingchange = unexpectedEvent;
nextFunction();
};
runEmulatorCmd("power status " + fromStatus);
}
else {
runEmulatorCmd("power status " + fromStatus, nextFunction);
}
}
function changeStatus(toStatus, toCharging, nextFunction) {
log("Changing power status to " + toStatus);
if (fromCharging !== toCharging) {
battery.onchargingchange = function (event) {
battery.onchargingchange = unexpectedEvent;
is(event.type, "chargingchange", "event type");
is(battery.charging, toCharging, "battery.charging");
resetStatus(toCharging, nextFunction);
};
runEmulatorCmd("power status " + toStatus);
}
else {
runEmulatorCmd("power status " + toStatus, function () {
is(battery.charging, toCharging, "battery.charging");
resetStatus(toCharging, nextFunction);
});
}
}
function toCharging() {
changeStatus("charging", true, toDischarging);
}
function toDischarging() {
changeStatus("discharging", false, toNotCharging);
}
function toNotCharging() {
changeStatus("not-charging", false, toUnknown);
}
function toUnknown() {
changeStatus("unknown", false, cleanUp);
}
function cleanUp() {
battery.onchargingchange = null;
battery.onlevelchange = null;
log("Resetting power status to charging");
runEmulatorCmd("power status charging", finish);
}
verifyInitialState();

93
dom/battery/test/marionette/test_deprecated_battery_status_not_charging.js

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
let battery = window.navigator.battery;
let fromStatus = "not-charging";
let fromCharging = false;
function verifyInitialState() {
ok(battery, "battery");
ok(battery.charging, "battery.charging");
runEmulatorCmd("power display", function (result) {
is(result.pop(), "OK", "power display successful");
ok(result.indexOf("status: Charging") !== -1, "power status charging");
setUp();
});
}
function unexpectedEvent(event) {
ok(false, "Unexpected " + event.type + " event");
}
function setUp() {
battery.onchargingchange = function () {