This commit is contained in:
Wes Kocher 2014-01-09 17:11:34 -08:00
Родитель 4fbefb39bf c5ca8fd03c
Коммит f83bd48c23
135 изменённых файлов: 2933 добавлений и 1026 удалений

Просмотреть файл

@ -32,7 +32,7 @@ const AUDIO_FILTERS = ['audio/basic', 'audio/L24', 'audio/mp4',
'audio/webm'];
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyServiceGetter(this, 'cpmm',
'@mozilla.org/childprocessmessagemanager;1',
@ -191,10 +191,8 @@ FilePicker.prototype = {
// Let's try to remove the full path and take just the filename.
if (name) {
let file = new FileUtils.File(data.result.blob.name);
if (file && file.leafName) {
name = file.leafName;
}
let names = OS.Path.split(name);
name = names.components[names.components.length - 1];
}
// the fallback is a filename composed by 'blob' + extension.

Просмотреть файл

@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
const Cc = Components.classes;
const Ci = Components.interfaces;
// use ppmm to handle file-picker message.
let ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1']
.getService(Ci.nsIMessageListenerManager);
let pickResult = null;
function processPickMessage(message) {
let sender = message.target.QueryInterface(Ci.nsIMessageSender);
// reply FilePicker's message
sender.sendAsyncMessage('file-picked', pickResult);
// notify caller
sendAsyncMessage('file-picked-posted', { type: 'file-picked-posted' });
}
function updatePickResult(result) {
pickResult = result;
sendAsyncMessage('pick-result-updated', { type: 'pick-result-updated' });
}
ppmm.addMessageListener('file-picker', processPickMessage);
// use update-pick-result to change the expected pick result.
addMessageListener('update-pick-result', updatePickResult);

Просмотреть файл

@ -3,5 +3,7 @@ run-if = toolkit == "gonk"
support-files =
permission_handler_chrome.js
SandboxPromptTest.html
filepicker_path_handler_chrome.js
[test_sandbox_permission.html]
[test_filepicker_path.html]

Просмотреть файл

@ -0,0 +1,135 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=949944
-->
<head>
<meta charset="utf-8">
<title>Permission Prompt Test</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body onload="processTestCase()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=949944"> [B2G][Helix][Browser][Wallpaper] use new File([blob], filename) to return a blob with filename when picking</a>
<script type="application/javascript">
'use strict';
var testCases = [
// case 1: returns blob with name
{ pickedResult: { success: true,
result: {
type: 'text/plain',
blob: new Blob(['1234567890'],
{ type: 'text/plain' }),
name: 'test1.txt'
}
},
fileName: 'test1.txt' },
// case 2: returns blob without name
{ pickedResult: { success: true,
result: {
type: 'text/plain',
blob: new Blob(['1234567890'],
{ type: 'text/plain' })
}
},
fileName: 'blob.txt' },
// case 3: returns blob with full path name
{ pickedResult: { success: true,
result: {
type: 'text/plain',
blob: new Blob(['1234567890'],
{ type: 'text/plain' }),
name: '/full/path/test3.txt'
}
},
fileName: 'test3.txt' },
// case 4: returns blob relative path name
{ pickedResult: { success: true,
result: {
type: 'text/plain',
blob: new Blob(['1234567890'],
{ type: 'text/plain' }),
name: 'relative/path/test4.txt'
}
},
fileName: 'test4.txt' },
// case 5: returns file with name
{ pickedResult: { success: true,
result: {
type: 'text/plain',
blob: new File(['1234567890'],
'useless-name.txt',
{ type: 'text/plain' }),
name: 'test5.txt'
}
},
fileName: 'test5.txt'},
// case 6: returns file without name. This case may fail because we
// need to make sure the DOMFile can be sent through
// sendAsyncMessage API.
{ pickedResult: { success: true,
result: {
type: 'text/plain',
blob: new File(['1234567890'],
'test6.txt',
{ type: 'text/plain' })
}
},
todo: true,
fileName: 'test6.txt'}
];
var chromeJS = SimpleTest.getTestFileURL('filepicker_path_handler_chrome.js');
var chromeScript = SpecialPowers.loadChromeScript(chromeJS);
var activeTestCase;
chromeScript.addMessageListener('pick-result-updated', handleMessage);
chromeScript.addMessageListener('file-picked-posted', handleMessage);
// handle messages returned from chromeScript
function handleMessage(data) {
var fileInput = document.getElementById('fileInput');
switch (data.type) {
case 'pick-result-updated':
fileInput.click();
break;
case 'file-picked-posted':
if (activeTestCase.todo) {
todo_is(fileInput.value, activeTestCase.fileName,
'DOMFile should be able to send through message.');
} else {
is(fileInput.value, activeTestCase.fileName);
}
processTestCase();
break;
}
}
function processTestCase() {
if (!testCases.length) {
SimpleTest.finish();
return;
}
activeTestCase = testCases.shift();
var expectedResult = activeTestCase.pickedResult;
if (navigator.userAgent.indexOf('Windows') > -1 &&
expectedResult.result.name) {
// If we run at a window box, we need to translate the path from '/' to '\\'
var name = expectedResult.result.name;
name = name.replace('/', '\\');
// If the name is an absolute path, we need to prepend drive letter.
if (name.startsWith('\\')) {
name = 'C:' + name;
}
// update the expected name.
expectedResult.result.name = name
}
chromeScript.sendAsyncMessage('update-pick-result', expectedResult);
}
</script>
<input type="file" id="fileInput">
</body>
</html>

Просмотреть файл

@ -1,4 +1,4 @@
{
"revision": "6e971c6a9f947d301a0401fcbc87141b8eba23b6",
"revision": "f1f4304e9f2fe7bcf79b1e6ead334706c119ac4a",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -790,7 +790,7 @@ pref("browser.safebrowsing.enabled", true);
pref("browser.safebrowsing.malware.enabled", true);
pref("browser.safebrowsing.debug", false);
pref("browser.safebrowsing.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&apikey=%GOOGLE_API_KEY%");
pref("browser.safebrowsing.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
pref("browser.safebrowsing.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
pref("browser.safebrowsing.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
pref("browser.safebrowsing.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
@ -802,7 +802,7 @@ pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-erro
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
#ifndef MOZILLA_OFFICIAL
pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download&apikey=%GOOGLE_API_KEY%");
pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download&key=%GOOGLE_API_KEY%");
#endif
#ifdef MOZILLA_OFFICIAL

Просмотреть файл

@ -541,6 +541,14 @@
@BINPATH@/components/Push.js
@BINPATH@/components/Push.manifest
@BINPATH@/components/PushServiceLauncher.js
#ifndef RELEASE_BUILD
@BINPATH@/components/InterAppComm.manifest
@BINPATH@/components/InterAppCommService.js
@BINPATH@/components/InterAppConnection.js
@BINPATH@/components/InterAppMessagePort.js
#endif
@BINPATH@/components/TCPSocket.js
@BINPATH@/components/TCPServerSocket.js
@BINPATH@/components/TCPSocketParentIntermediary.js

Просмотреть файл

@ -11,7 +11,7 @@ interface nsIChannel;
interface nsIDocShell;
interface nsIDomainPolicy;
[scriptable, uuid(2911ae60-1b5f-47e6-941e-1bb7b53a167d)]
[scriptable, uuid(712aa338-50a1-497b-be6f-dc3d97867c01)]
interface nsIScriptSecurityManager : nsIXPCSecurityManager
{
///////////////// Security Checks //////////////////
@ -160,12 +160,10 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
*/
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
///////////////////////
/**
* Return the principal of the specified object in the specified context.
*/
[noscript] nsIPrincipal getObjectPrincipal(in JSContextPtr cx,
in JSObjectPtr obj);
[implicit_jscontext] nsIPrincipal getObjectPrincipal(in jsval aObject);
/**
* Returns true if the principal of the currently running script is the

Просмотреть файл

@ -1487,14 +1487,14 @@ nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
}
NS_IMETHODIMP
nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
nsScriptSecurityManager::GetObjectPrincipal(const JS::Value &aObjectVal,
JSContext *aCx,
nsIPrincipal **result)
{
JS::Rooted<JSObject*> obj(aCx, aObj);
*result = doGetObjectPrincipal(obj);
if (!*result)
return NS_ERROR_FAILURE;
NS_ADDREF(*result);
NS_ENSURE_TRUE(aObjectVal.isObject(), NS_ERROR_FAILURE);
JS::RootedObject obj(aCx, &aObjectVal.toObject());
nsCOMPtr<nsIPrincipal> principal = doGetObjectPrincipal(obj);
principal.forget(result);
return NS_OK;
}

Просмотреть файл

@ -4051,6 +4051,7 @@ MOZ_USE_NATIVE_POPUP_WINDOWS=
MOZ_ANDROID_HISTORY=
MOZ_WEBSMS_BACKEND=
MOZ_ANDROID_BEAM=
MOZ_ANDROID_SYNTHAPKS=
ACCESSIBILITY=1
MOZ_TIME_MANAGER=
MOZ_PAY=
@ -5011,6 +5012,18 @@ if test -n "$MOZ_ANDROID_BEAM"; then
AC_DEFINE(MOZ_ANDROID_BEAM)
fi
dnl ========================================================
dnl = Synthesized Webapp APKs on Android
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(android-synthapks,
[ --enable-android-synthapks Enable synthesized APKs],
MOZ_ANDROID_SYNTHAPKS=1,
MOZ_ANDROID_SYNTHAPKS=)
if test -n "$MOZ_ANDROID_SYNTHAPKS"; then
AC_DEFINE(MOZ_ANDROID_SYNTHAPKS)
fi
dnl ========================================================
dnl = JS Debugger XPCOM component (js/jsd)
dnl ========================================================
@ -7766,7 +7779,7 @@ dnl ========================================================
if test -z "$SKIP_PATH_CHECKS"; then
if test -z "${GLIB_CFLAGS}" -o -z "${GLIB_LIBS}" ; then
if test "$MOZ_ENABLE_GTK2" ; then
if test "$MOZ_ENABLE_GTK" ; then
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 1.3.7 gobject-2.0)
fi
fi
@ -8328,6 +8341,7 @@ AC_SUBST(MOZ_METRO)
AC_SUBST(MOZ_ANDROID_HISTORY)
AC_SUBST(MOZ_WEBSMS_BACKEND)
AC_SUBST(MOZ_ANDROID_BEAM)
AC_SUBST(MOZ_ANDROID_SYNTHAPKS)
AC_SUBST(MOZ_DISABLE_GECKOVIEW)
AC_SUBST(ENABLE_STRIP)
AC_SUBST(PKG_SKIP_STRIP)

Просмотреть файл

@ -12,8 +12,8 @@ class nsDOMAttributeMap;
class nsIContent;
#define NS_IATTRIBUTE_IID \
{ 0x8d9d7dbf, 0xc42d, 0x4715, \
{ 0x95, 0xcf, 0x7a, 0x5e, 0xd5, 0xa4, 0x47, 0x70 } }
{ 0x727dc139, 0xf516, 0x46ff, \
{ 0x86, 0x11, 0x18, 0xea, 0xee, 0x4a, 0x3e, 0x6a } }
class nsIAttribute : public nsINode
{
@ -32,8 +32,6 @@ public:
return mNodeInfo;
}
virtual nsIContent* GetContent() const = 0;
/**
* Called when our ownerElement is moved into a new document.
* Updates the nodeinfo of this node.

Просмотреть файл

@ -77,7 +77,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr)
Element* ownerElement = tmp->GetContentInternal();
Element* ownerElement = tmp->GetElement();
if (tmp->IsBlack()) {
if (ownerElement) {
// The attribute owns the element via attribute map so we can
@ -128,16 +128,13 @@ Attr::SetMap(nsDOMAttributeMap *aMap)
mAttrMap = aMap;
}
nsIContent*
Attr::GetContent() const
{
return GetContentInternal();
}
Element*
Attr::GetElement() const
{
nsIContent* content = GetContent();
if (!mAttrMap) {
return nullptr;
}
nsIContent* content = mAttrMap->GetContent();
return content ? content->AsElement() : nullptr;
}
@ -188,7 +185,7 @@ Attr::GetNameAtom(nsIContent* aContent)
NS_IMETHODIMP
Attr::GetValue(nsAString& aValue)
{
nsIContent* content = GetContentInternal();
nsIContent* content = GetElement();
if (content) {
nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(content);
content->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
@ -203,7 +200,7 @@ Attr::GetValue(nsAString& aValue)
void
Attr::SetValue(const nsAString& aValue, ErrorResult& aRv)
{
nsIContent* content = GetContentInternal();
nsIContent* content = GetElement();
if (!content) {
mValue = aValue;
return;
@ -276,7 +273,7 @@ Attr::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
already_AddRefed<nsIURI>
Attr::GetBaseURI() const
{
nsINode *parent = GetContentInternal();
nsINode *parent = GetElement();
return parent ? parent->GetBaseURI() : nullptr;
}
@ -301,7 +298,7 @@ Attr::SetTextContentInternal(const nsAString& aTextContent,
NS_IMETHODIMP
Attr::GetIsId(bool* aReturn)
{
nsIContent* content = GetContentInternal();
nsIContent* content = GetElement();
if (!content)
{
*aReturn = false;
@ -387,11 +384,5 @@ Attr::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
return AttrBinding::Wrap(aCx, aScope, this);
}
Element*
Attr::GetContentInternal() const
{
return mAttrMap ? mAttrMap->GetContent() : nullptr;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -54,7 +54,6 @@ public:
// nsIAttribute interface
void SetMap(nsDOMAttributeMap *aMap) MOZ_OVERRIDE;
nsIContent *GetContent() const MOZ_OVERRIDE;
Element *GetElement() const;
nsresult SetOwnerDocument(nsIDocument* aDocument) MOZ_OVERRIDE;
@ -96,14 +95,13 @@ public:
protected:
virtual Element* GetNameSpaceElement()
{
return GetContentInternal();
return GetElement();
}
static bool sInitialized;
private:
already_AddRefed<nsIAtom> GetNameAtom(nsIContent* aContent);
Element* GetContentInternal() const;
nsString mValue;
};

Просмотреть файл

@ -56,7 +56,7 @@ function ContentSecurityPolicy() {
this._weakDocRequest = { get : function() { return null; } };
CSPdebug("CSP object initialized, no policies to enforce yet");
this._cache = { };
this._cache = new Map();
}
/*
@ -372,7 +372,7 @@ ContentSecurityPolicy.prototype = {
newpolicy._specCompliant = !!aSpecCompliant;
newpolicy._isInitialized = true;
this._policies.push(newpolicy);
this._cache = {}; // reset cache since effective policy changes
this._cache.clear(); // reset cache since effective policy changes
},
/**
@ -385,7 +385,7 @@ ContentSecurityPolicy.prototype = {
return;
}
this._policies.splice(index, 1);
this._cache = {}; // reset cache since effective policy changes
this._cache.clear(); // reset cache since effective policy changes
},
/**
@ -659,8 +659,8 @@ ContentSecurityPolicy.prototype = {
aMimeTypeGuess,
aOriginalUri) {
let key = this._createCacheKey(aContentLocation, aContentType);
if (key && this._cache[key]) {
return this._cache[key];
if (key && this._cache.has(key)) {
return this._cache.get(key);
}
#ifndef MOZ_B2G
@ -764,7 +764,7 @@ ContentSecurityPolicy.prototype = {
// Do not cache the result if this is a nonce-source preload
if (key && !possiblePreloadNonceConflict) {
this._cache[key] = ret;
this._cache.set(key, ret);
}
return ret;
},

Просмотреть файл

@ -774,10 +774,10 @@ nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
const nsINode *node1 = &aOtherNode, *node2 = this;
// Check if either node is an attribute
const nsIAttribute* attr1 = nullptr;
const Attr* attr1 = nullptr;
if (node1->IsNodeOfType(nsINode::eATTRIBUTE)) {
attr1 = static_cast<const nsIAttribute*>(node1);
const nsIContent* elem = attr1->GetContent();
attr1 = static_cast<const Attr*>(node1);
const nsIContent* elem = attr1->GetElement();
// If there is an owner element add the attribute
// to the chain and walk up to the element
if (elem) {
@ -786,8 +786,8 @@ nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
}
}
if (node2->IsNodeOfType(nsINode::eATTRIBUTE)) {
const nsIAttribute* attr2 = static_cast<const nsIAttribute*>(node2);
const nsIContent* elem = attr2->GetContent();
const Attr* attr2 = static_cast<const Attr*>(node2);
const nsIContent* elem = attr2->GetElement();
if (elem == node1 && attr1) {
// Both nodes are attributes on the same element.
// Compare position between the attributes.

Просмотреть файл

@ -41,6 +41,7 @@ TextTrackCue::SetDefaultCueSettings()
mSnapToLines = true;
mLine = WEBVTT_AUTO;
mAlign = AlignSetting::Middle;
mLineAlign = AlignSetting::Start;
mVertical = DirectionSetting::_empty;
}

Просмотреть файл

@ -82,8 +82,9 @@ public:
void SetStartTime(double aStartTime)
{
if (mStartTime == aStartTime)
if (mStartTime == aStartTime) {
return;
}
mStartTime = aStartTime;
CueChanged();
@ -96,8 +97,9 @@ public:
void SetEndTime(double aEndTime)
{
if (mEndTime == aEndTime)
if (mEndTime == aEndTime) {
return;
}
mEndTime = aEndTime;
CueChanged();
@ -110,8 +112,9 @@ public:
void SetPauseOnExit(bool aPauseOnExit)
{
if (mPauseOnExit == aPauseOnExit)
if (mPauseOnExit == aPauseOnExit) {
return;
}
mPauseOnExit = aPauseOnExit;
CueChanged();
@ -139,8 +142,9 @@ public:
void SetVertical(const DirectionSetting& aVertical)
{
if (mVertical == aVertical)
if (mVertical == aVertical) {
return;
}
mReset = true;
mVertical = aVertical;
@ -154,8 +158,9 @@ public:
void SetSnapToLines(bool aSnapToLines)
{
if (mSnapToLines == aSnapToLines)
if (mSnapToLines == aSnapToLines) {
return;
}
mReset = true;
mSnapToLines = aSnapToLines;
@ -174,6 +179,26 @@ public:
mLine = aLine;
}
AlignSetting LineAlign() const
{
return mLineAlign;
}
void SetLineAlign(AlignSetting& aLineAlign, ErrorResult& aRv)
{
if (mLineAlign == aLineAlign)
return;
if (aLineAlign == AlignSetting::Left ||
aLineAlign == AlignSetting::Right) {
return aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
}
mReset = true;
mLineAlign = aLineAlign;
CueChanged();
}
int32_t Position() const
{
return mPosition;
@ -181,9 +206,9 @@ public:
void SetPosition(int32_t aPosition, ErrorResult& aRv)
{
// XXXhumph: validate? bug 868519.
if (mPosition == aPosition)
if (mPosition == aPosition) {
return;
}
if (aPosition > 100 || aPosition < 0){
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
@ -223,8 +248,9 @@ public:
void SetAlign(AlignSetting& aAlign)
{
if (mAlign == aAlign)
if (mAlign == aAlign) {
return;
}
mReset = true;
mAlign = aAlign;
@ -238,8 +264,9 @@ public:
void SetText(const nsAString& aText)
{
if (mText == aText)
if (mText == aText) {
return;
}
mReset = true;
mText = aText;
@ -324,6 +351,7 @@ private:
DirectionSetting mVertical;
int mLine;
AlignSetting mAlign;
AlignSetting mLineAlign;
// Holds the computed DOM elements that represent the parsed cue text.
// http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-display-state

Просмотреть файл

@ -76,6 +76,34 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
cue.pauseOnExit = true;
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
// Check that cue line align works properly
is(cue.lineAlign, "start", "Cue's default line alignment should be start.");
var exceptionHappened = false;
try {
cue.lineAlign = "left";
} catch(e) {
exceptionHappened = true;
is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
}
ok(exceptionHappened, "Exception should have happened.");
exceptionHappened = false;
try {
cue.lineAlign = "right";
} catch(e) {
exceptionHappened = true;
is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
}
ok(exceptionHappened, "Exception should have happened.");
cue.lineAlign = "middle";
is(cue.lineAlign, "middle", "Cue's line align should be middle.");
cue.lineAlign = "START";
is(cue.lineAlign, "middle", "Cue's line align should be middle.");
cue.lineAlign = "end";
is(cue.lineAlign, "end", "Cue's line align should be end.");
// Check that we can create and add new VTTCues
var vttCue = new VTTCue(3.999, 4, "foo");
trackElement.track.addCue(vttCue);
@ -95,7 +123,7 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
trackElement.track.removeCue(cue);
is(cueList.length, 6, "Cue list length should be 6.");
var exceptionHappened = false;
exceptionHappened = false;
try {
// We should not be able to remove a cue that is not in the list.
cue = new VTTCue(1, 2, "foo");

Просмотреть файл

@ -70,6 +70,9 @@ this.AppsUtils = {
csp: aApp.csp,
installOrigin: aApp.installOrigin,
origin: aApp.origin,
#ifdef MOZ_ANDROID_SYNTHAPKS
packageName: aApp.packageName,
#endif
receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null,
installTime: aApp.installTime,
manifestURL: aApp.manifestURL,

Просмотреть файл

@ -40,6 +40,8 @@ for (let permName in PermissionsTable) {
expandedPermNames = expandPermissions(permName);
}
AllPossiblePermissions = AllPossiblePermissions.concat(expandedPermNames);
AllPossiblePermissions =
AllPossiblePermissions.concat(["offline-app", "pin-app"]);
}
this.PermissionsInstaller = {
@ -75,6 +77,11 @@ this.PermissionsInstaller = {
newPermNames = newPermNames.concat(expandedPermNames);
}
// Add the appcache related permissions.
if (newManifest.appcache_path) {
newPermNames = newPermNames.concat(["offline-app", "pin-app"]);
}
for (let idx in AllPossiblePermissions) {
let permName = AllPossiblePermissions[idx];
let index = newPermNames.indexOf(permName);
@ -118,6 +125,13 @@ this.PermissionsInstaller = {
break;
}
// Add the appcache related permissions. We allow it for all kinds of
// apps.
if (newManifest.appcache_path) {
this._setPermission("offline-app", "allow", aApp);
this._setPermission("pin-app", "allow", aApp);
}
for (let permName in newManifest.permissions) {
if (!PermissionsTable[permName]) {
Cu.reportError("PermissionsInstaller.jsm: '" + permName + "'" +

Просмотреть файл

@ -227,8 +227,6 @@ this.PermissionsTable = { geolocation: {
certified: ALLOW_ACTION,
substitute: [
"indexedDB-unlimited",
"offline-app",
"pin-app",
"default-persistent-storage"
]
},

Просмотреть файл

@ -1119,9 +1119,14 @@ this.DOMApplicationRegistry = {
msg.mm = mm;
switch (aMessage.name) {
case "Webapps:Install":
case "Webapps:Install": {
#ifdef MOZ_ANDROID_SYNTHAPKS
Services.obs.notifyObservers(null, "webapps-download-apk", JSON.stringify(msg));
#else
this.doInstall(msg, mm);
#endif
break;
}
case "Webapps:GetSelf":
this.getSelf(msg, mm);
break;
@ -1143,9 +1148,14 @@ this.DOMApplicationRegistry = {
case "Webapps:GetAll":
this.doGetAll(msg, mm);
break;
case "Webapps:InstallPackage":
case "Webapps:InstallPackage": {
#ifdef MOZ_ANDROID_SYNTHAPKS
Services.obs.notifyObservers(null, "webapps-download-apk", JSON.stringify(msg));
#else
this.doInstallPackage(msg, mm);
#endif
break;
}
case "Webapps:RegisterForMessages":
this.addMessageListener(msg.messages, msg.app, mm);
break;
@ -2012,6 +2022,65 @@ this.DOMApplicationRegistry = {
return manifestStatus === "web";
}
let checkManifest = (function() {
if (!app.manifest) {
sendError("MANIFEST_PARSE_ERROR");
return false;
}
// Disallow multiple hosted apps installations from the same origin for now.
// We will remove this code after multiple apps per origin are supported (bug 778277).
// This will also disallow reinstalls from the same origin for now.
for (let id in this.webapps) {
if (this.webapps[id].origin == app.origin &&
!this.webapps[id].packageHash &&
this._isLaunchable(this.webapps[id])) {
sendError("MULTIPLE_APPS_PER_ORIGIN_FORBIDDEN");
return false;
}
}
if (!AppsUtils.checkManifest(app.manifest, app)) {
sendError("INVALID_MANIFEST");
return false;
}
if (!AppsUtils.checkInstallAllowed(app.manifest, app.installOrigin)) {
sendError("INSTALL_FROM_DENIED");
return false;
}
if (!checkAppStatus(app.manifest)) {
sendError("INVALID_SECURITY_LEVEL");
return false;
}
return true;
}).bind(this);
let installApp = (function() {
app.manifestHash = this.computeManifestHash(app.manifest);
// We allow bypassing the install confirmation process to facilitate
// automation.
let prefName = "dom.mozApps.auto_confirm_install";
if (Services.prefs.prefHasUserValue(prefName) &&
Services.prefs.getBoolPref(prefName)) {
this.confirmInstall(aData);
} else {
Services.obs.notifyObservers(aMm, "webapps-ask-install",
JSON.stringify(aData));
}
}).bind(this);
// We may already have the manifest (e.g. AutoInstall),
// in which case we don't need to load it.
if (app.manifest) {
if (checkManifest()) {
installApp();
}
return;
}
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", app.manifestURL, true);
@ -2029,42 +2098,9 @@ this.DOMApplicationRegistry = {
}
app.manifest = xhr.response;
if (!app.manifest) {
sendError("MANIFEST_PARSE_ERROR");
return;
}
// Disallow multiple hosted apps installations from the same origin for now.
// We will remove this code after multiple apps per origin are supported (bug 778277).
// This will also disallow reinstalls from the same origin for now.
for (let id in this.webapps) {
if (this.webapps[id].origin == app.origin &&
!this.webapps[id].packageHash &&
this._isLaunchable(this.webapps[id])) {
sendError("MULTIPLE_APPS_PER_ORIGIN_FORBIDDEN");
return;
}
}
if (!AppsUtils.checkManifest(app.manifest, app)) {
sendError("INVALID_MANIFEST");
} else if (!AppsUtils.checkInstallAllowed(app.manifest, app.installOrigin)) {
sendError("INSTALL_FROM_DENIED");
} else if (!checkAppStatus(app.manifest)) {
sendError("INVALID_SECURITY_LEVEL");
} else {
if (checkManifest()) {
app.etag = xhr.getResponseHeader("Etag");
app.manifestHash = this.computeManifestHash(app.manifest);
// We allow bypassing the install confirmation process to facilitate
// automation.
let prefName = "dom.mozApps.auto_confirm_install";
if (Services.prefs.prefHasUserValue(prefName) &&
Services.prefs.getBoolPref(prefName)) {
this.confirmInstall(aData);
} else {
Services.obs.notifyObservers(aMm, "webapps-ask-install",
JSON.stringify(aData));
}
installApp();
}
} else {
sendError("MANIFEST_URL_ERROR");
@ -2088,6 +2124,53 @@ this.DOMApplicationRegistry = {
app.installOrigin + ": " + aError);
}.bind(this);
let checkUpdateManifest = (function() {
let manifest = app.updateManifest;
// Disallow reinstalls from the same manifest URL for now.
let id = this._appIdForManifestURL(app.manifestURL);
if (id !== null && this._isLaunchable(this.webapps[id])) {
sendError("REINSTALL_FORBIDDEN");
return false;
}
if (!(AppsUtils.checkManifest(manifest, app) && manifest.package_path)) {
sendError("INVALID_MANIFEST");
return false;
}
if (!AppsUtils.checkInstallAllowed(manifest, app.installOrigin)) {
sendError("INSTALL_FROM_DENIED");
return false;
}
return true;
}).bind(this);
let installApp = (function() {
app.manifestHash = this.computeManifestHash(app.updateManifest);
// We allow bypassing the install confirmation process to facilitate
// automation.
let prefName = "dom.mozApps.auto_confirm_install";
if (Services.prefs.prefHasUserValue(prefName) &&
Services.prefs.getBoolPref(prefName)) {
this.confirmInstall(aData);
} else {
Services.obs.notifyObservers(aMm, "webapps-ask-install",
JSON.stringify(aData));
}
}).bind(this);
// We may already have the manifest (e.g. AutoInstall),
// in which case we don't need to load it.
if (app.updateManifest) {
if (checkUpdateManifest()) {
installApp();
}
return;
}
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", app.manifestURL, true);
@ -2104,38 +2187,15 @@ this.DOMApplicationRegistry = {
return;
}
let manifest = app.updateManifest = xhr.response;
if (!manifest) {
app.updateManifest = xhr.response;
if (!app.updateManifest) {
sendError("MANIFEST_PARSE_ERROR");
return;
}
// Disallow reinstalls from the same manifest URL for now.
let id = this._appIdForManifestURL(app.manifestURL);
if (id !== null && this._isLaunchable(this.webapps[id])) {
sendError("REINSTALL_FORBIDDEN");
return;
}
if (!(AppsUtils.checkManifest(manifest, app) &&
manifest.package_path)) {
sendError("INVALID_MANIFEST");
} else if (!AppsUtils.checkInstallAllowed(manifest, app.installOrigin)) {
sendError("INSTALL_FROM_DENIED");
} else {
if (checkUpdateManifest()) {
app.etag = xhr.getResponseHeader("Etag");
app.manifestHash = this.computeManifestHash(manifest);
debug("at install package got app etag=" + app.etag);
// We allow bypassing the install confirmation process to facilitate
// automation.
let prefName = "dom.mozApps.auto_confirm_install";
if (Services.prefs.prefHasUserValue(prefName) &&
Services.prefs.getBoolPref(prefName)) {
this.confirmInstall(aData);
} else {
Services.obs.notifyObservers(aMm, "webapps-ask-install",
JSON.stringify(aData));
}
installApp();
}
}
else {
@ -2346,7 +2406,17 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
// saved in the registry.
this._saveApps((function() {
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
this.broadcastMessage("Webapps:Install:Return:OK", aData);
if (aData.isPackage && aData.autoInstall) {
// Skip directly to onInstallSuccessAck, since there isn't
// a WebappsRegistry to receive Webapps:Install:Return:OK and respond
// Webapps:Install:Return:Ack when an app is being auto-installed.
this.onInstallSuccessAck(app.manifestURL);
} else {
// Broadcast Webapps:Install:Return:OK so the WebappsRegistry can notify
// the installing page about the successful install, after which it'll
// respond Webapps:Install:Return:Ack, which calls onInstallSuccessAck.
this.broadcastMessage("Webapps:Install:Return:OK", aData);
}
Services.obs.notifyObservers(null, "webapps-installed",
JSON.stringify({ manifestURL: app.manifestURL }));
}).bind(this));
@ -2361,11 +2431,17 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
if (manifest.package_path) {
// If it is a local app then it must been installed from a local file
// instead of web.
let origPath = jsonManifest.package_path;
#ifdef MOZ_ANDROID_SYNTHAPKS
// In that case, we would already have the manifest, not just the update
// manifest.
dontNeedNetwork = !!aData.app.manifest;
#else
if (aData.app.localInstallPath) {
dontNeedNetwork = true;
jsonManifest.package_path = "file://" + aData.app.localInstallPath;
}
#endif
// origin for install apps is meaningless here, since it's app:// and this
// can't be used to resolve package paths.
manifest = new ManifestHelper(jsonManifest, app.manifestURL);
@ -2548,7 +2624,7 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
let fullPackagePath = aManifest.fullPackagePath();
// Check if it's a local file install (we've downloaded/sideloaded the
// package already or it did exist on the build).
// package already, it existed on the build, or it came with an APK).
// Note that this variable also controls whether files signed with expired
// certificates are accepted or not. If isLocalFileInstall is true and the
// device date is earlier than the build generation date, then the signature

Просмотреть файл

@ -1029,12 +1029,15 @@ private:
bool
Recv__delete__() MOZ_OVERRIDE
{
MOZ_ASSERT(mOpened);
MOZ_ASSERT(!mFinished);
mFinished = true;
MainProcessRunnable::Close();
if (mOpened) {
MainProcessRunnable::Close();
} else {
MainProcessRunnable::Fail();
}
return true;
}

Просмотреть файл

@ -2686,6 +2686,15 @@ class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
exceptionCode,
isCallbackReturnValue)
class CGCallbackTempRoot(CGGeneric):
def __init__(self, name):
define = """{ // Scope for tempRoot
JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());
${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());
}
""" % name
CGGeneric.__init__(self, define=define)
class JSToNativeConversionInfo():
"""
An object representing information about a JS-to-native conversion.
@ -3402,11 +3411,7 @@ for (uint32_t i = 0; i < length; ++i) {
declType = CGGeneric("nsRefPtr<%s>" % name);
else:
declType = CGGeneric("OwningNonNull<%s>" % name)
conversion = (
"{ // Scope for tempRoot\n"
" JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());\n"
" ${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());\n"
"}" % name)
conversion = CGIndenter(CGCallbackTempRoot(name)).define()
template = wrapObjectTemplate(conversion, type,
"${declName} = nullptr",
@ -3738,11 +3743,7 @@ for (uint32_t i = 0; i < length; ++i) {
declType = CGGeneric("nsRefPtr<%s>" % name);
else:
declType = CGGeneric("OwningNonNull<%s>" % name)
conversion = (
"{ // Scope for tempRoot\n"
" JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());\n"
" ${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());\n"
"}\n" % name)
conversion = CGIndenter(CGCallbackTempRoot(name)).define()
if allowTreatNonCallableAsNull and type.treatNonCallableAsNull():
haveCallable = "JS_ObjectIsCallable(cx, &${val}.toObject())"
@ -4092,8 +4093,7 @@ class CGArgumentConverter(CGThing):
"""
def __init__(self, argument, index, descriptorProvider,
argDescription,
invalidEnumValueFatal=True, lenientFloatCode=None,
allowTreatNonCallableAsNull=False):
invalidEnumValueFatal=True, lenientFloatCode=None):
CGThing.__init__(self)
self.argument = argument
self.argDescription = argDescription
@ -4122,7 +4122,6 @@ class CGArgumentConverter(CGThing):
self.argcAndIndex = None
self.invalidEnumValueFatal = invalidEnumValueFatal
self.lenientFloatCode = lenientFloatCode
self.allowTreatNonCallableAsNull = allowTreatNonCallableAsNull
def define(self):
typeConversion = getJSToNativeConversionInfo(
@ -4137,7 +4136,7 @@ class CGArgumentConverter(CGThing):
isClamp=self.argument.clamp,
lenientFloatCode=self.lenientFloatCode,
isMember="Variadic" if self.argument.variadic else False,
allowTreatNonCallableAsNull=self.allowTreatNonCallableAsNull,
allowTreatNonCallableAsNull=self.argument.allowTreatNonCallableAsNull(),
sourceDescription=self.argDescription)
if not self.argument.variadic:
@ -5106,7 +5105,6 @@ if (global.Failed()) {
cgThings.extend([CGArgumentConverter(arguments[i], i, self.descriptor,
argDescription % { "index": i + 1 },
invalidEnumValueFatal=not setter,
allowTreatNonCallableAsNull=setter,
lenientFloatCode=lenientFloatCode) for
i in range(argConversionStartsAt, self.argCount)])
@ -5687,11 +5685,12 @@ class FakeArgument():
A class that quacks like an IDLArgument. This is used to make
setters look like method calls or for special operations.
"""
def __init__(self, type, interfaceMember, name="arg"):
def __init__(self, type, interfaceMember, name="arg", allowTreatNonCallableAsNull=False):
self.type = type
self.optional = False
self.variadic = False
self.defaultValue = None
self._allowTreatNonCallableAsNull = allowTreatNonCallableAsNull
self.treatNullAs = interfaceMember.treatNullAs
if isinstance(interfaceMember, IDLAttribute):
self.enforceRange = interfaceMember.enforceRange
@ -5704,13 +5703,16 @@ class FakeArgument():
self.name = name
self.identifier = FakeIdentifier()
def allowTreatNonCallableAsNull(self):
return self._allowTreatNonCallableAsNull
class CGSetterCall(CGPerSignatureCall):
"""
A class to generate a native object setter call for a particular IDL
setter.
"""
def __init__(self, argType, nativeMethodName, descriptor, attr):
CGPerSignatureCall.__init__(self, None, [FakeArgument(argType, attr)],
CGPerSignatureCall.__init__(self, None, [FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
nativeMethodName, attr.isStatic(),
descriptor, attr, setter=True)
def wrap_return_value(self):
@ -11933,3 +11935,4 @@ class CGEventRoot(CGThing):
def define(self):
return self.root.define()

Просмотреть файл

@ -2848,6 +2848,7 @@ class IDLArgument(IDLObjectWithIdentifier):
self._isComplete = False
self.enforceRange = False
self.clamp = False
self._allowTreatNonCallableAsNull = False
assert not variadic or optional
@ -2874,6 +2875,8 @@ class IDLArgument(IDLObjectWithIdentifier):
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
[self.location]);
self.enforceRange = True
elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True
else:
raise WebIDLError("Unhandled extended attribute on an argument",
[attribute.location])
@ -2908,6 +2911,9 @@ class IDLArgument(IDLObjectWithIdentifier):
self.location)
assert self.defaultValue
def allowTreatNonCallableAsNull(self):
return self._allowTreatNonCallableAsNull
def _getDependentObjects(self):
deps = set([self.type])
if self.defaultValue:

Просмотреть файл

@ -2886,6 +2886,11 @@ BluetoothDBusService::GetServiceChannel(const nsAString& aDeviceAddress,
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
return NS_OK;
}
MOZ_ASSERT(!sAdapterPath.IsEmpty());
nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));

Просмотреть файл

@ -129,7 +129,7 @@ nsDOMIdentity.prototype = {
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);
},
request: function nsDOMIdentity_request(aOptions) {
request: function nsDOMIdentity_request(aOptions = {}) {
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);

Просмотреть файл

@ -107,6 +107,9 @@ this.SystemMessagePermissionsTable = {
"nfc-manager-tech-lost": {
"nfc-manager": []
},
"nfc-manager-send-file": {
"nfc-manager": []
},
"nfc-powerlevel-change": {
"settings": ["read", "write"]
},

Просмотреть файл

@ -110,7 +110,7 @@ MozNFCPeer.prototype = {
initialize: function(aWindow, aSessionToken) {
this._window = aWindow;
this.session = aSessionToken;
this.setSessionToken(aSessionToken);
},
// ChromeOnly interface
@ -127,6 +127,15 @@ MozNFCPeer.prototype = {
return this._nfcContentHelper.writeNDEF(this._window, records, this.session);
},
sendFile: function sendFile(blob) {
let data = {
"blob": blob.slice()
};
return this._nfcContentHelper.sendFile(this._window,
ObjectWrapper.wrap(data, this._window),
this.session);
},
classID: Components.ID("{c1b2bcf0-35eb-11e3-aa6e-0800200c9a66}"),
contractID: "@mozilla.org/nfc/NFCPeer;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,

Просмотреть файл

@ -8,7 +8,7 @@ var gData = [
permission: "contacts",
access: READWRITE,
expected: ["contacts-read", "contacts-create",
"contacts-write"]
"contacts-write"]
},
// test additional expansion and access not having read+create+write
{
@ -16,12 +16,12 @@ var gData = [
access: READWRITE,
expected: ["settings-read", "settings-write",
"indexedDB-chrome-settings-read",
"indexedDB-chrome-settings-write"]
"indexedDB-chrome-settings-write"]
},
// test substitute
{
permission: "storage",
expected: ["indexedDB-unlimited", "offline-app", "pin-app",
expected: ["indexedDB-unlimited",
"default-persistent-storage"]
},
// test unknown access

Просмотреть файл

@ -25,6 +25,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WakeLock)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WakeLock)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)

Просмотреть файл

@ -1,5 +1,6 @@
[DEFAULT]
[test_bug957899.html]
[test_power_basics.html]
[test_power_set_cpusleepallowed.html]
[test_power_set_screen_brightness.html]

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test bug 957899 - Crash in WakeLock</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript">
var wl = navigator.requestWakeLock('a');
ok(wl, "WakeLock created!");
ok(!(wl instanceof XPathEvaluator), "Crashing?");
</script>
</body>
</html>

Просмотреть файл

@ -51,7 +51,8 @@ const NFC_IPC_MSG_NAMES = [
"NFC:GetDetailsNDEF",
"NFC:MakeReadOnlyNDEF",
"NFC:Connect",
"NFC:Close"
"NFC:Close",
"NFC:SendFile"
];
const NFC_IPC_PEER_MSG_NAMES = [
@ -296,11 +297,11 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
return null;
}
// Add extra permission check for two IPC Peer events:
// Add extra permission check for below IPC Peer events:
// 'NFC:CheckP2PRegistration' , 'NFC:NotifyUserAcceptedP2P'
if ((msg.name == "NFC:CheckP2PRegistration") ||
(msg.name == "NFC:NotifyUserAcceptedP2P")) {
// ONLY privileged Content can send these two events
// ONLY privileged Content can send these events
if (!msg.target.assertPermission("nfc-manager")) {
debug("NFC message " + message.name +
" from a content process with no 'nfc-manager' privileges.");
@ -532,6 +533,7 @@ Nfc.prototype = {
break;
case "NFC:WriteNDEF": // Fall through
case "NFC:MakeReadOnlyNDEF":
case "NFC:SendFile":
if (!message.target.assertPermission("nfc-write")) {
debug("NFC message " + message.name +
" from a content process with no 'nfc-write' privileges.");
@ -574,6 +576,17 @@ Nfc.prototype = {
case "NFC:Close":
this.sendToWorker("close", message.json);
break;
case "NFC:SendFile":
// Chrome process is the arbitrator / mediator between
// system app (content process) that issued nfc 'sendFile' operation
// and system app that handles the system message :
// 'nfc-manager-send-file'. System app subsequently handover's
// the data to alternate carrier's (BT / WiFi) 'sendFile' interface.
// Notify system app to initiate BT send file operation
gSystemMessenger.broadcastMessage("nfc-manager-send-file",
message.json);
break;
default:
debug("UnSupported : Message Name " + message.name);
return null;

Просмотреть файл

@ -218,6 +218,23 @@ NfcContentHelper.prototype = {
return request;
},
sendFile: function sendFile(window, data, sessionToken) {
if (window == null) {
throw Components.Exception("Can't get window object",
Cr.NS_ERROR_UNEXPECTED);
}
let request = Services.DOMRequest.createRequest(window);
let requestId = btoa(this.getRequestId(request));
this._requestMap[requestId] = window;
cpmm.sendAsyncMessage("NFC:SendFile", {
requestId: requestId,
sessionToken: sessionToken,
blob: data.blob
});
return request;
},
registerTargetForPeerEvent: function registerTargetForPeerEvent(window,
appId, event, callback) {
if (window == null) {
@ -276,7 +293,6 @@ NfcContentHelper.prototype = {
},
// nsIObserver
observe: function observe(subject, topic, data) {
if (topic == "xpcom-shutdown") {
this.removeMessageListener();

Просмотреть файл

@ -7,7 +7,7 @@
interface nsIVariant;
[scriptable, function, uuid(271f48b0-c884-4f0b-a348-e29824c95168)]
[scriptable, function, uuid(26673d1a-4af4-470a-ba96-f1f54b1f2052)]
interface nsINfcPeerCallback : nsISupports
{
/**
@ -40,6 +40,27 @@ interface nsINfcContentHelper : nsISupports
nsIDOMDOMRequest connect(in nsIDOMWindow window, in unsigned long techType, in DOMString sessionToken);
nsIDOMDOMRequest close(in nsIDOMWindow window, in DOMString sessionToken);
/**
* Initiate Send file operation
*
* @param window
* Current window
*
* @param blob
* Raw data of the file to be sent. This object represents a file-like
* (nsIDOMFile) object of immutable, raw data. The blob data needs
* to be 'object wrapped' before calling this interface.
*
* @param sessionToken
* Current token
*
* Returns DOMRequest, if initiation of send file operation is successful
* then 'onsuccess' is called else 'onerror'
*/
nsIDOMDOMRequest sendFile(in nsIDOMWindow window,
in jsval blob,
in DOMString sessionToken);
/**
* Register the given application id with Chrome process
*

Просмотреть файл

@ -11,6 +11,7 @@
[JSImplementation="@mozilla.org/nfc/NFCPeer;1"]
interface MozNFCPeer {
DOMRequest sendNDEF(sequence<MozNdefRecord> records);
DOMRequest sendFile(Blob blob);
};
// Mozilla Only

Просмотреть файл

@ -38,6 +38,8 @@ interface VTTCue : EventTarget {
// XXXhumph: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20651
// attribute (long or AutoKeyword) line;
[SetterThrows]
attribute AlignSetting lineAlign;
[SetterThrows]
attribute long position;
[SetterThrows]
attribute long size;

Просмотреть файл

@ -7,8 +7,8 @@
#include "txExprResult.h"
#include "txNodeSet.h"
#include "nsError.h"
#include "mozilla/dom/Attr.h"
#include "mozilla/dom/Element.h"
#include "nsIAttribute.h"
#include "nsDOMClassInfoID.h"
#include "nsIDOMNode.h"
#include "nsIDOMDocument.h"
@ -362,7 +362,7 @@ nsXPathResult::Invalidate(const nsIContent* aChangeRoot)
->GetBindingParent();
} else if (contextNode->IsNodeOfType(nsINode::eATTRIBUTE)) {
nsIContent* parent =
static_cast<nsIAttribute*>(contextNode.get())->GetContent();
static_cast<Attr*>(contextNode.get())->GetElement();
if (parent) {
ctxBindingParent = parent->GetBindingParent();
}

Просмотреть файл

@ -21,10 +21,13 @@
#include "nsUnicharUtils.h"
#include "nsAttrName.h"
#include "nsTArray.h"
#include "mozilla/dom/Attr.h"
#include "mozilla/dom/Element.h"
#include <stdint.h>
#include <algorithm>
using mozilla::dom::Attr;
const uint32_t kUnknownIndex = uint32_t(-1);
txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
@ -690,7 +693,7 @@ txXPathNativeNode::createXPathNode(nsIDOMNode* aNode, bool aKeepRootAlive)
NS_ASSERTION(attr, "doesn't implement nsIAttribute");
nsINodeInfo *nodeInfo = attr->NodeInfo();
nsIContent *parent = attr->GetContent();
nsIContent *parent = static_cast<Attr*>(attr.get())->GetElement();
if (!parent) {
return nullptr;
}

Просмотреть файл

@ -3,8 +3,6 @@
# 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/.
VPATH = $(srcdir) $(srcdir)/unittest
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gtk3 gonk qt))
OS_CXXFLAGS += $(CAIRO_FT_CFLAGS)
endif

Просмотреть файл

@ -219,17 +219,6 @@ SplitBezier(const BezierControlPoints &aControlPoints,
aSecondSegmentControlPoints->mCP1 = cp1aaa;
aSecondSegmentControlPoints->mCP2 = cp2aa;
aSecondSegmentControlPoints->mCP3 = cp3a;
// Ensure the result is a nice cubic bezier.
if (aSecondSegmentControlPoints->mCP1 == aSecondSegmentControlPoints->mCP2 ||
aSecondSegmentControlPoints->mCP2 == aSecondSegmentControlPoints->mCP3) {
aSecondSegmentControlPoints->mCP2 = aSecondSegmentControlPoints->mCP1 +
(aSecondSegmentControlPoints->mCP3 - aSecondSegmentControlPoints->mCP1) *
Float(2. / 3.);
aSecondSegmentControlPoints->mCP3 = aControlPoints.mCP4 +
(aSecondSegmentControlPoints->mCP3 - aControlPoints.mCP4) *
Float(2. / 3.);
}
}
static void
@ -278,9 +267,16 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
Point cp21 = aControlPoints.mCP2 - aControlPoints.mCP1;
Point cp41 = aControlPoints.mCP4 - aControlPoints.mCP1;
Float s4 = (cp41.x * cp21.y - cp41.y * cp21.x) / hypotf(cp21.x, cp21.y);
if (!cp21.x && !cp21.y) {
// In this case s3 becomes lim[n->0] (cp41.x * n) / n - (cp41.y * n) / n = cp41.x - cp41.y.
*aMin = aT - pow(aTolerance / (cp41.x - cp41.y), Float(1. / 3.));
*aMax = aT + pow(aTolerance / (cp41.x - cp41.y), Float(1. / 3.));;
return;
}
Float tf = pow(abs(aTolerance / s4), Float(1. / 3.));
Float s3 = (cp41.x * cp21.y - cp41.y * cp21.x) / hypotf(cp21.x, cp21.y);
Float tf = pow(abs(aTolerance / s3), Float(1. / 3.));
*aMin = aT - tf * (1 - aT);
*aMax = aT + tf * (1 - aT);
@ -367,6 +363,9 @@ FindInflectionPoints(const BezierControlPoints &aControlPoints,
if (discriminant < 0) {
// No inflection points.
*aCount = 0;
} else if (discriminant == 0) {
*aCount = 1;
*aT1 = -b / (2 * a);
} else {
/* Use the following formula for computing the roots:
*
@ -419,10 +418,10 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
// For both inflection points, calulate the range where they can be linearly
// approximated if they are positioned within [0,1]
if (count > 0 && t1 >= 0 && t1 <= 1.0) {
if (count > 0 && t1 >= 0 && t1 < 1.0) {
FindInflectionApproximationRange(aControlPoints, &t1min, &t1max, t1, aTolerance);
}
if (count > 1 && t2 >= 0 && t2 <= 1.0) {
if (count > 1 && t2 >= 0 && t2 < 1.0) {
FindInflectionApproximationRange(aControlPoints, &t2min, &t2max, t2, aTolerance);
}
BezierControlPoints nextCPs = aControlPoints;
@ -430,34 +429,33 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
// Process ranges. [t1min, t1max] and [t2min, t2max] are approximated by line
// segments.
if (t1min < 1.0 && t1max > 0) {
if (t1min > 0) {
// Flatten the Bezier up until the first inflection point's approximation
// point.
SplitBezier(aControlPoints, &prevCPs,
&remainingCP, t1min);
FlattenBezierCurveSegment(prevCPs, aSink, aTolerance);
}
if (t1max < 1.0 && (count == 1 || t2min > t1max)) {
// The second inflection point's approximation range begins after the end
// of the first, approximate the first inflection point by a line and
// subsequently flatten up until the end or the next inflection point.
SplitBezier(aControlPoints, nullptr, &nextCPs, t1max);
aSink->LineTo(nextCPs.mCP1);
if (count > 1 && t2min > 1.0) {
// No more inflection points to deal with, flatten the rest of the curve.
FlattenBezierCurveSegment(nextCPs, aSink, aTolerance);
}
} else if (count > 1 && t2min > 1.0) {
// We've already concluded t2min <= t1max, so if this is true the
// approximation range for the first inflection point runs past the
// end of the curve, draw a line to the end and we're done.
aSink->LineTo(aControlPoints.mCP4);
return;
}
if (t1min > 0) {
// Flatten the Bezier up until the first inflection point's approximation
// point.
SplitBezier(aControlPoints, &prevCPs,
&remainingCP, t1min);
FlattenBezierCurveSegment(prevCPs, aSink, aTolerance);
}
if (t1max < 1.0 && (count == 1 || t2min > t1max)) {
// The second inflection point's approximation range begins after the end
// of the first, approximate the first inflection point by a line and
// subsequently flatten up until the end or the next inflection point.
SplitBezier(aControlPoints, nullptr, &nextCPs, t1max);
aSink->LineTo(nextCPs.mCP1);
if (count == 1 || (count > 1 && t2min >= 1.0)) {
// No more inflection points to deal with, flatten the rest of the curve.
FlattenBezierCurveSegment(nextCPs, aSink, aTolerance);
}
} else if (count > 1 && t2min > 1.0) {
// We've already concluded t2min <= t1max, so if this is true the
// approximation range for the first inflection point runs past the
// end of the curve, draw a line to the end and we're done.
aSink->LineTo(aControlPoints.mCP4);
return;
}
if (count > 1 && t2min < 1.0 && t2max > 0) {
if (t2min > 0 && t2min < t1max) {
// In this case the t2 approximation range starts inside the t1

Просмотреть файл

@ -2,22 +2,6 @@
# 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/.
# The below is a rough translation of build_angle.gypi:
# Target: 'preprocessor'
# src/compiler/preprocessor:
VPATH += $(srcdir)/src/compiler/preprocessor
# Target: 'translator_common'
# Requires: 'preprocessor'
VPATH += $(srcdir)/src/compiler
VPATH += $(srcdir)/src/compiler/depgraph
VPATH += $(srcdir)/src/compiler/timing
VPATH += $(srcdir)/src/third_party/compiler
VPATH += $(srcdir)/src/third_party/murmurhash
# Target: 'translator_glsl'
# Requires: 'translator_common'
# src/compiler:
ifdef MOZ_ANGLE_RENDERER
libs::

Просмотреть файл

@ -13,10 +13,6 @@ endif
# Below is a transcription of the EGL target from build_angle.gypi.
# Target: 'libEGL'
# Links with: 'libGLESv2'
# src/common:
VPATH += $(srcdir)/../common
# src/libEGL:
VPATH += $(srcdir)/../libEGL
DEFFILE = $(srcdir)/libEGL.def
RCFILE = $(srcdir)/libEGL.rc

Просмотреть файл

@ -10,27 +10,6 @@ ifndef GNU_CC
OS_CPPFLAGS += -EHsc
endif
# The below is a rough translation of build_angle.gypi,
# copied from src/Makefile.in.
# Target: 'preprocessor'
# src/compiler/preprocessor:
VPATH += $(srcdir)/../compiler/preprocessor
# Target: 'translator_common'
# Requires: 'preprocessor'
VPATH += $(srcdir)/renderer
VPATH += $(srcdir)/..
VPATH += $(srcdir)/../compiler
VPATH += $(srcdir)/../compiler/depgraph
VPATH += $(srcdir)/../compiler/timing
VPATH += $(srcdir)/../third_party/compiler
VPATH += $(srcdir)/../third_party/murmurhash
# Above should match the relevant targets from angle/Makefile.in.
VPATH += $(srcdir)/../common
# src/common:
DEFFILE = $(srcdir)/libGLESv2.def
RCFILE = $(srcdir)/libGLESv2.rc

Просмотреть файл

@ -100,20 +100,20 @@ Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
#else
int lWidth = 2;
#endif
float opacity = 0.7;
float opacity = 0.7f;
gfx::Color color;
if (aFlags & DIAGNOSTIC_CONTENT) {
color = gfx::Color(0.0, 1.0, 0.0, 1.0); // green
color = gfx::Color(0.0f, 1.0f, 0.0f, 1.0f); // green
if (aFlags & DIAGNOSTIC_COMPONENT_ALPHA) {
color = gfx::Color(0.0, 1.0, 1.0, 1.0); // greenish blue
color = gfx::Color(0.0f, 1.0f, 1.0f, 1.0f); // greenish blue
}
} else if (aFlags & DIAGNOSTIC_IMAGE) {
color = gfx::Color(1.0, 0.0, 0.0, 1.0); // red
color = gfx::Color(1.0f, 0.0f, 0.0f, 1.0f); // red
} else if (aFlags & DIAGNOSTIC_COLOR) {
color = gfx::Color(0.0, 0.0, 1.0, 1.0); // blue
color = gfx::Color(0.0f, 0.0f, 1.0f, 1.0f); // blue
} else if (aFlags & DIAGNOSTIC_CONTAINER) {
color = gfx::Color(0.8, 0.0, 0.8, 1.0); // purple
color = gfx::Color(0.8f, 0.0f, 0.8f, 1.0f); // purple
}
// make tile borders a bit more transparent to keep layer borders readable.
@ -121,10 +121,10 @@ Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
aFlags & DIAGNOSTIC_BIGIMAGE ||
aFlags & DIAGNOSTIC_REGION_RECT) {
lWidth = 1;
opacity = 0.5;
color.r *= 0.7;
color.g *= 0.7;
color.b *= 0.7;
opacity = 0.5f;
color.r *= 0.7f;
color.g *= 0.7f;
color.b *= 0.7f;
}
EffectChain effects;

Просмотреть файл

@ -3,18 +3,6 @@
# 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/.
VPATH = \
$(srcdir) \
$(srcdir)/basic \
$(srcdir)/client \
$(srcdir)/composite \
$(srcdir)/opengl \
$(srcdir)/d3d9 \
$(srcdir)/d3d10 \
$(srcdir)/d3d11 \
$(srcdir)/ipc \
$(NULL)
include $(topsrcdir)/config/rules.mk
CXXFLAGS += \

Просмотреть файл

@ -54,6 +54,11 @@ MacIOSurfaceTextureSourceBasic::GetSurface()
return mSourceSurface;
}
void
MacIOSurfaceTextureSourceBasic::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<BasicCompositor*>(aCompositor);
}
bool
MacIOSurfaceTextureHostBasic::Lock()

Просмотреть файл

@ -38,9 +38,7 @@ public:
virtual void DeallocateDeviceData() MOZ_OVERRIDE { }
void SetCompositor(BasicCompositor* aCompositor) {
mCompositor = aCompositor;
}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
protected:
BasicCompositor* mCompositor;

Просмотреть файл

@ -17,23 +17,16 @@ CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags)
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
#ifdef XP_MACOSX
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
const SurfaceDescriptorMacIOSurface& desc =
aDesc.get_SurfaceDescriptorMacIOSurface();
result = new MacIOSurfaceTextureHostBasic(aFlags, desc);
break;
}
#endif
default: {
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
break;
}
if (aDesc.type() == SurfaceDescriptor::TSurfaceDescriptorMacIOSurface) {
const SurfaceDescriptorMacIOSurface& desc =
aDesc.get_SurfaceDescriptorMacIOSurface();
RefPtr<TextureHost> result = new MacIOSurfaceTextureHostBasic(aFlags, desc);
return result;
}
#endif
return result;
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
}
} // namespace layers

Просмотреть файл

@ -176,7 +176,7 @@ static void DrawVelGraph(const nsIntRect& aClipRect,
float opacity = 1.0;
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0.2,0,0,1));
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0.2f,0,0,1));
compositor->DrawQuad(graphRect,
clipRect,
effects,

Просмотреть файл

@ -428,8 +428,10 @@ CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
srcBox.back = 0;
const IntSize& srcSize = sourceD3D11->GetSize();
if (srcBox.right <= srcSize.width &&
srcBox.bottom <= srcSize.height) {
MOZ_ASSERT(srcSize.width >= 0 && srcSize.height >= 0,
"render targets should have nonnegative sizes");
if (srcBox.right <= static_cast<uint32_t>(srcSize.width) &&
srcBox.bottom <= static_cast<uint32_t>(srcSize.height)) {
mContext->CopySubresourceRegion(texture, 0,
0, 0, 0,
sourceD3D11->GetD3D11Texture(), 0,

Просмотреть файл

@ -32,6 +32,7 @@ SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat)
return DXGI_FORMAT_A8_UNORM;
default:
MOZ_ASSERT(false, "unsupported format");
return DXGI_FORMAT_UNKNOWN;
}
}

Просмотреть файл

@ -235,8 +235,6 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
}
case CompositableOperation::TOpUpdateTexture: {
const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
CompositableHost* compositable = AsCompositable(op);
MOZ_ASSERT(compositable);
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());
MOZ_ASSERT(texture);

Просмотреть файл

@ -303,6 +303,8 @@ IPDL_SOURCES = [
'ipc/PTexture.ipdl',
]
FAIL_ON_WARNINGS = True
MSVC_ENABLE_PGO = True
include('/ipc/chromium/chromium-config.mozbuild')

Просмотреть файл

@ -845,8 +845,6 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
LOCAL_GL_ONE, LOCAL_GL_ONE);
mGLContext->fEnable(LOCAL_GL_BLEND);
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
if (aClipRectOut && !aClipRectIn) {
aClipRectOut->SetRect(0, 0, width, height);
}
@ -1098,6 +1096,8 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
}
IntRect intClipRect;
clipRect.ToIntRect(&intClipRect);
ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);
ScopedScissorRect autoScissor(mGLContext,
intClipRect.x,
FlipY(intClipRect.y + intClipRect.height),

Просмотреть файл

@ -141,12 +141,12 @@ GrallocTextureSourceOGL::gl() const
}
void
GrallocTextureSourceOGL::SetCompositor(CompositorOGL* aCompositor)
GrallocTextureSourceOGL::SetCompositor(Compositor* aCompositor)
{
if (mCompositor && !aCompositor) {
DeallocateDeviceData();
}
mCompositor = aCompositor;
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}

Просмотреть файл

@ -51,7 +51,7 @@ public:
gl::GLContext* gl() const;
void SetCompositor(CompositorOGL* aCompositor);
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
void ForgetBuffer()
{

Просмотреть файл

@ -81,6 +81,12 @@ MacIOSurfaceTextureSourceOGL::BindTexture(GLenum aTextureUnit)
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
}
void
MacIOSurfaceTextureSourceOGL::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
gl::GLContext*
MacIOSurfaceTextureSourceOGL::gl() const
{

Просмотреть файл

@ -44,9 +44,7 @@ public:
// MacIOSurfaceTextureSourceOGL doesn't own any gl texture
virtual void DeallocateDeviceData() {}
void SetCompositor(CompositorOGL* aCompositor) {
mCompositor = aCompositor;
}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
gl::GLContext* gl() const;

Просмотреть файл

@ -355,9 +355,9 @@ SharedTextureSourceOGL::DetachSharedHandle()
}
void
SharedTextureSourceOGL::SetCompositor(CompositorOGL* aCompositor)
SharedTextureSourceOGL::SetCompositor(Compositor* aCompositor)
{
mCompositor = aCompositor;
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool

Просмотреть файл

@ -269,7 +269,7 @@ public:
void DetachSharedHandle();
void SetCompositor(CompositorOGL* aCompositor);
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
gl::GLContext* gl() const;

Просмотреть файл

@ -3,25 +3,6 @@
# 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/.
VPATH += \
$(srcdir)/src/core \
$(srcdir)/src/gpu \
$(srcdir)/src/gpu/effects \
$(srcdir)/src/gpu/gl \
$(srcdir)/src/image \
$(srcdir)/src/images \
$(srcdir)/src/lazy \
$(srcdir)/src/pipe \
$(srcdir)/src/ports \
$(srcdir)/src/opts \
$(srcdir)/src/effects \
$(srcdir)/src/effects/gradients \
$(srcdir)/src/utils \
$(srcdir)/src/utils/android \
$(srcdir)/src/utils/mac \
$(srcdir)/src/sfnt \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gonk))
OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(CAIRO_FT_CFLAGS)
endif

Просмотреть файл

@ -137,18 +137,6 @@ public:
NS_IMPL_ISUPPORTS2(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
NS_IMETHODIMP
SRGBOverrideObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *someData)
{
NS_ASSERTION(NS_strcmp(someData,
MOZ_UTF16("gfx.color_mangement.force_srgb")),
"Restarting CMS on wrong pref!");
ShutdownCMS();
return NS_OK;
}
#define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
#define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
@ -164,10 +152,29 @@ SRGBOverrideObserver::Observe(nsISupports *aSubject,
#define BIDI_NUMERAL_PREF "bidi.numeral"
#define GFX_PREF_CMS_RENDERING_INTENT "gfx.color_management.rendering_intent"
#define GFX_PREF_CMS_DISPLAY_PROFILE "gfx.color_management.display_profile"
#define GFX_PREF_CMS_ENABLED_OBSOLETE "gfx.color_management.enabled"
#define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
#define GFX_PREF_CMS_ENABLEV4 "gfx.color_management.enablev4"
#define GFX_PREF_CMS_MODE "gfx.color_management.mode"
NS_IMETHODIMP
SRGBOverrideObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t* someData)
{
NS_ASSERTION(NS_strcmp(someData,
MOZ_UTF16(GFX_PREF_CMS_FORCE_SRGB)) == 0,
"Restarting CMS on wrong pref!");
ShutdownCMS();
return NS_OK;
}
static const char* kObservedPrefs[] = {
"gfx.downloadable_fonts.",
"gfx.font_rendering.",
"bidi.numeral",
BIDI_NUMERAL_PREF,
nullptr
};
@ -454,7 +461,7 @@ gfxPlatform::Init()
/* Create and register our CMS Override observer. */
gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, "gfx.color_management.force_srgb");
Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
gPlatform->mFontPrefsObserver = new FontPrefsObserver();
Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
@ -524,7 +531,7 @@ gfxPlatform::Shutdown()
if (gPlatform) {
/* Unregister our CMS Override callback. */
NS_ASSERTION(gPlatform->mSRGBOverrideObserver, "mSRGBOverrideObserver has alreay gone");
Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, "gfx.color_management.force_srgb");
Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
gPlatform->mSRGBOverrideObserver = nullptr;
NS_ASSERTION(gPlatform->mFontPrefsObserver, "mFontPrefsObserver has alreay gone");
@ -1627,13 +1634,13 @@ gfxPlatform::GetCMSMode()
nsresult rv;
int32_t mode;
rv = Preferences::GetInt("gfx.color_management.mode", &mode);
rv = Preferences::GetInt(GFX_PREF_CMS_MODE, &mode);
if (NS_SUCCEEDED(rv) && (mode >= 0) && (mode < eCMSMode_AllCount)) {
gCMSMode = static_cast<eCMSMode>(mode);
}
bool enableV4;
rv = Preferences::GetBool("gfx.color_management.enablev4", &enableV4);
rv = Preferences::GetBool(GFX_PREF_CMS_ENABLEV4, &enableV4);
if (NS_SUCCEEDED(rv) && enableV4) {
qcms_enable_iccv4();
}
@ -1648,7 +1655,7 @@ gfxPlatform::GetRenderingIntent()
/* Try to query the pref system for a rendering intent. */
int32_t pIntent;
if (NS_SUCCEEDED(Preferences::GetInt("gfx.color_management.rendering_intent", &pIntent))) {
if (NS_SUCCEEDED(Preferences::GetInt(GFX_PREF_CMS_RENDERING_INTENT, &pIntent))) {
/* If the pref is within range, use it as an override. */
if ((pIntent >= QCMS_INTENT_MIN) && (pIntent <= QCMS_INTENT_MAX)) {
gCMSIntent = pIntent;
@ -1713,12 +1720,12 @@ gfxPlatform::CreateCMSOutputProfile()
default value of this preference, which means nsIPrefBranch::GetBoolPref
will typically throw (and leave its out-param untouched).
*/
if (Preferences::GetBool("gfx.color_management.force_srgb", false)) {
if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB, false)) {
gCMSOutputProfile = GetCMSsRGBProfile();
}
if (!gCMSOutputProfile) {
nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
nsAdoptingCString fname = Preferences::GetCString(GFX_PREF_CMS_DISPLAY_PROFILE);
if (!fname.IsEmpty()) {
gCMSOutputProfile = qcms_profile_from_path(fname);
}
@ -1860,11 +1867,11 @@ static void MigratePrefs()
{
/* Migrate from the boolean color_management.enabled pref - we now use
color_management.mode. */
if (Preferences::HasUserValue("gfx.color_management.enabled")) {
if (Preferences::GetBool("gfx.color_management.enabled", false)) {
Preferences::SetInt("gfx.color_management.mode", static_cast<int32_t>(eCMSMode_All));
if (Preferences::HasUserValue(GFX_PREF_CMS_ENABLED_OBSOLETE)) {
if (Preferences::GetBool(GFX_PREF_CMS_ENABLED_OBSOLETE, false)) {
Preferences::SetInt(GFX_PREF_CMS_MODE, static_cast<int32_t>(eCMSMode_All));
}
Preferences::ClearUser("gfx.color_management.enabled");
Preferences::ClearUser(GFX_PREF_CMS_ENABLED_OBSOLETE);
}
}

Просмотреть файл

@ -1009,7 +1009,7 @@ ShellObjectMetadataCallback(JSContext *cx, JSObject **pmetadata)
int stackIndex = 0;
for (NonBuiltinScriptFrameIter iter(cx); !iter.done(); ++iter) {
if (iter.isFunctionFrame()) {
if (iter.isFunctionFrame() && iter.compartment() == cx->compartment()) {
if (!JS_DefinePropertyById(cx, stack, INT_TO_JSID(stackIndex), ObjectValue(*iter.callee()),
JS_PropertyStub, JS_StrictPropertyStub, 0))
{

Просмотреть файл

@ -220,7 +220,7 @@ function isRootedPointerTypeName(name)
if (name.startsWith('MaybeRooted<'))
return /\(js::AllowGC\)1u>::RootType/.test(name);
return name.startsWith('Rooted');
return name.startsWith('Rooted') || name.startsWith('PersistentRooted');
}
function isSuppressConstructor(name)

Просмотреть файл

@ -0,0 +1,9 @@
setObjectMetadataCallback(true);
var g = newGlobal()
g.eval("function f(a) { return h(); }");
g.h = function () {
return [1, 2, 3];
};
var o = getObjectMetadata(g.f(5));
assertEq(o.stack.length, 1);
assertEq(o.stack[0], g.h);

Просмотреть файл

@ -14,10 +14,12 @@ function f() {
for (var len of [ 3, 30, 300, 3000, 30000 ]) {
var arr = ctor(len);
for (var i = 0; i < arr.length; i++)
assertEq(arr[i], 0);
assertEq(arr[i], 0, "index " + i + " of " + ctor.name + " len " + len);
}
}
}
f();
f();
gc()
f();

Просмотреть файл

@ -0,0 +1,7 @@
// |jit-test| error:TypeError
function f() {
((function g(x) {
g(x.slice)
})([]))
}
new f

Просмотреть файл

@ -6411,11 +6411,11 @@ CodeGenerator::visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic)
bool
CodeGenerator::addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
PropertyName *name, TypedOrValueRegister output,
bool allowGetters)
bool allowGetters, bool monitoredResult)
{
switch (gen->info().executionMode()) {
case SequentialExecution: {
GetPropertyIC cache(liveRegs, objReg, name, output, allowGetters);
GetPropertyIC cache(liveRegs, objReg, name, output, allowGetters, monitoredResult);
return addCache(ins, allocateCache(cache));
}
case ParallelExecution: {
@ -6474,9 +6474,10 @@ CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV *ins)
Register objReg = ToRegister(ins->getOperand(0));
PropertyName *name = ins->mir()->name();
bool allowGetters = ins->mir()->allowGetters();
bool monitoredResult = ins->mir()->monitoredResult();
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
return addGetPropertyCache(ins, liveRegs, objReg, name, output, allowGetters);
return addGetPropertyCache(ins, liveRegs, objReg, name, output, allowGetters, monitoredResult);
}
bool
@ -6486,9 +6487,10 @@ CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT *ins)
Register objReg = ToRegister(ins->getOperand(0));
PropertyName *name = ins->mir()->name();
bool allowGetters = ins->mir()->allowGetters();
bool monitoredResult = ins->mir()->monitoredResult();
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->getDef(0)));
return addGetPropertyCache(ins, liveRegs, objReg, name, output, allowGetters);
return addGetPropertyCache(ins, liveRegs, objReg, name, output, allowGetters, monitoredResult);
}
typedef bool (*GetPropertyICFn)(JSContext *, size_t, HandleObject, MutableHandleValue);

Просмотреть файл

@ -345,7 +345,7 @@ class CodeGenerator : public CodeGeneratorSpecific
private:
bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
PropertyName *name, TypedOrValueRegister output,
bool allowGetters);
bool allowGetters, bool monitoredResult);
bool addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
TypedOrValueRegister output, bool monitoredResult,
bool allowDoubleResult);

Просмотреть файл

@ -4683,7 +4683,8 @@ IonBuilder::createThisScripted(MDefinition *callee)
// and thus invalidation.
MInstruction *getProto;
if (!invalidatedIdempotentCache()) {
MGetPropertyCache *getPropCache = MGetPropertyCache::New(alloc(), callee, names().prototype);
MGetPropertyCache *getPropCache = MGetPropertyCache::New(alloc(), callee, names().prototype,
/* monitored = */ false);
getPropCache->setIdempotent();
getProto = getPropCache;
} else {
@ -8612,8 +8613,19 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
return true;
}
if (accessGetter)
barrier = true;
if (needsToMonitorMissingProperties(types))
barrier = true;
// Caches can read values from prototypes, so update the barrier to
// reflect such possible values.
if (!barrier)
barrier = PropertyReadOnPrototypeNeedsTypeBarrier(constraints(), obj, name, types);
current->pop();
MGetPropertyCache *load = MGetPropertyCache::New(alloc(), obj, name);
MGetPropertyCache *load = MGetPropertyCache::New(alloc(), obj, name, barrier);
// Try to mark the cache as idempotent.
//
@ -8643,17 +8655,6 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
if (load->isEffectful() && !resumeAfter(load))
return false;
if (accessGetter)
barrier = true;
if (needsToMonitorMissingProperties(types))
barrier = true;
// Caches can read values from prototypes, so update the barrier to
// reflect such possible values.
if (!barrier)
barrier = PropertyReadOnPrototypeNeedsTypeBarrier(constraints(), obj, name, types);
MIRType rvalType = MIRTypeFromValueType(types->getKnownTypeTag());
if (barrier || IsNullOrUndefined(rvalType))
rvalType = MIRType_Value;

Просмотреть файл

@ -1749,7 +1749,8 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
#endif
// Monitor changes to cache entry.
types::TypeScript::Monitor(cx, script, pc, vp);
if (!cache.monitoredResult())
types::TypeScript::Monitor(cx, script, pc, vp);
}
return true;
@ -3416,7 +3417,8 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
if (cache.isDisabled()) {
if (!GetObjectElementOperation(cx, JSOp(*pc), obj, /* wasObject = */true, idval, res))
return false;
types::TypeScript::Monitor(cx, script, pc, res);
if (!cache.monitoredResult())
types::TypeScript::Monitor(cx, script, pc, res);
return true;
}
@ -3472,7 +3474,8 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
cache.resetFailedUpdates();
}
types::TypeScript::Monitor(cx, script, pc, res);
if (!cache.monitoredResult())
types::TypeScript::Monitor(cx, script, pc, res);
return true;
}

Просмотреть файл

@ -531,6 +531,7 @@ class GetPropertyIC : public RepatchIonCache
size_t numLocations_;
bool allowGetters_ : 1;
bool monitoredResult_ : 1;
bool hasTypedArrayLengthStub_ : 1;
bool hasStrictArgumentsLengthStub_ : 1;
bool hasNormalArgumentsLengthStub_ : 1;
@ -540,7 +541,7 @@ class GetPropertyIC : public RepatchIonCache
GetPropertyIC(RegisterSet liveRegs,
Register object, PropertyName *name,
TypedOrValueRegister output,
bool allowGetters)
bool allowGetters, bool monitoredResult)
: liveRegs_(liveRegs),
object_(object),
name_(name),
@ -548,6 +549,7 @@ class GetPropertyIC : public RepatchIonCache
locationsIndex_(0),
numLocations_(0),
allowGetters_(allowGetters),
monitoredResult_(monitoredResult),
hasTypedArrayLengthStub_(false),
hasStrictArgumentsLengthStub_(false),
hasNormalArgumentsLengthStub_(false),
@ -571,6 +573,9 @@ class GetPropertyIC : public RepatchIonCache
bool allowGetters() const {
return allowGetters_ && !idempotent();
}
bool monitoredResult() const {
return monitoredResult_;
}
bool hasTypedArrayLengthStub() const {
return hasTypedArrayLengthStub_;
}

Просмотреть файл

@ -587,9 +587,15 @@ LinearScanAllocator::populateSafepoints()
// If the payload is an argument, we'll scan that explicitly as
// part of the frame. It is therefore safe to not add any
// safepoint entry.
if (payloadAlloc->isArgument())
// safepoint entry, as long as the vreg does not have a stack
// slot as canonical spill slot.
if (payloadAlloc->isArgument() &&
(!payload->canonicalSpill() || payload->canonicalSpill() == payloadAlloc))
{
JS_ASSERT(typeAlloc->isArgument());
JS_ASSERT(!type->canonicalSpill() || type->canonicalSpill() == typeAlloc);
continue;
}
if (isSpilledAt(typeInterval, inputOf(ins)) &&
isSpilledAt(payloadInterval, inputOf(ins)))

Просмотреть файл

@ -6572,16 +6572,18 @@ class MGetPropertyCache
CompilerRootPropertyName name_;
bool idempotent_;
bool allowGetters_;
bool monitoredResult_;
CacheLocationList location_;
InlinePropertyTable *inlinePropertyTable_;
MGetPropertyCache(MDefinition *obj, PropertyName *name)
MGetPropertyCache(MDefinition *obj, PropertyName *name, bool monitoredResult)
: MUnaryInstruction(obj),
name_(name),
idempotent_(false),
allowGetters_(false),
monitoredResult_(monitoredResult),
location_(),
inlinePropertyTable_(nullptr)
{
@ -6596,8 +6598,9 @@ class MGetPropertyCache
public:
INSTRUCTION_HEADER(GetPropertyCache)
static MGetPropertyCache *New(TempAllocator &alloc, MDefinition *obj, PropertyName *name) {
return new(alloc) MGetPropertyCache(obj, name);
static MGetPropertyCache *New(TempAllocator &alloc, MDefinition *obj, PropertyName *name,
bool monitoredResult) {
return new(alloc) MGetPropertyCache(obj, name, monitoredResult);
}
InlinePropertyTable *initInlinePropertyTable(TempAllocator &alloc, jsbytecode *pc) {
@ -6630,6 +6633,9 @@ class MGetPropertyCache
bool allowGetters() const {
return allowGetters_;
}
bool monitoredResult() const {
return monitoredResult_;
}
void setAllowGetters() {
allowGetters_ = true;
}

Просмотреть файл

@ -1041,8 +1041,6 @@ CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTyp
// contents of |frozen| though with new speculative types, and these need
// to be reflected in |actual| for AddClearDefiniteFunctionUsesInScript
// to work.
JS_ASSERT(actual->isSubset(frozen));
if (!frozen->isSubset(actual)) {
TypeSet::TypeList list;
frozen->enumerateTypes(&list);
@ -1055,16 +1053,40 @@ CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTyp
void
types::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
{
#ifdef DEBUG
// Assert no new types have been added to the StackTypeSets. Do this before
// calling CheckDefinitePropertiesTypeSet, as it may add new types to the
// StackTypeSets and break these invariants if a script is inlined more
// than once. See also CheckDefinitePropertiesTypeSet.
for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
const CompilerConstraintList::FrozenScript &entry = constraints->frozenScript(i);
JS_ASSERT(entry.script->types);
JSScript *script = entry.script;
JS_ASSERT(script->types);
CheckDefinitePropertiesTypeSet(cx, entry.thisTypes, types::TypeScript::ThisTypes(entry.script));
unsigned nargs = entry.script->function() ? entry.script->function()->nargs() : 0;
for (size_t i = 0; i < nargs; i++)
CheckDefinitePropertiesTypeSet(cx, &entry.argTypes[i], types::TypeScript::ArgTypes(entry.script, i));
for (size_t i = 0; i < entry.script->nTypeSets(); i++)
CheckDefinitePropertiesTypeSet(cx, &entry.bytecodeTypes[i], &entry.script->types->typeArray()[i]);
JS_ASSERT(TypeScript::ThisTypes(script)->isSubset(entry.thisTypes));
unsigned nargs = script->function() ? script->function()->nargs() : 0;
for (size_t j = 0; j < nargs; j++)
JS_ASSERT(TypeScript::ArgTypes(script, j)->isSubset(&entry.argTypes[j]));
for (size_t j = 0; j < script->nTypeSets(); j++)
JS_ASSERT(script->types->typeArray()[j].isSubset(&entry.bytecodeTypes[j]));
}
#endif
for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
const CompilerConstraintList::FrozenScript &entry = constraints->frozenScript(i);
JSScript *script = entry.script;
JS_ASSERT(script->types);
CheckDefinitePropertiesTypeSet(cx, entry.thisTypes, TypeScript::ThisTypes(script));
unsigned nargs = script->function() ? script->function()->nargs() : 0;
for (size_t j = 0; j < nargs; j++)
CheckDefinitePropertiesTypeSet(cx, &entry.argTypes[j], TypeScript::ArgTypes(script, j));
for (size_t j = 0; j < script->nTypeSets(); j++)
CheckDefinitePropertiesTypeSet(cx, &entry.bytecodeTypes[j], &script->types->typeArray()[j]);
}
}

Просмотреть файл

@ -1216,10 +1216,19 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t le
length_ = length;
argumentsNotIncluded_ = argumentsNotIncluded;
// Don't use background compression if there is only one core since this
// will contend with JS execution (which affects benchmarketting). Also,
// since this thread is about to perform a blocking wait, require that there
// are at least 2 worker threads:
// There are several cases where source compression is not a good idea:
// - If the script is enormous, then decompression can take seconds. With
// lazy parsing, decompression is not uncommon, so this can significantly
// increase latency.
// - If there is only one core, then compression will contend with JS
// execution (which hurts benchmarketing).
// - If the source contains a giant string, then parsing will finish much
// faster than compression which increases latency (this case is handled
// in Parser::stringLiteral).
//
// Lastly, since the parsing thread will eventually perform a blocking wait
// on the compresion task's worker thread, require that there are at least 2
// worker threads:
// - If we are on a worker thread, there must be another worker thread to
// execute our compression task.
// - If we are on the main thread, there must be at least two worker
@ -1227,7 +1236,11 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t le
// thread (see WorkerThreadState::canStartParseTask) which would cause a
// deadlock if there wasn't a second worker thread that could make
// progress on our compression task.
if (task && cx->cpuCount() > 1 && cx->workerThreadCount() >= 2) {
const size_t HUGE_SCRIPT = 5 * 1024 * 1024;
if (length < HUGE_SCRIPT &&
cx->cpuCount() > 1 &&
cx->workerThreadCount() >= 2)
{
task->ss = this;
task->chars = src;
ready_ = false;

Просмотреть файл

@ -249,7 +249,7 @@ AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr =
}
bool
ArrayBufferObject::allocateSlots(JSContext *maybecx, uint32_t bytes)
ArrayBufferObject::allocateSlots(JSContext *maybecx, uint32_t bytes, bool clear)
{
/*
* ArrayBufferObjects delegate added properties to another JSObject, so
@ -267,6 +267,8 @@ ArrayBufferObject::allocateSlots(JSContext *maybecx, uint32_t bytes)
elements = header->elements();
} else {
setFixedElements();
if (clear)
memset(dataPointer(), 0, bytes);
}
initElementsHeader(getElementsHeader(), bytes);
@ -631,12 +633,9 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, bool clear /* = true *
* The beginning stores an ObjectElements header structure holding the
* length. The rest of it is a flat data store for the array buffer.
*/
if (!obj->as<ArrayBufferObject>().allocateSlots(cx, nbytes))
if (!obj->as<ArrayBufferObject>().allocateSlots(cx, nbytes, clear))
return nullptr;
if (clear)
memset(obj->as<ArrayBufferObject>().dataPointer(), 0, nbytes);
return obj;
}

Просмотреть файл

@ -165,7 +165,7 @@ class ArrayBufferObject : public JSObject
void addView(ArrayBufferViewObject *view);
bool allocateSlots(JSContext *cx, uint32_t size);
bool allocateSlots(JSContext *cx, uint32_t size, bool clear);
void changeContents(JSContext *cx, ObjectElements *newHeader);

Просмотреть файл

@ -258,15 +258,8 @@ mozJSSubScriptLoader::DoLoadSubScriptWithOptions(const nsAString& url,
if (!targetObj)
return NS_ERROR_FAILURE;
if (targetObj != result_obj) {
nsCOMPtr<nsIScriptSecurityManager> secman =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
if (!secman)
return NS_ERROR_FAILURE;
rv = secman->GetObjectPrincipal(cx, targetObj, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
}
if (targetObj != result_obj)
principal = GetObjectPrincipal(targetObj);
JSAutoCompartment ac(cx, targetObj);

Просмотреть файл

@ -652,14 +652,9 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
return NS_NOINTERFACE;
RootedObject selfObj(ccx, self->GetJSObject());
nsCOMPtr<nsIPrincipal> objPrin;
nsresult rv = secMan->GetObjectPrincipal(ccx, selfObj,
getter_AddRefs(objPrin));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIPrincipal> objPrin = GetObjectPrincipal(selfObj);
bool isSystem;
rv = secMan->IsSystemPrincipal(objPrin, &isSystem);
nsresult rv = secMan->IsSystemPrincipal(objPrin, &isSystem);
if ((NS_FAILED(rv) || !isSystem) && !IS_WN_REFLECTOR(selfObj)) {
// A content object.
nsRefPtr<SameOriginCheckedComponent> checked =

Просмотреть файл

@ -0,0 +1,6 @@
function run_test() {
var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"].getService(
Components.interfaces.nsIScriptSecurityManager);
do_check_true(secMan.isSystemPrincipal(secMan.getObjectPrincipal({})));
}

Просмотреть файл

@ -72,6 +72,7 @@ fail-if = os == "android"
[test_url.js]
[test_sandbox_atob.js]
[test_isProxy.js]
[test_getObjectPrincipal.js]
[test_watchdog_enable.js]
head = head_watchdog.js
[test_watchdog_disable.js]

Просмотреть файл

@ -0,0 +1,27 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
<script>
document.addEventListener("MozReftestInvalidate", doTest, false);
setTimeout(doTest, 4000); // fallback for running outside reftest
function doTest() {
document.getElementById("g").transform.baseVal.getItem(0).setTranslate(20, 20);
document.getElementById("r2").transform.baseVal.getItem(0).setTranslate(70, 70);
document.getElementById("r1").transform.baseVal.getItem(0).setTranslate(180, 180);
document.documentElement.removeAttribute("class");
}
</script>
<rect width="100%" height="100%" fill="lime"/>
<g transform="translate(20 20)">
<rect transform="translate(70 70)" width="40" height="40" fill="red"/>
<rect transform="translate(180 180)" width="40" height="40" fill="red"/>
</g>
<g transform="translate(0 1)" id="g">
<rect transform="translate(49 49)" width="42" height="42" id="r2" fill="lime"/>
<rect transform="translate(89 89)" width="42" height="42" id="r1" fill="lime"/>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

@ -173,6 +173,7 @@ skip-if(B2G) == foreignObject-style-change-01.svg pass.svg
== foreignObject-dynamic-abspos-01.html foreignObject-dynamic-abspos-01-ref.html
fuzzy-if(Android,18,600) == foreignObject-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
== foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
== g-transform-01.svg pass.svg
== getElementById-a-element-01.svg pass.svg
fuzzy-if(Android||B2G,9,980) == gradient-live-01a.svg gradient-live-01-ref.svg
fuzzy-if(Android||B2G,9,980) == gradient-live-01b.svg gradient-live-01-ref.svg

Просмотреть файл

@ -3058,7 +3058,8 @@ class nsDisplaySVGText : public nsDisplayItem {
public:
nsDisplaySVGText(nsDisplayListBuilder* aBuilder,
SVGTextFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
: nsDisplayItem(aBuilder, aFrame),
mDisableSubpixelAA(false)
{
MOZ_COUNT_CTOR(nsDisplaySVGText);
NS_ABORT_IF_FALSE(aFrame, "Must have a frame!");
@ -3071,10 +3072,15 @@ public:
NS_DISPLAY_DECL_NAME("nsDisplaySVGText", TYPE_SVG_TEXT)
virtual void DisableComponentAlpha() MOZ_OVERRIDE {
mDisableSubpixelAA = true;
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
private:
bool mDisableSubpixelAA;
};
void
@ -3097,6 +3103,9 @@ void
nsDisplaySVGText::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
gfxContextAutoDisableSubpixelAntialiasing
disable(aCtx->ThebesContext(), mDisableSubpixelAA);
// ToReferenceFrame includes our mRect offset, but painting takes
// account of that too. To avoid double counting, we subtract that
// here.

Просмотреть файл

@ -426,7 +426,7 @@ stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
c = strchr(munged_ifname, '.');
while (c != NULL) {
*c = '+';
c = strchr(munged_ifname, '+');
c = strchr(munged_ifname, '.');
}
r_log(NR_LOG_STUN, LOG_INFO, "Converted ifname: %s", munged_ifname);

Просмотреть файл

@ -813,3 +813,9 @@ pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
// This pref requires a restart to take effect.
pref("browser.snippets.enabled", false);
#ifdef MOZ_ANDROID_SYNTHAPKS
// The URL of the APK factory from which we obtain APKs for webapps.
// XXX This currently points to jhugman's prototype server.
pref("browser.webapps.apkFactoryUrl", "http://107.22.148.17:8080/application.apk");
#endif

Просмотреть файл

@ -156,6 +156,25 @@
</intent-filter>
</activity>
#ifdef MOZ_ANDROID_SYNTHAPKS
<activity android:name="org.mozilla.gecko.webapp.WebAppDispatcher"
android:noHistory="true" >
<intent-filter>
<!-- catch links from synthetic apks -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/webapp" />
</intent-filter>
</activity>
<receiver android:name="org.mozilla.gecko.webapp.UninstallListener" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
#endif
<activity android:name=".WebApp"
android:label="@string/webapp_generic_name"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
@ -178,7 +197,7 @@
this number in sync with the total number of web apps handled in
WebAppAllocator. -->
#define FRAGMENT WebAppManifestFragment.xml.frag
#define FRAGMENT WebAppManifestFragment.xml.frag.in
#include WebAppFragmentRepeater.inc
<!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->

Просмотреть файл

@ -139,6 +139,13 @@ public class AppConstants {
false;
#endif
public static final boolean MOZ_ANDROID_SYNTHAPKS =
#ifdef MOZ_ANDROID_SYNTHAPKS
true;
#else
false;
#endif
// See this wiki page for more details about channel specific build defines:
// https://wiki.mozilla.org/Platform/Channel-specific_build_defines
public static final boolean RELEASE_BUILD =

Просмотреть файл

@ -28,6 +28,7 @@ import org.mozilla.gecko.util.GeckoEventResponder;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UiAsyncTask;
import org.mozilla.gecko.webapp.UninstallListener;
import org.mozilla.gecko.widget.ButtonToast;
import org.json.JSONArray;
@ -55,6 +56,7 @@ import android.location.LocationListener;
import android.net.wifi.ScanResult;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@ -631,6 +633,25 @@ public abstract class GeckoApp
final String title = message.getString("title");
final String type = message.getString("shortcutType");
GeckoAppShell.removeShortcut(title, url, origin, type);
} else if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("WebApps:InstallApk")) {
GeckoAppShell.installApk(this, message.getString("filePath"), message.getString("data"));
} else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("WebApps:PreInstall")) {
String name = message.getString("name");
String manifestURL = message.getString("manifestURL");
String origin = message.getString("origin");
// preInstallWebapp will return a File object pointing to the profile directory of the webapp
mCurrentResponse = GeckoAppShell.preInstallWebApp(name, manifestURL, origin).toString();
} else if (event.equals("WebApps:PostInstall")) {
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
GeckoAppShell.postInstallWebApp(message.getString("packageName"), message.getString("origin"));
} else {
String name = message.getString("name");
String manifestURL = message.getString("manifestURL");
String iconURL = message.getString("iconURL");
String originalOrigin = message.getString("originalOrigin");
String origin = message.getString("origin");
GeckoAppShell.postInstallWebApp(name, manifestURL, origin, iconURL, originalOrigin);
}
} else if (event.equals("WebApps:Open")) {
String manifestURL = message.getString("manifestURL");
String origin = message.getString("origin");
@ -638,30 +659,8 @@ public abstract class GeckoApp
if (intent == null)
return;
startActivity(intent);
} else if (event.equals("WebApps:Install")) {
String name = message.getString("name");
String manifestURL = message.getString("manifestURL");
String iconURL = message.getString("iconURL");
String origin = message.getString("origin");
// preInstallWebapp will return a File object pointing to the profile directory of the webapp
mCurrentResponse = GeckoAppShell.preInstallWebApp(name, manifestURL, origin).toString();
GeckoAppShell.postInstallWebApp(name, manifestURL, origin, iconURL, origin);
} else if (event.equals("WebApps:PreInstall")) {
String name = message.getString("name");
String manifestURL = message.getString("manifestURL");
String origin = message.getString("origin");
// preInstallWebapp will return a File object pointing to the profile directory of the webapp
mCurrentResponse = GeckoAppShell.preInstallWebApp(name, manifestURL, origin).toString();
} else if (event.equals("WebApps:PostInstall")) {
String name = message.getString("name");
String manifestURL = message.getString("manifestURL");
String iconURL = message.getString("iconURL");
String originalOrigin = message.getString("originalOrigin");
String origin = message.getString("origin");
GeckoAppShell.postInstallWebApp(name, manifestURL, origin, iconURL, originalOrigin);
} else if (event.equals("WebApps:Uninstall")) {
String origin = message.getString("origin");
GeckoAppShell.uninstallWebApp(origin);
} else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("WebApps:Uninstall")) {
GeckoAppShell.uninstallWebApp(message.getString("origin"));
} else if (event.equals("Share:Text")) {
String text = message.getString("text");
GeckoAppShell.openUriExternal(text, "text/plain", "", "", Intent.ACTION_SEND, "");
@ -1342,6 +1341,11 @@ public abstract class GeckoApp
GeckoApp.this.onLocaleReady(uiLocale);
}
});
// Perform webapp uninstalls as appropiate.
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
UninstallListener.initUninstallPackageScan(getApplicationContext());
}
}
});
@ -1558,10 +1562,11 @@ public abstract class GeckoApp
registerEventListener("Accessibility:Event");
registerEventListener("Accessibility:Ready");
registerEventListener("Shortcut:Remove");
registerEventListener("WebApps:Open");
// TODO Consider moving webapp install-related things into InstallHelper.
registerEventListener("WebApps:InstallApk");
registerEventListener("WebApps:PreInstall");
registerEventListener("WebApps:PostInstall");
registerEventListener("WebApps:Install");
registerEventListener("WebApps:Open");
registerEventListener("WebApps:Uninstall");
registerEventListener("Share:Text");
registerEventListener("Share:Image");
@ -1898,6 +1903,9 @@ public abstract class GeckoApp
Tabs.LOADURL_USER_ENTERED |
Tabs.LOADURL_EXTERNAL);
} else if (action != null && action.startsWith(ACTION_WEBAPP_PREFIX)) {
// A lightweight mechanism for loading a web page as a webapp
// without installing the app natively nor registering it in the DOM
// application registry.
String uri = getURIFromIntent(intent);
GeckoAppShell.sendEventToGecko(GeckoEvent.createWebappLoadEvent(uri));
} else if (ACTION_BOOKMARK.equals(action)) {
@ -2085,10 +2093,10 @@ public abstract class GeckoApp
unregisterEventListener("Accessibility:Event");
unregisterEventListener("Accessibility:Ready");
unregisterEventListener("Shortcut:Remove");
unregisterEventListener("WebApps:Open");
unregisterEventListener("WebApps:InstallApk");
unregisterEventListener("WebApps:PreInstall");
unregisterEventListener("WebApps:PostInstall");
unregisterEventListener("WebApps:Install");
unregisterEventListener("WebApps:Open");
unregisterEventListener("WebApps:Uninstall");
unregisterEventListener("Share:Text");
unregisterEventListener("Share:Image");

Просмотреть файл

@ -16,11 +16,16 @@ import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
import org.mozilla.gecko.prompts.PromptService;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.util.ActivityResultHandler;
import org.mozilla.gecko.util.EventDispatcher;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.ProxySelector;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.webapp.InstallListener;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ActivityManager;
@ -28,6 +33,7 @@ import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@ -62,6 +68,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@ -97,6 +104,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URI;
import java.net.URL;
@ -372,6 +380,7 @@ public class GeckoAppShell
});
// and go
Log.d(LOGTAG, "GeckoLoader.nativeRun " + combinedArgs);
GeckoLoader.nativeRun(combinedArgs);
// Remove pumpMessageLoop() idle handler
@ -700,33 +709,61 @@ public class GeckoAppShell
gRestartScheduled = true;
}
// The old implementation of preInstallWebApp. Not used by MOZ_ANDROID_SYNTHAPKS.
public static File preInstallWebApp(String aTitle, String aURI, String aOrigin) {
int index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, (String) null);
GeckoProfile profile = GeckoProfile.get(getContext(), "webapp" + index);
return profile.getDir();
}
// The old implementation of postInstallWebApp. Not used by MOZ_ANDROID_SYNTHAPKS.
public static void postInstallWebApp(String aTitle, String aURI, String aOrigin, String aIconURL, String aOriginalOrigin) {
WebAppAllocator allocator = WebAppAllocator.getInstance(getContext());
int index = allocator.getIndexForApp(aOriginalOrigin);
assert index != -1 && aIconURL != null;
allocator.updateAppAllocation(aOrigin, index, BitmapUtils.getBitmapFromDataURI(aIconURL));
createShortcut(aTitle, aURI, aOrigin, aIconURL, "webapp");
WebAppAllocator allocator = WebAppAllocator.getInstance(getContext());
int index = allocator.getIndexForApp(aOriginalOrigin);
assert index != -1 && aIconURL != null;
allocator.updateAppAllocation(aOrigin, index, BitmapUtils.getBitmapFromDataURI(aIconURL));
createShortcut(aTitle, aURI, aOrigin, aIconURL, "webapp");
}
// The new implementation of postInstallWebApp. Used by MOZ_ANDROID_SYNTHAPKS.
public static void postInstallWebApp(String aPackageName, String aOrigin) {
org.mozilla.gecko.webapp.WebAppAllocator allocator = org.mozilla.gecko.webapp.WebAppAllocator.getInstance(getContext());
int index = allocator.findOrAllocatePackage(aPackageName);
allocator.putOrigin(index, aOrigin);
}
public static Intent getWebAppIntent(String aURI, String aOrigin, String aTitle, Bitmap aIcon) {
int index;
if (aIcon != null && !TextUtils.isEmpty(aTitle))
index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, aIcon);
else
index = WebAppAllocator.getInstance(getContext()).getIndexForApp(aOrigin);
Intent intent;
if (index == -1)
return null;
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
org.mozilla.gecko.webapp.WebAppAllocator slots = org.mozilla.gecko.webapp.WebAppAllocator.getInstance(getContext());
int index = slots.getIndexForOrigin(aOrigin);
return getWebAppIntent(index, aURI);
if (index == -1) {
return null;
}
String packageName = slots.getAppForIndex(index);
intent = getContext().getPackageManager().getLaunchIntentForPackage(packageName);
if (aURI != null) {
intent.setData(Uri.parse(aURI));
}
} else {
int index;
if (aIcon != null && !TextUtils.isEmpty(aTitle))
index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, aIcon);
else
index = WebAppAllocator.getInstance(getContext()).getIndexForApp(aOrigin);
if (index == -1)
return null;
intent = getWebAppIntent(index, aURI);
}
return intent;
}
// The old implementation of getWebAppIntent. Not used by MOZ_ANDROID_SYNTHAPKS.
public static Intent getWebAppIntent(int aIndex, String aURI) {
Intent intent = new Intent();
intent.setAction(GeckoApp.ACTION_WEBAPP_PREFIX + aIndex);
@ -803,7 +840,6 @@ public class GeckoAppShell
// the intent to be launched by the shortcut
Intent shortcutIntent;
if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
int index = WebAppAllocator.getInstance(getContext()).getIndexForApp(aUniqueURI);
shortcutIntent = getWebAppIntent(aURI, aUniqueURI, "", null);
if (shortcutIntent == null)
return;
@ -835,7 +871,12 @@ public class GeckoAppShell
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
int index = WebAppAllocator.getInstance(getContext()).releaseIndexForApp(uniqueURI);
int index;
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
index = org.mozilla.gecko.webapp.WebAppAllocator.getInstance(getContext()).releaseIndexForApp(uniqueURI);
} else {
index = WebAppAllocator.getInstance(getContext()).releaseIndexForApp(uniqueURI);
}
// if -1, nothing to do; we didn't think it was installed anyway
if (index == -1)
@ -2681,4 +2722,55 @@ public class GeckoAppShell
return "DIRECT";
}
public static void installApk(final Activity context, String filePath, String data) {
// This is the data that mozApps.install sent to Webapps.jsm.
JSONObject argsObj = null;
// We get the manifest url out of javascript here so we can use it as a checksum
// in a minute, when a package has been installed.
String manifestUrl = null;
try {
argsObj = new JSONObject(data);
manifestUrl = argsObj.getJSONObject("app").getString("manifestURL");
} catch (JSONException e) {
Log.e(LOGTAG, "can't get manifest URL from JSON data", e);
// TODO: propagate the error back to the mozApps.install caller.
return;
}
// We will check the manifestUrl from the one in the APK.
// Thus, we can have a one-to-one mapping of apk to receiver.
final InstallListener receiver = new InstallListener(manifestUrl, argsObj);
// Listen for packages being installed.
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
context.registerReceiver(receiver, filter);
// Now call the package installer.
File file = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
sActivityHelper.startIntentForActivity(context, intent, new ActivityResultHandler() {
@Override
public void onActivityResult(int resultCode, Intent data) {
// The InstallListener will catch the case where the user pressed install.
// Now deal with if the user pressed cancel.
if (resultCode == Activity.RESULT_CANCELED) {
try {
context.unregisterReceiver(receiver);
receiver.cleanup();
} catch (java.lang.IllegalArgumentException e) {
// IllegalArgumentException happens because resultCode is RESULT_CANCELED
// when the user presses the Done button in the install confirmation dialog,
// even though the install has been successful (and InstallListener already
// unregistered the receiver).
Log.e(LOGTAG, "error unregistering install receiver: ", e);
}
}
}
});
}
}

