mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-23 23:57:31 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
2ffe6398eb
42 changed files with 222 additions and 1023 deletions
|
|
@ -526,7 +526,6 @@ hardware/lights.h
|
||||||
hardware/power.h
|
hardware/power.h
|
||||||
hardware_legacy/power.h
|
hardware_legacy/power.h
|
||||||
hardware_legacy/uevent.h
|
hardware_legacy/uevent.h
|
||||||
hardware_legacy/vibrator.h
|
|
||||||
#endif
|
#endif
|
||||||
HIToolbox/HIToolbox.h
|
HIToolbox/HIToolbox.h
|
||||||
hlink.h
|
hlink.h
|
||||||
|
|
|
||||||
|
|
@ -97,11 +97,6 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
static bool sVibratorEnabled = false;
|
|
||||||
static uint32_t sMaxVibrateMS = 0;
|
|
||||||
static uint32_t sMaxVibrateListLen = 0;
|
|
||||||
static const char* kVibrationPermissionType = "vibration";
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
AddPermission(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPermission,
|
AddPermission(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPermission,
|
||||||
uint32_t aExpireType, int64_t aExpireTime)
|
uint32_t aExpireType, int64_t aExpireTime)
|
||||||
|
|
@ -152,12 +147,7 @@ GetPermission(nsIPrincipal* aPrincipal, const char* aType)
|
||||||
void
|
void
|
||||||
Navigator::Init()
|
Navigator::Init()
|
||||||
{
|
{
|
||||||
Preferences::AddBoolVarCache(&sVibratorEnabled,
|
// Add any Preferences::Add*VarCache(&sPref, "pref", default) here if needed.
|
||||||
"dom.vibrator.enabled", true);
|
|
||||||
Preferences::AddUintVarCache(&sMaxVibrateMS,
|
|
||||||
"dom.vibrator.max_vibrate_ms", 10000);
|
|
||||||
Preferences::AddUintVarCache(&sMaxVibrateListLen,
|
|
||||||
"dom.vibrator.max_vibrate_list_len", 128);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigator::Navigator(nsPIDOMWindowInner* aWindow)
|
Navigator::Navigator(nsPIDOMWindowInner* aWindow)
|
||||||
|
|
@ -705,82 +695,6 @@ Navigator::RefreshMIMEArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class VibrateWindowListener : public nsIDOMEventListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VibrateWindowListener(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument)
|
|
||||||
{
|
|
||||||
mWindow = do_GetWeakReference(aWindow);
|
|
||||||
mDocument = do_GetWeakReference(aDocument);
|
|
||||||
|
|
||||||
NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
|
|
||||||
aDocument->AddSystemEventListener(visibilitychange,
|
|
||||||
this, /* listener */
|
|
||||||
true, /* use capture */
|
|
||||||
false /* wants untrusted */);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveListener();
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIDOMEVENTLISTENER
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~VibrateWindowListener()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsWeakPtr mWindow;
|
|
||||||
nsWeakPtr mDocument;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(VibrateWindowListener, nsIDOMEventListener)
|
|
||||||
|
|
||||||
StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
|
|
||||||
|
|
||||||
static bool
|
|
||||||
MayVibrate(nsIDocument* doc) {
|
|
||||||
// Hidden documents cannot start or stop a vibration.
|
|
||||||
return (doc && !doc->Hidden());
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDocument> doc =
|
|
||||||
do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
|
|
||||||
|
|
||||||
if (!MayVibrate(doc)) {
|
|
||||||
// It's important that we call CancelVibrate(), not Vibrate() with an
|
|
||||||
// empty list, because Vibrate() will fail if we're no longer focused, but
|
|
||||||
// CancelVibrate() will succeed, so long as nobody else has started a new
|
|
||||||
// vibration pattern.
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
|
|
||||||
hal::CancelVibrate(window);
|
|
||||||
RemoveListener();
|
|
||||||
gVibrateWindowListener = nullptr;
|
|
||||||
// Careful: The line above might have deleted |this|!
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
VibrateWindowListener::RemoveListener()
|
|
||||||
{
|
|
||||||
nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument);
|
|
||||||
if (!target) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
|
|
||||||
target->RemoveSystemEventListener(visibilitychange, this,
|
|
||||||
true /* use capture */);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
|
|
@ -809,111 +723,6 @@ Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Navigator::SetVibrationPermission(bool aPermitted, bool aPersistent)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsTArray<uint32_t> pattern;
|
|
||||||
pattern.SwapElements(mRequestedVibrationPattern);
|
|
||||||
|
|
||||||
if (!mWindow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
|
||||||
|
|
||||||
if (!MayVibrate(doc)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aPermitted) {
|
|
||||||
// Add a listener to cancel the vibration if the document becomes hidden,
|
|
||||||
// and remove the old visibility listener, if there was one.
|
|
||||||
if (!gVibrateWindowListener) {
|
|
||||||
// If gVibrateWindowListener is null, this is the first time we've vibrated,
|
|
||||||
// and we need to register a listener to clear gVibrateWindowListener on
|
|
||||||
// shutdown.
|
|
||||||
ClearOnShutdown(&gVibrateWindowListener);
|
|
||||||
} else {
|
|
||||||
gVibrateWindowListener->RemoveListener();
|
|
||||||
}
|
|
||||||
gVibrateWindowListener = new VibrateWindowListener(mWindow, doc);
|
|
||||||
hal::Vibrate(pattern, mWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aPersistent) {
|
|
||||||
AddPermission(doc->NodePrincipal(), kVibrationPermissionType,
|
|
||||||
aPermitted ? nsIPermissionManager::ALLOW_ACTION :
|
|
||||||
nsIPermissionManager::DENY_ACTION,
|
|
||||||
nsIPermissionManager::EXPIRE_SESSION, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Navigator::Vibrate(uint32_t aDuration)
|
|
||||||
{
|
|
||||||
AutoTArray<uint32_t, 1> pattern;
|
|
||||||
pattern.AppendElement(aDuration);
|
|
||||||
return Vibrate(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Navigator::Vibrate(const nsTArray<uint32_t>& aPattern)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (!mWindow) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
|
||||||
|
|
||||||
if (!MayVibrate(doc)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<uint32_t> pattern(aPattern);
|
|
||||||
|
|
||||||
if (pattern.Length() > sMaxVibrateListLen) {
|
|
||||||
pattern.SetLength(sMaxVibrateListLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < pattern.Length(); ++i) {
|
|
||||||
pattern[i] = std::min(sMaxVibrateMS, pattern[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The spec says we check sVibratorEnabled after we've done the sanity
|
|
||||||
// checking on the pattern.
|
|
||||||
if (!sVibratorEnabled) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRequestedVibrationPattern.SwapElements(pattern);
|
|
||||||
uint32_t permission = GetPermission(mWindow, kVibrationPermissionType);
|
|
||||||
|
|
||||||
if (permission == nsIPermissionManager::ALLOW_ACTION ||
|
|
||||||
mRequestedVibrationPattern.IsEmpty() ||
|
|
||||||
(mRequestedVibrationPattern.Length() == 1 &&
|
|
||||||
mRequestedVibrationPattern[0] == 0)) {
|
|
||||||
// Always allow cancelling vibration and respect session permissions.
|
|
||||||
SetVibrationPermission(true /* permitted */, false /* persistent */);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
if (!obs || permission == nsIPermissionManager::DENY_ACTION) {
|
|
||||||
// Abort without observer service or on denied session permission.
|
|
||||||
SetVibrationPermission(false /* permitted */, false /* persistent */);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request user permission.
|
|
||||||
obs->NotifyObservers(ToSupports(this), "Vibration:Request", nullptr);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
// Pointer Events interface
|
// Pointer Events interface
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|
|
||||||
|
|
@ -149,9 +149,6 @@ public:
|
||||||
// NavigatorBinding::ClearCachedUserAgentValue(this);
|
// NavigatorBinding::ClearCachedUserAgentValue(this);
|
||||||
void ClearUserAgentCache();
|
void ClearUserAgentCache();
|
||||||
|
|
||||||
bool Vibrate(uint32_t aDuration);
|
|
||||||
bool Vibrate(const nsTArray<uint32_t>& aDuration);
|
|
||||||
void SetVibrationPermission(bool aPermitted, bool aPersistent);
|
|
||||||
uint32_t MaxTouchPoints();
|
uint32_t MaxTouchPoints();
|
||||||
void GetAppCodeName(nsString& aAppCodeName, ErrorResult& aRv)
|
void GetAppCodeName(nsString& aAppCodeName, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,6 @@ run-if = e10s
|
||||||
[test_storagePermissionsReject.html]
|
[test_storagePermissionsReject.html]
|
||||||
[test_storagePermissionsRejectForeign.html]
|
[test_storagePermissionsRejectForeign.html]
|
||||||
[test_stylesheetPI.html]
|
[test_stylesheetPI.html]
|
||||||
[test_vibrator.html]
|
|
||||||
[test_WebKitCSSMatrix.html]
|
[test_WebKitCSSMatrix.html]
|
||||||
[test_windowedhistoryframes.html]
|
[test_windowedhistoryframes.html]
|
||||||
[test_windowProperties.html]
|
[test_windowProperties.html]
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Test for Vibrator</title>
|
|
||||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- Although we can't test that the vibrator works properly, we can test that
|
|
||||||
navigator.vibrate throws an exception where appropriate. -->
|
|
||||||
|
|
||||||
<script class="testbody" type="text/javascript;version=1.7">
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
var result;
|
|
||||||
function expectFailure(param) {
|
|
||||||
result = navigator.vibrate(param);
|
|
||||||
is(result, false, 'vibrate(' + param + ') should have failed.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function expectSuccess(param) {
|
|
||||||
result = navigator.vibrate(param);
|
|
||||||
is(result, true, 'vibrate(' + param + ') must succeed.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function tests(aEnabled) {
|
|
||||||
// Some edge cases that the bindings should handle for us.
|
|
||||||
expectSuccess(null);
|
|
||||||
expectSuccess(undefined);
|
|
||||||
// -1 will be converted to the highest unsigned long then clamped.
|
|
||||||
expectSuccess(-1);
|
|
||||||
expectSuccess('a');
|
|
||||||
// -1 will be converted to the highest unsigned long then clamped.
|
|
||||||
expectSuccess([100, -1]);
|
|
||||||
expectSuccess([100, 'a']);
|
|
||||||
|
|
||||||
var maxVibrateMs = SpecialPowers.getIntPref('dom.vibrator.max_vibrate_ms');
|
|
||||||
var maxVibrateListLen = SpecialPowers.getIntPref('dom.vibrator.max_vibrate_list_len');
|
|
||||||
|
|
||||||
// If we pass a vibration pattern with a value higher than max_vibrate_ms or a
|
|
||||||
// pattern longer than max_vibrate_list_len, the call should succeed but the
|
|
||||||
// pattern should be modified to match the restrictions.
|
|
||||||
|
|
||||||
// Values will be clamped to dom.vibrator.max_vibrate_ms.
|
|
||||||
expectSuccess(maxVibrateMs + 1);
|
|
||||||
expectSuccess([maxVibrateMs + 1]);
|
|
||||||
|
|
||||||
var arr = [];
|
|
||||||
for (var i = 0; i < maxVibrateListLen + 1; i++) {
|
|
||||||
arr[i] = 0;
|
|
||||||
}
|
|
||||||
// The array will be truncated to have a length equal to dom.vibrator.max_vibrate_list_len.
|
|
||||||
expectSuccess(arr);
|
|
||||||
|
|
||||||
|
|
||||||
expectSuccess(0);
|
|
||||||
expectSuccess([]);
|
|
||||||
expectSuccess('1000');
|
|
||||||
expectSuccess(1000);
|
|
||||||
expectSuccess(1000.1);
|
|
||||||
expectSuccess([0, 0, 0]);
|
|
||||||
expectSuccess(['1000', 1000]);
|
|
||||||
expectSuccess([1000, 1000]);
|
|
||||||
expectSuccess([1000, 1000.1]);
|
|
||||||
|
|
||||||
// The following loop shouldn't cause us to crash. See bug 701716.
|
|
||||||
for (var i = 0; i < 10000; i++) {
|
|
||||||
navigator.vibrate([100, 100]);
|
|
||||||
}
|
|
||||||
ok(true, "Didn't crash after issuing a lot of vibrate() calls.");
|
|
||||||
if(!aEnabled)
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecialPowers.pushPermissions([
|
|
||||||
{type: 'vibration', allow: true, context: document}
|
|
||||||
], function() {
|
|
||||||
// Test with the vibrator pref enabled.
|
|
||||||
SpecialPowers.pushPrefEnv({"set": [['dom.vibrator.enabled', true]]}, function() {
|
|
||||||
tests(true);
|
|
||||||
SpecialPowers.pushPrefEnv({"set": [['dom.vibrator.enabled', false]]}, tests(false));
|
|
||||||
});
|
|
||||||
// Everything should be the same when the vibrator is disabled -- in
|
|
||||||
// particular, a disabled vibrator shouldn't eat failures we'd otherwise
|
|
||||||
// observe.
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
@ -13,9 +13,9 @@
|
||||||
* http://www.w3.org/TR/beacon/#sec-beacon-method
|
* http://www.w3.org/TR/beacon/#sec-beacon-method
|
||||||
* https://html.spec.whatwg.org/#navigatorconcurrenthardware
|
* https://html.spec.whatwg.org/#navigatorconcurrenthardware
|
||||||
*
|
*
|
||||||
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
* © Copyright 2004-2020 Apple Computer, Inc., Mozilla Foundation,
|
||||||
* Opera Software ASA. You are granted a license to use, reproduce
|
* Opera Software ASA and Moonchild Productions. You are granted a license to use,
|
||||||
* and create derivative works of this document.
|
* reproduce and create derivative works of this document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
|
// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
|
||||||
|
|
@ -124,14 +124,6 @@ interface NavigatorGeolocation {
|
||||||
};
|
};
|
||||||
Navigator implements NavigatorGeolocation;
|
Navigator implements NavigatorGeolocation;
|
||||||
|
|
||||||
// http://www.w3.org/TR/vibration/#vibration-interface
|
|
||||||
partial interface Navigator {
|
|
||||||
// We don't support sequences in unions yet
|
|
||||||
//boolean vibrate ((unsigned long or sequence<unsigned long>) pattern);
|
|
||||||
boolean vibrate(unsigned long duration);
|
|
||||||
boolean vibrate(sequence<unsigned long> pattern);
|
|
||||||
};
|
|
||||||
|
|
||||||
// http://www.w3.org/TR/pointerevents/#extensions-to-the-navigator-interface
|
// http://www.w3.org/TR/pointerevents/#extensions-to-the-navigator-interface
|
||||||
partial interface Navigator {
|
partial interface Navigator {
|
||||||
[Pref="dom.w3c_pointer_events.enabled"]
|
[Pref="dom.w3c_pointer_events.enabled"]
|
||||||
|
|
@ -140,17 +132,6 @@ partial interface Navigator {
|
||||||
|
|
||||||
// Mozilla-specific extensions
|
// Mozilla-specific extensions
|
||||||
|
|
||||||
// Chrome-only interface for Vibration API permission handling.
|
|
||||||
partial interface Navigator {
|
|
||||||
/* Set permission state to device vibration.
|
|
||||||
* @param permitted permission state (true for allowing vibration)
|
|
||||||
* @param persistent make the permission session-persistent
|
|
||||||
*/
|
|
||||||
[ChromeOnly]
|
|
||||||
void setVibrationPermission(boolean permitted,
|
|
||||||
optional boolean persistent = true);
|
|
||||||
};
|
|
||||||
|
|
||||||
callback interface MozIdleObserver {
|
callback interface MozIdleObserver {
|
||||||
// Time is in seconds and is read only when idle observers are added
|
// Time is in seconds and is read only when idle observers are added
|
||||||
// and removed.
|
// and removed.
|
||||||
|
|
|
||||||
79
hal/Hal.cpp
79
hal/Hal.cpp
|
|
@ -94,87 +94,8 @@ WindowIsActive(nsPIDOMWindowInner* aWindow)
|
||||||
return !document->Hidden();
|
return !document->Hidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
|
|
||||||
|
|
||||||
void InitLastIDToVibrate()
|
|
||||||
{
|
|
||||||
gLastIDToVibrate = new WindowIdentifier::IDArrayType();
|
|
||||||
ClearOnShutdown(&gLastIDToVibrate);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void
|
|
||||||
Vibrate(const nsTArray<uint32_t>& pattern, nsPIDOMWindowInner* window)
|
|
||||||
{
|
|
||||||
Vibrate(pattern, WindowIdentifier(window));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Vibrate(const nsTArray<uint32_t>& pattern, const WindowIdentifier &id)
|
|
||||||
{
|
|
||||||
AssertMainThread();
|
|
||||||
|
|
||||||
// Only active windows may start vibrations. If |id| hasn't gone
|
|
||||||
// through the IPC layer -- that is, if our caller is the outside
|
|
||||||
// world, not hal_proxy -- check whether the window is active. If
|
|
||||||
// |id| has gone through IPC, don't check the window's visibility;
|
|
||||||
// only the window corresponding to the bottommost process has its
|
|
||||||
// visibility state set correctly.
|
|
||||||
if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) {
|
|
||||||
HAL_LOG("Vibrate: Window is inactive, dropping vibrate.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InSandbox()) {
|
|
||||||
if (!gLastIDToVibrate) {
|
|
||||||
InitLastIDToVibrate();
|
|
||||||
}
|
|
||||||
*gLastIDToVibrate = id.AsArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't forward our ID if we are not in the sandbox, because hal_impl
|
|
||||||
// doesn't need it, and we don't want it to be tempted to read it. The
|
|
||||||
// empty identifier will assert if it's used.
|
|
||||||
PROXY_IF_SANDBOXED(Vibrate(pattern, InSandbox() ? id : WindowIdentifier()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CancelVibrate(nsPIDOMWindowInner* window)
|
|
||||||
{
|
|
||||||
CancelVibrate(WindowIdentifier(window));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CancelVibrate(const WindowIdentifier &id)
|
|
||||||
{
|
|
||||||
AssertMainThread();
|
|
||||||
|
|
||||||
// Although only active windows may start vibrations, a window may
|
|
||||||
// cancel its own vibration even if it's no longer active.
|
|
||||||
//
|
|
||||||
// After a window is marked as inactive, it sends a CancelVibrate
|
|
||||||
// request. We want this request to cancel a playing vibration
|
|
||||||
// started by that window, so we certainly don't want to reject the
|
|
||||||
// cancellation request because the window is now inactive.
|
|
||||||
//
|
|
||||||
// But it could be the case that, after this window became inactive,
|
|
||||||
// some other window came along and started a vibration. We don't
|
|
||||||
// want this window's cancellation request to cancel that window's
|
|
||||||
// actively-playing vibration!
|
|
||||||
//
|
|
||||||
// To solve this problem, we keep track of the id of the last window
|
|
||||||
// to start a vibration, and only accepts cancellation requests from
|
|
||||||
// the same window. All other cancellation requests are ignored.
|
|
||||||
|
|
||||||
if (InSandbox() || (gLastIDToVibrate && *gLastIDToVibrate == id.AsArray())) {
|
|
||||||
// Don't forward our ID if we are not in the sandbox, because hal_impl
|
|
||||||
// doesn't need it, and we don't want it to be tempted to read it. The
|
|
||||||
// empty identifier will assert if it's used.
|
|
||||||
PROXY_IF_SANDBOXED(CancelVibrate(InSandbox() ? id : WindowIdentifier()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class InfoType>
|
template <class InfoType>
|
||||||
class ObserversManager
|
class ObserversManager
|
||||||
{
|
{
|
||||||
|
|
|
||||||
35
hal/Hal.h
35
hal/Hal.h
|
|
@ -50,41 +50,6 @@ typedef Observer<SystemTimezoneChangeInformation> SystemTimezoneChangeObserver;
|
||||||
|
|
||||||
namespace MOZ_HAL_NAMESPACE {
|
namespace MOZ_HAL_NAMESPACE {
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn the default vibrator device on/off per the pattern specified
|
|
||||||
* by |pattern|. Each element in the pattern is the number of
|
|
||||||
* milliseconds to turn the vibrator on or off. The first element in
|
|
||||||
* |pattern| is an "on" element, the next is "off", and so on.
|
|
||||||
*
|
|
||||||
* If |pattern| is empty, any in-progress vibration is canceled.
|
|
||||||
*
|
|
||||||
* Only an active window within an active tab may call Vibrate; calls
|
|
||||||
* from inactive windows and windows on inactive tabs do nothing.
|
|
||||||
*
|
|
||||||
* If you're calling hal::Vibrate from the outside world, pass an
|
|
||||||
* nsIDOMWindow* in place of the WindowIdentifier parameter.
|
|
||||||
* The method with WindowIdentifier will be called automatically.
|
|
||||||
*/
|
|
||||||
void Vibrate(const nsTArray<uint32_t>& pattern,
|
|
||||||
nsPIDOMWindowInner* aWindow);
|
|
||||||
void Vibrate(const nsTArray<uint32_t>& pattern,
|
|
||||||
const hal::WindowIdentifier &id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel a vibration started by the content window identified by
|
|
||||||
* WindowIdentifier.
|
|
||||||
*
|
|
||||||
* If the window was the last window to start a vibration, the
|
|
||||||
* cancellation request will go through even if the window is not
|
|
||||||
* active.
|
|
||||||
*
|
|
||||||
* As with hal::Vibrate(), if you're calling hal::CancelVibrate from the outside
|
|
||||||
* world, pass an nsIDOMWindow*. The method with WindowIdentifier will be called
|
|
||||||
* automatically.
|
|
||||||
*/
|
|
||||||
void CancelVibrate(nsPIDOMWindowInner* aWindow);
|
|
||||||
void CancelVibrate(const hal::WindowIdentifier &id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the device's screen is currently enabled.
|
* Determine whether the device's screen is currently enabled.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "Hal.h"
|
|
||||||
|
|
||||||
using mozilla::hal::WindowIdentifier;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace hal_impl {
|
|
||||||
|
|
||||||
void
|
|
||||||
Vibrate(const nsTArray<uint32_t>& pattern, const hal::WindowIdentifier &)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
CancelVibrate(const hal::WindowIdentifier &)
|
|
||||||
{}
|
|
||||||
|
|
||||||
} // namespace hal_impl
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
@ -29,7 +29,6 @@ if CONFIG['OS_TARGET'] == 'Linux':
|
||||||
'fallback/FallbackAlarm.cpp',
|
'fallback/FallbackAlarm.cpp',
|
||||||
'fallback/FallbackScreenConfiguration.cpp',
|
'fallback/FallbackScreenConfiguration.cpp',
|
||||||
'fallback/FallbackSensor.cpp',
|
'fallback/FallbackSensor.cpp',
|
||||||
'fallback/FallbackVibration.cpp',
|
|
||||||
'linux/LinuxMemory.cpp',
|
'linux/LinuxMemory.cpp',
|
||||||
'linux/LinuxPower.cpp',
|
'linux/LinuxPower.cpp',
|
||||||
]
|
]
|
||||||
|
|
@ -39,7 +38,6 @@ elif CONFIG['OS_TARGET'] == 'WINNT':
|
||||||
'fallback/FallbackMemory.cpp',
|
'fallback/FallbackMemory.cpp',
|
||||||
'fallback/FallbackPower.cpp',
|
'fallback/FallbackPower.cpp',
|
||||||
'fallback/FallbackScreenConfiguration.cpp',
|
'fallback/FallbackScreenConfiguration.cpp',
|
||||||
'fallback/FallbackVibration.cpp',
|
|
||||||
'windows/WindowsSensor.cpp',
|
'windows/WindowsSensor.cpp',
|
||||||
]
|
]
|
||||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||||
|
|
@ -48,7 +46,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||||
'fallback/FallbackMemory.cpp',
|
'fallback/FallbackMemory.cpp',
|
||||||
'fallback/FallbackPower.cpp',
|
'fallback/FallbackPower.cpp',
|
||||||
'fallback/FallbackScreenConfiguration.cpp',
|
'fallback/FallbackScreenConfiguration.cpp',
|
||||||
'fallback/FallbackVibration.cpp',
|
|
||||||
]
|
]
|
||||||
elif CONFIG['OS_TARGET'] in ('OpenBSD', 'NetBSD', 'FreeBSD', 'DragonFly'):
|
elif CONFIG['OS_TARGET'] in ('OpenBSD', 'NetBSD', 'FreeBSD', 'DragonFly'):
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
|
@ -57,7 +54,6 @@ elif CONFIG['OS_TARGET'] in ('OpenBSD', 'NetBSD', 'FreeBSD', 'DragonFly'):
|
||||||
'fallback/FallbackPower.cpp',
|
'fallback/FallbackPower.cpp',
|
||||||
'fallback/FallbackScreenConfiguration.cpp',
|
'fallback/FallbackScreenConfiguration.cpp',
|
||||||
'fallback/FallbackSensor.cpp',
|
'fallback/FallbackSensor.cpp',
|
||||||
'fallback/FallbackVibration.cpp',
|
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
|
@ -66,7 +62,6 @@ else:
|
||||||
'fallback/FallbackPower.cpp',
|
'fallback/FallbackPower.cpp',
|
||||||
'fallback/FallbackScreenConfiguration.cpp',
|
'fallback/FallbackScreenConfiguration.cpp',
|
||||||
'fallback/FallbackSensor.cpp',
|
'fallback/FallbackSensor.cpp',
|
||||||
'fallback/FallbackVibration.cpp',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,6 @@ child:
|
||||||
async NotifySystemTimezoneChange(SystemTimezoneChangeInformation aSystemTimezoneChangeInfo);
|
async NotifySystemTimezoneChange(SystemTimezoneChangeInformation aSystemTimezoneChangeInfo);
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
async Vibrate(uint32_t[] pattern, uint64_t[] id, PBrowser browser);
|
|
||||||
async CancelVibrate(uint64_t[] id, PBrowser browser);
|
|
||||||
|
|
||||||
async EnableNetworkNotifications();
|
async EnableNetworkNotifications();
|
||||||
async DisableNetworkNotifications();
|
async DisableNetworkNotifications();
|
||||||
sync GetCurrentNetworkInformation()
|
sync GetCurrentNetworkInformation()
|
||||||
|
|
|
||||||
|
|
@ -45,28 +45,6 @@ Hal()
|
||||||
return sHal;
|
return sHal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Vibrate(const nsTArray<uint32_t>& pattern, const WindowIdentifier &id)
|
|
||||||
{
|
|
||||||
HAL_LOG("Vibrate: Sending to parent process.");
|
|
||||||
|
|
||||||
AutoTArray<uint32_t, 8> p(pattern);
|
|
||||||
|
|
||||||
WindowIdentifier newID(id);
|
|
||||||
newID.AppendProcessID();
|
|
||||||
Hal()->SendVibrate(p, newID.AsArray(), TabChild::GetFrom(newID.GetWindow()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CancelVibrate(const WindowIdentifier &id)
|
|
||||||
{
|
|
||||||
HAL_LOG("CancelVibrate: Sending to parent process.");
|
|
||||||
|
|
||||||
WindowIdentifier newID(id);
|
|
||||||
newID.AppendProcessID();
|
|
||||||
Hal()->SendCancelVibrate(newID.AsArray(), TabChild::GetFrom(newID.GetWindow()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EnableNetworkNotifications()
|
EnableNetworkNotifications()
|
||||||
{
|
{
|
||||||
|
|
@ -379,36 +357,6 @@ public:
|
||||||
hal::UnregisterSystemTimezoneChangeObserver(this);
|
hal::UnregisterSystemTimezoneChangeObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvVibrate(InfallibleTArray<unsigned int>&& pattern,
|
|
||||||
InfallibleTArray<uint64_t>&& id,
|
|
||||||
PBrowserParent *browserParent) override
|
|
||||||
{
|
|
||||||
// We give all content vibration permission.
|
|
||||||
// TabParent *tabParent = TabParent::GetFrom(browserParent);
|
|
||||||
/* xxxkhuey wtf
|
|
||||||
nsCOMPtr<nsIDOMWindow> window =
|
|
||||||
do_QueryInterface(tabParent->GetBrowserDOMWindow());
|
|
||||||
*/
|
|
||||||
WindowIdentifier newID(id, nullptr);
|
|
||||||
hal::Vibrate(pattern, newID);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvCancelVibrate(InfallibleTArray<uint64_t> &&id,
|
|
||||||
PBrowserParent *browserParent) override
|
|
||||||
{
|
|
||||||
//TabParent *tabParent = TabParent::GetFrom(browserParent);
|
|
||||||
/* XXXkhuey wtf
|
|
||||||
nsCOMPtr<nsIDOMWindow> window =
|
|
||||||
tabParent->GetBrowserDOMWindow();
|
|
||||||
*/
|
|
||||||
WindowIdentifier newID(id, nullptr);
|
|
||||||
hal::CancelVibrate(newID);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvEnableNetworkNotifications() override {
|
RecvEnableNetworkNotifications() override {
|
||||||
// We give all content access to this network-status information.
|
// We give all content access to this network-status information.
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,4 @@ The in-tree copy is updated by running
|
||||||
sh update.sh
|
sh update.sh
|
||||||
from within the modules/brotli directory.
|
from within the modules/brotli directory.
|
||||||
|
|
||||||
Current version: [commit e61745a6b7add50d380cfd7d3883dd6c62fc2c71].
|
Current version: 1.0.9 Re-release [commit e61745a6b7add50d380cfd7d3883dd6c62fc2c71].
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Script to update the mozilla in-tree copy of the Brotli decompressor.
|
# Script to update the mozilla in-tree copy of the Brotli library.
|
||||||
# Run this within the /modules/brotli directory of the source tree.
|
# Run this within the /modules/brotli directory of the source tree.
|
||||||
|
|
||||||
MY_TEMP_DIR=`mktemp -d -t brotli_update.XXXXXX` || exit 1
|
MY_TEMP_DIR=`mktemp -d -t brotli_update.XXXXXX` || exit 1
|
||||||
GIT=git
|
|
||||||
|
|
||||||
$GIT clone git://github.com/google/brotli.git ${MY_TEMP_DIR}/brotli
|
git clone https://github.com/google/brotli ${MY_TEMP_DIR}/brotli
|
||||||
$GIT -C ${MY_TEMP_DIR}/brotli checkout v1.0.9
|
git -C ${MY_TEMP_DIR}/brotli checkout v1.0.9
|
||||||
|
|
||||||
COMMIT=$(${GIT} -C ${MY_TEMP_DIR}/brotli rev-parse HEAD)
|
COMMIT=$(git -C ${MY_TEMP_DIR}/brotli rev-parse HEAD)
|
||||||
perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[commit ${COMMIT}]/" README.mozilla;
|
perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[commit ${COMMIT}]/" README.mozilla;
|
||||||
|
|
||||||
DIRS="common dec enc include tools"
|
DIRS="common dec enc include tools"
|
||||||
|
|
@ -20,9 +19,7 @@ for d in $DIRS; do
|
||||||
done
|
done
|
||||||
rm -rf ${MY_TEMP_DIR}
|
rm -rf ${MY_TEMP_DIR}
|
||||||
|
|
||||||
#hg addremove $DIRS
|
|
||||||
|
|
||||||
echo "###"
|
echo "###"
|
||||||
echo "### Updated brotli/dec to $COMMIT."
|
echo "### Updated brotli to $COMMIT."
|
||||||
echo "### Remember to verify and commit the changes to source control!"
|
echo "### Remember to verify and commit the changes to source control!"
|
||||||
echo "###"
|
echo "###"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "nsJARInputStream.h"
|
#include "nsJARInputStream.h"
|
||||||
#include "zipstruct.h" // defines ZIP compression codes
|
#include "zipstruct.h" // defines ZIP compression codes
|
||||||
|
#include "brotli/decode.h"
|
||||||
#include "nsZipArchive.h"
|
#include "nsZipArchive.h"
|
||||||
|
|
||||||
#include "nsEscape.h"
|
#include "nsEscape.h"
|
||||||
|
|
@ -51,6 +52,13 @@ nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
|
||||||
mOutCrc = crc32(0L, Z_NULL, 0);
|
mOutCrc = crc32(0L, Z_NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MOZ_JAR_BROTLI:
|
||||||
|
mBrotliState = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
|
||||||
|
mMode = MODE_BROTLI;
|
||||||
|
mInCrc = item->CRC32();
|
||||||
|
mOutCrc = crc32(0L, Z_NULL, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
@ -166,6 +174,7 @@ nsJARInputStream::Available(uint64_t *_retval)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_INFLATE:
|
case MODE_INFLATE:
|
||||||
|
case MODE_BROTLI:
|
||||||
case MODE_COPY:
|
case MODE_COPY:
|
||||||
*_retval = mOutSize - mZs.total_out;
|
*_retval = mOutSize - mZs.total_out;
|
||||||
break;
|
break;
|
||||||
|
|
@ -195,7 +204,8 @@ MOZ_WIN_MEM_TRY_BEGIN
|
||||||
return ReadDirectory(aBuffer, aCount, aBytesRead);
|
return ReadDirectory(aBuffer, aCount, aBytesRead);
|
||||||
|
|
||||||
case MODE_INFLATE:
|
case MODE_INFLATE:
|
||||||
if (mFd) {
|
case MODE_BROTLI:
|
||||||
|
if (mZs.total_out < mOutSize) {
|
||||||
rv = ContinueInflate(aBuffer, aCount, aBytesRead);
|
rv = ContinueInflate(aBuffer, aCount, aBytesRead);
|
||||||
}
|
}
|
||||||
// be aggressive about releasing the file!
|
// be aggressive about releasing the file!
|
||||||
|
|
@ -246,6 +256,9 @@ nsJARInputStream::Close()
|
||||||
if (mMode == MODE_INFLATE) {
|
if (mMode == MODE_INFLATE) {
|
||||||
inflateEnd(&mZs);
|
inflateEnd(&mZs);
|
||||||
}
|
}
|
||||||
|
if (mMode == MODE_BROTLI) {
|
||||||
|
BrotliDecoderDestroyInstance(mBrotliState);
|
||||||
|
}
|
||||||
mMode = MODE_CLOSED;
|
mMode = MODE_CLOSED;
|
||||||
mFd = nullptr;
|
mFd = nullptr;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
@ -255,6 +268,8 @@ nsresult
|
||||||
nsJARInputStream::ContinueInflate(char* aBuffer, uint32_t aCount,
|
nsJARInputStream::ContinueInflate(char* aBuffer, uint32_t aCount,
|
||||||
uint32_t* aBytesRead)
|
uint32_t* aBytesRead)
|
||||||
{
|
{
|
||||||
|
bool finished = false;
|
||||||
|
|
||||||
// No need to check the args, ::Read did that, but assert them at least
|
// No need to check the args, ::Read did that, but assert them at least
|
||||||
NS_ASSERTION(aBuffer,"aBuffer parameter must not be null");
|
NS_ASSERTION(aBuffer,"aBuffer parameter must not be null");
|
||||||
NS_ASSERTION(aBytesRead,"aBytesRead parameter must not be null");
|
NS_ASSERTION(aBytesRead,"aBytesRead parameter must not be null");
|
||||||
|
|
@ -266,11 +281,35 @@ nsJARInputStream::ContinueInflate(char* aBuffer, uint32_t aCount,
|
||||||
mZs.avail_out = std::min(aCount, (mOutSize-oldTotalOut));
|
mZs.avail_out = std::min(aCount, (mOutSize-oldTotalOut));
|
||||||
mZs.next_out = (unsigned char*)aBuffer;
|
mZs.next_out = (unsigned char*)aBuffer;
|
||||||
|
|
||||||
// now inflate
|
if (mMode == MODE_INFLATE) {
|
||||||
int zerr = inflate(&mZs, Z_SYNC_FLUSH);
|
// now inflate
|
||||||
if ((zerr != Z_OK) && (zerr != Z_STREAM_END)) {
|
int zerr = inflate(&mZs, Z_SYNC_FLUSH);
|
||||||
nsZipArchive::sFileCorruptedReason = "nsJARInputStream: error while inflating";
|
if ((zerr != Z_OK) && (zerr != Z_STREAM_END)) {
|
||||||
return NS_ERROR_FILE_CORRUPTED;
|
nsZipArchive::sFileCorruptedReason = "nsJARInputStream: error while inflating";
|
||||||
|
return NS_ERROR_FILE_CORRUPTED;
|
||||||
|
}
|
||||||
|
finished = (zerr == Z_STREAM_END);
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(mMode == MODE_BROTLI);
|
||||||
|
/* The brotli library wants size_t, but z_stream only contains
|
||||||
|
* unsigned int for avail_* and unsigned long for total_*.
|
||||||
|
* So use temporary stack values. */
|
||||||
|
size_t avail_in = mZs.avail_in;
|
||||||
|
size_t avail_out = mZs.avail_out;
|
||||||
|
size_t total_out = mZs.total_out;
|
||||||
|
BrotliDecoderResult result = BrotliDecoderDecompressStream(
|
||||||
|
mBrotliState,
|
||||||
|
&avail_in, const_cast<const unsigned char**>(&mZs.next_in),
|
||||||
|
&avail_out, &mZs.next_out, &total_out);
|
||||||
|
/* We don't need to update avail_out, it's not used outside this
|
||||||
|
* function. */
|
||||||
|
mZs.total_out = total_out;
|
||||||
|
mZs.avail_in = avail_in;
|
||||||
|
if (result == BROTLI_DECODER_RESULT_ERROR) {
|
||||||
|
nsZipArchive::sFileCorruptedReason = "nsJARInputStream: brotli decompression error";
|
||||||
|
return NS_ERROR_FILE_CORRUPTED;
|
||||||
|
}
|
||||||
|
finished = (result == BROTLI_DECODER_RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
*aBytesRead = (mZs.total_out - oldTotalOut);
|
*aBytesRead = (mZs.total_out - oldTotalOut);
|
||||||
|
|
@ -280,8 +319,10 @@ nsJARInputStream::ContinueInflate(char* aBuffer, uint32_t aCount,
|
||||||
|
|
||||||
// be aggressive about ending the inflation
|
// be aggressive about ending the inflation
|
||||||
// for some reason we don't always get Z_STREAM_END
|
// for some reason we don't always get Z_STREAM_END
|
||||||
if (zerr == Z_STREAM_END || mZs.total_out == mOutSize) {
|
if (finished || mZs.total_out == mOutSize) {
|
||||||
inflateEnd(&mZs);
|
if (mMode == MODE_INFLATE) {
|
||||||
|
inflateEnd(&mZs);
|
||||||
|
}
|
||||||
|
|
||||||
// stop returning valid data as soon as we know we have a bad CRC
|
// stop returning valid data as soon as we know we have a bad CRC
|
||||||
if (mOutCrc != mInCrc) {
|
if (mOutCrc != mInCrc) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
|
struct BrotliDecoderStateStruct;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
* Class nsJARInputStream declaration. This class defines the type of the
|
* Class nsJARInputStream declaration. This class defines the type of the
|
||||||
* object returned by calls to nsJAR::GetInputStream(filename) for the
|
* object returned by calls to nsJAR::GetInputStream(filename) for the
|
||||||
|
|
@ -20,9 +22,15 @@
|
||||||
class nsJARInputStream final : public nsIInputStream
|
class nsJARInputStream final : public nsIInputStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsJARInputStream() :
|
nsJARInputStream()
|
||||||
mOutSize(0), mInCrc(0), mOutCrc(0), mNameLen(0),
|
: mOutSize(0)
|
||||||
mCurPos(0), mArrPos(0), mMode(MODE_NOTINITED)
|
, mInCrc(0)
|
||||||
|
, mOutCrc(0)
|
||||||
|
, mBrotliState(nullptr)
|
||||||
|
, mNameLen(0)
|
||||||
|
, mCurPos(0)
|
||||||
|
, mArrPos(0)
|
||||||
|
, mMode(MODE_NOTINITED)
|
||||||
{
|
{
|
||||||
memset(&mZs, 0, sizeof(z_stream));
|
memset(&mZs, 0, sizeof(z_stream));
|
||||||
}
|
}
|
||||||
|
|
@ -45,6 +53,7 @@ class nsJARInputStream final : public nsIInputStream
|
||||||
uint32_t mInCrc; // CRC as provided by the zipentry
|
uint32_t mInCrc; // CRC as provided by the zipentry
|
||||||
uint32_t mOutCrc; // CRC as calculated by me
|
uint32_t mOutCrc; // CRC as calculated by me
|
||||||
z_stream mZs; // zip data structure
|
z_stream mZs; // zip data structure
|
||||||
|
BrotliDecoderStateStruct* mBrotliState; // Brotli decoder state
|
||||||
|
|
||||||
/* For directory reading */
|
/* For directory reading */
|
||||||
RefPtr<nsJAR> mJar; // string reference to zipreader
|
RefPtr<nsJAR> mJar; // string reference to zipreader
|
||||||
|
|
@ -59,6 +68,7 @@ class nsJARInputStream final : public nsIInputStream
|
||||||
MODE_CLOSED,
|
MODE_CLOSED,
|
||||||
MODE_DIRECTORY,
|
MODE_DIRECTORY,
|
||||||
MODE_INFLATE,
|
MODE_INFLATE,
|
||||||
|
MODE_BROTLI,
|
||||||
MODE_COPY
|
MODE_COPY
|
||||||
} JISMode;
|
} JISMode;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This module implements a simple archive extractor for the PKZIP format.
|
* This module implements a simple archive extractor.
|
||||||
*
|
*
|
||||||
* The underlying nsZipArchive is NOT thread-safe. Do not pass references
|
* The underlying nsZipArchive is NOT thread-safe. Do not pass references
|
||||||
* or pointers to it across thread boundaries.
|
* or pointers to it across thread boundaries.
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#define READTYPE int32_t
|
#define READTYPE int32_t
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
#include "brotli/decode.h"
|
||||||
#include "nsISupportsUtils.h"
|
#include "nsISupportsUtils.h"
|
||||||
#include "prio.h"
|
#include "prio.h"
|
||||||
#include "plstr.h"
|
#include "plstr.h"
|
||||||
|
|
@ -1186,6 +1187,7 @@ nsZipCursor::nsZipCursor(nsZipItem *item, nsZipArchive *aZip, uint8_t* aBuf,
|
||||||
: mItem(item)
|
: mItem(item)
|
||||||
, mBuf(aBuf)
|
, mBuf(aBuf)
|
||||||
, mBufSize(aBufSize)
|
, mBufSize(aBufSize)
|
||||||
|
, mBrotliState(nullptr)
|
||||||
, mCRC(0)
|
, mCRC(0)
|
||||||
, mDoCRC(doCRC)
|
, mDoCRC(doCRC)
|
||||||
{
|
{
|
||||||
|
|
@ -1201,6 +1203,10 @@ nsZipCursor::nsZipCursor(nsZipItem *item, nsZipArchive *aZip, uint8_t* aBuf,
|
||||||
mZs.avail_in = item->Size();
|
mZs.avail_in = item->Size();
|
||||||
mZs.next_in = (Bytef*)aZip->GetData(item);
|
mZs.next_in = (Bytef*)aZip->GetData(item);
|
||||||
|
|
||||||
|
if (mItem->Compression() == MOZ_JAR_BROTLI) {
|
||||||
|
mBrotliState = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (doCRC)
|
if (doCRC)
|
||||||
mCRC = crc32(0L, Z_NULL, 0);
|
mCRC = crc32(0L, Z_NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -1210,6 +1216,9 @@ nsZipCursor::~nsZipCursor()
|
||||||
if (mItem->Compression() == DEFLATED) {
|
if (mItem->Compression() == DEFLATED) {
|
||||||
inflateEnd(&mZs);
|
inflateEnd(&mZs);
|
||||||
}
|
}
|
||||||
|
if (mItem->Compression() == MOZ_JAR_BROTLI) {
|
||||||
|
BrotliDecoderDestroyInstance(mBrotliState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* nsZipCursor::ReadOrCopy(uint32_t *aBytesRead, bool aCopy) {
|
uint8_t* nsZipCursor::ReadOrCopy(uint32_t *aBytesRead, bool aCopy) {
|
||||||
|
|
@ -1246,6 +1255,29 @@ MOZ_WIN_MEM_TRY_BEGIN
|
||||||
*aBytesRead = mZs.next_out - buf;
|
*aBytesRead = mZs.next_out - buf;
|
||||||
verifyCRC = (zerr == Z_STREAM_END);
|
verifyCRC = (zerr == Z_STREAM_END);
|
||||||
break;
|
break;
|
||||||
|
case MOZ_JAR_BROTLI: {
|
||||||
|
buf = mBuf;
|
||||||
|
mZs.next_out = buf;
|
||||||
|
/* The brotli library wants size_t, but z_stream only contains
|
||||||
|
* unsigned int for avail_*. So use temporary stack values. */
|
||||||
|
size_t avail_out = mBufSize;
|
||||||
|
size_t avail_in = mZs.avail_in;
|
||||||
|
BrotliDecoderResult result = BrotliDecoderDecompressStream(
|
||||||
|
mBrotliState,
|
||||||
|
&avail_in, const_cast<const unsigned char**>(&mZs.next_in),
|
||||||
|
&avail_out, &mZs.next_out, nullptr);
|
||||||
|
/* We don't need to update avail_out, it's not used outside this
|
||||||
|
* function. */
|
||||||
|
mZs.avail_in = avail_in;
|
||||||
|
|
||||||
|
if (result == BROTLI_DECODER_RESULT_ERROR) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aBytesRead = mZs.next_out - buf;
|
||||||
|
verifyCRC = (result == BROTLI_DECODER_RESULT_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -1272,7 +1304,9 @@ nsZipItemPtr_base::nsZipItemPtr_base(nsZipArchive *aZip,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
if (item->Compression() == DEFLATED) {
|
bool compressed = (item->Compression() == DEFLATED) ||
|
||||||
|
(item->Compression() == MOZ_JAR_BROTLI);
|
||||||
|
if (compressed) {
|
||||||
size = item->RealSize();
|
size = item->RealSize();
|
||||||
mAutoBuf = MakeUniqueFallible<uint8_t[]>(size);
|
mAutoBuf = MakeUniqueFallible<uint8_t[]>(size);
|
||||||
if (!mAutoBuf) {
|
if (!mAutoBuf) {
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
class nsZipFind;
|
class nsZipFind;
|
||||||
struct PRFileDesc;
|
struct PRFileDesc;
|
||||||
|
struct BrotliDecoderStateStruct;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file defines some of the basic structures used by libjar to
|
* This file defines some of the basic structures used by libjar to
|
||||||
|
|
@ -314,6 +315,7 @@ private:
|
||||||
uint8_t *mBuf;
|
uint8_t *mBuf;
|
||||||
uint32_t mBufSize;
|
uint32_t mBufSize;
|
||||||
z_stream mZs;
|
z_stream mZs;
|
||||||
|
BrotliDecoderStateStruct* mBrotliState;
|
||||||
uint32_t mCRC;
|
uint32_t mCRC;
|
||||||
bool mDoCRC;
|
bool mDoCRC;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ typedef struct ZipEnd_
|
||||||
#define TOKENIZED 7
|
#define TOKENIZED 7
|
||||||
#define DEFLATED 8
|
#define DEFLATED 8
|
||||||
#define UNSUPPORTED 0xFF
|
#define UNSUPPORTED 0xFF
|
||||||
|
/* non-standard extension */
|
||||||
|
#define MOZ_JAR_BROTLI 0x81
|
||||||
|
|
||||||
#endif /* _zipstruct_h */
|
#endif /* _zipstruct_h */
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pref("keyword.enabled", false);
|
||||||
pref("general.useragent.locale", "chrome://global/locale/intl.properties");
|
pref("general.useragent.locale", "chrome://global/locale/intl.properties");
|
||||||
pref("general.useragent.compatMode.gecko", false);
|
pref("general.useragent.compatMode.gecko", false);
|
||||||
pref("general.useragent.compatMode.firefox", false);
|
pref("general.useragent.compatMode.firefox", false);
|
||||||
pref("general.useragent.compatMode.version", "68.9");
|
pref("general.useragent.compatMode.version", "68.0");
|
||||||
pref("general.useragent.appVersionIsBuildID", false);
|
pref("general.useragent.appVersionIsBuildID", false);
|
||||||
|
|
||||||
// This pref exists only for testing purposes. In order to disable all
|
// This pref exists only for testing purposes. In order to disable all
|
||||||
|
|
@ -4746,10 +4746,6 @@ pref("dom.event.handling-user-input-time-limit", 1000);
|
||||||
// Whether we should layerize all animated images (if otherwise possible).
|
// Whether we should layerize all animated images (if otherwise possible).
|
||||||
pref("layout.animated-image-layers.enabled", false);
|
pref("layout.animated-image-layers.enabled", false);
|
||||||
|
|
||||||
pref("dom.vibrator.enabled", true);
|
|
||||||
pref("dom.vibrator.max_vibrate_ms", 10000);
|
|
||||||
pref("dom.vibrator.max_vibrate_list_len", 128);
|
|
||||||
|
|
||||||
// Abort API
|
// Abort API
|
||||||
pref("dom.abortController.enabled", true);
|
pref("dom.abortController.enabled", true);
|
||||||
|
|
||||||
|
|
@ -5421,8 +5417,8 @@ pref("osfile.reset_worker_delay", 30000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MOZ_WIDGET_ANDROID)
|
#if !defined(MOZ_WIDGET_ANDROID)
|
||||||
pref("dom.webkitBlink.dirPicker.enabled", true);
|
pref("dom.webkitBlink.dirPicker.enabled", false);
|
||||||
pref("dom.webkitBlink.filesystem.enabled", true);
|
pref("dom.webkitBlink.filesystem.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NIGHTLY_BUILD
|
#ifdef NIGHTLY_BUILD
|
||||||
|
|
|
||||||
|
|
@ -535,7 +535,7 @@ class Jarrer(FileRegistry, BaseFile):
|
||||||
dest = Dest(dest)
|
dest = Dest(dest)
|
||||||
assert isinstance(dest, Dest)
|
assert isinstance(dest, Dest)
|
||||||
|
|
||||||
from mozpack.mozjar import JarWriter, JarReader
|
from mozpack.mozjar import JarWriter, JarReader, JAR_BROTLI
|
||||||
try:
|
try:
|
||||||
old_jar = JarReader(fileobj=dest)
|
old_jar = JarReader(fileobj=dest)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import struct
|
import struct
|
||||||
|
import subprocess
|
||||||
import zlib
|
import zlib
|
||||||
import os
|
import os
|
||||||
from zipfile import (
|
from zipfile import (
|
||||||
|
|
@ -15,9 +16,11 @@ from zipfile import (
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from urlparse import urlparse, ParseResult
|
from urlparse import urlparse, ParseResult
|
||||||
import mozpack.path as mozpath
|
import mozpack.path as mozpath
|
||||||
|
from mozbuild.util import memoize
|
||||||
|
|
||||||
JAR_STORED = ZIP_STORED
|
JAR_STORED = ZIP_STORED
|
||||||
JAR_DEFLATED = ZIP_DEFLATED
|
JAR_DEFLATED = ZIP_DEFLATED
|
||||||
|
JAR_BROTLI = 0x81
|
||||||
MAX_WBITS = 15
|
MAX_WBITS = 15
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -262,13 +265,14 @@ class JarFileReader(object):
|
||||||
corresponding to the file in the jar archive, data a buffer containing
|
corresponding to the file in the jar archive, data a buffer containing
|
||||||
the file data.
|
the file data.
|
||||||
'''
|
'''
|
||||||
assert header['compression'] in [JAR_DEFLATED, JAR_STORED]
|
assert header['compression'] in [JAR_DEFLATED, JAR_STORED, JAR_BROTLI]
|
||||||
self._data = data
|
self._data = data
|
||||||
# Copy some local file header fields.
|
# Copy some local file header fields.
|
||||||
for name in ['filename', 'compressed_size',
|
for name in ['filename', 'compressed_size',
|
||||||
'uncompressed_size', 'crc32']:
|
'uncompressed_size', 'crc32']:
|
||||||
setattr(self, name, header[name])
|
setattr(self, name, header[name])
|
||||||
self.compressed = header['compression'] == JAR_DEFLATED
|
self.compressed = header['compression'] != JAR_STORED
|
||||||
|
self.compress = header['compression']
|
||||||
|
|
||||||
def read(self, length=-1):
|
def read(self, length=-1):
|
||||||
'''
|
'''
|
||||||
|
|
@ -317,7 +321,11 @@ class JarFileReader(object):
|
||||||
if hasattr(self, '_uncompressed_data'):
|
if hasattr(self, '_uncompressed_data'):
|
||||||
return self._uncompressed_data
|
return self._uncompressed_data
|
||||||
data = self.compressed_data
|
data = self.compressed_data
|
||||||
if self.compressed:
|
if self.compress == JAR_STORED:
|
||||||
|
data = data.tobytes()
|
||||||
|
elif self.compress == JAR_BROTLI:
|
||||||
|
data = Brotli.decompress(data.tobytes())
|
||||||
|
elif self.compress == JAR_DEFLATED:
|
||||||
data = zlib.decompress(data.tobytes(), -MAX_WBITS)
|
data = zlib.decompress(data.tobytes(), -MAX_WBITS)
|
||||||
else:
|
else:
|
||||||
data = data.tobytes()
|
data = data.tobytes()
|
||||||
|
|
@ -360,6 +368,13 @@ class JarReader(object):
|
||||||
'''
|
'''
|
||||||
del self._data
|
del self._data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def compression(self):
|
||||||
|
entries = self.entries
|
||||||
|
if not entries:
|
||||||
|
return JAR_STORED
|
||||||
|
return max(f['compression'] for f in entries.itervalues())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entries(self):
|
def entries(self):
|
||||||
'''
|
'''
|
||||||
|
|
@ -473,6 +488,8 @@ class JarWriter(object):
|
||||||
self._data = fileobj
|
self._data = fileobj
|
||||||
else:
|
else:
|
||||||
self._data = open(file, 'wb')
|
self._data = open(file, 'wb')
|
||||||
|
if compress is True:
|
||||||
|
compress = JAR_DEFLATED
|
||||||
self._compress = compress
|
self._compress = compress
|
||||||
self._compress_level = compress_level
|
self._compress_level = compress_level
|
||||||
self._contents = OrderedDict()
|
self._contents = OrderedDict()
|
||||||
|
|
@ -574,12 +591,13 @@ class JarWriter(object):
|
||||||
'''
|
'''
|
||||||
Add a new member to the jar archive, with the given name and the given
|
Add a new member to the jar archive, with the given name and the given
|
||||||
data.
|
data.
|
||||||
The compress option indicates if the given data should be compressed
|
The compress option indicates how the given data should be compressed
|
||||||
(True), not compressed (False), or compressed according to the default
|
(one of JAR_STORED, JAR_DEFLATE or JAR_BROTLI), or compressed according
|
||||||
defined when creating the JarWriter (None).
|
to the default defined when creating the JarWriter (None). True and
|
||||||
When the data should be compressed (True or None with self.compress ==
|
False are allowed values for backwards compatibility, mapping,
|
||||||
True), it is only really compressed if the compressed size is smaller
|
respectively, to JAR_DEFLATE and JAR_STORED.
|
||||||
than the uncompressed size.
|
When the data should be compressed, it is only really compressed if
|
||||||
|
the compressed size is smaller than the uncompressed size.
|
||||||
The mode option gives the unix permissions that should be stored
|
The mode option gives the unix permissions that should be stored
|
||||||
for the jar entry.
|
for the jar entry.
|
||||||
If a duplicated member is found skip_duplicates will prevent raising
|
If a duplicated member is found skip_duplicates will prevent raising
|
||||||
|
|
@ -594,8 +612,12 @@ class JarWriter(object):
|
||||||
raise JarWriterError("File %s already in JarWriter" % name)
|
raise JarWriterError("File %s already in JarWriter" % name)
|
||||||
if compress is None:
|
if compress is None:
|
||||||
compress = self._compress
|
compress = self._compress
|
||||||
if (isinstance(data, JarFileReader) and data.compressed == compress) \
|
if compress is True:
|
||||||
or (isinstance(data, Deflater) and data.compress == compress):
|
compress = JAR_DEFLATED
|
||||||
|
if compress is False:
|
||||||
|
compress = JAR_STORED
|
||||||
|
if (isinstance(data, (JarFileReader, Deflater)) and \
|
||||||
|
data.compress == compress):
|
||||||
deflater = data
|
deflater = data
|
||||||
else:
|
else:
|
||||||
deflater = Deflater(compress, compress_level=self._compress_level)
|
deflater = Deflater(compress, compress_level=self._compress_level)
|
||||||
|
|
@ -619,7 +641,7 @@ class JarWriter(object):
|
||||||
if deflater.compressed:
|
if deflater.compressed:
|
||||||
entry['min_version'] = 20 # Version 2.0 supports deflated streams
|
entry['min_version'] = 20 # Version 2.0 supports deflated streams
|
||||||
entry['general_flag'] = 2 # Max compression
|
entry['general_flag'] = 2 # Max compression
|
||||||
entry['compression'] = JAR_DEFLATED
|
entry['compression'] = deflater.compress
|
||||||
else:
|
else:
|
||||||
entry['min_version'] = 10 # Version 1.0 for stored streams
|
entry['min_version'] = 10 # Version 1.0 for stored streams
|
||||||
entry['general_flag'] = 0
|
entry['general_flag'] = 0
|
||||||
|
|
@ -659,14 +681,21 @@ class Deflater(object):
|
||||||
'''
|
'''
|
||||||
def __init__(self, compress=True, compress_level=9):
|
def __init__(self, compress=True, compress_level=9):
|
||||||
'''
|
'''
|
||||||
Initialize a Deflater. The compress argument determines whether to
|
Initialize a Deflater. The compress argument determines how to
|
||||||
try to compress at all.
|
compress.
|
||||||
'''
|
'''
|
||||||
self._data = BytesIO()
|
self._data = BytesIO()
|
||||||
|
if compress is True:
|
||||||
|
compress = JAR_DEFLATED
|
||||||
|
elif compress is False:
|
||||||
|
compress = JAR_STORED
|
||||||
self.compress = compress
|
self.compress = compress
|
||||||
if compress:
|
if compress in (JAR_DEFLATED, JAR_BROTLI):
|
||||||
self._deflater = zlib.compressobj(compress_level, zlib.DEFLATED,
|
if compress == JAR_DEFLATED:
|
||||||
-MAX_WBITS)
|
self._deflater = zlib.compressobj(
|
||||||
|
compress_level, zlib.DEFLATED, -MAX_WBITS)
|
||||||
|
else:
|
||||||
|
self._deflater = BrotliCompress()
|
||||||
self._deflated = BytesIO()
|
self._deflated = BytesIO()
|
||||||
else:
|
else:
|
||||||
self._deflater = None
|
self._deflater = None
|
||||||
|
|
@ -759,6 +788,46 @@ class Deflater(object):
|
||||||
return self._data.getvalue()
|
return self._data.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
class Brotli(object):
|
||||||
|
@staticmethod
|
||||||
|
@memoize
|
||||||
|
def brotli_tool():
|
||||||
|
from buildconfig import topobjdir, substs
|
||||||
|
return os.path.join(topobjdir, 'dist', 'host', 'bin',
|
||||||
|
'brotli' + substs.get('BIN_SUFFIX', ''))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def run_brotli_tool(args, input):
|
||||||
|
proc = subprocess.Popen([Brotli.brotli_tool()] + args,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE)
|
||||||
|
(stdout, _) = proc.communicate(input)
|
||||||
|
ret = proc.wait()
|
||||||
|
if ret != 0:
|
||||||
|
raise Exception("Brotli compression failed")
|
||||||
|
return stdout
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def compress(data):
|
||||||
|
return Brotli.run_brotli_tool(['--lgwin=17'], data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def decompress(data):
|
||||||
|
return Brotli.run_brotli_tool(['--decompress'], data)
|
||||||
|
|
||||||
|
|
||||||
|
class BrotliCompress(object):
|
||||||
|
def __init__(self):
|
||||||
|
self._buf = BytesIO()
|
||||||
|
|
||||||
|
def compress(self, data):
|
||||||
|
self._buf.write(data)
|
||||||
|
return b''
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
return Brotli.compress(self._buf.getvalue())
|
||||||
|
|
||||||
|
|
||||||
class JarLog(dict):
|
class JarLog(dict):
|
||||||
'''
|
'''
|
||||||
Helper to read the file Gecko generates when setting MOZ_JAR_LOG_FILE.
|
Helper to read the file Gecko generates when setting MOZ_JAR_LOG_FILE.
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ from mozpack.chrome.manifest import (
|
||||||
Manifest,
|
Manifest,
|
||||||
)
|
)
|
||||||
from mozpack.errors import errors
|
from mozpack.errors import errors
|
||||||
|
from mozpack.mozjar import JAR_DEFLATED
|
||||||
from mozpack.packager.unpack import UnpackFinder
|
from mozpack.packager.unpack import UnpackFinder
|
||||||
from createprecomplete import generate_precomplete
|
from createprecomplete import generate_precomplete
|
||||||
|
|
||||||
|
|
@ -241,16 +242,17 @@ def repack(source, l10n, extra_l10n={}, non_resources=[], non_chrome=set()):
|
||||||
finders[base] = UnpackFinder(path)
|
finders[base] = UnpackFinder(path)
|
||||||
l10n_finder = ComposedFinder(finders)
|
l10n_finder = ComposedFinder(finders)
|
||||||
copier = FileCopier()
|
copier = FileCopier()
|
||||||
|
compress = min(app_finder.compressed, JAR_DEFLATED)
|
||||||
if app_finder.kind == 'flat':
|
if app_finder.kind == 'flat':
|
||||||
formatter = FlatFormatter(copier)
|
formatter = FlatFormatter(copier)
|
||||||
elif app_finder.kind == 'jar':
|
elif app_finder.kind == 'jar':
|
||||||
formatter = JarFormatter(copier,
|
formatter = JarFormatter(copier,
|
||||||
optimize=app_finder.optimizedjars,
|
optimize=app_finder.optimizedjars,
|
||||||
compress=app_finder.compressed)
|
compress=compress)
|
||||||
elif app_finder.kind == 'omni':
|
elif app_finder.kind == 'omni':
|
||||||
formatter = OmniJarFormatter(copier, app_finder.omnijar,
|
formatter = OmniJarFormatter(copier, app_finder.omnijar,
|
||||||
optimize=app_finder.optimizedjars,
|
optimize=app_finder.optimizedjars,
|
||||||
compress=app_finder.compressed,
|
compress=compress,
|
||||||
non_resources=non_resources)
|
non_resources=non_resources)
|
||||||
|
|
||||||
with errors.accumulate():
|
with errors.accumulate():
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class UnpackFinder(BaseFinder):
|
||||||
self.omnijar = None
|
self.omnijar = None
|
||||||
self.jarlogs = {}
|
self.jarlogs = {}
|
||||||
self.optimizedjars = False
|
self.optimizedjars = False
|
||||||
self.compressed = True
|
self.compressed = False
|
||||||
|
|
||||||
jars = set()
|
jars = set()
|
||||||
|
|
||||||
|
|
@ -146,8 +146,7 @@ class UnpackFinder(BaseFinder):
|
||||||
jar = JarReader(fileobj=file.open())
|
jar = JarReader(fileobj=file.open())
|
||||||
if jar.is_optimized:
|
if jar.is_optimized:
|
||||||
self.optimizedjars = True
|
self.optimizedjars = True
|
||||||
if not any(f.compressed for f in jar):
|
self.compressed = max(self.compressed, jar.compression)
|
||||||
self.compressed = False
|
|
||||||
if jar.last_preloaded:
|
if jar.last_preloaded:
|
||||||
jarlog = jar.entries.keys()
|
jarlog = jar.entries.keys()
|
||||||
self.jarlogs[path] = jarlog[:jarlog.index(jar.last_preloaded) + 1]
|
self.jarlogs[path] = jarlog[:jarlog.index(jar.last_preloaded) + 1]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
@dontcallmedom
|
|
||||||
@zqzhang
|
|
||||||
@xinliux
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: test that the vibrate() method is present (with or without vendor prefix)</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom'/>
|
|
||||||
<meta name='assert' content='Check that the vibrate() method is present.'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
This test checks for the presence of the <code>vibrate()</code> method, taking
|
|
||||||
vendor prefixes into account.
|
|
||||||
</p>
|
|
||||||
<div id='log'></div>
|
|
||||||
<script src='/resources/testharness.js'></script>
|
|
||||||
<script src='/resources/testharnessreport.js'></script>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
test(function () {
|
|
||||||
assert_true(undefined !== navigator.vibrate, "navigator.vibrate exists");
|
|
||||||
}, "vibrate() is present on navigator");
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<meta charset='utf-8'>
|
|
||||||
<title>Vibration API: cancel ongoing vibrate() when hidden by switching tab/window</title>
|
|
||||||
<link rel='author' title='Intel' href='http://www.intel.com'>
|
|
||||||
<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
|
|
||||||
<meta name='flags' content='interact'>
|
|
||||||
<meta name='assert' content='If the visibilitychange event is dispatched at the Document in a browsing context, cancel the pre-existing instance of the processing vibration patterns algorithm'>
|
|
||||||
<style>
|
|
||||||
button {
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate for a short period of time (roughly one
|
|
||||||
second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
|
|
||||||
the test has failed.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
var win;
|
|
||||||
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById('vib').onclick = function () {
|
|
||||||
navigator.vibrate(5000);
|
|
||||||
setTimeout(function () {
|
|
||||||
win = window.open('about:blank', '_blank');
|
|
||||||
setTimeout(function() {
|
|
||||||
win.close();
|
|
||||||
}, 100);
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: cancel ongoing vibrate() with 0</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, interact'/>
|
|
||||||
<meta name='assert' content='If pattern is 0, cancel the pre-existing instance of the processing vibration patterns algorithm'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate for a short period of time (roughly one
|
|
||||||
second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
|
|
||||||
the test has failed.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate(5000);
|
|
||||||
setTimeout(function () {
|
|
||||||
navigator.vibrate(0);
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<meta charset='utf-8'>
|
|
||||||
<title>Vibration API: cancel ongoing vibrate() with [0]</title>
|
|
||||||
<link rel='author' title='Intel' href='http://www.intel.com'>
|
|
||||||
<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
|
|
||||||
<meta name='flags' content='interact'>
|
|
||||||
<meta name='assert' content='If pattern contains a single entry with a value of 0, cancel the pre-existing instance of the processing vibration patterns algorithm'>
|
|
||||||
<style>
|
|
||||||
button {
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate for a short period of time (roughly one
|
|
||||||
second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
|
|
||||||
the test has failed.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById('vib').onclick = function () {
|
|
||||||
navigator.vibrate(5000);
|
|
||||||
setTimeout(function () {
|
|
||||||
navigator.vibrate([0]);
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: cancel ongoing vibrate() with []</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, interact'/>
|
|
||||||
<meta name='assert' content='If pattern is an empty list, cancel the pre-existing instance of the processing vibration patterns algorithm'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate for a short period of time (roughly one
|
|
||||||
second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
|
|
||||||
the test has failed.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate(5000);
|
|
||||||
setTimeout(function () {
|
|
||||||
navigator.vibrate([]);
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: cancel ongoing vibrate() with a new call to vibrate</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, interact'/>
|
|
||||||
<meta name='assert' content='Cancel the pre-existing instance of the processing vibration patterns algorithm, if any.'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate continuously for a short period of time (roughly one
|
|
||||||
second), then vibrate a series of short bursts. If the initial continuously vibration is longer (roughly five
|
|
||||||
seconds, it should feel somewhat long) or if there is no series of short vibration bursts then the test has
|
|
||||||
failed.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate(5000);
|
|
||||||
setTimeout(function () {
|
|
||||||
navigator.vibrate([200, 200, 200, 200, 200, 200, 200, 200, 200]);
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<meta charset=utf-8>
|
|
||||||
<title>IDL harness tests for Vibration API</title>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
This test validates the IDL defined by the Vibration API.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This test uses <a href="/resources/idlharness.js">idlharness.js</a>
|
|
||||||
</p>
|
|
||||||
<div id="log"></div>
|
|
||||||
<script src=/resources/testharness.js></script>
|
|
||||||
<script src=/resources/testharnessreport.js></script>
|
|
||||||
<script src=/resources/WebIDLParser.js></script>
|
|
||||||
<script src=/resources/idlharness.js></script>
|
|
||||||
<script>
|
|
||||||
var idl_array = new IdlArray();
|
|
||||||
idl_array.add_untested_idls("interface Navigator {};");
|
|
||||||
idl_array.add_idls("partial interface Navigator { boolean vibrate ((unsigned long or sequence<unsigned long>) pattern);};");
|
|
||||||
idl_array.add_objects({Navigator: ['navigator']});
|
|
||||||
idl_array.test();
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<meta charset='utf-8'>
|
|
||||||
<title>Vibration API: vibrate(invalid)</title>
|
|
||||||
<link rel='author' title='Intel' href='http://www.intel.com'>
|
|
||||||
<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
|
|
||||||
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
This test checks the <code>vibrate()</code> method with invalid parameter,
|
|
||||||
taking vendor prefixes into account.
|
|
||||||
</p>
|
|
||||||
<div id='log'></div>
|
|
||||||
<script src='/resources/testharness.js'></script>
|
|
||||||
<script src='/resources/testharnessreport.js'></script>
|
|
||||||
<script src='../support/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_throws(new TypeError(), function() {
|
|
||||||
navigator.vibrate();
|
|
||||||
}, 'Argument is required, so was expecting a TypeError.');
|
|
||||||
}, 'Missing pattern argument');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate(undefined);
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of undefined resolves to []');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate(null);
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of null resolves to []');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate('one');
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of empty string resolves to [""]');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate('one');
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of string resolves to ["one"]');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate(new String('one'));
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of String instance resolves to ["one"]');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate(NaN);
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of NaN resolves to [NaN]');
|
|
||||||
|
|
||||||
test(function() {
|
|
||||||
try {
|
|
||||||
navigator.vibrate({});
|
|
||||||
} catch(e) {
|
|
||||||
assert_unreached('error message: ' + e.message);
|
|
||||||
}
|
|
||||||
}, 'pattern of {} resolves to [{}]');
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: test a pattern array parameter to vibrate() with an extra (even) item</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, interact'/>
|
|
||||||
<meta name='assert' content='If the length of pattern is even, then remove the last entry in pattern.'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate three times for one second, separated
|
|
||||||
by one second intervals.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate([1000, 1000, 1000, 1000, 1000, 1000]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: test a pattern array parameter to vibrate()</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, interact'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate three times for one second, separated
|
|
||||||
by one second intervals.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate([1000, 1000, 1000, 1000, 1000]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<meta charset='utf-8'>
|
|
||||||
<title>Vibration API: test a pattern array with 0ms vibration and still to vibrate()</title>
|
|
||||||
<link rel='author' title='Intel' href='http://www.intel.com'>
|
|
||||||
<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
|
|
||||||
<meta name='flags' content='interact'>
|
|
||||||
<style>
|
|
||||||
button {
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate continuously for about two seconds, once.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<div id='log'></div>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate([0, 0, 2000]);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: test that calls to vibrate() are silently ignored when the device cannot vibrate</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, no-vibrator'/>
|
|
||||||
<meta name='assert' content='If the device does not provide a vibration mechanism, or it is disabled, the user agent must silently ignore any invocations of the vibrate() method.'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
<strong>This test is only useful on devices that do not have vibration capability</strong>.
|
|
||||||
If your device supports vibration, then <strong>skip</strong> this test. An implementation
|
|
||||||
supporting this API but running on a device that cannot vibrate must silently ignore the
|
|
||||||
call (we test that it doesn't throw).
|
|
||||||
</p>
|
|
||||||
<div id='log'></div>
|
|
||||||
<script src='/resources/testharness.js'></script>
|
|
||||||
<script src='/resources/testharnessreport.js'></script>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
test(function () {
|
|
||||||
assert_true(navigator.vibrate(1000), "vibrate() returns true when vibration is not supported");
|
|
||||||
}, "Calling vibrate returns true");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: test a simple array parameter to vibrate()</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate continuously for about two seconds, once.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<div id='log'></div>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate([2000]);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'/>
|
|
||||||
<title>Vibration API: test a simple scalar parameter to vibrate()</title>
|
|
||||||
<link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
|
|
||||||
<meta name='flags' content='dom, interact'/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Description</h1>
|
|
||||||
<p>
|
|
||||||
After hitting the button below, your device must vibrate continuously for about two seconds, once.
|
|
||||||
</p>
|
|
||||||
<button id='vib'>Vibrate!</button>
|
|
||||||
<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
|
|
||||||
<script>
|
|
||||||
if (undefined !== navigator.vibrate) {
|
|
||||||
document.getElementById("vib").onclick = function () {
|
|
||||||
navigator.vibrate(2000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -50,7 +50,7 @@ stage-package: $(MOZ_PKG_MANIFEST) $(MOZ_PKG_MANIFEST_DEPS)
|
||||||
) \
|
) \
|
||||||
$(if $(JARLOG_DIR),$(addprefix --jarlog ,$(wildcard $(JARLOG_FILE_AB_CD)))) \
|
$(if $(JARLOG_DIR),$(addprefix --jarlog ,$(wildcard $(JARLOG_FILE_AB_CD)))) \
|
||||||
$(if $(OPTIMIZEJARS),--optimizejars) \
|
$(if $(OPTIMIZEJARS),--optimizejars) \
|
||||||
$(if $(DISABLE_JAR_COMPRESSION),--disable-compression) \
|
$(addprefix --compress ,$(JAR_COMPRESSION)) \
|
||||||
$(addprefix --unify ,$(UNIFY_DIST)) \
|
$(addprefix --unify ,$(UNIFY_DIST)) \
|
||||||
$(MOZ_PKG_MANIFEST) '$(DIST)' '$(DIST)'/$(STAGEPATH)$(MOZ_PKG_DIR)$(if $(MOZ_PKG_MANIFEST),,$(_BINPATH)) \
|
$(MOZ_PKG_MANIFEST) '$(DIST)' '$(DIST)'/$(STAGEPATH)$(MOZ_PKG_DIR)$(if $(MOZ_PKG_MANIFEST),,$(_BINPATH)) \
|
||||||
$(if $(filter omni,$(MOZ_PACKAGER_FORMAT)),$(if $(NON_OMNIJAR_FILES),--non-resource $(NON_OMNIJAR_FILES)))
|
$(if $(filter omni,$(MOZ_PACKAGER_FORMAT)),$(if $(NON_OMNIJAR_FILES),--non-resource $(NON_OMNIJAR_FILES)))
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ from mozpack.copier import (
|
||||||
Jarrer,
|
Jarrer,
|
||||||
)
|
)
|
||||||
from mozpack.errors import errors
|
from mozpack.errors import errors
|
||||||
|
from mozpack.mozjar import JAR_BROTLI
|
||||||
from mozpack.unify import UnifiedBuildFinder
|
from mozpack.unify import UnifiedBuildFinder
|
||||||
import mozpack.path as mozpath
|
import mozpack.path as mozpath
|
||||||
import buildconfig
|
import buildconfig
|
||||||
|
|
@ -270,9 +271,9 @@ def main():
|
||||||
help='Enable jar optimizations')
|
help='Enable jar optimizations')
|
||||||
parser.add_argument('--unify', default='',
|
parser.add_argument('--unify', default='',
|
||||||
help='Base directory of another build to unify with')
|
help='Base directory of another build to unify with')
|
||||||
parser.add_argument('--disable-compression', action='store_false',
|
parser.add_argument('--compress', choices=('none', 'deflate', 'brotli'),
|
||||||
dest='compress', default=True,
|
default='deflate',
|
||||||
help='Disable jar compression')
|
help='Use given jar compression (default: deflate)')
|
||||||
parser.add_argument('manifest', default=None, nargs='?',
|
parser.add_argument('manifest', default=None, nargs='?',
|
||||||
help='Manifest file name')
|
help='Manifest file name')
|
||||||
parser.add_argument('source', help='Source directory')
|
parser.add_argument('source', help='Source directory')
|
||||||
|
|
@ -290,15 +291,21 @@ def main():
|
||||||
for name, value in [split_define(d) for d in args.defines]:
|
for name, value in [split_define(d) for d in args.defines]:
|
||||||
defines[name] = value
|
defines[name] = value
|
||||||
|
|
||||||
|
compress = {
|
||||||
|
'none': False,
|
||||||
|
'deflate': True,
|
||||||
|
'brotli': JAR_BROTLI,
|
||||||
|
}[args.compress]
|
||||||
|
|
||||||
copier = FileCopier()
|
copier = FileCopier()
|
||||||
if args.format == 'flat':
|
if args.format == 'flat':
|
||||||
formatter = FlatFormatter(copier)
|
formatter = FlatFormatter(copier)
|
||||||
elif args.format == 'jar':
|
elif args.format == 'jar':
|
||||||
formatter = JarFormatter(copier, compress=args.compress, optimize=args.optimizejars)
|
formatter = JarFormatter(copier, compress=compress, optimize=args.optimizejars)
|
||||||
elif args.format == 'omni':
|
elif args.format == 'omni':
|
||||||
formatter = OmniJarFormatter(copier,
|
formatter = OmniJarFormatter(copier,
|
||||||
buildconfig.substs['OMNIJAR_NAME'],
|
buildconfig.substs['OMNIJAR_NAME'],
|
||||||
compress=args.compress,
|
compress=compress,
|
||||||
optimize=args.optimizejars,
|
optimize=args.optimizejars,
|
||||||
non_resources=args.non_resource)
|
non_resources=args.non_resource)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ ifneq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||||
OPTIMIZEJARS = 1
|
OPTIMIZEJARS = 1
|
||||||
ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||||
ifdef NIGHTLY_BUILD
|
ifdef NIGHTLY_BUILD
|
||||||
DISABLE_JAR_COMPRESSION = 1
|
JAR_COMPRESSION ?= none
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue