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)
This commit is contained in:
2021-12-23 09:44:29 +08:00
parent f9c3c72b8c
commit 9e4ed9857d
81 changed files with 1306 additions and 442 deletions
+6 -2
View File
@@ -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
+1 -1
View File
@@ -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.)
+14 -1
View File
@@ -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
View File
@@ -0,0 +1,3 @@
browser.jar:
% resource app %
defaults/permissions (permissions)
+2
View File
@@ -89,3 +89,5 @@ if CONFIG['MOZ_LINKER']:
if CONFIG['HAVE_CLOCK_MONOTONIC']:
OS_LIBS += CONFIG['REALTIME_LIBS']
JAR_MANIFESTS += ['jar.mn']
+20
View File
@@ -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
View File
@@ -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);
+1 -14
View File
@@ -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
View File
@@ -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;
+1 -25
View File
@@ -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
+15 -1
View File
@@ -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
View File
@@ -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);
}
+16 -1
View File
@@ -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,
+1 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+33 -1
View File
@@ -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) {
+3 -1
View File
@@ -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
View File
@@ -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
View File
@@ -2489,6 +2489,8 @@ public:
nsIDocument* aDoc,
nsIHttpChannel* aChannel);
static bool PushEnabled(JSContext* aCx, JSObject* aObj);
private:
static bool InitializeEventTable();
+13 -7
View File
@@ -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
View File
@@ -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;
+51 -2
View File
@@ -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)
{
+2 -8
View File
@@ -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
View File
@@ -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]
@@ -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);
}
@@ -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();
});
});
}
@@ -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();
});
});
}
@@ -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();
});
});
}
@@ -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();
});
});
}
@@ -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();
});
});
}
@@ -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();
@@ -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();
@@ -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();
@@ -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();
@@ -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 () {
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, toDischarging);
}
function toDischarging() {
changeStatus("discharging", false, toFull);
}
function toFull() {
changeStatus("full", true, 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();
@@ -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 = "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();
});
}
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, toDischarging);
}
function toDischarging() {
changeStatus("discharging", false, toFull);
}
function toFull() {
changeStatus("full", true, toNotCharging);
}
function toNotCharging() {
changeStatus("not-charging", 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();
+6
View File
@@ -1,2 +1,8 @@
[test_battery_basics.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
[test_battery_charging.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
[test_battery_discharging.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
[test_deprecated_battery_basics.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
+13 -10
View File
@@ -12,20 +12,23 @@
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
/** Test for Battery API **/
ok("getBattery" in navigator, "navigator.getBattery should exist");
ok('battery' in navigator, "navigator.battery should exist");
navigator.getBattery().then(function (battery) {
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
var battery = navigator.battery;
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.default", true]]}, function () {
ok(battery.charging, "Battery should be charging by default");
is(battery.chargingTime, 0, "Battery chargingTime " + battery.chargingTime + " should be zero by default");
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity by default");
is(battery.level, 1.0, "Battery level " + battery.level + " should be 1.0 by default");
if (battery.charging) {
ok(battery.chargingTime >= 0, "Battery chargingTime " + battery.chargingTime + " should be nonnegative when charging");
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity when charging");
} else {
is(battery.chargingTime, Infinity, "Battery chargingTime should be Infinity when discharging");
ok(battery.dischargingTime > 0, "Battery dischargingTime " + battery.dischargingTime + " should be positive when discharging");
}
SimpleTest.finish();
});
});
</script>
</pre>
@@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
/** Test for Battery API **/
navigator.getBattery().then(function (battery) {
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.charging", true]]}, function () {
is(battery.charging, true, "Battery should be charging");
ok(battery.chargingTime >= 0, "Battery chargingTime " + battery.chargingTime + " should be nonnegative when charging");
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity when charging");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>
@@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
/** Test for Battery API **/
navigator.getBattery().then(function (battery) {
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.discharging", true]]}, function () {
is(battery.charging, false, "Battery should be discharging");
is(battery.chargingTime, Infinity, "Battery chargingTime should be Infinity when discharging");
ok(battery.dischargingTime > 0, "Battery dischargingTime " + battery.dischargingTime + " should be positive when discharging");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>
@@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Battery API **/
ok("battery" in navigator, "navigator.battery should exist");
var battery = navigator.battery;
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
if (battery.charging) {
ok(battery.chargingTime >= 0, "Battery chargingTime " + battery.chargingTime + " should be nonnegative when charging");
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity when charging");
} else {
is(battery.chargingTime, Infinity, "Battery chargingTime should be Infinity when discharging");
ok(battery.dischargingTime > 0, "Battery dischargingTime " + battery.dischargingTime + " should be positive when discharging");
}
</script>
</pre>
</body>
</html>
+20
View File
@@ -14,6 +14,7 @@
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/URL.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/workers/bindings/URL.h"
#include "WorkerPrivate.h"
@@ -42,6 +43,25 @@ Request::~Request()
{
}
// static
bool
Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.requestcontext.enabled", false);
}
using namespace workers;
// Otherwise, check the pref via the WorkerPrivate
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->RequestContextEnabled();
}
already_AddRefed<InternalRequest>
Request::GetInternalRequest()
{
+3
View File
@@ -34,6 +34,9 @@ class Request final : public nsISupports
public:
Request(nsIGlobalObject* aOwner, InternalRequest* aRequest);
static bool
RequestContextEnabled(JSContext* aCx, JSObject* aObj);
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
{
-17
View File
@@ -129,23 +129,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushSubscription)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
// PushManager
// static
bool
PushManager::Enabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.push.enabled", false);
}
// XXXnsm: As of this patch it seems like Push will be enabled before or with
// ServiceWorkers, so this seems OK for now.
ServiceWorkerGlobalScope* scope = nullptr;
nsresult rv = UnwrapObject<prototypes::id::ServiceWorkerGlobalScope_workers,
mozilla::dom::ServiceWorkerGlobalScopeBinding_workers::NativeType>(aObj, scope);
return NS_SUCCEEDED(rv);
}
PushManager::PushManager(nsIGlobalObject* aGlobal, const nsAString& aScope)
: mGlobal(aGlobal), mScope(aScope)
{
-3
View File
@@ -106,9 +106,6 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushManager)
static bool
Enabled(JSContext* aCx, JSObject* aObj);
explicit PushManager(nsIGlobalObject* aGlobal, const nsAString& aScope);
nsIGlobalObject*
+5 -1
View File
@@ -7,7 +7,11 @@ function handlePush(event) {
self.clients.matchAll().then(function(result) {
if (event instanceof PushEvent &&
event.data instanceof PushMessageData) {
event.data instanceof PushMessageData &&
event.data.text === undefined &&
event.data.json === undefined &&
event.data.arrayBuffer === undefined &&
event.data.blob === undefined) {
result[0].postMessage({type: "finished", okay: "yes"});
return;
@@ -2,7 +2,8 @@ function testScript(script) {
function setupPrefs() {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({
"set": [["dom.serviceWorkers.enabled", true],
"set": [["dom.requestcontext.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]
}, resolve);
+1
View File
@@ -35,6 +35,7 @@ skip-if = e10s || buildapp == 'b2g' # Bug 1173163 for e10s, bug 1137683 for b2g
[test_formdataparsing_sw_reroute.html]
skip-if = buildapp == 'b2g' # Bug 1137683
[test_request.html]
[test_request_context.html]
[test_request_sw_reroute.html]
skip-if = buildapp == 'b2g' # Bug 1137683
[test_response.html]
@@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Make sure that Request.context is not exposed by default</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
var req = new Request("");
ok(!("context" in req), "Request.context should not be exposed by default");
</script>
</body>
</html>
-9
View File
@@ -10,15 +10,6 @@
*/
[ChromeOnly, Exposed=(Window,System)]
interface ChromeUtils : ThreadSafeChromeUtils {
/**
* A helper that converts OriginAttributesDictionary to cookie jar opaque
* identfier.
*
* @param originAttrs The originAttributes from the caller.
*/
static ByteString
originAttributesToCookieJar(optional OriginAttributesDictionary originAttrs);
/**
* A helper that converts OriginAttributesDictionary to a opaque suffix string.
*
+8 -7
View File
@@ -124,14 +124,15 @@ interface NavigatorGeolocation {
Navigator implements NavigatorGeolocation;
// http://www.w3.org/TR/battery-status/#navigatorbattery-interface
[NoInterfaceObject]
interface NavigatorBattery {
// XXXbz Per spec this should be non-nullable, but we return null in
// torn-down windows. See bug 884925.
[Throws, Pref="dom.battery.enabled"]
readonly attribute BatteryManager? battery;
partial interface Navigator {
[Throws, Pref="dom.battery.enabled"]
Promise<BatteryManager> getBattery();
// Deprecated. Use getBattery() instead.
// XXXbz Per spec this should be non-nullable, but we return null in
// torn-down windows. See bug 884925.
[Throws, Pref="dom.battery.enabled", BinaryName="deprecatedBattery"]
readonly attribute BatteryManager? battery;
};
Navigator implements NavigatorBattery;
// https://wiki.mozilla.org/WebAPI/DataStore
[NoInterfaceObject,
+4 -2
View File
@@ -7,7 +7,9 @@
* https://w3c.github.io/push-api/
*/
[Constructor(DOMString type, optional PushEventInit eventInitDict), Exposed=ServiceWorker]
[Constructor(DOMString type, optional PushEventInit eventInitDict),
Func="nsContentUtils::PushEnabled",
Exposed=ServiceWorker]
interface PushEvent : ExtendableEvent {
readonly attribute PushMessageData data;
};
@@ -16,4 +18,4 @@ typedef USVString PushMessageDataInit;
dictionary PushEventInit : ExtendableEventInit {
PushMessageDataInit data;
};
};
+1 -1
View File
@@ -22,7 +22,7 @@ interface PushManagerImpl {
[Func="ServiceWorkerRegistration::WebPushMethodHider"] void setScope(DOMString scope);
};
[Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled"]
[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]
interface PushManager {
[ChromeOnly, Throws, Exposed=Window]
void setPushManagerImpl(PushManagerImpl store);
+9 -6
View File
@@ -7,11 +7,14 @@
* https://w3c.github.io/push-api/
*/
[Exposed=ServiceWorker]
[Func="nsContentUtils::PushEnabled",
Exposed=ServiceWorker]
interface PushMessageData
{
ArrayBuffer arrayBuffer();
Blob blob();
object json();
USVString text();
};
// FIXME(nsm): Bug 1149195.
// These methods will be exposed once encryption is supported.
// ArrayBuffer arrayBuffer();
// Blob blob();
// object json();
// USVString text();
};
+1 -1
View File
@@ -9,7 +9,7 @@
interface Principal;
[Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled",
[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled",
ChromeConstructor(DOMString pushEndpoint, DOMString scope)]
interface PushSubscription
{
+3
View File
@@ -17,6 +17,7 @@ interface Request {
readonly attribute USVString url;
[SameObject] readonly attribute Headers headers;
[Func="mozilla::dom::Request::RequestContextEnabled"]
readonly attribute RequestContext context;
readonly attribute DOMString referrer;
readonly attribute RequestMode mode;
@@ -41,6 +42,8 @@ dictionary RequestInit {
RequestCache cache;
};
// Gecko currently does not ship RequestContext, so please don't use it in IDL
// that is exposed to script.
enum RequestContext {
"audio", "beacon", "cspreport", "download", "embed", "eventsource", "favicon", "fetch",
"font", "form", "frame", "hyperlink", "iframe", "image", "imageset", "import",
+1 -1
View File
@@ -28,7 +28,7 @@ interface ServiceWorkerRegistration : EventTarget {
partial interface ServiceWorkerRegistration {
#ifndef MOZ_SIMPLEPUSH
[Throws, Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled"]
[Throws, Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]
readonly attribute PushManager pushManager;
#endif
};
+10
View File
@@ -64,6 +64,16 @@ Performance::GetPerformanceTimingFromString(const nsAString& aProperty)
return 0;
}
void
Performance::InsertUserEntry(PerformanceEntry* aEntry)
{
if (mWorkerPrivate->PerformanceLoggingEnabled()) {
PerformanceBase::LogEntry(aEntry,
NS_ConvertUTF16toUTF8(mWorkerPrivate->ScriptURL()));
}
PerformanceBase::InsertUserEntry(aEntry);
}
DOMHighResTimeStamp
Performance::DeltaFromNavigationStart(DOMHighResTimeStamp aTime)
{
+2
View File
@@ -26,6 +26,8 @@ public:
private:
~Performance();
void InsertUserEntry(PerformanceEntry* aEntry) override;
WorkerPrivate* mWorkerPrivate;
public:
+30
View File
@@ -158,6 +158,7 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_DOM_CACHES_ENABLED "dom.caches.enabled"
#define PREF_DOM_CACHES_TESTING_ENABLED "dom.caches.testing.enabled"
#define PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED "dom.performance.enable_user_timing_logging"
#define PREF_DOM_WORKERNOTIFICATION_ENABLED "dom.webnotifications.enabled"
#define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
#define PREF_INTL_ACCEPT_LANGUAGES "intl.accept_languages"
@@ -165,6 +166,8 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_SERVICEWORKERS_TESTING_ENABLED "dom.serviceWorkers.testing.enabled"
#define PREF_INTERCEPTION_ENABLED "dom.serviceWorkers.interception.enabled"
#define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
#define PREF_PUSH_ENABLED "dom.push.enabled"
#define PREF_REQUESTCONTEXT_ENABLED "dom.requestcontext.enabled"
namespace {
@@ -1910,10 +1913,22 @@ RuntimeService::Init()
WorkerPrefChanged,
PREF_DOM_CACHES_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES_TESTING))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PERFORMANCE_LOGGING_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_SERVICEWORKERS_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS_TESTING))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_PUSH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
@@ -2117,6 +2132,10 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_DOM_CACHES_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES_TESTING))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PERFORMANCE_LOGGING_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_INTERCEPTION_OPAQUE_ENABLED,
@@ -2137,6 +2156,14 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_DOM_WORKERNOTIFICATION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_WORKERNOTIFICATION))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_PUSH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
@@ -2675,6 +2702,7 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
case WORKERPREF_DOM_CACHES:
case WORKERPREF_DOM_CACHES_TESTING:
case WORKERPREF_DOM_WORKERNOTIFICATION:
case WORKERPREF_PERFORMANCE_LOGGING_ENABLED:
#ifdef DUMP_CONTROLLED_BY_PREF
case WORKERPREF_DUMP:
#endif
@@ -2682,6 +2710,8 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
case WORKERPREF_INTERCEPTION_OPAQUE_ENABLED:
case WORKERPREF_SERVICEWORKERS:
case WORKERPREF_SERVICEWORKERS_TESTING:
case WORKERPREF_PUSH:
case WORKERPREF_REQUESTCONTEXT:
sDefaultPreferences[key] = Preferences::GetBool(aPrefName, false);
break;
+1
View File
@@ -20,6 +20,7 @@
#endif
#include "nsProxyRelease.h"
#include "nsContentUtils.h"
class nsIInterceptedChannel;
+21
View File
@@ -1318,6 +1318,27 @@ public:
return mPreferences[WORKERPREF_DOM_CACHES_TESTING];
}
bool
PerformanceLoggingEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_PERFORMANCE_LOGGING_ENABLED];
}
bool
PushEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_PUSH];
}
bool
RequestContextEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_REQUESTCONTEXT];
}
bool
OnLine() const
{
+3
View File
@@ -205,6 +205,9 @@ enum WorkerPreference
WORKERPREF_DOM_CACHES_TESTING, // dom.caches.testing.enabled
WORKERPREF_SERVICEWORKERS_TESTING, // dom.serviceWorkers.testing.enabled
WORKERPREF_INTERCEPTION_OPAQUE_ENABLED, // dom.serviceWorkers.interception.opaque.enabled
WORKERPREF_PERFORMANCE_LOGGING_ENABLED, // dom.performance.enable_user_timing_logging
WORKERPREF_PUSH, // dom.push.enabled
WORKERPREF_REQUESTCONTEXT, // dom.requestcontext.enabled
WORKERPREF_COUNT
};
@@ -68,6 +68,7 @@ onload = function() {
["dom.caches.enabled", true],
["dom.image.picture.enabled", true],
["dom.image.srcset.enabled", true],
["dom.requestcontext.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.interception.enabled", true],
["dom.serviceWorkers.enabled", true],
@@ -48,8 +48,6 @@ var ecmaGlobals =
"Number",
"Object",
"Proxy",
"PushEvent",
"PushMessageData",
"RangeError",
"ReferenceError",
"Reflect",
@@ -168,9 +166,13 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"Promise",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PushManager",
{ name: "PushEvent", b2g: false, android: false, release: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
"PushSubscription",
{ name: "PushManager", b2g: false, android: false, release: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PushMessageData", b2g: false, android: false, release: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PushSubscription", b2g: false, android: false, release: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
@@ -157,6 +157,10 @@ var interfaceNamesInGlobalScope =
"PerformanceMeasure",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Promise",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PushManager", b2g: false, android: false, release: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PushSubscription", b2g: false, android: false, release: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
"Request",
// IMPORTANT: Do not change this list without review from a DOM peer!
+39 -2
View File
@@ -37,6 +37,8 @@
#include "mozilla/net/NeckoMessageUtils.h"
#include "mozilla/Preferences.h"
#include "nsReadLine.h"
#include "mozilla/Telemetry.h"
#include "nsIConsoleService.h"
static nsPermissionManager *gPermissionManager = nullptr;
@@ -67,6 +69,18 @@ ChildProcess()
return nullptr;
}
static void
LogToConsole(const nsAString& aMsg)
{
nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1"));
if (!console) {
NS_WARNING("Failed to log message to console.");
return;
}
nsAutoString msg(aMsg);
console->LogStringMessage(msg.get());
}
#define ENSURE_NOT_CHILD_PROCESS_(onError) \
PR_BEGIN_MACRO \
@@ -473,29 +487,52 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// cache a connection to the hosts database
rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
NS_ENSURE_SUCCESS(rv, rv);
if (rv == NS_ERROR_FILE_CORRUPTED) {
LogToConsole(NS_LITERAL_STRING("permissions.sqlite is corrupted! Try again!"));
// Add telemetry probe
mozilla::Telemetry::Accumulate(mozilla::Telemetry::PERMISSIONS_SQL_CORRUPTED, 1);
// delete corrupted permissions.sqlite and try again
rv = permissionsFile->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
LogToConsole(NS_LITERAL_STRING("Corrupted permissions.sqlite has been removed."));
rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
NS_ENSURE_SUCCESS(rv, rv);
LogToConsole(NS_LITERAL_STRING("OpenDatabase to permissions.sqlite is successful!"));
}
bool ready;
mDBConn->GetConnectionReady(&ready);
if (!ready) {
LogToConsole(NS_LITERAL_STRING("Fail to get connection to permissions.sqlite! Try again!"));
// delete and try again
rv = permissionsFile->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
LogToConsole(NS_LITERAL_STRING("Defective permissions.sqlite has been removed."));
// Add telemetry probe
mozilla::Telemetry::Accumulate(mozilla::Telemetry::DEFECTIVE_PERMISSIONS_SQL_REMOVED, 1);
rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
NS_ENSURE_SUCCESS(rv, rv);
LogToConsole(NS_LITERAL_STRING("OpenDatabase to permissions.sqlite is successful!"));
mDBConn->GetConnectionReady(&ready);
if (!ready)
return NS_ERROR_UNEXPECTED;
}
LogToConsole(NS_LITERAL_STRING("Get a connection to permissions.sqlite."));
bool tableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"), &tableExists);
if (!tableExists) {
rv = CreateTable();
NS_ENSURE_SUCCESS(rv, rv);
LogToConsole(NS_LITERAL_STRING("DB table(moz_hosts) is created!"));
} else {
// table already exists; check the schema version before reading
int32_t dbSchemaVersion;
@@ -0,0 +1,8 @@
// |jit-test| error: TypeError
var g = newGlobal();
g.debuggeeGlobal = this;
g.eval("(" + function () {
dbg = new Debugger(debuggeeGlobal);
dbg.onExceptionUnwind = Map;
} + ")();");
throw new Error("oops");
+7 -1
View File
@@ -1367,7 +1367,13 @@ FindStartPC(JSContext* cx, const FrameIter& iter, int spindex, int skipStackHits
if (spindex == JSDVG_SEARCH_STACK) {
size_t index = iter.numFrameSlots();
MOZ_ASSERT(index >= size_t(parser.stackDepthAtPC(current)));
// The decompiler may be called from inside functions that are not
// called from script, but via the C++ API directly, such as
// Invoke. In that case, the youngest script frame may have a
// completely unrelated pc and stack depth, so we give up.
if (index < size_t(parser.stackDepthAtPC(current)))
return true;
// We search from fp->sp to base to find the most recently calculated
// value matching v under assumption that it is the value that caused
+4 -1
View File
@@ -3430,7 +3430,7 @@ pref("intl.imm.vertical_writing.always_assume_not_supported", false);
// We cannot retrieve active IME name with IMM32 API if a TIP of TSF is active.
// This pref can specify active IME name when Japanese TIP is active.
// For example:
// Google Japanese Input: "Google 日本語入力 IMM32 モジュール"
// Google Japanese Input: "Google ?¥æœ¬èªžå…¥??IMM32 ?¢ã‚¸?¥ãƒ¼??
// ATOK 2011: "ATOK 2011" (similarly, e.g., ATOK 2013 is "ATOK 2013")
pref("intl.imm.japanese.assume_active_tip_name_as", "");
@@ -5196,4 +5196,7 @@ pref("dom.fetch.enabled", true);
// Turn rewriting of youtube embeds on/off
pref("plugins.rewrite_youtube_embeds", true);
// Expose Request.context. Currently disabled since the spec is in flux.
pref("dom.requestcontext.enabled", false);
pref("devtools.serviceWorkers.testing.enabled", false);
@@ -0,0 +1,52 @@
[battery-interface-idlharness.html]
type: testharness
[Navigator interface: operation getBattery()]
expected: FAIL
[BatteryManager must be primary interface of navigator.getBattery()]
expected: FAIL
[Stringification of navigator.getBattery()]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "charging" with the proper type (0)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "chargingTime" with the proper type (1)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "dischargingTime" with the proper type (2)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "level" with the proper type (3)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "onchargingchange" with the proper type (4)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "onchargingtimechange" with the proper type (5)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "ondischargingtimechange" with the proper type (6)]
expected: FAIL
[BatteryManager interface: navigator.getBattery() must inherit property "onlevelchange" with the proper type (7)]
expected: FAIL
[EventTarget interface: navigator.getBattery() must inherit property "addEventListener" with the proper type (0)]
expected: FAIL
[EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on navigator.getBattery() with too few arguments must throw TypeError]
expected: FAIL
[EventTarget interface: navigator.getBattery() must inherit property "removeEventListener" with the proper type (1)]
expected: FAIL
[EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on navigator.getBattery() with too few arguments must throw TypeError]
expected: FAIL
[EventTarget interface: navigator.getBattery() must inherit property "dispatchEvent" with the proper type (2)]
expected: FAIL
[EventTarget interface: calling dispatchEvent(Event) on navigator.getBattery() with too few arguments must throw TypeError]
expected: FAIL
@@ -1,6 +1,37 @@
[battery-interface.html]
type: testharness
expected: ERROR
[getBattery is present on navigator]
[onchargingchange: treat object as null]
expected: FAIL
[onchargingchange: treat object with non-callable call property as null]
expected: FAIL
[onchargingchange: treat array as null]
expected: FAIL
[onchargingtimechange: treat object as null]
expected: FAIL
[onchargingtimechange: treat object with non-callable call property as null]
expected: FAIL
[onchargingtimechange: treat array as null]
expected: FAIL
[ondischargingtimechange: treat object as null]
expected: FAIL
[ondischargingtimechange: treat object with non-callable call property as null]
expected: FAIL
[ondischargingtimechange: treat array as null]
expected: FAIL
[onlevelchange: treat object as null]
expected: FAIL
[onlevelchange: treat object with non-callable call property as null]
expected: FAIL
[onlevelchange: treat array as null]
expected: FAIL
@@ -1,8 +0,0 @@
[battery-promise.html]
type: testharness
[navigator.getBattery() return BatteryManager]
expected: FAIL
[navigator.getBattery() shall always return the same promise]
expected: FAIL
@@ -6783,5 +6783,15 @@
"high": "100",
"n_buckets": "20",
"description": "Proportion (%) of reschedulings of the main process to another CPU during the execution of code inside a JS compartment. Updated while we are measuring jank."
},
"PERMISSIONS_SQL_CORRUPTED": {
"expires_in_version": "never",
"kind": "count",
"description": "Record the permissions.sqlite init failure"
},
"DEFECTIVE_PERMISSIONS_SQL_REMOVED": {
"expires_in_version": "never",
"kind": "count",
"description": "Record the removal of defective permissions.sqlite"
}
}
@@ -1,26 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/Services.jsm");
var ssm = Services.scriptSecurityManager;
function run_test() {
const appId = 12;
var browserAttrs = {appId: appId, inBrowser: true};
// ChromeUtils.originAttributesToCookieJar should return the same value with
// the cookieJar of the principal created from the same origin attribute.
var cookieJar_1 = ChromeUtils.originAttributesToCookieJar(browserAttrs);
var dummy = Services.io.newURI("http://example.com", null, null);
var cookieJar_2 = ssm.createCodebasePrincipal(dummy, browserAttrs).cookieJar;
do_check_eq(cookieJar_1, cookieJar_2);
// App and mozbrowser shouldn't have the same cookieJar identifier.
var appAttrs = {appId: appId, inBrowser: false};
var cookieJar_3 = ChromeUtils.originAttributesToCookieJar(appAttrs);
do_check_neq(cookieJar_1, cookieJar_3);
// If the attribute is null the cookieJar identifier should be empty.
var cookieJar_4 = ChromeUtils.originAttributesToCookieJar();
do_check_eq(cookieJar_4, "");
}
@@ -81,7 +81,6 @@ support-files =
[test_eval-03.js]
[test_eval-04.js]
[test_eval-05.js]
[test_originAttributesToCookieJar.js]
[test_promises_actor_attach.js]
[test_promises_actor_exist.js]
[test_promises_actor_list_promises.js]
+16 -5
View File
@@ -5,12 +5,12 @@
"use strict";
/** This module wraps around navigator.battery (https://developer.mozilla.org/en-US/docs/Web/API/Navigator.battery).
/** This module wraps around navigator.getBattery (https://developer.mozilla.org/en-US/docs/Web/API/Navigator.getBattery).
* and provides a framework for spoofing battery values in test code.
* To spoof the battery values, set `Debugging.fake = true` after exporting this with a BackstagePass,
* after which you can spoof a property yb setting the relevant property of the Battery object.
* after which you can spoof a property yb setting the relevant property of the BatteryManager object.
*/
this.EXPORTED_SYMBOLS = ["Battery"];
this.EXPORTED_SYMBOLS = ["GetBattery", "Battery"];
const Ci = Components.interfaces;
const Cc = Components.classes;
@@ -40,6 +40,17 @@ this.Debugging = {
fake: false
}
this.GetBattery = function () {
return new Services.appShell.hiddenDOMWindow.Promise(function (resolve, reject) {
// Return fake values if spoofing is enabled, otherwise fetch the real values from the BatteryManager API
if (Debugging.fake) {
resolve(gFakeBattery);
return;
}
Services.appShell.hiddenDOMWindow.navigator.getBattery().then(resolve, reject);
});
};
this.Battery = {};
for (let k of ["charging", "chargingTime", "dischargingTime", "level"]) {
@@ -54,9 +65,9 @@ for (let k of ["charging", "chargingTime", "dischargingTime", "level"]) {
},
set: function(fakeSetting) {
if (!Debugging.fake) {
throw new Error("Tried to set fake battery value when battery spoofing was disabled");
throw new Error("Tried to set fake battery value when battery spoofing was disabled");
}
gFakeBattery[prop] = fakeSetting;
}
})
}
}
-31
View File
@@ -210,37 +210,6 @@ this.BrowserUtils = {
return "_blank";
},
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
// Don't modify non-default targets or targets that aren't in top-level app
// tab docshells (isAppTab will be false for app tab subframes).
if (originalTarget != "" || !isAppTab)
return originalTarget;
// External links from within app tabs should always open in new tabs
// instead of replacing the app tab's page (Bug 575561)
let linkHost;
let docHost;
try {
linkHost = linkURI.host;
docHost = linkNode.ownerDocument.documentURIObject.host;
} catch(e) {
// nsIURI.host can throw for non-nsStandardURL nsIURIs.
// If we fail to get either host, just return originalTarget.
return originalTarget;
}
if (docHost == linkHost)
return originalTarget;
// Special case: ignore "www" prefix if it is part of host string
let [longHost, shortHost] =
linkHost.length > docHost.length ? [linkHost, docHost] : [docHost, linkHost];
if (longHost == "www." + shortHost)
return originalTarget;
return "_blank";
},
/**
* Map the plugin's name to a filtered version more suitable for UI.
*
-173
View File
@@ -11,10 +11,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
const WEBRTC_PLAYER_NAME = "WebRTC Player";
const MIRROR_PORT = 8011;
const JSON_MESSAGE_TERMINATOR = "\r\n";
function log(msg) {
//Services.console.logStringMessage(msg);
}
@@ -34,7 +30,6 @@ function RokuApp(service) {
this.app = "Firefox Nightly";
#endif
this.mediaAppID = -1;
this.mirrorAppID = -1;
}
RokuApp.prototype = {
@@ -54,8 +49,6 @@ RokuApp.prototype = {
for (let app of apps) {
if (app.textContent == this.app) {
this.mediaAppID = app.id;
} else if (app.textContent == WEBRTC_PLAYER_NAME) {
this.mirrorAppID = app.id
}
}
}
@@ -145,44 +138,6 @@ RokuApp.prototype = {
callback();
}
}
},
mirror: function(callback, win, viewport, mirrorStartedCallback, contentWindow) {
if (this.mirrorAppID == -1) {
// The status function may not have been called yet if mirrorAppID is -1
this.status(this._createRemoteMirror.bind(this, callback, win, viewport, mirrorStartedCallback, contentWindow));
} else {
this._createRemoteMirror(callback, win, viewport, mirrorStartedCallback, contentWindow);
}
},
_createRemoteMirror: function(callback, win, viewport, mirrorStartedCallback, contentWindow) {
if (this.mirrorAppID == -1) {
// TODO: Inform user to install Roku WebRTC Player Channel.
log("RokuApp: Failed to find Mirror App ID.");
} else {
let url = this.resourceURL + "launch/" + this.mirrorAppID;
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
xhr.open("POST", url, true);
xhr.overrideMimeType("text/plain");
xhr.addEventListener("load", (function() {
// 204 seems to be returned if the channel is already running
if ((xhr.status == 200) || (xhr.status == 204)) {
this.remoteMirror = new RemoteMirror(this.resourceURL, win, viewport, mirrorStartedCallback, contentWindow);
}
}).bind(this), false);
xhr.addEventListener("error", function() {
log("RokuApp: XHR Failed to launch application: " + WEBRTC_PLAYER_NAME);
}, false);
xhr.send(null);
}
if (callback) {
callback();
}
}
}
@@ -278,131 +233,3 @@ RemoteMedia.prototype = {
return this._status;
}
}
function RemoteMirror(url, win, viewport, mirrorStartedCallback, contentWindow) {
this._serverURI = Services.io.newURI(url , null, null);
this._window = win;
this._iceCandidates = [];
this.mirrorStarted = mirrorStartedCallback;
// This code insures the generated tab mirror is not wider than 1280 nor taller than 720
// Better dimensions should be chosen after the Roku Channel is working.
let windowId = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
const MAX_WIDTH = 1280;
const MAX_HEIGHT = 720;
let constraints = {
video: {
mediaSource: "browser",
browserWindow: windowId,
scrollWithPage: true,
advanced: [
{
width: { min: 0, max: MAX_WIDTH },
height: { min: 0, max: MAX_HEIGHT }
},
{ aspectRatio: MAX_WIDTH/MAX_HEIGHT }
]
}
};
this._window.navigator.mozGetUserMedia(constraints, this._onReceiveGUMStream.bind(this), function() {});
}
RemoteMirror.prototype = {
_sendOffer: function(offer) {
if (!this._baseSocket) {
this._baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket);
}
this._jsonOffer = JSON.stringify(offer);
this._socket = this._baseSocket.open(this._serverURI.host, MIRROR_PORT, { useSecureTransport: false, binaryType: "string" });
this._socket.onopen = this._onSocketOpen.bind(this);
this._socket.ondata = this._onSocketData.bind(this);
this._socket.onerror = this._onSocketError.bind(this);
},
_onReceiveGUMStream: function(stream) {
this._pc = new this._window.mozRTCPeerConnection;
this._pc.addStream(stream);
this._pc.onicecandidate = (evt => {
// Usually the last candidate is null, expected?
if (!evt.candidate) {
return;
}
let jsonCandidate = JSON.stringify(evt.candidate);
this._iceCandidates.push(jsonCandidate);
this._sendIceCandidates();
});
this._pc.createOffer(offer => {
this._pc.setLocalDescription(
new this._window.mozRTCSessionDescription(offer),
() => this._sendOffer(offer),
() => log("RemoteMirror: Failed to set local description."));
},
() => log("RemoteMirror: Failed to create offer."));
},
_stopMirror: function() {
if (this._socket) {
this._socket.close();
this._socket = null;
}
if (this._pc) {
this._pc.close();
this._pc = null;
}
this._jsonOffer = null;
this._iceCandidates = [];
},
_onSocketData: function(response) {
if (response.type == "data") {
response.data.split(JSON_MESSAGE_TERMINATOR).forEach(data => {
if (data) {
let parsedData = JSON.parse(data);
if (parsedData.type == "answer") {
this._pc.setRemoteDescription(
new this._window.mozRTCSessionDescription(parsedData),
() => this.mirrorStarted(this._stopMirror.bind(this)),
() => log("RemoteMirror: Failed to set remote description."));
} else {
this._pc.addIceCandidate(new this._window.mozRTCIceCandidate(parsedData))
}
} else {
log("RemoteMirror: data is null");
}
});
} else if (response.type == "error") {
log("RemoteMirror: Got socket error.");
this._stopMirror();
} else {
log("RemoteMirror: Got unhandled socket event: " + response.type);
}
},
_onSocketError: function(err) {
log("RemoteMirror: Error socket.onerror: " + (err.data ? err.data : "NO DATA"));
this._stopMirror();
},
_onSocketOpen: function() {
this._open = true;
if (this._jsonOffer) {
let jsonOffer = this._jsonOffer + JSON_MESSAGE_TERMINATOR;
this._socket.send(jsonOffer, jsonOffer.length);
this._jsonOffer = null;
this._sendIceCandidates();
}
},
_sendIceCandidates: function() {
if (this._socket && this._open) {
this._iceCandidates.forEach(value => {
value = value + JSON_MESSAGE_TERMINATOR;
this._socket.send(value, value.length);
});
this._iceCandidates = [];
}
}
};
@@ -6,8 +6,11 @@ let imported = Components.utils.import("resource://gre/modules/Battery.jsm", thi
Cu.import("resource://gre/modules/Services.jsm", this);
function test() {
waitForExplicitFinish();
is(imported.Debugging.fake, false, "Battery spoofing is initially false")
// begin deprecated battery API testing
for (let k of ["charging", "chargingTime", "dischargingTime", "level"]) {
Assert.throws(() => Battery[k] = 10, "Setting battery " + k + "preference without spoofing enabled should throw");
ok(Battery[k] == Services.appShell.hiddenDOMWindow.navigator.battery[k], "Battery "+ k + " is correctly set");
@@ -27,4 +30,36 @@ function test() {
ok(!Battery.charging, "Test for charging setter");
is(Battery.dischargingTime, 50, "Test for dischargingTime setter");
is(Battery.level, 0.7, "Test for level setter");
}
imported.Debugging.fake = false;
// end deprecated battery API testing
GetBattery().then(function (battery) {
for (let k of ["charging", "chargingTime", "dischargingTime", "level"]) {
let backup = battery[k];
battery[k] = "__magic__";
is(battery[k], backup, "Setting battery " + k + "preference without spoofing enabled should fail");
}
imported.Debugging.fake = true;
// reload again to get the fake one
GetBattery().then(function (battery) {
battery.charging = true;
battery.chargingTime = 100;
battery.level = 0.5;
ok(battery.charging, "Test for charging setter");
is(battery.chargingTime, 100, "Test for chargingTime setter");
is(battery.level, 0.5, "Test for level setter");
battery.charging = false;
battery.dischargingTime = 50;
battery.level = 0.7;
ok(!battery.charging, "Test for charging setter");
is(battery.dischargingTime, 50, "Test for dischargingTime setter");
is(battery.level, 0.7, "Test for level setter");
finish();
});
});
}