Просмотреть файл

@ -547,11 +547,16 @@ public final class GeckoProfile {
// If this is the first time its created, we also add a General section
// look for the first profile number that isn't taken yet
int profileNum = 0;
while (parser.getSection("Profile" + profileNum) != null) {
boolean isDefaultSet = false;
INISection profileSection;
while ((profileSection = parser.getSection("Profile" + profileNum)) != null) {
profileNum++;
if (profileSection.getProperty("Default") != null) {
isDefaultSet = true;
}
}
INISection profileSection = new INISection("Profile" + profileNum);
profileSection = new INISection("Profile" + profileNum);
profileSection.setProperty("Name", mName);
profileSection.setProperty("IsRelative", 1);
profileSection.setProperty("Path", saltedName);
@ -560,8 +565,11 @@ public final class GeckoProfile {
INISection generalSection = new INISection("General");
generalSection.setProperty("StartWithLastProfile", 1);
parser.addSection(generalSection);
}
// only set as default if this is the first profile we're creating
if (!isDefaultSet && !mName.startsWith("webapp")) {
// only set as default if this is the first non-webapp
// profile we're creating
profileSection.setProperty("Default", 1);
}

Просмотреть файл

@ -42,6 +42,7 @@ DEFINES += \
GARBAGE += \
AndroidManifest.xml \
WebAppManifestFragment.xml.frag \
classes.dex \
gecko.ap_ \
res/values/strings.xml \
@ -131,6 +132,7 @@ PP_JAVAFILES := $(filter-out $(gecko_package_dir)/R.java,$(gecko-mozglue_PP_JAVA
manifest := \
AndroidManifest.xml.in \
WebAppManifestFragment.xml.frag.in \
$(NULL)
PP_TARGETS += manifest
@ -182,6 +184,7 @@ res/values/strings.xml: FORCE
all_resources = \
$(CURDIR)/AndroidManifest.xml \
$(CURDIR)/WebAppManifestFragment.xml.frag \
$(android_res_files) \
$(ANDROID_GENERATED_RESFILES) \
$(NULL)

Просмотреть файл

@ -6,10 +6,13 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@;
#ifdef MOZ_ANDROID_SYNTHAPKS
import org.mozilla.gecko.webapp.WebAppImpl;
#else
import org.mozilla.gecko.WebAppImpl;
#endif
/**
* This class serves only as a namespace wrapper for WebAppImpl.
*/
public class WebApp extends WebAppImpl {}

Просмотреть файл

@ -10,9 +10,12 @@ import org.mozilla.gecko.util.ThreadUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.util.Log;
import java.util.ArrayList;
public class WebAppAllocator {
private final String LOGTAG = "GeckoWebAppAllocator";
// The number of WebApp# and WEBAPP# activites/apps/intents

Просмотреть файл

@ -2,11 +2,16 @@
android:label="@string/webapp_generic_name"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:windowSoftInputMode="stateUnspecified|adjustResize"
android:process=":@ANDROID_PACKAGE_NAME@.WebApp@APPNUM@"
android:theme="@style/Gecko.App"
#ifdef MOZ_ANDROID_SYNTHAPKS
android:launchMode="singleTop"
android:exported="true"
/>
#else
android:launchMode="singleTask"
android:taskAffinity="org.mozilla.gecko.WEBAPP@APPNUM@"
android:process=":@ANDROID_PACKAGE_NAME@.WebApp@APPNUM@"
android:excludeFromRecents="true"
android:theme="@style/Gecko.App">
android:excludeFromRecents="true">
<intent-filter>
<action android:name="org.mozilla.gecko.WEBAPP@APPNUM@" />
</intent-filter>
@ -14,4 +19,4 @@
<action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
</intent-filter>
</activity>
#endif

Просмотреть файл

@ -13,6 +13,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
@ -294,6 +295,24 @@ public final class BitmapUtils {
return null;
}
public static Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
int width = drawable.getIntrinsicWidth();
width = width > 0 ? width : 1;
int height = drawable.getIntrinsicHeight();
height = height > 0 ? height : 1;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
public static int getResource(Uri resourceUrl, int defaultIcon) {
int icon = defaultIcon;

Просмотреть файл

@ -321,6 +321,13 @@ gbjar.sources += [
'updater/UpdateService.java',
'updater/UpdateServiceHelper.java',
'VideoPlayer.java',
'webapp/ApkResources.java',
'webapp/InstallHelper.java',
'webapp/InstallListener.java',
'webapp/UninstallListener.java',
'webapp/WebAppAllocator.java',
'webapp/WebAppDispatcher.java',
'webapp/WebAppImpl.java',
'WebAppAllocator.java',
'WebAppImpl.java',
'widget/ActivityChooserModel.java',

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше