зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to m-c; a=me
This commit is contained in:
Коммит
0b84a96de6
|
@ -75,7 +75,6 @@ EXPORTS = \
|
|||
nsApplicationAccessibleWrap.h \
|
||||
mozDocAccessible.h \
|
||||
mozAccessible.h \
|
||||
mozAccessibleWrapper.h \
|
||||
mozAccessibleProtocol.h \
|
||||
mozActionElements.h \
|
||||
mozTextAccessible.h \
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Original Author: Håkan Waara <hwaara@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsAccessibleWrap.h"
|
||||
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
#import "mozAccessible.h"
|
||||
|
||||
/* Wrapper class.
|
||||
|
||||
This is needed because C++-only headers such as nsAccessibleWrap.h must not depend
|
||||
on Objective-C and Cocoa. Classes in accessible/src/base depend on them, and other modules in turn
|
||||
depend on them, so in the end all of Mozilla would end up having to link against Cocoa and be renamed .mm :-)
|
||||
|
||||
In order to have a mozAccessible object wrapped, the user passes itself (nsAccessible*) and the subclass of
|
||||
mozAccessible that should be instantiated.
|
||||
|
||||
In the header file, the AccessibleWrapper is used as the member, and is forward-declared (because this header
|
||||
cannot be #included directly.
|
||||
*/
|
||||
|
||||
struct AccessibleWrapper {
|
||||
mozAccessible *object;
|
||||
AccessibleWrapper (nsAccessibleWrap *parent, Class classType) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
object = (mozAccessible*)[[classType alloc] initWithAccessible:parent];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
~AccessibleWrapper () {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
// if some third-party still holds on to the object, it's important that it is marked
|
||||
// as expired, so it can't do any harm (e.g., walk into an expired hierarchy of nodes).
|
||||
[object expire];
|
||||
|
||||
[object release];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
mozAccessible* getNativeObject () {
|
||||
return object;
|
||||
}
|
||||
|
||||
bool isIgnored () {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
return (bool)[object accessibilityIsIgnored];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
|
||||
}
|
||||
};
|
|
@ -55,7 +55,9 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
struct AccessibleWrapper;
|
||||
#if defined(__OBJC__)
|
||||
@class mozAccessible;
|
||||
#endif
|
||||
|
||||
class nsAccessibleWrap : public nsAccessible
|
||||
{
|
||||
|
@ -100,8 +102,14 @@ class nsAccessibleWrap : public nsAccessible
|
|||
*/
|
||||
bool AncestorIsFlat();
|
||||
|
||||
// Wrapper around our native object.
|
||||
AccessibleWrapper *mNativeWrapper;
|
||||
/**
|
||||
* mozAccessible object. If we are in Objective-C, we use the actual Obj-C class.
|
||||
*/
|
||||
#if defined(__OBJC__)
|
||||
mozAccessible* mNativeObject;
|
||||
#else
|
||||
id mNativeObject;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Define unsupported wrap classes here
|
||||
|
|
|
@ -41,46 +41,49 @@
|
|||
|
||||
#import "nsRoleMap.h"
|
||||
|
||||
#import "mozAccessibleWrapper.h"
|
||||
#import "mozAccessible.h"
|
||||
#import "mozActionElements.h"
|
||||
#import "mozTextAccessible.h"
|
||||
|
||||
nsAccessibleWrap::
|
||||
nsAccessibleWrap(nsIContent *aContent, nsIWeakReference *aShell) :
|
||||
nsAccessible(aContent, aShell), mNativeWrapper(nsnull)
|
||||
nsAccessible(aContent, aShell), mNativeObject(nil)
|
||||
{
|
||||
}
|
||||
|
||||
nsAccessibleWrap::~nsAccessibleWrap()
|
||||
{
|
||||
if (mNativeWrapper) {
|
||||
delete mNativeWrapper;
|
||||
mNativeWrapper = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsAccessibleWrap::Init ()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (!nsAccessible::Init())
|
||||
return false;
|
||||
|
||||
if (!mNativeWrapper && !AncestorIsFlat()) {
|
||||
if (!mNativeObject && !AncestorIsFlat()) {
|
||||
// Create our native object using the class type specified in GetNativeType().
|
||||
mNativeWrapper = new AccessibleWrapper (this, GetNativeType());
|
||||
if (!mNativeWrapper)
|
||||
mNativeObject = [[GetNativeType() alloc] initWithAccessible:this];
|
||||
if(!mNativeObject)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibleWrap::GetNativeInterface (void **aOutInterface)
|
||||
{
|
||||
if (mNativeWrapper) {
|
||||
*aOutInterface = (void**)mNativeWrapper->getNativeObject();
|
||||
NS_ENSURE_ARG_POINTER(aOutInterface);
|
||||
|
||||
*aOutInterface = nsnull;
|
||||
|
||||
if (mNativeObject) {
|
||||
*aOutInterface = static_cast<void*>(mNativeObject);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -141,9 +144,10 @@ nsAccessibleWrap::GetNativeType ()
|
|||
void
|
||||
nsAccessibleWrap::Shutdown ()
|
||||
{
|
||||
if (mNativeWrapper) {
|
||||
delete mNativeWrapper;
|
||||
mNativeWrapper = nsnull;
|
||||
if (mNativeObject) {
|
||||
[mNativeObject expire];
|
||||
[mNativeObject release];
|
||||
mNativeObject = nil;
|
||||
}
|
||||
|
||||
nsAccessible::Shutdown();
|
||||
|
@ -201,10 +205,9 @@ nsAccessibleWrap::InvalidateChildren()
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (mNativeWrapper) {
|
||||
mozAccessible *object = mNativeWrapper->getNativeObject();
|
||||
[object invalidateChildren];
|
||||
}
|
||||
if (mNativeObject)
|
||||
[mNativeObject invalidateChildren];
|
||||
|
||||
nsAccessible::InvalidateChildren();
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
|
@ -215,7 +218,11 @@ nsAccessibleWrap::InvalidateChildren()
|
|||
bool
|
||||
nsAccessibleWrap::IsIgnored()
|
||||
{
|
||||
return (mNativeWrapper == nsnull) || mNativeWrapper->isIgnored();
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
return (mNativeObject == nil) || [mNativeObject accessibilityIsIgnored];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include "nsDocAccessibleWrap.h"
|
||||
|
||||
#import "mozAccessibleWrapper.h"
|
||||
#import "mozAccessible.h"
|
||||
|
||||
nsDocAccessibleWrap::
|
||||
nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
|
||||
|
@ -56,12 +56,10 @@ nsDocAccessibleWrap::Init ()
|
|||
if (!nsDocAccessible::Init())
|
||||
return false;
|
||||
|
||||
NS_ASSERTION(!mNativeWrapper, "nsDocAccessibleWrap::Init() called more than once!");
|
||||
|
||||
if (!mNativeWrapper) {
|
||||
if (!mNativeObject) {
|
||||
// Create our native object using the class type specified in GetNativeType().
|
||||
mNativeWrapper = new AccessibleWrapper (this, GetNativeType());
|
||||
if (!mNativeWrapper)
|
||||
mNativeObject = [[GetNativeType() alloc] initWithAccessible:this];
|
||||
if (!mNativeObject)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,6 @@
|
|||
#include "nsIWidget.h"
|
||||
#include "nsIViewManager.h"
|
||||
|
||||
#import "mozAccessibleWrapper.h"
|
||||
|
||||
|
||||
nsRootAccessibleWrap::
|
||||
nsRootAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
|
||||
nsIWeakReference *aShell) :
|
||||
|
|
|
@ -42,7 +42,7 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = chrome locales app
|
||||
DIRS = chrome components locales app
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/testing/testsuite-targets.mk
|
||||
|
|
|
@ -65,11 +65,7 @@ pref("browser.cache.memory.capacity", 1024); // kilobytes
|
|||
pref("image.cache.size", 1048576); // bytes
|
||||
|
||||
/* offline cache prefs */
|
||||
pref("browser.offline-apps.notify", true);
|
||||
pref("browser.cache.offline.enable", true);
|
||||
pref("browser.cache.offline.capacity", 5120); // kilobytes
|
||||
pref("offline-apps.quota.max", 2048); // kilobytes
|
||||
pref("offline-apps.quota.warn", 1024); // kilobytes
|
||||
pref("browser.offline-apps.notify", false);
|
||||
|
||||
/* protocol warning prefs */
|
||||
pref("network.protocol-handler.warn-external.tel", false);
|
||||
|
|
|
@ -68,6 +68,7 @@ function startupHttpd(baseDir, port) {
|
|||
Services.scriptloader.loadSubScript(httpdURL, httpd);
|
||||
let server = new httpd.nsHttpServer();
|
||||
server.registerDirectory('/', new LocalFile(baseDir));
|
||||
server.registerContentType('appcache', 'text/cache-manifest');
|
||||
server.start(port);
|
||||
}
|
||||
|
||||
|
@ -114,6 +115,7 @@ var shell = {
|
|||
|
||||
window.controllers.appendController(this);
|
||||
window.addEventListener('keypress', this);
|
||||
window.addEventListener('MozApplicationManifest', this);
|
||||
this.home.addEventListener('load', this, true);
|
||||
|
||||
try {
|
||||
|
@ -147,6 +149,7 @@ var shell = {
|
|||
stop: function shell_stop() {
|
||||
window.controllers.removeController(this);
|
||||
window.removeEventListener('keypress', this);
|
||||
window.removeEventListener('MozApplicationManifest', this);
|
||||
},
|
||||
|
||||
supportsCommand: function shell_supportsCommand(cmd) {
|
||||
|
@ -195,6 +198,29 @@ var shell = {
|
|||
this.home.removeEventListener('load', this, true);
|
||||
this.sendEvent(window, 'ContentStart');
|
||||
break;
|
||||
case 'MozApplicationManifest':
|
||||
try {
|
||||
let contentWindow = evt.originalTarget.defaultView;
|
||||
let documentElement = contentWindow.document.documentElement;
|
||||
if (!documentElement)
|
||||
return;
|
||||
|
||||
let manifest = documentElement.getAttribute("manifest");
|
||||
if (!manifest)
|
||||
return;
|
||||
|
||||
let documentURI = contentWindow.document.documentURIObject;
|
||||
let manifestURI = Services.io.newURI(manifest, null, documentURI);
|
||||
Services.perms.add(documentURI, 'offline-app',
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
let updateService = Cc['@mozilla.org/offlinecacheupdate-service;1']
|
||||
.getService(Ci.nsIOfflineCacheUpdateService);
|
||||
updateService.scheduleUpdate(manifestURI, documentURI, window);
|
||||
} catch (e) {
|
||||
dump('Error while creating offline cache: ' + e + '\n');
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
sendEvent: function shell_sendEvent(content, type, details) {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# the Mozilla Foundation <http://www.mozilla.org/>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = B2GComponents
|
||||
XPIDL_MODULE = B2GComponents
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
B2GComponents.manifest \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -42,6 +42,7 @@ security/manager/locales/Makefile
|
|||
b2g/app/Makefile
|
||||
$MOZ_BRANDING_DIRECTORY/Makefile
|
||||
b2g/chrome/Makefile
|
||||
b2g/components/Makefile
|
||||
b2g/installer/Makefile
|
||||
b2g/locales/Makefile
|
||||
b2g/Makefile"
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
var tab1, tab2;
|
||||
|
||||
function focus_in_navbar() {
|
||||
function focus_in_navbar()
|
||||
{
|
||||
var parent = document.activeElement.parentNode;
|
||||
while (parent && parent.id != "nav-bar")
|
||||
parent = parent.parentNode;
|
||||
|
||||
return (parent != null);
|
||||
return parent != null;
|
||||
}
|
||||
|
||||
function test() {
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
tab1 = gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
|
@ -20,7 +22,8 @@ function test() {
|
|||
|
||||
function step2()
|
||||
{
|
||||
isnot(document.activeElement, tab1, "mouse on tab not activeElement");
|
||||
is(gBrowser.selectedTab, tab1, "1st click on tab1 selects tab");
|
||||
isnot(document.activeElement, tab1, "1st click on tab1 does not activate tab");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(tab1, {});
|
||||
setTimeout(step3, 0);
|
||||
|
@ -28,18 +31,21 @@ function step2()
|
|||
|
||||
function step3()
|
||||
{
|
||||
isnot(document.activeElement, tab1, "mouse on tab again activeElement");
|
||||
is(gBrowser.selectedTab, tab1, "2nd click on selected tab1 keeps tab selected");
|
||||
isnot(document.activeElement, tab1, "2nd click on selected tab1 does not activate tab");
|
||||
|
||||
if (gNavToolbox.getAttribute("tabsontop") == "true") {
|
||||
ok(true, "[tabsontop=true] focusing URLBar then sending 1 Shift+Tab.");
|
||||
gURLBar.focus();
|
||||
EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
|
||||
} else {
|
||||
ok(true, "[tabsontop=false] focusing SearchBar then sending Tab(s) until out of nav-bar.");
|
||||
document.getElementById("searchbar").focus();
|
||||
|
||||
while (focus_in_navbar())
|
||||
EventUtils.synthesizeKey("VK_TAB", { });
|
||||
}
|
||||
is(document.activeElement, tab1, "tab key to tab activeElement");
|
||||
is(gBrowser.selectedTab, tab1, "tab key to selected tab1 keeps tab selected");
|
||||
is(document.activeElement, tab1, "tab key to selected tab1 activates tab");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(tab1, {});
|
||||
setTimeout(step4, 0);
|
||||
|
@ -47,7 +53,8 @@ function step3()
|
|||
|
||||
function step4()
|
||||
{
|
||||
is(document.activeElement, tab1, "mouse on tab while focused still activeElement");
|
||||
is(gBrowser.selectedTab, tab1, "3rd click on activated tab1 keeps tab selected");
|
||||
is(document.activeElement, tab1, "3rd click on activated tab1 keeps tab activated");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(tab2, {});
|
||||
setTimeout(step5, 0);
|
||||
|
@ -56,9 +63,11 @@ function step4()
|
|||
function step5()
|
||||
{
|
||||
// The tabbox selects a tab within a setTimeout in a bubbling mousedown event
|
||||
// listener, and focuses the current tab if another tab previously had focus
|
||||
is(document.activeElement, tab2, "mouse on another tab while focused still activeElement");
|
||||
// listener, and focuses the current tab if another tab previously had focus.
|
||||
is(gBrowser.selectedTab, tab2, "click on tab2 while tab1 is activated selects tab");
|
||||
is(document.activeElement, tab2, "click on tab2 while tab1 is activated activates tab");
|
||||
|
||||
ok(true, "focusing content then sending middle-button mousedown to tab2.");
|
||||
content.focus();
|
||||
EventUtils.synthesizeMouseAtCenter(tab2, {button: 1, type: "mousedown"});
|
||||
setTimeout(step6, 0);
|
||||
|
@ -66,10 +75,11 @@ function step5()
|
|||
|
||||
function step6()
|
||||
{
|
||||
isnot(document.activeElement, tab2, "tab not focused via middle click");
|
||||
is(gBrowser.selectedTab, tab2, "middle-button mousedown on selected tab2 keeps tab selected");
|
||||
isnot(document.activeElement, tab2, "middle-button mousedown on selected tab2 does not activate tab");
|
||||
|
||||
gBrowser.removeTab(tab1);
|
||||
gBrowser.removeTab(tab2);
|
||||
gBrowser.removeTab(tab1);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -221,7 +221,8 @@ var gEditItemOverlay = {
|
|||
this._allTags = this._getCommonTags();
|
||||
this._initTextField("tagsField", this._allTags.join(", "), false);
|
||||
this._element("itemsCountText").value =
|
||||
PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
|
||||
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
|
||||
this._itemIds.length,
|
||||
[this._itemIds.length]);
|
||||
}
|
||||
|
||||
|
|
|
@ -713,8 +713,8 @@ var PlacesOrganizer = {
|
|||
var itemsCountLabel = document.getElementById("itemsCountText");
|
||||
selectItemDesc.hidden = false;
|
||||
itemsCountLabel.value =
|
||||
PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
|
||||
[aNodeList.length]);
|
||||
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
|
||||
aNodeList.length, [aNodeList.length]);
|
||||
infoBox.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
@ -743,13 +743,9 @@ var PlacesOrganizer = {
|
|||
}
|
||||
else {
|
||||
selectItemDesc.hidden = false;
|
||||
if (rowCount == 1)
|
||||
itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.oneItem");
|
||||
else {
|
||||
itemsCountLabel.value =
|
||||
PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
|
||||
[rowCount]);
|
||||
}
|
||||
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
|
||||
rowCount, [rowCount]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -50,6 +50,9 @@ var Cu = Components.utils;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
return PlacesUtils;
|
||||
|
@ -79,6 +82,31 @@ var PlacesUIUtils = {
|
|||
return bundle.formatStringFromName(key, params, params.length);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a localized plural string for the specified key name and numeric value
|
||||
* substituting parameters.
|
||||
*
|
||||
* @param aKey
|
||||
* String, key for looking up the localized string in the bundle
|
||||
* @param aNumber
|
||||
* Number based on which the final localized form is looked up
|
||||
* @param aParams
|
||||
* Array whose items will substitute #1, #2,... #n parameters
|
||||
* in the string.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en/Localization_and_Plurals
|
||||
* @return The localized plural string.
|
||||
*/
|
||||
getPluralString: function PUIU_getPluralString(aKey, aNumber, aParams) {
|
||||
let str = PluralForm.get(aNumber, bundle.GetStringFromName(aKey));
|
||||
|
||||
// Replace #1 with aParams[0], #2 with aParams[1], and so on.
|
||||
return str.replace(/\#(\d+)/g, function (matchedId, matchedNumber) {
|
||||
let param = aParams[parseInt(matchedNumber, 10) - 1];
|
||||
return param !== undefined ? param : matchedId;
|
||||
});
|
||||
},
|
||||
|
||||
getString: function PUIU_getString(key) {
|
||||
return bundle.GetStringFromName(key);
|
||||
},
|
||||
|
|
|
@ -596,18 +596,6 @@ var gAdvancedPane = {
|
|||
},
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The Extensions checkbox and button are disabled only if the enable Addon
|
||||
* update preference is locked.
|
||||
*/
|
||||
updateAddonUpdateUI: function ()
|
||||
{
|
||||
var enabledPref = document.getElementById("extensions.update.enabled");
|
||||
var enableAddonUpdate = document.getElementById("enableAddonUpdate");
|
||||
|
||||
enableAddonUpdate.disabled = enabledPref.locked;
|
||||
},
|
||||
|
||||
// ENCRYPTION TAB
|
||||
|
||||
/*
|
||||
|
|
|
@ -110,8 +110,6 @@
|
|||
type="bool"/>
|
||||
#endif
|
||||
|
||||
<preference id="extensions.update.enabled" name="extensions.update.enabled" type="bool"
|
||||
onchange="gAdvancedPane.updateAddonUpdateUI();"/>
|
||||
<preference id="browser.search.update" name="browser.search.update" type="bool"/>
|
||||
|
||||
<!-- Encryption tab -->
|
||||
|
@ -330,10 +328,6 @@
|
|||
#endif
|
||||
<groupbox id="updateOthers">
|
||||
<caption label="&updateOthers.label;"/>
|
||||
<checkbox id="enableAddonUpdate"
|
||||
label="&enableAddonsUpdate3.label;"
|
||||
accesskey="&enableAddonsUpdate3.accesskey;"
|
||||
preference="extensions.update.enabled"/>
|
||||
<checkbox id="enableSearchUpdate"
|
||||
label="&enableSearchUpdate.label;"
|
||||
accesskey="&enableSearchUpdate.accesskey;"
|
||||
|
|
|
@ -111,7 +111,6 @@ function inspectorRuleTrap()
|
|||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
ignoreAllUncaughtExceptions();
|
||||
|
||||
tab1 = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab1;
|
||||
|
|
|
@ -222,7 +222,6 @@ function finishInspectorTests(subject, topic, aWinIdString)
|
|||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
ignoreAllUncaughtExceptions();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
|
|
@ -137,7 +137,6 @@ function ruleViewOpened2()
|
|||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
ignoreAllUncaughtExceptions();
|
||||
|
||||
tab1 = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab1;
|
||||
|
|
|
@ -72,6 +72,7 @@ components/sidebar.xpt
|
|||
components/dom_telephony.xpt
|
||||
components/dom_system_b2g.xpt
|
||||
#endif
|
||||
components/uconvd.dll
|
||||
components/WeaveCrypto.js
|
||||
components/WeaveCrypto.manifest
|
||||
components/xmlextras.xpt
|
||||
|
|
|
@ -59,8 +59,11 @@ saveSearch.inputLabel=Name:
|
|||
saveSearch.inputDefaultText=New Search
|
||||
|
||||
detailsPane.noItems=No items
|
||||
detailsPane.oneItem=One item
|
||||
detailsPane.multipleItems=%S items
|
||||
# LOCALIZATION NOTE (detailsPane.itemsCountLabel): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of items
|
||||
# example: 111 items
|
||||
detailsPane.itemsCountLabel=One item;#1 items
|
||||
|
||||
mostVisitedTitle=Most Visited
|
||||
recentlyBookmarkedTitle=Recently Bookmarked
|
||||
|
|
|
@ -76,8 +76,6 @@
|
|||
<!ENTITY useService.accesskey "b">
|
||||
|
||||
<!ENTITY updateOthers.label "Automatically update:">
|
||||
<!ENTITY enableAddonsUpdate3.label "Add-ons">
|
||||
<!ENTITY enableAddonsUpdate3.accesskey "o">
|
||||
<!ENTITY enableSearchUpdate.label "Search Engines">
|
||||
<!ENTITY enableSearchUpdate.accesskey "E">
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ toolbarbutton.bookmark-item[open="true"] {
|
|||
-moz-padding-end: 2px;
|
||||
}
|
||||
|
||||
.bookmark-item > .toolbarbutton-icon {
|
||||
.bookmark-item:not(#bookmarks-menu-button) > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
|
|
@ -478,6 +478,7 @@ MOZ_GRAPHITE_LIBS = @MOZ_GRAPHITE_LIBS@
|
|||
MOZ_GRAPHITE = @MOZ_GRAPHITE@
|
||||
MOZ_OTS_LIBS = @MOZ_OTS_LIBS@
|
||||
MOZ_SKIA_LIBS = @MOZ_SKIA_LIBS@
|
||||
MOZ_ENABLE_SKIA = @MOZ_ENABLE_SKIA@
|
||||
|
||||
MOZ_NATIVE_SQLITE = @MOZ_NATIVE_SQLITE@
|
||||
SQLITE_CFLAGS = @SQLITE_CFLAGS@
|
||||
|
|
|
@ -23,18 +23,18 @@ def main(args):
|
|||
except IndexError:
|
||||
usage()
|
||||
|
||||
paths.append(path)
|
||||
paths.append(os.path.abspath(path))
|
||||
continue
|
||||
|
||||
if arg.startswith('-I'):
|
||||
paths.append(args.pop(0)[2:])
|
||||
paths.append(os.path.abspath(args.pop(0)[2:]))
|
||||
continue
|
||||
|
||||
break
|
||||
|
||||
script = args[0]
|
||||
|
||||
sys.path[0:0] = [os.path.dirname(script)] + paths
|
||||
sys.path[0:0] = [os.path.abspath(os.path.dirname(script))] + paths
|
||||
sys.argv = args
|
||||
sys.argc = len(args)
|
||||
|
||||
|
|
29
configure.in
29
configure.in
|
@ -3977,11 +3977,10 @@ AC_CACHE_CHECK(for modern C++ template specialization syntax support,
|
|||
X<Y> y_x;,
|
||||
ac_cv_cpp_modern_specialize_template_syntax=yes,
|
||||
ac_cv_cpp_modern_specialize_template_syntax=no)])
|
||||
if test "$ac_cv_cpp_modern_specialize_template_syntax" = yes ; then
|
||||
AC_DEFINE(HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX)
|
||||
if test "$ac_cv_cpp_modern_specialize_template_syntax" = no ; then
|
||||
AC_MSG_ERROR([The C++ compiler does not support template specialization])
|
||||
fi
|
||||
|
||||
|
||||
dnl Some compilers support only full specialization, and some don't.
|
||||
AC_CACHE_CHECK(whether partial template specialization works,
|
||||
ac_cv_cpp_partial_specialization,
|
||||
|
@ -8019,6 +8018,21 @@ AC_SUBST(GLIB_CFLAGS)
|
|||
AC_SUBST(GLIB_LIBS)
|
||||
AC_SUBST(GLIB_GMODULE_LIBS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl Graphics checks.
|
||||
dnl ========================================================
|
||||
|
||||
if test "${OS_ARCH}" = "Darwin" -o "${OS_TARGET}" = "Android"; then
|
||||
MOZ_ENABLE_SKIA=1
|
||||
else
|
||||
MOZ_ENABLE_SKIA=
|
||||
fi
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(skia,
|
||||
[ --enable-skia Enable use of Skia],
|
||||
MOZ_ENABLE_SKIA=1,
|
||||
MOZ_ENABLE_SKIA=)
|
||||
|
||||
dnl ========================================================
|
||||
dnl Check for cairo
|
||||
dnl ========================================================
|
||||
|
@ -8199,7 +8213,13 @@ AC_SUBST(MOZ_OTS_LIBS)
|
|||
dnl ========================================================
|
||||
dnl Skia
|
||||
dnl ========================================================
|
||||
MOZ_SKIA_LIBS='$(DEPTH)/gfx/skia/$(LIB_PREFIX)skia.$(LIB_SUFFIX)'
|
||||
if test "$MOZ_ENABLE_SKIA"; then
|
||||
MOZ_SKIA_LIBS='$(DEPTH)/gfx/skia/$(LIB_PREFIX)skia.$(LIB_SUFFIX)'
|
||||
AC_DEFINE(MOZ_ENABLE_SKIA)
|
||||
else
|
||||
MOZ_SKIA_LIBS=
|
||||
fi
|
||||
AC_SUBST(MOZ_ENABLE_SKIA)
|
||||
AC_SUBST(MOZ_SKIA_LIBS)
|
||||
|
||||
dnl ========================================================
|
||||
|
@ -8780,7 +8800,6 @@ HAVE_CPP_2BYTE_WCHAR_T
|
|||
HAVE_CPP_AMBIGUITY_RESOLVING_USING
|
||||
HAVE_CPP_CHAR16_T
|
||||
HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
|
||||
HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
|
||||
HAVE_CPP_PARTIAL_SPECIALIZATION
|
||||
HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
|
||||
HAVE_STATVFS
|
||||
|
|
|
@ -192,7 +192,6 @@ struct nsShortcutCandidate {
|
|||
class nsContentUtils
|
||||
{
|
||||
friend class nsAutoScriptBlockerSuppressNodeRemoved;
|
||||
friend class mozilla::AutoRestore<bool>;
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::TimeDuration TimeDuration;
|
||||
|
||||
|
|
|
@ -756,7 +756,7 @@ struct NormalizeNewlinesCharTraits<CharT*> {
|
|||
|
||||
#else
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct NormalizeNewlinesCharTraits<char*> {
|
||||
public:
|
||||
typedef char value_type;
|
||||
|
@ -771,7 +771,7 @@ struct NormalizeNewlinesCharTraits<char*> {
|
|||
char* mCharPtr;
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct NormalizeNewlinesCharTraits<PRUnichar*> {
|
||||
public:
|
||||
typedef PRUnichar value_type;
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsDefaultComparator <nsNameSpaceEntry, nsIAtom*> {
|
||||
public:
|
||||
bool Equals(const nsNameSpaceEntry& aEntry, nsIAtom* const& aPrefix) const {
|
||||
|
@ -53,7 +53,7 @@ class nsDefaultComparator <nsNameSpaceEntry, nsIAtom*> {
|
|||
}
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsDefaultComparator <nsNameSpaceEntry, PRInt32> {
|
||||
public:
|
||||
bool Equals(const nsNameSpaceEntry& aEntry, const PRInt32& aNameSpace) const {
|
||||
|
|
|
@ -162,7 +162,6 @@ const PRInt32 kBackward = 1;
|
|||
|
||||
//#define DEBUG_charset
|
||||
|
||||
#define NS_USE_NEW_VIEW_SOURCE 1
|
||||
#define NS_USE_NEW_PLAIN_TEXT 1
|
||||
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
|
@ -657,8 +656,7 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
|||
nsCAutoString contentType;
|
||||
aChannel->GetContentType(contentType);
|
||||
|
||||
bool viewSource = aCommand && !nsCRT::strcmp(aCommand, "view-source") &&
|
||||
NS_USE_NEW_VIEW_SOURCE;
|
||||
bool viewSource = aCommand && !nsCRT::strcmp(aCommand, "view-source");
|
||||
bool plainText = (contentType.EqualsLiteral(TEXT_PLAIN) ||
|
||||
contentType.EqualsLiteral(TEXT_CSS) ||
|
||||
contentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
|
||||
|
|
|
@ -72,7 +72,7 @@ static const double NS_PER_S = 1e9;
|
|||
// a full seek.
|
||||
static const int SEEK_DECODE_MARGIN = 250000;
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<NesteggPacketHolder> : public nsPointerRefTraits<NesteggPacketHolder>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -100,12 +100,10 @@ BatteryManager::Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext)
|
|||
|
||||
hal::RegisterBatteryObserver(this);
|
||||
|
||||
hal::BatteryInformation* batteryInfo = new hal::BatteryInformation();
|
||||
hal::GetCurrentBatteryInformation(batteryInfo);
|
||||
hal::BatteryInformation batteryInfo;
|
||||
hal::GetCurrentBatteryInformation(&batteryInfo);
|
||||
|
||||
UpdateFromBatteryInfo(*batteryInfo);
|
||||
|
||||
delete batteryInfo;
|
||||
UpdateFromBatteryInfo(batteryInfo);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -52,10 +52,10 @@ TEST_FILES = \
|
|||
exceptions_in_success_events_iframe.html \
|
||||
helpers.js \
|
||||
leaving_page_iframe.html \
|
||||
test_add_put.html \
|
||||
test_add_twice_failure.html \
|
||||
test_advance.html \
|
||||
test_autoIncrement_indexes.html \
|
||||
test_bad_keypath.html \
|
||||
test_bfcache.html \
|
||||
test_clear.html \
|
||||
test_cmp.html \
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Property Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function testSteps()
|
||||
{
|
||||
const name = window.location.pathname;
|
||||
let openRequest = mozIndexedDB.open(name, 1);
|
||||
openRequest.onerror = errorHandler;
|
||||
openRequest.onupgradeneeded = grabEventAndContinueHandler;
|
||||
openRequest.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
let db = event.target.result;
|
||||
let trans = event.target.transaction;
|
||||
|
||||
for each (let autoincrement in [true, false]) {
|
||||
for each (let keypath in [false, true, "missing", "invalid"]) {
|
||||
for each (let method in ["put", "add"]) {
|
||||
for each (let explicit in [true, false, undefined, "invalid"]) {
|
||||
for each (let existing in [true, false]) {
|
||||
let speccedNoKey = (keypath == false || keypath == "missing") &&
|
||||
!explicit;
|
||||
|
||||
// We can't do 'existing' checks if we use autogenerated key
|
||||
if (speccedNoKey && autoincrement && existing) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create store
|
||||
if (db.objectStoreNames.contains("mystore"))
|
||||
db.deleteObjectStore("mystore");
|
||||
let store = db.createObjectStore("mystore",
|
||||
{ autoIncrement: autoincrement,
|
||||
keyPath: (keypath ? "id" : null) });
|
||||
|
||||
test = " for test " + JSON.stringify({ autoincrement: autoincrement,
|
||||
keypath: keypath,
|
||||
method: method,
|
||||
explicit: explicit === undefined ? "undefined" : explicit,
|
||||
existing: existing });
|
||||
|
||||
// Insert "existing" data if needed
|
||||
if (existing) {
|
||||
if (keypath)
|
||||
store.add({ existing: "data", id: 5 }).onsuccess = grabEventAndContinueHandler;
|
||||
else
|
||||
store.add({ existing: "data" }, 5).onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
let e = yield;
|
||||
is(e.type, "success", "success inserting existing" + test);
|
||||
is(e.target.result, 5, "inserted correct key" + test);
|
||||
}
|
||||
|
||||
// Set up value to be inserted
|
||||
let value = { theObj: true };
|
||||
if (keypath === true) {
|
||||
value.id = 5;
|
||||
}
|
||||
else if (keypath === "invalid") {
|
||||
value.id = /x/;
|
||||
}
|
||||
|
||||
// Which arguments are passed to function
|
||||
args = [value];
|
||||
if (explicit === true) {
|
||||
args.push(5);
|
||||
}
|
||||
else if (explicit === undefined) {
|
||||
args.push(undefined);
|
||||
}
|
||||
else if (explicit === "invalid") {
|
||||
args.push(/x/);
|
||||
}
|
||||
|
||||
let expected = expectedResult(method, keypath, explicit, autoincrement, existing);
|
||||
|
||||
ok(true, "making call" + test);
|
||||
|
||||
// Make function call for throwing functions
|
||||
if (expected === "throw") {
|
||||
try {
|
||||
store[method].apply(store, args);
|
||||
ok(false, "should have thrown" + test);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(true, "did throw" + test);
|
||||
ok(ex instanceof IDBDatabaseException, "Got a IDBDatabaseException" + test);
|
||||
is(ex.code, IDBDatabaseException.DATA_ERR, "expect a DATA_ERR" + test);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make non-throwing function call
|
||||
let req = store[method].apply(store, args);
|
||||
req.onsuccess = req.onerror = grabEventAndContinueHandler
|
||||
let e = yield;
|
||||
|
||||
// Figure out what key we used
|
||||
let key = 5;
|
||||
if (autoincrement && speccedNoKey) {
|
||||
key = 1;
|
||||
}
|
||||
|
||||
// Adjust value if expected
|
||||
if (autoincrement && keypath && speccedNoKey) {
|
||||
value.id = key;
|
||||
}
|
||||
|
||||
// Check result
|
||||
if (expected === "error") {
|
||||
is(e.type, "error", "write should fail" + test);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
continue;
|
||||
}
|
||||
|
||||
is(e.type, "success", "write should succeed" + test);
|
||||
if (autoincrement && speccedNoKey) {
|
||||
todo_is(e.target.result, key, "(fix ai) write should return correct key" + test);
|
||||
key = e.target.result;
|
||||
if (keypath) {
|
||||
value.id = key;
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(e.target.result, key, "write should return correct key" + test);
|
||||
}
|
||||
|
||||
store.get(key).onsuccess = grabEventAndContinueHandler;
|
||||
e = yield;
|
||||
is(e.type, "success", "read back should succeed" + test);
|
||||
is(JSON.stringify(e.target.result),
|
||||
JSON.stringify(value),
|
||||
"read back should return correct value" + test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function expectedResult(method, keypath, explicit, autoincrement, existing) {
|
||||
if (keypath && explicit)
|
||||
return "throw";
|
||||
if (!keypath && !explicit && !autoincrement)
|
||||
return "throw";
|
||||
if (keypath == "invalid")
|
||||
return "throw";
|
||||
if (keypath == "missing" && !autoincrement)
|
||||
return "throw";
|
||||
if (explicit == "invalid")
|
||||
return "throw";
|
||||
|
||||
if (method == "add" && existing)
|
||||
return "error";
|
||||
|
||||
return "success";
|
||||
}
|
||||
|
||||
openRequest.onsuccess = grabEventAndContinueHandler;
|
||||
yield;
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
|
@ -1,49 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Property Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function testSteps()
|
||||
{
|
||||
const name = window.location.pathname;
|
||||
const description = "My Test Database";
|
||||
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = request.result;
|
||||
|
||||
let objectStore = db.createObjectStore("foo", { keyPath: "keyPath" });
|
||||
|
||||
request = objectStore.add({keyPath:"foo"});
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
try {
|
||||
request = objectStore.add({});
|
||||
ok(false, "Shouldn't get here!");
|
||||
}
|
||||
catch (e) {
|
||||
is(e.code, IDBDatabaseException.DATA_ERR, "Good error");
|
||||
}
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
|
@ -2001,19 +2001,6 @@ _releasevariantvalue(NPVariant* variant)
|
|||
VOID_TO_NPVARIANT(*variant);
|
||||
}
|
||||
|
||||
bool NP_CALLBACK
|
||||
_tostring(NPObject* npobj, NPVariant *result)
|
||||
{
|
||||
NS_ERROR("Write me!");
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_tostring called from the wrong thread\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void NP_CALLBACK
|
||||
_setexception(NPObject* npobj, const NPUTF8 *message)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is B2G Audio Manager.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "AudioManager.h"
|
||||
#include <media/AudioSystem.h>
|
||||
|
||||
using namespace mozilla::dom::telephony;
|
||||
using namespace android;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AudioManager, nsIAudioManager)
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetMicrophoneMuted(bool* aMicrophoneMuted)
|
||||
{
|
||||
if (AudioSystem::isMicrophoneMuted(aMicrophoneMuted)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::SetMicrophoneMuted(bool aMicrophoneMuted)
|
||||
{
|
||||
if (AudioSystem::muteMicrophone(aMicrophoneMuted)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetMasterVolume(float* aMasterVolume)
|
||||
{
|
||||
if (AudioSystem::getMasterVolume(aMasterVolume)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::SetMasterVolume(float aMasterVolume)
|
||||
{
|
||||
if (AudioSystem::setMasterVolume(aMasterVolume)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetMasterMuted(bool* aMasterMuted)
|
||||
{
|
||||
if (AudioSystem::getMasterMute(aMasterMuted)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::SetMasterMuted(bool aMasterMuted)
|
||||
{
|
||||
if (AudioSystem::setMasterMute(aMasterMuted)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetPhoneState(PRInt32* aState)
|
||||
{
|
||||
*aState = mPhoneState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::SetPhoneState(PRInt32 aState)
|
||||
{
|
||||
if (AudioSystem::setPhoneState(aState)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::SetForceForUse(PRInt32 aUsage, PRInt32 aForce)
|
||||
{
|
||||
if (AudioSystem::setForceUse((AudioSystem::force_use)aUsage,
|
||||
(AudioSystem::forced_config)aForce)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetForceForUse(PRInt32 aUsage, PRInt32* aForce) {
|
||||
*aForce = AudioSystem::getForceUse((AudioSystem::force_use)aUsage);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is B2G Audio Manager.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_system_b2g_audiomanager_h__
|
||||
#define mozilla_dom_system_b2g_audiomanager_h__
|
||||
|
||||
#include "nsIAudioManager.h"
|
||||
|
||||
|
||||
// {b2b51423-502d-4d77-89b3-7786b562b084}
|
||||
#define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
|
||||
{0x89, 0x10, 0xf9, 0x3c, 0x55, 0xe6, 0x62, 0xec}}
|
||||
#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace telephony {
|
||||
|
||||
class AudioManager : public nsIAudioManager
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAUDIOMANAGER
|
||||
|
||||
AudioManager() : mPhoneState(PHONE_STATE_CURRENT)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
PRInt32 mPhoneState;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace telephony */
|
||||
} /* namespace dom */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif // mozilla_dom_system_b2g_audiomanager_h__
|
|
@ -54,7 +54,14 @@ CPPSRCS = \
|
|||
RadioManager.cpp \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = nsIRadioWorker.idl
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += AudioManager.cpp
|
||||
endif
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIAudioManager.idl \
|
||||
nsIRadioWorker.idl \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is B2G Audio Manager.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(d2124467-7209-4b2e-a91a-cf3f90681e3c)]
|
||||
interface nsIAudioManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Microphone muted?
|
||||
*/
|
||||
attribute boolean microphoneMuted;
|
||||
|
||||
/**
|
||||
* The master volume.
|
||||
*/
|
||||
attribute float masterVolume;
|
||||
|
||||
/**
|
||||
* Master volume muted?
|
||||
*/
|
||||
attribute boolean masterMuted;
|
||||
|
||||
/**
|
||||
* Set the phone's audio mode.
|
||||
*/
|
||||
const long PHONE_STATE_INVALID = -2;
|
||||
const long PHONE_STATE_CURRENT = -1;
|
||||
const long PHONE_STATE_NORMAL = 0;
|
||||
const long PHONE_STATE_RINGTONE = 1;
|
||||
const long PHONE_STATE_IN_CALL = 2;
|
||||
const long PHONE_STATE_IN_COMMUNICATION = 3;
|
||||
|
||||
attribute long phoneState;
|
||||
|
||||
/**
|
||||
* Configure a particular device ("force") to be used for one of the uses
|
||||
* (communication, media playback, etc.)
|
||||
*/
|
||||
const long FORCE_NONE = 0; // the default
|
||||
const long FORCE_SPEAKER = 1;
|
||||
const long FORCE_HEADPHONES = 2;
|
||||
const long FORCE_BT_SCO = 3;
|
||||
const long FORCE_BT_A2DP = 4;
|
||||
const long FORCE_WIRED_ACCESSORY = 5;
|
||||
const long FORCE_BT_CAR_DOCK = 6;
|
||||
const long FORCE_BT_DESK_DOCK = 7;
|
||||
|
||||
const long USE_COMMUNICATION = 0;
|
||||
const long USE_MEDIA = 1;
|
||||
const long USE_RECORD = 2;
|
||||
const long USE_DOCK = 3;
|
||||
|
||||
void setForceForUse(in long usage, in long force);
|
||||
long getForceForUse(in long usage);
|
||||
};
|
|
@ -356,6 +356,20 @@ Telephony.prototype = {
|
|||
return call;
|
||||
},
|
||||
|
||||
get muted() {
|
||||
return this.telephone.microphoneMuted;
|
||||
},
|
||||
set muted(value) {
|
||||
this.telephone.microphoneMuted = value;
|
||||
},
|
||||
|
||||
get speakerOn() {
|
||||
return this.telephone.speakerEnabled;
|
||||
},
|
||||
set speakerOn(value) {
|
||||
this.telephone.speakerEnabled = value;
|
||||
},
|
||||
|
||||
// Additional stuff that's useful.
|
||||
|
||||
signalStrength: null,
|
||||
|
|
|
@ -40,13 +40,16 @@
|
|||
interface nsIDOMEventListener;
|
||||
interface mozIDOMTelephonyCall;
|
||||
|
||||
[scriptable, uuid(24371c72-1631-477d-b26e-f14db369bc22)]
|
||||
[scriptable, uuid(55b23b6e-ef31-4a30-bddb-15ce9274dad8)]
|
||||
interface mozIDOMTelephony : nsIDOMEventTarget {
|
||||
|
||||
readonly attribute jsval liveCalls;
|
||||
mozIDOMTelephonyCall dial(in DOMString number);
|
||||
attribute nsIDOMEventListener onincoming;
|
||||
|
||||
attribute boolean muted;
|
||||
attribute boolean speakerOn;
|
||||
|
||||
//XXX philikon's additions
|
||||
attribute nsIDOMEventListener onoperatorchange;
|
||||
attribute nsIDOMEventListener onradiostatechange;
|
||||
|
|
|
@ -48,7 +48,7 @@ interface nsITelephoneCallback : nsISupports {
|
|||
void onsignalstrengthchange(in jsval event);
|
||||
};
|
||||
|
||||
[scriptable, uuid(3d3deb80-fa5e-4e05-9153-91ee614f67d5)]
|
||||
[scriptable, uuid(f6baa721-665e-403e-8a98-acaa0d8bf267)]
|
||||
interface nsITelephone : nsISupports {
|
||||
|
||||
readonly attribute jsval currentState;
|
||||
|
@ -57,6 +57,8 @@ interface nsITelephone : nsISupports {
|
|||
void hangUp(in long callIndex);
|
||||
void answerCall();
|
||||
void rejectCall();
|
||||
attribute bool microphoneMuted;
|
||||
attribute bool speakerEnabled;
|
||||
|
||||
void registerCallback(in nsITelephoneCallback callback);
|
||||
void unregisterCallback(in nsITelephoneCallback callback);
|
||||
|
|
|
@ -45,7 +45,47 @@ const DEBUG = true; // set to false to suppress debug messages
|
|||
const TELEPHONYWORKER_CONTRACTID = "@mozilla.org/telephony/worker;1";
|
||||
const TELEPHONYWORKER_CID = Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
|
||||
|
||||
const DOM_CALL_READYSTATE_DIALING = "dialing";
|
||||
const DOM_CALL_READYSTATE_RINGING = "ringing";
|
||||
const DOM_CALL_READYSTATE_BUSY = "busy";
|
||||
const DOM_CALL_READYSTATE_CONNECTING = "connecting";
|
||||
const DOM_CALL_READYSTATE_CONNECTED = "connected";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTING = "disconnecting";
|
||||
const DOM_CALL_READYSTATE_DISCONNECTED = "disconnected";
|
||||
const DOM_CALL_READYSTATE_INCOMING = "incoming";
|
||||
const DOM_CALL_READYSTATE_HOLDING = "holding";
|
||||
const DOM_CALL_READYSTATE_HELD = "held";
|
||||
|
||||
|
||||
/**
|
||||
* Fake nsIAudioManager implementation so that we can run the telephony
|
||||
* code in a non-Gonk build.
|
||||
*/
|
||||
let FakeAudioManager = {
|
||||
microphoneMuted: false,
|
||||
masterVolume: 1.0,
|
||||
masterMuted: false,
|
||||
phoneState: Ci.nsIAudioManager.PHONE_STATE_CURRENT,
|
||||
_forceForUse: {},
|
||||
setForceForUse: function setForceForUse(usage, force) {
|
||||
this._forceForUse[usage] = force;
|
||||
},
|
||||
getForceForUse: function setForceForUse(usage) {
|
||||
return this._forceForUse[usage] || Ci.nsIAudioManager.FORCE_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
|
||||
try {
|
||||
return Cc["@mozilla.org/telephony/audiomanager;1"]
|
||||
.getService(Ci.nsIAudioManager);
|
||||
} catch (ex) {
|
||||
//TODO on the phone this should not fall back as silently.
|
||||
debug("Using fake audio manager.");
|
||||
return FakeAudioManager;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function nsTelephonyWorker() {
|
||||
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
|
||||
|
@ -88,12 +128,19 @@ nsTelephonyWorker.prototype = {
|
|||
event.lineno + ": " + event.message + "\n");
|
||||
},
|
||||
|
||||
/**
|
||||
* Process the incoming message from the RIL worker:
|
||||
* (1) Update the current state. This way any component that hasn't
|
||||
* been listening for callbacks can easily catch up by looking at
|
||||
* this.currentState.
|
||||
* (2) Update state in related systems such as the audio.
|
||||
* (3) Multiplex the message to telephone callbacks.
|
||||
*/
|
||||
onmessage: function onmessage(event) {
|
||||
let message = event.data;
|
||||
debug("Received message: " + JSON.stringify(message));
|
||||
let value;
|
||||
switch (message.type) {
|
||||
case "callstatechange":
|
||||
case "signalstrengthchange":
|
||||
this.currentState.signalStrength = message.signalStrength;
|
||||
break;
|
||||
|
@ -107,13 +154,7 @@ nsTelephonyWorker.prototype = {
|
|||
this.currentState.cardState = message.cardState;
|
||||
break;
|
||||
case "callstatechange":
|
||||
// Reuse the message object as the value here since there's more to
|
||||
// the call state than just the callState integer.
|
||||
if (message.callState == DOM_CALL_READYSTATE_DISCONNECTED) {
|
||||
delete this.currentState.callState[message.callIndex];
|
||||
} else {
|
||||
this.currentState.callState[value.callIndex] = message;
|
||||
}
|
||||
this.handleCallState(message);
|
||||
break;
|
||||
default:
|
||||
// Got some message from the RIL worker that we don't know about.
|
||||
|
@ -129,6 +170,52 @@ nsTelephonyWorker.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call state changes by updating our current state and
|
||||
* the audio system.
|
||||
*/
|
||||
handleCallState: function handleCallState(message) {
|
||||
let currentCalls = this.currentState.currentCalls;
|
||||
let oldState = currentCalls[message.callIndex];
|
||||
|
||||
// Update current state.
|
||||
if (message.callState == DOM_CALL_READYSTATE_DISCONNECTED) {
|
||||
delete currentCalls[message.callIndex];
|
||||
} else {
|
||||
currentCalls[message.callIndex] = message;
|
||||
}
|
||||
|
||||
// Update the audio system.
|
||||
//TODO this does not handle multiple concurrent calls yet.
|
||||
switch (message.callState) {
|
||||
case DOM_CALL_READYSTATE_DIALING:
|
||||
this.worker.postMessage({type: "setMute", mute: false});
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
gAudioManager.setForceForUse(Ci.nsIAudioManager.USE_COMMUNICATION,
|
||||
Ci.nsIAudioManager.FORCE_NONE);
|
||||
break;
|
||||
case DOM_CALL_READYSTATE_INCOMING:
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_RINGTONE;
|
||||
break;
|
||||
case DOM_CALL_READYSTATE_CONNECTED:
|
||||
if (!oldState ||
|
||||
oldState.callState == DOM_CALL_READYSTATE_INCOMING ||
|
||||
oldState.callState == DOM_CALL_READYSTATE_CONNECTING) {
|
||||
// It's an incoming call, so tweak the audio now. If it was an
|
||||
// outgoing call, it would have been tweaked at dialing.
|
||||
this.worker.postMessage({type: "setMute", mute: false});
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
gAudioManager.setForceForUse(Ci.nsIAudioManager.USE_COMMUNICATION,
|
||||
Ci.nsIAudioManager.FORCE_NONE);
|
||||
}
|
||||
break;
|
||||
case DOM_CALL_READYSTATE_DISCONNECTED:
|
||||
this.worker.postMessage({type: "setMute", mute: true});
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIRadioWorker
|
||||
|
||||
worker: null,
|
||||
|
@ -155,6 +242,33 @@ nsTelephonyWorker.prototype = {
|
|||
this.worker.postMessage({type: "rejectCall"});
|
||||
},
|
||||
|
||||
get microphoneMuted() {
|
||||
return gAudioManager.microphoneMuted;
|
||||
},
|
||||
set microphoneMuted(value) {
|
||||
if (value == this.microphoneMuted) {
|
||||
return;
|
||||
}
|
||||
gAudioManager.phoneState = value ?
|
||||
Ci.nsIAudioManager.PHONE_STATE_IN_COMMUNICATION :
|
||||
Ci.nsIAudioManager.PHONE_STATE_IN_CALL; //XXX why is this needed?
|
||||
gAudioManager.microphoneMuted = value;
|
||||
},
|
||||
|
||||
get speakerEnabled() {
|
||||
return (gAudioManager.getForceForUse(Ci.nsIAudioManager.USE_COMMUNICATION)
|
||||
== Ci.nsIAudioManager.FORCE_SPEAKER);
|
||||
},
|
||||
set speakerEnabled(value) {
|
||||
if (value == this.speakerEnabled) {
|
||||
return;
|
||||
}
|
||||
gAudioManager.phoneState = Ci.nsIAudioManager.PHONE_STATE_IN_CALL; // XXX why is this needed?
|
||||
let force = value ? Ci.nsIAudioManager.FORCE_SPEAKER :
|
||||
Ci.nsIAudioManager.FORCE_NONE;
|
||||
gAudioManager.setForceUse(Ci.nsIAudioManager.USE_COMMUNICATION, force);
|
||||
},
|
||||
|
||||
_callbacks: null,
|
||||
|
||||
registerCallback: function registerCallback(callback) {
|
||||
|
|
|
@ -637,6 +637,19 @@ let RIL = {
|
|||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Mute or unmute the radio.
|
||||
*
|
||||
* @param mute
|
||||
* Boolean to indicate whether to mute or unmute the radio.
|
||||
*/
|
||||
setMute: function setMute(mute) {
|
||||
Buf.newParcel(REQUEST_SET_MUTE);
|
||||
Buf.writeUint32(1);
|
||||
Buf.writeUint32(mute ? 1 : 0);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Answer an incoming call.
|
||||
*/
|
||||
|
@ -867,7 +880,9 @@ RIL[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION() {
|
|||
Phone.onBasebandVersion(version);
|
||||
},
|
||||
RIL[REQUEST_SEPARATE_CONNECTION] = null;
|
||||
RIL[REQUEST_SET_MUTE] = null;
|
||||
RIL[REQUEST_SET_MUTE] = function REQUEST_SET_MUTE(length) {
|
||||
Phone.onSetMute();
|
||||
};
|
||||
RIL[REQUEST_GET_MUTE] = null;
|
||||
RIL[REQUEST_QUERY_CLIP] = null;
|
||||
RIL[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
|
||||
|
@ -946,12 +961,16 @@ RIL[UNSOLICITED_STK_CALL_SETUP] = null;
|
|||
RIL[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null;
|
||||
RIL[UNSOLICITED_SIM_REFRESH] = null;
|
||||
RIL[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() {
|
||||
let info = {
|
||||
let info;
|
||||
let isCDMA = false; //XXX TODO hard-code this for now
|
||||
if (isCDMA) {
|
||||
info = {
|
||||
isPresent: Buf.readUint32(),
|
||||
signalType: Buf.readUint32(),
|
||||
alertPitch: Buf.readUint32(),
|
||||
signal: Buf.readUint32()
|
||||
};
|
||||
}
|
||||
Phone.onCallRing(info);
|
||||
};
|
||||
RIL[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = null;
|
||||
|
@ -1125,7 +1144,7 @@ let Phone = {
|
|||
callIndex: callIndex,
|
||||
number: currentCall.number,
|
||||
name: currentCall.name});
|
||||
delete this.currentCalls[currentCall];
|
||||
delete this.currentCalls[callIndex];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1164,8 +1183,8 @@ let Phone = {
|
|||
},
|
||||
|
||||
onCallRing: function onCallRing(info) {
|
||||
debug("onCallRing " + JSON.stringify(info)); //DEBUG
|
||||
RIL.getCurrentCalls();
|
||||
// For now we don't need to do anything here because we'll also get a
|
||||
// call state changed notification.
|
||||
},
|
||||
|
||||
onNetworkStateChanged: function onNetworkStateChanged() {
|
||||
|
@ -1248,6 +1267,9 @@ let Phone = {
|
|||
onRejectCall: function onRejectCall() {
|
||||
},
|
||||
|
||||
onSetMute: function onSetMute() {
|
||||
},
|
||||
|
||||
onSendSMS: function onSendSMS(messageRef, ackPDU, errorCode) {
|
||||
//TODO
|
||||
},
|
||||
|
@ -1299,6 +1321,18 @@ let Phone = {
|
|||
RIL.hangUp(options.callIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Mute or unmute the radio.
|
||||
*
|
||||
* @param mute
|
||||
* Boolean to indicate whether to mute or unmute the radio.
|
||||
*/
|
||||
setMute: function setMute(options) {
|
||||
//TODO need to check whether call is holding/waiting/background
|
||||
// and then use REQUEST_HANGUP_WAITING_OR_BACKGROUND
|
||||
RIL.setMute(options.mute);
|
||||
},
|
||||
|
||||
/**
|
||||
* Answer an incoming call.
|
||||
*/
|
||||
|
|
|
@ -75,25 +75,29 @@ CPPSRCS = \
|
|||
|
||||
DEFINES += -DMOZ_GFX -DUSE_CAIRO
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
ifdef MOZ_ENABLE_SKIA
|
||||
CPPSRCS += \
|
||||
SourceSurfaceSkia.cpp \
|
||||
DrawTargetSkia.cpp \
|
||||
PathSkia.cpp \
|
||||
ScaledFontSkia.cpp \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DUSE_SKIA
|
||||
|
||||
endif
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
ifdef MOZ_ENABLE_SKIA
|
||||
CPPSRCS += \
|
||||
ScaledFontMac.cpp \
|
||||
$(NULL)
|
||||
DEFINES += -DUSE_SKIA
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += \
|
||||
SourceSurfaceSkia.cpp \
|
||||
DrawTargetSkia.cpp \
|
||||
ScaledFontSkia.cpp \
|
||||
PathSkia.cpp \
|
||||
$(NULL)
|
||||
DEFINES += -DUSE_SKIA -DSK_BUILD_FOR_ANDROID_NDK
|
||||
DEFINES += -DSK_BUILD_FOR_ANDROID_NDK
|
||||
endif
|
||||
|
||||
DEFINES += -DSK_A32_SHIFT=24 -DSK_R32_SHIFT=16 -DSK_G32_SHIFT=8 -DSK_B32_SHIFT=0
|
||||
|
@ -109,13 +113,14 @@ CPPSRCS += \
|
|||
SourceSurfaceD2DTarget.cpp \
|
||||
PathD2D.cpp \
|
||||
ScaledFontDWrite.cpp \
|
||||
SourceSurfaceSkia.cpp \
|
||||
DrawTargetSkia.cpp \
|
||||
PathSkia.cpp \
|
||||
ScaledFontSkia.cpp \
|
||||
$(NULL)
|
||||
DEFINES += -DWIN32
|
||||
|
||||
ifdef MOZ_ENABLE_SKIA
|
||||
CPPSRCS += \
|
||||
ScaledFontWin.cpp \
|
||||
$(NULL)
|
||||
DEFINES += -DWIN32 -DUSE_SKIA
|
||||
endif
|
||||
endif
|
||||
|
||||
#ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
|
|
|
@ -54,7 +54,7 @@ endif
|
|||
|
||||
DIRS += 2d ycbcr angle src qcms gl layers harfbuzz/src ots/src thebes ipc
|
||||
|
||||
ifeq (,$(filter-out cocoa android windows,$(MOZ_WIDGET_TOOLKIT)))
|
||||
ifdef MOZ_ENABLE_SKIA
|
||||
DIRS += skia
|
||||
endif
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ private:
|
|||
*/
|
||||
class nsMainThreadSurfaceRef;
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<nsMainThreadSurfaceRef> {
|
||||
public:
|
||||
typedef gfxASurface* RawRef;
|
||||
|
|
|
@ -383,12 +383,6 @@ nsRenderingContext::InvertRect(const nsRect& aRect)
|
|||
mThebes->SetOperator(lastOp);
|
||||
}
|
||||
|
||||
void
|
||||
nsRenderingContext::DrawEllipse(const nsRect& aRect)
|
||||
{
|
||||
DrawEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
}
|
||||
|
||||
void
|
||||
nsRenderingContext::DrawEllipse(nscoord aX, nscoord aY,
|
||||
nscoord aWidth, nscoord aHeight)
|
||||
|
|
|
@ -103,7 +103,6 @@ public:
|
|||
void DrawRect(const nsRect& aRect);
|
||||
void DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
|
||||
void DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
|
||||
void DrawEllipse(const nsRect& aRect);
|
||||
|
||||
void FillRect(const nsRect& aRect);
|
||||
void FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
|
||||
{
|
||||
public:
|
||||
|
@ -57,14 +57,14 @@ public:
|
|||
static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<FcFontSet> : public nsPointerRefTraits<FcFontSet>
|
||||
{
|
||||
public:
|
||||
static void Release(FcFontSet *ptr) { FcFontSetDestroy(ptr); }
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<FcCharSet> : public nsPointerRefTraits<FcCharSet>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -135,10 +135,10 @@ public:
|
|||
static void AddRef(T *aPtr) { g_object_ref(aPtr); }
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<PangoFont> : public gfxGObjectRefTraits<PangoFont> { };
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<PangoCoverage>
|
||||
: public nsPointerRefTraits<PangoCoverage> {
|
||||
public:
|
||||
|
|
|
@ -48,14 +48,14 @@
|
|||
* We are specializing nsAutoRef class.
|
||||
*/
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<DBusGProxy> : public nsPointerRefTraits<DBusGProxy>
|
||||
{
|
||||
public:
|
||||
static void Release(DBusGProxy* ptr) { g_object_unref(ptr); }
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
class nsAutoRefTraits<GHashTable> : public nsPointerRefTraits<GHashTable>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -174,8 +174,9 @@ NS_IMETHODIMP nsBMPEncoder::StartImageEncode(PRUint32 aWidth,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Returns the image buffer size
|
||||
NS_IMETHODIMP nsBMPEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
|
||||
// Returns the number of bytes in the image buffer used.
|
||||
// For a BMP file, this is all bytes in the buffer.
|
||||
NS_IMETHODIMP nsBMPEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOutputSize);
|
||||
*aOutputSize = mImageBufferSize;
|
||||
|
|
|
@ -111,9 +111,10 @@ NS_IMETHODIMP nsICOEncoder::InitFromData(const PRUint8* aData,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// Returns the image buffer size
|
||||
// Returns the number of bytes in the image buffer used
|
||||
// For an ICO file, this is all bytes in the buffer.
|
||||
NS_IMETHODIMP
|
||||
nsICOEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
|
||||
nsICOEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOutputSize);
|
||||
*aOutputSize = mImageBufferSize;
|
||||
|
@ -147,16 +148,16 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
|
|||
aStride, aInputFormat, noParams);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 imageBufferSize;
|
||||
mContainedEncoder->GetImageBufferSize(&imageBufferSize);
|
||||
PRUint32 PNGImageBufferSize;
|
||||
mContainedEncoder->GetImageBufferUsed(&PNGImageBufferSize);
|
||||
mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE +
|
||||
imageBufferSize;
|
||||
PNGImageBufferSize;
|
||||
mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
|
||||
if (!mImageBufferStart) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mImageBufferCurr = mImageBufferStart;
|
||||
mICODirEntry.mBytesInRes = imageBufferSize;
|
||||
mICODirEntry.mBytesInRes = PNGImageBufferSize;
|
||||
|
||||
EncodeFileHeader();
|
||||
EncodeInfoHeader();
|
||||
|
@ -164,8 +165,8 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
|
|||
char *imageBuffer;
|
||||
rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
memcpy(mImageBufferCurr, imageBuffer, imageBufferSize);
|
||||
mImageBufferCurr += imageBufferSize;
|
||||
memcpy(mImageBufferCurr, imageBuffer, PNGImageBufferSize);
|
||||
mImageBufferCurr += PNGImageBufferSize;
|
||||
} else {
|
||||
mContainedEncoder = new nsBMPEncoder();
|
||||
nsresult rv;
|
||||
|
@ -181,10 +182,10 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
|
|||
PRUint32 andMaskSize = ((GetRealWidth() + 31) / 32) * 4 * // row AND mask
|
||||
GetRealHeight(); // num rows
|
||||
|
||||
PRUint32 imageBufferSize;
|
||||
mContainedEncoder->GetImageBufferSize(&imageBufferSize);
|
||||
PRUint32 BMPImageBufferSize;
|
||||
mContainedEncoder->GetImageBufferUsed(&BMPImageBufferSize);
|
||||
mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE +
|
||||
imageBufferSize + andMaskSize;
|
||||
BMPImageBufferSize + andMaskSize;
|
||||
mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
|
||||
if (!mImageBufferStart) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -192,7 +193,7 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
|
|||
mImageBufferCurr = mImageBufferStart;
|
||||
|
||||
// The icon buffer does not include the BFH at all.
|
||||
mICODirEntry.mBytesInRes = imageBufferSize - BFH_LENGTH + andMaskSize;
|
||||
mICODirEntry.mBytesInRes = BMPImageBufferSize - BFH_LENGTH + andMaskSize;
|
||||
|
||||
// Encode the icon headers
|
||||
EncodeFileHeader();
|
||||
|
@ -202,13 +203,13 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
|
|||
rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH,
|
||||
imageBufferSize - BFH_LENGTH);
|
||||
BMPImageBufferSize - BFH_LENGTH);
|
||||
// We need to fix the BMP height to be *2 for the AND mask
|
||||
PRUint32 fixedHeight = GetRealHeight() * 2;
|
||||
fixedHeight = NATIVE32_TO_LITTLE(fixedHeight);
|
||||
// The height is stored at an offset of 8 from the DIB header
|
||||
memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight));
|
||||
mImageBufferCurr += imageBufferSize - BFH_LENGTH;
|
||||
mImageBufferCurr += BMPImageBufferSize - BFH_LENGTH;
|
||||
|
||||
// Calculate rowsize in DWORD's
|
||||
PRUint32 rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
|
||||
|
|
|
@ -221,11 +221,11 @@ NS_IMETHODIMP nsJPEGEncoder::StartImageEncode(PRUint32 aWidth,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Returns the image buffer size
|
||||
NS_IMETHODIMP nsJPEGEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
|
||||
// Returns the number of bytes in the image buffer used.
|
||||
NS_IMETHODIMP nsJPEGEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOutputSize);
|
||||
*aOutputSize = mImageBufferSize;
|
||||
*aOutputSize = mImageBufferUsed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -206,11 +206,11 @@ NS_IMETHODIMP nsPNGEncoder::StartImageEncode(PRUint32 aWidth,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Returns the image buffer size
|
||||
NS_IMETHODIMP nsPNGEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
|
||||
// Returns the number of bytes in the image buffer used.
|
||||
NS_IMETHODIMP nsPNGEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOutputSize);
|
||||
*aOutputSize = mImageBufferSize;
|
||||
*aOutputSize = mImageBufferUsed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
/**
|
||||
* imgIEncoder interface
|
||||
*/
|
||||
[scriptable, uuid(d02e2d95-072d-4b91-8b8f-1300e45fcb2b)]
|
||||
[scriptable, uuid(4baa2d6e-fee7-42df-ae3f-5fbebc0c267c)]
|
||||
interface imgIEncoder : nsIAsyncInputStream
|
||||
{
|
||||
// Possible values for outputOptions. Multiple values are semicolon-separated.
|
||||
|
@ -159,8 +159,9 @@ interface imgIEncoder : nsIAsyncInputStream
|
|||
|
||||
/*
|
||||
* Sometimes an encoder can contain another encoder and direct access
|
||||
* to its buffer is necessary.
|
||||
* to its buffer is necessary. It is only safe to assume that the buffer
|
||||
* returned from getImageBuffer() is of size equal to getImageBufferUsed().
|
||||
*/
|
||||
[noscript] unsigned long getImageBufferSize();
|
||||
[noscript] unsigned long getImageBufferUsed();
|
||||
[noscript] charPtr getImageBuffer();
|
||||
};
|
||||
|
|
|
@ -536,26 +536,6 @@ nsresult imgFrame::ImageUpdated(const nsIntRect &aUpdateRect)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32 imgFrame::GetX() const
|
||||
{
|
||||
return mOffset.x;
|
||||
}
|
||||
|
||||
PRInt32 imgFrame::GetY() const
|
||||
{
|
||||
return mOffset.y;
|
||||
}
|
||||
|
||||
PRInt32 imgFrame::GetWidth() const
|
||||
{
|
||||
return mSize.width;
|
||||
}
|
||||
|
||||
PRInt32 imgFrame::GetHeight() const
|
||||
{
|
||||
return mSize.height;
|
||||
}
|
||||
|
||||
nsIntRect imgFrame::GetRect() const
|
||||
{
|
||||
return nsIntRect(mOffset, mSize);
|
||||
|
|
|
@ -72,10 +72,6 @@ public:
|
|||
|
||||
nsresult ImageUpdated(const nsIntRect &aUpdateRect);
|
||||
|
||||
PRInt32 GetX() const;
|
||||
PRInt32 GetY() const;
|
||||
PRInt32 GetWidth() const;
|
||||
PRInt32 GetHeight() const;
|
||||
nsIntRect GetRect() const;
|
||||
gfxASurface::gfxImageFormat GetFormat() const;
|
||||
bool GetNeedsBackground() const;
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
#define LOG(args...) printf(args);
|
||||
#endif
|
||||
|
||||
#define RIL_SOCKET_NAME "/dev/socket/rilproxy"
|
||||
|
||||
using namespace base;
|
||||
using namespace std;
|
||||
|
||||
|
@ -144,10 +146,10 @@ RilClient::OpenSocket()
|
|||
size_t namelen;
|
||||
int err;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
strcpy(addr.sun_path, "/dev/socket/rilb2g");
|
||||
strcpy(addr.sun_path, RIL_SOCKET_NAME);
|
||||
addr.sun_family = AF_LOCAL;
|
||||
mSocket.mFd = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||
alen = strlen("/dev/socket/rilb2g") + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||
alen = strlen(RIL_SOCKET_NAME) + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||
#else
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in addr;
|
||||
|
|
|
@ -87,7 +87,7 @@ template <size_t i> struct CeilingLog2 {
|
|||
|
||||
/* Round up to the nearest power of 2. */
|
||||
template <size_t i> struct RoundUpPow2 {
|
||||
static const size_t result = 1u << CeilingLog2<i>::result;
|
||||
static const size_t result = size_t(1) << CeilingLog2<i>::result;
|
||||
};
|
||||
template <> struct RoundUpPow2<0> {
|
||||
static const size_t result = 1;
|
||||
|
|
|
@ -226,6 +226,7 @@ private:
|
|||
OP_MOV_OvEAX = 0xA3,
|
||||
OP_MOV_EAXIv = 0xB8,
|
||||
OP_GROUP2_EvIb = 0xC1,
|
||||
OP_RET_Iz = 0xC2,
|
||||
OP_RET = 0xC3,
|
||||
OP_GROUP11_EvIb = 0xC6,
|
||||
OP_GROUP11_EvIz = 0xC7,
|
||||
|
@ -2302,6 +2303,15 @@ public:
|
|||
m_formatter.oneByteOp(OP_RET);
|
||||
}
|
||||
|
||||
void ret(int imm)
|
||||
{
|
||||
js::JaegerSpew(js::JSpew_Insns,
|
||||
IPFX "ret %d\n", MAYBE_PAD,
|
||||
imm);
|
||||
m_formatter.oneByteOp(OP_RET_Iz);
|
||||
m_formatter.immediate16(imm);
|
||||
}
|
||||
|
||||
void predictNotTaken()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
|
|
|
@ -23,18 +23,18 @@ def main(args):
|
|||
except IndexError:
|
||||
usage()
|
||||
|
||||
paths.append(path)
|
||||
paths.append(os.path.abspath(path))
|
||||
continue
|
||||
|
||||
if arg.startswith('-I'):
|
||||
paths.append(args.pop(0)[2:])
|
||||
paths.append(os.path.abspath(args.pop(0)[2:]))
|
||||
continue
|
||||
|
||||
break
|
||||
|
||||
script = args[0]
|
||||
|
||||
sys.path[0:0] = [os.path.dirname(script)] + paths
|
||||
sys.path[0:0] = [os.path.abspath(os.path.dirname(script))] + paths
|
||||
sys.argv = args
|
||||
sys.argc = len(args)
|
||||
|
||||
|
|
|
@ -3703,11 +3703,10 @@ AC_CACHE_CHECK(for modern C++ template specialization syntax support,
|
|||
X<Y> y_x;,
|
||||
ac_cv_cpp_modern_specialize_template_syntax=yes,
|
||||
ac_cv_cpp_modern_specialize_template_syntax=no)])
|
||||
if test "$ac_cv_cpp_modern_specialize_template_syntax" = yes ; then
|
||||
AC_DEFINE(HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX)
|
||||
if test "$ac_cv_cpp_modern_specialize_template_syntax" = no ; then
|
||||
AC_MSG_ERROR([The C++ compiler does not support template specialization])
|
||||
fi
|
||||
|
||||
|
||||
dnl Some compilers support only full specialization, and some don't.
|
||||
AC_CACHE_CHECK(whether partial template specialization works,
|
||||
ac_cv_cpp_partial_specialization,
|
||||
|
|
|
@ -2788,7 +2788,8 @@ EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSBool callContex
|
|||
if (op == JSOP_ARGUMENTS || op == JSOP_CALLEE) {
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
return JS_FALSE;
|
||||
if (callContext && Emit1(cx, bce, JSOP_PUSH) < 0)
|
||||
/* Need to provide |this| value for call */
|
||||
if (callContext && Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (!pn->pn_cookie.isFree()) {
|
||||
|
@ -6075,7 +6076,8 @@ EmitReturn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
} else {
|
||||
if (Emit1(cx, bce, JSOP_PUSH) < 0)
|
||||
/* No explicit return value provided */
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6355,9 +6357,9 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
* in jsinterp.cpp for JSOP_LAMBDA followed by JSOP_{SET,INIT}PROP.
|
||||
*
|
||||
* Then (or in a call case that has no explicit reference-base
|
||||
* object) we emit JSOP_PUSH to produce the |this| slot required
|
||||
* for calls (which non-strict mode functions will box into the
|
||||
* global object).
|
||||
* object) we emit JSOP_UNDEFINED to produce the undefined |this|
|
||||
* value required for calls (which non-strict mode functions
|
||||
* will box into the global object).
|
||||
*/
|
||||
ParseNode *pn2 = pn->pn_head;
|
||||
switch (pn2->getKind()) {
|
||||
|
@ -6379,16 +6381,16 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
JS_ASSERT(pn2->isOp(JSOP_XMLNAME));
|
||||
if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, bce))
|
||||
return false;
|
||||
callop = true; /* suppress JSOP_PUSH after */
|
||||
callop = true; /* suppress JSOP_UNDEFINED after */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
callop = false; /* trigger JSOP_PUSH after */
|
||||
callop = false; /* trigger JSOP_UNDEFINED after */
|
||||
break;
|
||||
}
|
||||
if (!callop && Emit1(cx, bce, JSOP_PUSH) < 0)
|
||||
if (!callop && Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
return false;
|
||||
|
||||
/* Remember start of callable-object bytecode for decompilation hint. */
|
||||
|
@ -7027,7 +7029,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (!EmitTree(cx, bce, pn->pn_kid))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (Emit1(cx, bce, JSOP_PUSH) < 0)
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (pn->pn_hidden && NewSrcNote(cx, bce, SRC_HIDDEN) < 0)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
load(libdir + 'eqArrayHelper.js');
|
||||
|
||||
assertEqArray(eval('[]'), []);
|
||||
assertEqArray(eval('[,]'), [,]);
|
||||
assertEqArray(eval('[,,]'), [,,]);
|
||||
assertEqArray(eval('[1, 1, ]'), [1,1, ]);
|
||||
assertEqArray(eval('[1, 1, true]'), [1, 1, true]);
|
||||
assertEqArray(eval('[1, false, true]'), [1, false, true]);
|
|
@ -5,7 +5,7 @@ function build_getter(i) {
|
|||
|
||||
function test()
|
||||
{
|
||||
var N = internalConst("OBJECT_MARK_STACK_LENGTH") + 2;
|
||||
var N = internalConst("MARK_STACK_LENGTH") + 2;
|
||||
var o = {};
|
||||
var descriptor = { enumerable: true};
|
||||
for (var i = 0; i != N; ++i) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
@ -102,8 +102,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj);
|
|||
extern bool
|
||||
js_InitContextBusyArrayTable(JSContext *cx);
|
||||
|
||||
namespace js
|
||||
{
|
||||
namespace js {
|
||||
|
||||
/* Create a dense array with no capacity allocated, length set to 0. */
|
||||
extern JSObject * JS_FASTCALL
|
||||
|
@ -136,7 +135,7 @@ NewDenseCopiedArray(JSContext *cx, uint32 length, const Value *vp, JSObject *pro
|
|||
extern JSObject *
|
||||
NewSlowEmptyArray(JSContext *cx);
|
||||
|
||||
}
|
||||
} /* namespace js */
|
||||
|
||||
extern JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
@ -162,10 +161,7 @@ array_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSB
|
|||
extern bool
|
||||
GetElements(JSContext *cx, JSObject *aobj, jsuint length, js::Value *vp);
|
||||
|
||||
}
|
||||
|
||||
/* Natives exposed for optimization by the interpreter and JITs. */
|
||||
namespace js {
|
||||
|
||||
extern JSBool
|
||||
array_sort(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
@ -213,7 +209,4 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id,
|
|||
JSBool
|
||||
js_Array(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
extern JSBool JS_FASTCALL
|
||||
js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i);
|
||||
|
||||
#endif /* jsarray_h___ */
|
||||
|
|
|
@ -437,12 +437,8 @@ struct JSRuntime
|
|||
/* The reason that an interrupt-triggered GC should be called. */
|
||||
js::gcstats::Reason gcTriggerReason;
|
||||
|
||||
/* Pre-allocated space for the GC mark stacks. Pointer type ensures alignment. */
|
||||
void *gcMarkStackObjs[js::OBJECT_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackTypes[js::TYPE_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
|
||||
/* Pre-allocated space for the GC mark stack. */
|
||||
uintptr_t gcMarkStackArray[js::MARK_STACK_LENGTH];
|
||||
|
||||
/*
|
||||
* Compartment that triggered GC. If more than one Compatment need GC,
|
||||
|
|
|
@ -697,15 +697,6 @@ CreateEvalCallObject(JSContext *cx, StackFrame *fp)
|
|||
|
||||
} // namespace js
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain)
|
||||
{
|
||||
JS_ASSERT(!js_IsNamedLambda(fun));
|
||||
JS_ASSERT(scopeChain);
|
||||
JS_ASSERT(callee);
|
||||
return CallObject::create(cx, fun->script(), *scopeChain, callee);
|
||||
}
|
||||
|
||||
void
|
||||
js_PutCallObject(StackFrame *fp)
|
||||
{
|
||||
|
|
|
@ -312,9 +312,6 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
uintN flags, JSObject *parent, JSAtom *atom,
|
||||
js::gc::AllocKind kind = JSFunction::FinalizeKind);
|
||||
|
||||
extern void
|
||||
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JSFunction * JS_FASTCALL
|
||||
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, JSObject *proto,
|
||||
js::gc::AllocKind kind = JSFunction::FinalizeKind);
|
||||
|
@ -345,16 +342,9 @@ js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
|
|||
extern void
|
||||
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
|
||||
|
||||
extern JSObject * JS_FASTCALL
|
||||
js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain);
|
||||
|
||||
extern void
|
||||
js_PutCallObject(js::StackFrame *fp);
|
||||
|
||||
extern JSBool JS_FASTCALL
|
||||
js_PutCallObjectOnTrace(JSObject *scopeChain, uint32 nargs, js::Value *argv,
|
||||
uint32 nvars, js::Value *slots);
|
||||
|
||||
namespace js {
|
||||
|
||||
CallObject *
|
||||
|
|
|
@ -1735,11 +1735,7 @@ namespace js {
|
|||
GCMarker::GCMarker(JSContext *cx)
|
||||
: color(BLACK),
|
||||
unmarkedArenaStackTop(NULL),
|
||||
objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
|
||||
ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
|
||||
typeStack(cx->runtime->gcMarkStackTypes, sizeof(cx->runtime->gcMarkStackTypes)),
|
||||
xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
|
||||
largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges))
|
||||
stack(cx->runtime->gcMarkStackArray)
|
||||
{
|
||||
JS_TRACER_INIT(this, cx, NULL);
|
||||
markLaterArenas = 0;
|
||||
|
@ -1793,7 +1789,8 @@ MarkDelayedChildren(GCMarker *trc, Arena *a)
|
|||
void
|
||||
GCMarker::markDelayedChildren()
|
||||
{
|
||||
while (unmarkedArenaStackTop) {
|
||||
JS_ASSERT(unmarkedArenaStackTop);
|
||||
do {
|
||||
/*
|
||||
* If marking gets delayed at the same arena again, we must repeat
|
||||
* marking of its things. For that we pop arena from the stack and
|
||||
|
@ -1806,7 +1803,7 @@ GCMarker::markDelayedChildren()
|
|||
a->aheader.hasDelayedMarking = 0;
|
||||
markLaterArenas--;
|
||||
MarkDelayedChildren(this, a);
|
||||
}
|
||||
} while (unmarkedArenaStackTop);
|
||||
JS_ASSERT(!markLaterArenas);
|
||||
}
|
||||
|
||||
|
@ -3497,6 +3494,7 @@ EndVerifyBarriers(JSContext *cx)
|
|||
|
||||
JS_ASSERT(trc->number == rt->gcNumber);
|
||||
|
||||
if (rt->gcIncrementalTracer->hasDelayedChildren())
|
||||
rt->gcIncrementalTracer->markDelayedChildren();
|
||||
|
||||
rt->gcVerifyData = NULL;
|
||||
|
|
124
js/src/jsgc.h
124
js/src/jsgc.h
|
@ -63,6 +63,7 @@
|
|||
#include "gc/Statistics.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/Vector.h"
|
||||
#include "js/TemplateLib.h"
|
||||
|
||||
struct JSCompartment;
|
||||
|
||||
|
@ -1593,50 +1594,68 @@ struct ConservativeGCThreadData {
|
|||
template<class T>
|
||||
struct MarkStack {
|
||||
T *stack;
|
||||
uintN tos, limit;
|
||||
T *tos;
|
||||
T *limit;
|
||||
|
||||
bool push(T item) {
|
||||
if (tos == limit)
|
||||
return false;
|
||||
stack[tos++] = item;
|
||||
*tos++ = item;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isEmpty() { return tos == 0; }
|
||||
bool push(T item1, T item2) {
|
||||
T *nextTos = tos + 2;
|
||||
if (nextTos > limit)
|
||||
return false;
|
||||
tos[0] = item1;
|
||||
tos[1] = item2;
|
||||
tos = nextTos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return tos == stack;
|
||||
}
|
||||
|
||||
T pop() {
|
||||
JS_ASSERT(!isEmpty());
|
||||
return stack[--tos];
|
||||
return *--tos;
|
||||
}
|
||||
|
||||
T &peek() {
|
||||
JS_ASSERT(!isEmpty());
|
||||
return stack[tos-1];
|
||||
}
|
||||
|
||||
MarkStack(void **buffer, size_t size)
|
||||
{
|
||||
tos = 0;
|
||||
limit = size / sizeof(T) - 1;
|
||||
stack = (T *)buffer;
|
||||
}
|
||||
template<size_t N>
|
||||
MarkStack(T (&buffer)[N])
|
||||
: stack(buffer),
|
||||
tos(buffer),
|
||||
limit(buffer + N) { }
|
||||
};
|
||||
|
||||
struct LargeMarkItem
|
||||
{
|
||||
JSObject *obj;
|
||||
uintN markpos;
|
||||
|
||||
LargeMarkItem(JSObject *obj) : obj(obj), markpos(0) {}
|
||||
};
|
||||
|
||||
static const size_t OBJECT_MARK_STACK_SIZE = 32768 * sizeof(JSObject *);
|
||||
static const size_t ROPES_MARK_STACK_SIZE = 1024 * sizeof(JSString *);
|
||||
static const size_t XML_MARK_STACK_SIZE = 1024 * sizeof(JSXML *);
|
||||
static const size_t TYPE_MARK_STACK_SIZE = 1024 * sizeof(types::TypeObject *);
|
||||
static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
|
||||
static const size_t MARK_STACK_LENGTH = 32768;
|
||||
|
||||
struct GCMarker : public JSTracer {
|
||||
/*
|
||||
* We use a common mark stack to mark GC things of different types and use
|
||||
* the explicit tags to distinguish them when it cannot be deduced from
|
||||
* the context of push or pop operation.
|
||||
*
|
||||
* Currently we need only 4 tags. However that can be extended to 8 if
|
||||
* necessary. We tag either pointers to GC things or pointers to Value
|
||||
* arrays. So the pointers are always at least 8-byte aligned.
|
||||
*/
|
||||
enum StackTag {
|
||||
ValueArrayTag,
|
||||
ObjectTag,
|
||||
TypeTag,
|
||||
XmlTag,
|
||||
LastTag = XmlTag
|
||||
};
|
||||
|
||||
static const uintptr_t StackTagMask = 3;
|
||||
|
||||
static void staticAsserts() {
|
||||
JS_STATIC_ASSERT(StackTagMask >= uintptr_t(LastTag));
|
||||
}
|
||||
|
||||
private:
|
||||
/* The color is only applied to objects, functions and xml. */
|
||||
uint32 color;
|
||||
|
@ -1654,11 +1673,7 @@ struct GCMarker : public JSTracer {
|
|||
void dumpConservativeRoots();
|
||||
#endif
|
||||
|
||||
MarkStack<JSObject *> objStack;
|
||||
MarkStack<JSRope *> ropeStack;
|
||||
MarkStack<types::TypeObject *> typeStack;
|
||||
MarkStack<JSXML *> xmlStack;
|
||||
MarkStack<LargeMarkItem> largeStack;
|
||||
MarkStack<uintptr_t> stack;
|
||||
|
||||
public:
|
||||
explicit GCMarker(JSContext *cx);
|
||||
|
@ -1683,36 +1698,47 @@ struct GCMarker : public JSTracer {
|
|||
|
||||
void delayMarkingChildren(const void *thing);
|
||||
|
||||
bool hasDelayedChildren() const {
|
||||
return !!unmarkedArenaStackTop;
|
||||
}
|
||||
|
||||
void markDelayedChildren();
|
||||
|
||||
bool isMarkStackEmpty() {
|
||||
return objStack.isEmpty() &&
|
||||
ropeStack.isEmpty() &&
|
||||
typeStack.isEmpty() &&
|
||||
xmlStack.isEmpty() &&
|
||||
largeStack.isEmpty();
|
||||
return stack.isEmpty();
|
||||
}
|
||||
|
||||
void drainMarkStack();
|
||||
|
||||
void pushObject(JSObject *obj) {
|
||||
if (!objStack.push(obj))
|
||||
delayMarkingChildren(obj);
|
||||
}
|
||||
inline void processMarkStackTop();
|
||||
|
||||
void pushRope(JSRope *rope) {
|
||||
if (!ropeStack.push(rope))
|
||||
delayMarkingChildren(rope);
|
||||
void pushObject(JSObject *obj) {
|
||||
pushTaggedPtr(ObjectTag, obj);
|
||||
}
|
||||
|
||||
void pushType(types::TypeObject *type) {
|
||||
if (!typeStack.push(type))
|
||||
delayMarkingChildren(type);
|
||||
pushTaggedPtr(TypeTag, type);
|
||||
}
|
||||
|
||||
void pushXML(JSXML *xml) {
|
||||
if (!xmlStack.push(xml))
|
||||
delayMarkingChildren(xml);
|
||||
pushTaggedPtr(XmlTag, xml);
|
||||
}
|
||||
|
||||
void pushTaggedPtr(StackTag tag, void *ptr) {
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
|
||||
JS_ASSERT(!(addr & StackTagMask));
|
||||
if (!stack.push(addr | uintptr_t(tag)))
|
||||
delayMarkingChildren(ptr);
|
||||
}
|
||||
|
||||
bool pushValueArray(void *start, void *end) {
|
||||
JS_STATIC_ASSERT(ValueArrayTag == 0);
|
||||
JS_ASSERT(start < end);
|
||||
uintptr_t startAddr = reinterpret_cast<uintptr_t>(start);
|
||||
uintptr_t endAddr = reinterpret_cast<uintptr_t>(end);
|
||||
JS_ASSERT(!(startAddr & StackTagMask));
|
||||
JS_ASSERT(!(endAddr & StackTagMask));
|
||||
return stack.push(endAddr, startAddr);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -280,6 +280,9 @@ MarkXML(JSTracer *trc, const MarkablePtr<JSXML> &xml, const char *name)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define JS_SAME_COMPARTMENT_ASSERT(thing1, thing2) \
|
||||
JS_ASSERT((thing1)->compartment() == (thing2)->compartment())
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
JS_ASSERT_IF((rt)->gcCurrentCompartment, \
|
||||
(thing)->compartment() == (rt)->gcCurrentCompartment);
|
||||
|
@ -352,14 +355,13 @@ PushMarkStack(GCMarker *gcmarker, const Shape *thing)
|
|||
ScanShape(gcmarker, thing);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
ScanBaseShape(GCMarker *gcmarker, BaseShape *base);
|
||||
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
|
||||
{
|
||||
JS_OPT_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment,
|
||||
thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment);
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
|
||||
/* We mark base shapes directly rather than pushing on the stack. */
|
||||
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||
|
@ -665,24 +667,10 @@ MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
|
|||
MarkIdRangeUnbarriered(trc, len, vec, name);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanValue(GCMarker *gcmarker, const Value &v)
|
||||
{
|
||||
if (v.isMarkable()) {
|
||||
JSGCTraceKind kind = v.gcKind();
|
||||
if (kind == JSTRACE_STRING) {
|
||||
PushMarkStack(gcmarker, v.toString());
|
||||
} else {
|
||||
JS_ASSERT(kind == JSTRACE_OBJECT);
|
||||
PushMarkStack(gcmarker, &v.toObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ScanShape(GCMarker *gcmarker, const Shape *shape)
|
||||
{
|
||||
restart:
|
||||
restart:
|
||||
PushMarkStack(gcmarker, shape->base());
|
||||
|
||||
jsid id = shape->maybePropid();
|
||||
|
@ -696,20 +684,33 @@ restart:
|
|||
goto restart;
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
|
||||
{
|
||||
for (;;) {
|
||||
if (base->hasGetterObject())
|
||||
PushMarkStack(gcmarker, base->getterObject());
|
||||
|
||||
if (base->hasSetterObject())
|
||||
PushMarkStack(gcmarker, base->setterObject());
|
||||
|
||||
if (base->isOwned())
|
||||
PushMarkStack(gcmarker, base->baseUnowned());
|
||||
|
||||
if (JSObject *parent = base->getObjectParent())
|
||||
PushMarkStack(gcmarker, parent);
|
||||
|
||||
if (base->isOwned()) {
|
||||
/*
|
||||
* Make sure that ScanBaseShape is not recursive so its inlining
|
||||
* is possible.
|
||||
*/
|
||||
UnownedBaseShape *unowned = base->baseUnowned();
|
||||
JS_SAME_COMPARTMENT_ASSERT(base, unowned);
|
||||
if (unowned->markIfUnmarked(gcmarker->getMarkColor())) {
|
||||
base = unowned;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -732,11 +733,22 @@ ScanLinearString(GCMarker *gcmarker, JSLinearString *str)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The function tries to scan the whole rope tree using the marking stack as
|
||||
* temporary storage. If that becomes full, the unscanned ropes are added to
|
||||
* the delayed marking list. When the function returns, the marking stack is
|
||||
* at the same depth as it was on entry. This way we avoid using tags when
|
||||
* pushing ropes to the stack as ropes never leaks to other users of the
|
||||
* stack. This also assumes that a rope can only point to other ropes or
|
||||
* linear strings, it cannot refer to GC things of other types.
|
||||
*/
|
||||
static void
|
||||
ScanRope(GCMarker *gcmarker, JSRope *rope)
|
||||
{
|
||||
uintptr_t *savedTos = gcmarker->stack.tos;
|
||||
for (;;) {
|
||||
JS_ASSERT(GetGCThingTraceKind(rope) == JSTRACE_STRING);
|
||||
JS_ASSERT(rope->JSString::isRope());
|
||||
do {
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, rope);
|
||||
JS_ASSERT(rope->isMarked());
|
||||
JSRope *next = NULL;
|
||||
|
@ -755,16 +767,33 @@ ScanRope(GCMarker *gcmarker, JSRope *rope)
|
|||
ScanLinearString(gcmarker, &left->asLinear());
|
||||
} else {
|
||||
/*
|
||||
* Both children are ropes, set aside the right one to scan
|
||||
* it later.
|
||||
* When both children are ropes, set aside the right one to
|
||||
* scan it later.
|
||||
*/
|
||||
if (next)
|
||||
gcmarker->pushRope(next);
|
||||
if (next && !gcmarker->stack.push(reinterpret_cast<uintptr_t>(next)))
|
||||
gcmarker->delayMarkingChildren(next);
|
||||
next = &left->asRope();
|
||||
}
|
||||
}
|
||||
if (next) {
|
||||
rope = next;
|
||||
} while (rope);
|
||||
} else if (savedTos != gcmarker->stack.tos) {
|
||||
JS_ASSERT(savedTos < gcmarker->stack.tos);
|
||||
rope = reinterpret_cast<JSRope *>(gcmarker->stack.pop());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(savedTos == gcmarker->stack.tos);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanString(GCMarker *gcmarker, JSString *str)
|
||||
{
|
||||
if (str->isLinear())
|
||||
ScanLinearString(gcmarker, &str->asLinear());
|
||||
else
|
||||
ScanRope(gcmarker, &str->asRope());
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -773,21 +802,48 @@ PushMarkStack(GCMarker *gcmarker, JSString *str)
|
|||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, str);
|
||||
|
||||
/*
|
||||
* We scan the string directly rather than pushing on the stack except
|
||||
* when we have a rope and both its children are also ropes.
|
||||
* As string can only refer to other strings we fully scan its GC graph
|
||||
* using the explicit stack when navigating the rope tree to avoid
|
||||
* dealing with strings on the stack in drainMarkStack.
|
||||
*/
|
||||
if (str->markIfUnmarked()) {
|
||||
if (str->isLinear())
|
||||
ScanLinearString(gcmarker, &str->asLinear());
|
||||
else
|
||||
ScanRope(gcmarker, &str->asRope());
|
||||
if (str->markIfUnmarked())
|
||||
ScanString(gcmarker, str);
|
||||
}
|
||||
|
||||
static JS_NEVER_INLINE void
|
||||
DelayMarkingValueArray(GCMarker *gcmarker, HeapValue *begin, HeapValue *end)
|
||||
{
|
||||
for (HeapValue *vp = begin; vp != end; ++vp) {
|
||||
const Value &v = *vp;
|
||||
Cell *cell;
|
||||
uint32 color;
|
||||
if (v.isString()) {
|
||||
cell = v.toString();
|
||||
color = BLACK;
|
||||
} else if (v.isObject()) {
|
||||
cell = &v.toObject();
|
||||
color = gcmarker->getMarkColor();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (cell->markIfUnmarked(color))
|
||||
gcmarker->delayMarkingChildren(cell);
|
||||
}
|
||||
}
|
||||
|
||||
static const uintN LARGE_OBJECT_CHUNK_SIZE = 2048;
|
||||
static inline void
|
||||
PushValueArray(GCMarker *gcmarker, HeapValue *array, size_t size)
|
||||
{
|
||||
if (size != 0) {
|
||||
JS_ASSERT(array);
|
||||
HeapValue *end = array + size;
|
||||
if (!gcmarker->pushValueArray(array, end))
|
||||
DelayMarkingValueArray(gcmarker, array, end);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ScanObject(GCMarker *gcmarker, JSObject *obj)
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ScanObjectWithoutSlots(GCMarker *gcmarker, JSObject *obj)
|
||||
{
|
||||
types::TypeObject *type = obj->typeFromGC();
|
||||
PushMarkStack(gcmarker, type);
|
||||
|
@ -799,54 +855,15 @@ ScanObject(GCMarker *gcmarker, JSObject *obj)
|
|||
Class *clasp = shape->getObjectClass();
|
||||
if (clasp->trace) {
|
||||
if (clasp == &ArrayClass) {
|
||||
if (obj->getDenseArrayInitializedLength() > LARGE_OBJECT_CHUNK_SIZE) {
|
||||
if (!gcmarker->largeStack.push(LargeMarkItem(obj)))
|
||||
clasp->trace(gcmarker, obj);
|
||||
} else {
|
||||
clasp->trace(gcmarker, obj);
|
||||
}
|
||||
PushValueArray(gcmarker,
|
||||
obj->getDenseArrayElements(),
|
||||
obj->getDenseArrayInitializedLength());
|
||||
} else {
|
||||
clasp->trace(gcmarker, obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (shape->isNative()) {
|
||||
uint32 nslots = obj->slotSpan();
|
||||
if (nslots > LARGE_OBJECT_CHUNK_SIZE) {
|
||||
if (gcmarker->largeStack.push(LargeMarkItem(obj)))
|
||||
return;
|
||||
}
|
||||
|
||||
obj->scanSlots(gcmarker);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ScanLargeObject(GCMarker *gcmarker, LargeMarkItem &item)
|
||||
{
|
||||
JSObject *obj = item.obj;
|
||||
|
||||
uintN start = item.markpos;
|
||||
uintN stop;
|
||||
uint32 capacity;
|
||||
if (obj->isDenseArray()) {
|
||||
capacity = obj->getDenseArrayInitializedLength();
|
||||
stop = JS_MIN(start + LARGE_OBJECT_CHUNK_SIZE, capacity);
|
||||
for (uintN i=stop; i>start; i--)
|
||||
ScanValue(gcmarker, obj->getDenseArrayElement(i-1));
|
||||
} else {
|
||||
JS_ASSERT(obj->isNative());
|
||||
capacity = obj->slotSpan();
|
||||
stop = JS_MIN(start + LARGE_OBJECT_CHUNK_SIZE, capacity);
|
||||
for (uintN i=stop; i>start; i--)
|
||||
ScanValue(gcmarker, obj->nativeGetSlot(i-1));
|
||||
}
|
||||
|
||||
if (stop == capacity)
|
||||
return true;
|
||||
|
||||
item.markpos += LARGE_OBJECT_CHUNK_SIZE;
|
||||
return false;
|
||||
return shape->isNative();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1046,39 +1063,105 @@ MarkChildren(JSTracer *trc, JSXML *xml)
|
|||
|
||||
} /* namespace gc */
|
||||
|
||||
inline void
|
||||
GCMarker::processMarkStackTop()
|
||||
{
|
||||
/*
|
||||
* The code uses explicit goto to eliminate the tail recursion that
|
||||
* compilers cannot optimize on their own.
|
||||
*/
|
||||
HeapValue *vp, *end;
|
||||
JSObject *obj;
|
||||
|
||||
uintptr_t addr = stack.pop();
|
||||
uintptr_t tag = addr & StackTagMask;
|
||||
if (tag == ValueArrayTag) {
|
||||
/*
|
||||
* We set ValueArrayTag to zero to avoid bit setting and clearing when
|
||||
* pushing and poping tagged value array pointers. This is the most
|
||||
* common stack operation as we push the array on the stack again when
|
||||
* we find the next unmarked object in the array.
|
||||
*/
|
||||
JS_STATIC_ASSERT(ValueArrayTag == 0);
|
||||
uintptr_t addr2 = stack.pop();
|
||||
JS_ASSERT(addr <= addr2);
|
||||
JS_ASSERT((addr2 - addr) % sizeof(Value) == 0);
|
||||
vp = reinterpret_cast<HeapValue *>(addr);
|
||||
end = reinterpret_cast<HeapValue *>(addr2);
|
||||
goto scan_value_array;
|
||||
}
|
||||
|
||||
addr &= ~StackTagMask;
|
||||
if (tag == ObjectTag) {
|
||||
obj = reinterpret_cast<JSObject *>(addr);
|
||||
goto scan_obj;
|
||||
} else if (tag == TypeTag) {
|
||||
ScanTypeObject(this, reinterpret_cast<types::TypeObject *>(addr));
|
||||
} else {
|
||||
JS_ASSERT(tag == XmlTag);
|
||||
MarkChildren(this, reinterpret_cast<JSXML *>(addr));
|
||||
}
|
||||
return;
|
||||
|
||||
scan_value_array:
|
||||
JS_ASSERT(vp < end);
|
||||
do {
|
||||
const Value &v = *vp++;
|
||||
if (v.isString()) {
|
||||
JSString *str = v.toString();
|
||||
if (str->markIfUnmarked())
|
||||
ScanString(this, str);
|
||||
} else if (v.isObject()) {
|
||||
obj = &v.toObject();
|
||||
if (obj->markIfUnmarked(getMarkColor())) {
|
||||
if (vp != end && !pushValueArray(vp, end))
|
||||
DelayMarkingValueArray(this, vp, end);
|
||||
goto scan_obj;
|
||||
}
|
||||
}
|
||||
} while (vp != end);
|
||||
return;
|
||||
|
||||
scan_obj:
|
||||
if (ScanObjectWithoutSlots(this, obj)) {
|
||||
unsigned nslots = obj->slotSpan();
|
||||
vp = obj->fixedSlots();
|
||||
if (obj->slots) {
|
||||
unsigned nfixed = obj->numFixedSlots();
|
||||
if (nslots > nfixed) {
|
||||
PushValueArray(this, vp, nfixed);
|
||||
vp = obj->slots;
|
||||
end = vp + (nslots - nfixed);
|
||||
goto scan_value_array;
|
||||
}
|
||||
}
|
||||
if (nslots) {
|
||||
end = vp + nslots;
|
||||
goto scan_value_array;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
GCMarker::drainMarkStack()
|
||||
{
|
||||
JSRuntime *rt = runtime;
|
||||
rt->gcCheckCompartment = rt->gcCurrentCompartment;
|
||||
|
||||
while (!isMarkStackEmpty()) {
|
||||
while (!ropeStack.isEmpty())
|
||||
ScanRope(this, ropeStack.pop());
|
||||
for (;;) {
|
||||
while (!stack.isEmpty())
|
||||
processMarkStackTop();
|
||||
if (!hasDelayedChildren())
|
||||
break;
|
||||
|
||||
while (!objStack.isEmpty())
|
||||
ScanObject(this, objStack.pop());
|
||||
|
||||
while (!typeStack.isEmpty())
|
||||
ScanTypeObject(this, typeStack.pop());
|
||||
|
||||
while (!xmlStack.isEmpty())
|
||||
MarkChildren(this, xmlStack.pop());
|
||||
|
||||
if (!largeStack.isEmpty()) {
|
||||
LargeMarkItem &item = largeStack.peek();
|
||||
if (ScanLargeObject(this, item))
|
||||
largeStack.pop();
|
||||
}
|
||||
|
||||
if (isMarkStackEmpty()) {
|
||||
/*
|
||||
* Mark children of things that caused too deep recursion during the above
|
||||
* tracing. Don't do this until we're done with everything else.
|
||||
* Mark children of things that caused too deep recursion during the
|
||||
* above tracing. Don't do this until we're done with everything
|
||||
* else.
|
||||
*/
|
||||
markDelayedChildren();
|
||||
}
|
||||
}
|
||||
|
||||
rt->gcCheckCompartment = NULL;
|
||||
}
|
||||
|
@ -1127,29 +1210,3 @@ CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
|||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
inline void
|
||||
JSObject::scanSlots(GCMarker *gcmarker)
|
||||
{
|
||||
/*
|
||||
* Scan the fixed slots and the dynamic slots separately, to avoid
|
||||
* branching inside nativeGetSlot().
|
||||
*/
|
||||
unsigned i, nslots = slotSpan();
|
||||
if (slots) {
|
||||
unsigned nfixed = numFixedSlots();
|
||||
if (nslots > nfixed) {
|
||||
HeapValue *vp = fixedSlots();
|
||||
for (i = 0; i < nfixed; i++, vp++)
|
||||
ScanValue(gcmarker, *vp);
|
||||
vp = slots;
|
||||
for (; i < nslots; i++, vp++)
|
||||
ScanValue(gcmarker, *vp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(nslots <= numFixedSlots());
|
||||
HeapValue *vp = fixedSlots();
|
||||
for (i = 0; i < nslots; i++, vp++)
|
||||
ScanValue(gcmarker, *vp);
|
||||
}
|
||||
|
|
|
@ -3421,7 +3421,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
|
||||
/* Bytecodes pushing values of known type. */
|
||||
case JSOP_VOID:
|
||||
case JSOP_PUSH:
|
||||
case JSOP_UNDEFINED:
|
||||
pushed[0].addType(cx, Type::UndefinedType());
|
||||
break;
|
||||
case JSOP_ZERO:
|
||||
|
|
|
@ -1995,9 +1995,9 @@ END_CASE(JSOP_LINENO)
|
|||
BEGIN_CASE(JSOP_BLOCKCHAIN)
|
||||
END_CASE(JSOP_BLOCKCHAIN)
|
||||
|
||||
BEGIN_CASE(JSOP_PUSH)
|
||||
BEGIN_CASE(JSOP_UNDEFINED)
|
||||
PUSH_UNDEFINED();
|
||||
END_CASE(JSOP_PUSH)
|
||||
END_CASE(JSOP_UNDEFINED)
|
||||
|
||||
BEGIN_CASE(JSOP_POP)
|
||||
regs.sp--;
|
||||
|
|
|
@ -1191,7 +1191,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
|
|||
size_t length = linearStr->length();
|
||||
|
||||
/*
|
||||
* If the eval string starts with '(' and ends with ')', it may be JSON.
|
||||
* If the eval string starts with '(' or '[' and ends with ')' or ']', it may be JSON.
|
||||
* Try the JSON parser first because it's much faster. If the eval string
|
||||
* isn't JSON, JSON parsing will probably fail quickly, so little time
|
||||
* will be lost.
|
||||
|
@ -1202,7 +1202,8 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
|
|||
* JSON with eval and using strict mode, you deserve to be slow.
|
||||
*/
|
||||
if (length > 2 &&
|
||||
chars[0] == '(' && chars[length - 1] == ')' &&
|
||||
((chars[0] == '[' && chars[length - 1] == ']') ||
|
||||
(chars[0] == '(' && chars[length - 1] == ')')) &&
|
||||
(!caller || !caller->script()->strictModeCode))
|
||||
{
|
||||
/*
|
||||
|
@ -1218,7 +1219,8 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
|
|||
break;
|
||||
|
||||
if (cp == end) {
|
||||
JSONParser parser(cx, chars + 1, length - 2,
|
||||
bool isArray = (chars[0] == '[');
|
||||
JSONParser parser(cx, isArray ? chars : chars + 1, isArray ? length : length - 2,
|
||||
JSONParser::StrictJSON, JSONParser::NoError);
|
||||
Value tmp;
|
||||
if (!parser.parse(&tmp))
|
||||
|
|
|
@ -457,6 +457,7 @@ struct JSObject : js::gc::Cell
|
|||
{
|
||||
private:
|
||||
friend struct js::Shape;
|
||||
friend struct js::GCMarker;
|
||||
|
||||
/*
|
||||
* Shape of the object, encodes the layout of the object's properties and
|
||||
|
@ -546,8 +547,6 @@ struct JSObject : js::gc::Cell
|
|||
inline bool hasClass(const js::Class *c) const;
|
||||
inline const js::ObjectOps *getOps() const;
|
||||
|
||||
inline void scanSlots(js::GCMarker *gcmarker);
|
||||
|
||||
/*
|
||||
* An object is a delegate if it is on another object's prototype or scope
|
||||
* chain, and therefore the delegate might be asked implicitly to get or
|
||||
|
|
|
@ -1917,7 +1917,7 @@ DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
|||
const char *rval;
|
||||
|
||||
LOAD_OP_DATA(pc);
|
||||
LOCAL_ASSERT(op == JSOP_PUSH || op == JSOP_GETLOCAL);
|
||||
LOCAL_ASSERT(op == JSOP_GETLOCAL);
|
||||
|
||||
todo = Sprint(&ss->sprinter, "%s[", VarPrefix(sn));
|
||||
if (todo < 0 || !PushOff(ss, todo, JSOP_NOP))
|
||||
|
@ -1934,7 +1934,7 @@ DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
|||
if (pc == endpc)
|
||||
return pc;
|
||||
LOAD_OP_DATA(pc);
|
||||
if (op != JSOP_PUSH && op != JSOP_GETLOCAL)
|
||||
if (op != JSOP_GETLOCAL)
|
||||
break;
|
||||
if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
|
||||
return NULL;
|
||||
|
@ -2548,20 +2548,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
}
|
||||
break;
|
||||
|
||||
case JSOP_PUSH:
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
|
||||
pc = DecompileGroupAssignment(ss, pc, endpc, sn, &todo);
|
||||
if (!pc)
|
||||
return NULL;
|
||||
LOCAL_ASSERT(*pc == JSOP_POPN);
|
||||
len = oplen = JSOP_POPN_LENGTH;
|
||||
goto end_groupassignment;
|
||||
}
|
||||
#endif
|
||||
/* FALL THROUGH */
|
||||
|
||||
case JSOP_BINDNAME:
|
||||
case JSOP_BINDGNAME:
|
||||
todo = Sprint(&ss->sprinter, "");
|
||||
|
@ -4193,8 +4179,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
LOCAL_ASSERT(*pc == JSOP_NULLBLOCKCHAIN);
|
||||
pc += JSOP_NULLBLOCKCHAIN_LENGTH;
|
||||
}
|
||||
LOCAL_ASSERT(*pc == JSOP_PUSH);
|
||||
pc += JSOP_PUSH_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_UNDEFINED);
|
||||
pc += JSOP_UNDEFINED_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_CALL);
|
||||
LOCAL_ASSERT(GET_ARGC(pc) == 0);
|
||||
len = JSOP_CALL_LENGTH;
|
||||
|
@ -5225,10 +5211,6 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
|
|||
JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
|
||||
op != JSOP_DUP && op != JSOP_DUP2);
|
||||
|
||||
/* JSOP_PUSH is used to generate undefined for group assignment holes. */
|
||||
if (op == JSOP_PUSH)
|
||||
return JS_strdup(cx, js_undefined_str);
|
||||
|
||||
/*
|
||||
* |this| could convert to a very long object initialiser, so cite it by
|
||||
* its keyword name instead.
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Long-standing JavaScript bytecodes. */
|
||||
OPDEF(JSOP_PUSH, 1, "push", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNDEFINED, 1, js_undefined_str, "", 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD)
|
||||
OPDEF(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
|
|
|
@ -1681,9 +1681,9 @@ mjit::Compiler::generateMethod()
|
|||
BEGIN_CASE(JSOP_NOP)
|
||||
END_CASE(JSOP_NOP)
|
||||
|
||||
BEGIN_CASE(JSOP_PUSH)
|
||||
BEGIN_CASE(JSOP_UNDEFINED)
|
||||
frame.push(UndefinedValue());
|
||||
END_CASE(JSOP_PUSH)
|
||||
END_CASE(JSOP_UNDEFINED)
|
||||
|
||||
BEGIN_CASE(JSOP_POPV)
|
||||
BEGIN_CASE(JSOP_SETRVAL)
|
||||
|
|
|
@ -1309,8 +1309,8 @@ InternalConst(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!flat)
|
||||
return false;
|
||||
|
||||
if (JS_FlatStringEqualsAscii(flat, "OBJECT_MARK_STACK_LENGTH")) {
|
||||
vp[0] = UINT_TO_JSVAL(js::OBJECT_MARK_STACK_SIZE / sizeof(JSObject *));
|
||||
if (JS_FlatStringEqualsAscii(flat, "MARK_STACK_LENGTH")) {
|
||||
vp[0] = UINT_TO_JSVAL(js::MARK_STACK_LENGTH);
|
||||
} else {
|
||||
JS_ReportError(cx, "unknown const name");
|
||||
return false;
|
||||
|
|
|
@ -2325,8 +2325,6 @@ CallMethodHelper::GetArraySizeFromParam(uint8 paramIndex,
|
|||
if (NS_FAILED(rv))
|
||||
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
|
||||
|
||||
const nsXPTType& type = mMethodInfo->GetParam(paramIndex).GetType();
|
||||
|
||||
*result = GetDispatchParam(paramIndex)->val.u32;
|
||||
|
||||
return true;
|
||||
|
@ -2354,8 +2352,6 @@ CallMethodHelper::GetInterfaceTypeFromParam(uint8 paramIndex,
|
|||
if (NS_FAILED(rv))
|
||||
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
|
||||
|
||||
const nsXPTType& type = mMethodInfo->GetParam(paramIndex).GetType();
|
||||
|
||||
nsID* p = (nsID*) GetDispatchParam(paramIndex)->val.p;
|
||||
if (!p)
|
||||
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include "nsDOMClassInfoID.h"
|
||||
|
||||
#define DEFINE_UNWRAP_CAST(_interface, _base, _bit) \
|
||||
NS_SPECIALIZE_TEMPLATE \
|
||||
template <> \
|
||||
inline JSBool \
|
||||
xpc_qsUnwrapThis<_interface>(JSContext *cx, \
|
||||
JSObject *obj, \
|
||||
|
@ -62,7 +62,7 @@ xpc_qsUnwrapThis<_interface>(JSContext *cx, \
|
|||
return true; \
|
||||
} \
|
||||
\
|
||||
NS_SPECIALIZE_TEMPLATE \
|
||||
template <> \
|
||||
inline nsresult \
|
||||
xpc_qsUnwrapArg<_interface>(JSContext *cx, \
|
||||
jsval v, \
|
||||
|
@ -104,7 +104,7 @@ castToElement(nsIContent *content, jsval val, nsGenericElement **ppInterface,
|
|||
return true;
|
||||
}
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
inline JSBool
|
||||
xpc_qsUnwrapThis<nsGenericElement>(JSContext *cx,
|
||||
JSObject *obj,
|
||||
|
@ -135,7 +135,7 @@ xpc_qsUnwrapThis<nsGenericElement>(JSContext *cx,
|
|||
return ok;
|
||||
}
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
inline nsresult
|
||||
xpc_qsUnwrapArg<nsGenericElement>(JSContext *cx,
|
||||
jsval v,
|
||||
|
|
|
@ -131,6 +131,11 @@ using mozilla::dom::indexedDB::IndexedDatabaseManager;
|
|||
#ifdef MOZ_B2G_RIL
|
||||
#include "RadioManager.h"
|
||||
using mozilla::dom::telephony::RadioManager;
|
||||
#include "nsITelephone.h"
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "AudioManager.h"
|
||||
using mozilla::dom::telephony::AudioManager;
|
||||
#endif
|
||||
|
||||
// Editor stuff
|
||||
|
@ -346,7 +351,9 @@ RadioInterfaceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(AudioManager)
|
||||
#else
|
||||
#if defined(XP_UNIX) || \
|
||||
defined(_WINDOWS) || \
|
||||
defined(machintosh) || \
|
||||
|
@ -854,6 +861,9 @@ NS_DEFINE_NAMED_CID(INDEXEDDB_MANAGER_CID);
|
|||
NS_DEFINE_NAMED_CID(TELEPHONYRADIO_CID);
|
||||
NS_DEFINE_NAMED_CID(TELEPHONYRADIOINTERFACE_CID);
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_DEFINE_NAMED_CID(NS_AUDIOMANAGER_CID);
|
||||
#endif
|
||||
#ifdef ENABLE_EDITOR_API_LOG
|
||||
NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_CID);
|
||||
#else
|
||||
|
@ -993,6 +1003,9 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
|||
{ &kTELEPHONYRADIO_CID, true, NULL, RadioManagerConstructor },
|
||||
{ &kTELEPHONYRADIOINTERFACE_CID, true, NULL, RadioInterfaceConstructor },
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ &kNS_AUDIOMANAGER_CID, true, NULL, AudioManagerConstructor },
|
||||
#endif
|
||||
#ifdef ENABLE_EDITOR_API_LOG
|
||||
{ &kNS_HTMLEDITOR_CID, false, NULL, nsHTMLEditorLogConstructor },
|
||||
#else
|
||||
|
@ -1126,6 +1139,9 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
|||
{ TELEPHONYRADIO_CONTRACTID, &kTELEPHONYRADIO_CID },
|
||||
{ TELEPHONYRADIOINTERFACE_CONTRACTID, &kTELEPHONYRADIOINTERFACE_CID },
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ NS_AUDIOMANAGER_CONTRACTID, &kNS_AUDIOMANAGER_CID },
|
||||
#endif
|
||||
#ifdef ENABLE_EDITOR_API_LOG
|
||||
{ "@mozilla.org/editor/htmleditor;1", &kNS_HTMLEDITOR_CID },
|
||||
#else
|
||||
|
|
|
@ -4744,14 +4744,14 @@ template <class SpecifiedValueItem>
|
|||
struct InitialInheritLocationFor {
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct InitialInheritLocationFor<nsCSSValueList> {
|
||||
static nsCSSValue nsCSSValueList::* Location() {
|
||||
return &nsCSSValueList::mValue;
|
||||
}
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct InitialInheritLocationFor<nsCSSValuePairList> {
|
||||
static nsCSSValue nsCSSValuePairList::* Location() {
|
||||
return &nsCSSValuePairList::mXValue;
|
||||
|
@ -4762,7 +4762,7 @@ template <class SpecifiedValueItem, class ComputedValueItem>
|
|||
struct BackgroundItemComputer {
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct BackgroundItemComputer<nsCSSValueList, PRUint8>
|
||||
{
|
||||
static void ComputeValue(nsStyleContext* aStyleContext,
|
||||
|
@ -4775,7 +4775,7 @@ struct BackgroundItemComputer<nsCSSValueList, PRUint8>
|
|||
}
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct BackgroundItemComputer<nsCSSValueList, nsStyleImage>
|
||||
{
|
||||
static void ComputeValue(nsStyleContext* aStyleContext,
|
||||
|
@ -4801,7 +4801,7 @@ static const BackgroundPositionAxis gBGPosAxes[] = {
|
|||
&nsStyleBackground::Position::mYPosition }
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Position>
|
||||
{
|
||||
static void ComputeValue(nsStyleContext* aStyleContext,
|
||||
|
@ -4863,7 +4863,7 @@ static const BackgroundSizeAxis gBGSizeAxes[] = {
|
|||
&nsStyleBackground::Size::mHeightType }
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
template <>
|
||||
struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Size>
|
||||
{
|
||||
static void ComputeValue(nsStyleContext* aStyleContext,
|
||||
|
|
|
@ -581,7 +581,7 @@ nsSVGPatternFrame::ConstructCTM(const gfxRect &callerBBox,
|
|||
|
||||
const nsSVGViewBoxRect viewBox = GetViewBox().GetAnimValue();
|
||||
|
||||
if (viewBox.height <= 0.0f && viewBox.width <= 0.0f) {
|
||||
if (viewBox.height <= 0.0f || viewBox.width <= 0.0f) {
|
||||
return tCTM;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="reftest-wait">
|
||||
<!-- Test to be sure that a zero-sized-in-one-dimension viewBox doesn't
|
||||
make us fail assertions. -->
|
||||
<script>
|
||||
document.addEventListener("MozReftestInvalidate", waitAndFinish, false);
|
||||
|
||||
function waitAndFinish() {
|
||||
// Sadly, MozReftestInvalidate fires sooner than PaintPattern here, so
|
||||
// we need to wait a little bit to give PaintPattern a chance to hit
|
||||
// this bug.
|
||||
setTimeout(finish, 100);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
<pattern id="test" viewBox="0 0 1 0">
|
||||
<rect/>
|
||||
</pattern>
|
||||
<rect width="200" height="200" fill="url(#test)"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 730 B |
|
@ -0,0 +1,23 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="reftest-wait">
|
||||
<!-- Test to be sure that a zero-sized-in-one-dimension viewBox doesn't
|
||||
make us fail assertions. -->
|
||||
<script>
|
||||
document.addEventListener("MozReftestInvalidate", waitAndFinish, false);
|
||||
|
||||
function waitAndFinish() {
|
||||
// Sadly, MozReftestInvalidate fires sooner than PaintPattern here, so
|
||||
// we need to wait a little bit to give PaintPattern a chance to hit
|
||||
// this bug.
|
||||
setTimeout(finish, 100);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
<pattern id="test" viewBox="0 0 0 1">
|
||||
<rect/>
|
||||
</pattern>
|
||||
<rect width="200" height="200" fill="url(#test)"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 730 B |
|
@ -119,3 +119,5 @@ load 682411-1.svg
|
|||
load 692203-1.svg
|
||||
load 692203-2.svg
|
||||
load 693424-1.svg
|
||||
load 709920-1.svg
|
||||
load 709920-2.svg
|
||||
|
|
|
@ -52,8 +52,8 @@ CSRCS = \
|
|||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
CSRCS = \
|
||||
sydney_audio_gonk.c \
|
||||
CPPSRCS = \
|
||||
sydney_audio_gonk.cpp \
|
||||
$(NULL)
|
||||
else ifeq ($(MOZ_WIDGET_TOOLKIT),android)
|
||||
CSRCS = \
|
||||
|
|
|
@ -36,9 +36,12 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
extern "C" {
|
||||
#include "sydney_audio.h"
|
||||
}
|
||||
|
||||
#include "android/log.h"
|
||||
#include "media/AudioTrack.h"
|
||||
|
||||
#ifndef ALOG
|
||||
#if defined(DEBUG) || defined(FORCE_ALOG)
|
||||
|
@ -48,13 +51,17 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* Gonk implementation based on sydney_audio_mac.c */
|
||||
/* XXX This is temporary until we figure out a way to hook ALSA up */
|
||||
/* Gonk implementation based on sydney_audio_android.c */
|
||||
|
||||
#define NANOSECONDS_PER_SECOND 1000000000
|
||||
#define NANOSECONDS_IN_MILLISECOND 1000000
|
||||
#define MILLISECONDS_PER_SECOND 1000
|
||||
|
||||
using namespace android;
|
||||
|
||||
struct sa_stream {
|
||||
AudioTrack *output_unit;
|
||||
|
||||
unsigned int rate;
|
||||
unsigned int channels;
|
||||
unsigned int isPaused;
|
||||
|
@ -103,10 +110,11 @@ sa_stream_create_pcm(
|
|||
* Allocate the instance and required resources.
|
||||
*/
|
||||
sa_stream_t *s;
|
||||
if ((s = malloc(sizeof(sa_stream_t))) == NULL) {
|
||||
if ((s = (sa_stream_t *)malloc(sizeof(sa_stream_t))) == NULL) {
|
||||
return SA_ERROR_OOM;
|
||||
}
|
||||
|
||||
s->output_unit = NULL;
|
||||
s->rate = rate;
|
||||
s->channels = channels;
|
||||
s->isPaused = 0;
|
||||
|
@ -115,7 +123,7 @@ sa_stream_create_pcm(
|
|||
s->timePlaying = 0;
|
||||
s->amountWritten = 0;
|
||||
|
||||
s->bufferSize = rate * channels;
|
||||
s->bufferSize = 0;
|
||||
|
||||
*_s = s;
|
||||
return SA_SUCCESS;
|
||||
|
@ -128,8 +136,47 @@ sa_stream_open(sa_stream_t *s) {
|
|||
if (s == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
if (s->output_unit != NULL) {
|
||||
return SA_ERROR_INVALID;
|
||||
}
|
||||
|
||||
return SA_ERROR_NO_DEVICE;
|
||||
int32_t chanConfig = s->channels == 1 ?
|
||||
AudioSystem::CHANNEL_OUT_MONO : AudioSystem::CHANNEL_OUT_STEREO;
|
||||
|
||||
int frameCount;
|
||||
if (AudioTrack::getMinFrameCount(&frameCount, AudioSystem::DEFAULT,
|
||||
s->rate) != NO_ERROR) {
|
||||
return SA_ERROR_INVALID;
|
||||
}
|
||||
int minsz = frameCount * s->channels * sizeof(int16_t);
|
||||
|
||||
s->bufferSize = s->rate * s->channels * sizeof(int16_t);
|
||||
if (s->bufferSize < minsz) {
|
||||
s->bufferSize = minsz;
|
||||
}
|
||||
|
||||
AudioTrack *track =
|
||||
new AudioTrack(AudioSystem::SYSTEM,
|
||||
s->rate,
|
||||
AudioSystem::PCM_16_BIT,
|
||||
chanConfig,
|
||||
frameCount,
|
||||
0,
|
||||
NULL, NULL,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (track->initCheck() != NO_ERROR) {
|
||||
delete track;
|
||||
return SA_ERROR_INVALID;
|
||||
}
|
||||
|
||||
s->output_unit = track;
|
||||
|
||||
ALOG("%p - New stream %u %u bsz=%u min=%u", s, s->rate, s->channels,
|
||||
s->bufferSize, minsz);
|
||||
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,7 +186,20 @@ sa_stream_destroy(sa_stream_t *s) {
|
|||
if (s == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
// XXX
|
||||
|
||||
static bool firstLeaked = 0;
|
||||
if (s->output_unit) {
|
||||
s->output_unit->stop();
|
||||
s->output_unit->flush();
|
||||
// XXX: Figure out why we crash if we don't leak the first AudioTrack
|
||||
if (firstLeaked)
|
||||
delete s->output_unit;
|
||||
else
|
||||
firstLeaked = true;
|
||||
}
|
||||
free(s);
|
||||
|
||||
ALOG("%p - Stream destroyed", s);
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -153,14 +213,42 @@ sa_stream_destroy(sa_stream_t *s) {
|
|||
int
|
||||
sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) {
|
||||
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
if (nbytes == 0) {
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
// XXX
|
||||
return SA_SUCCESS;
|
||||
|
||||
const char *p = (char *)data;
|
||||
ssize_t r = 0;
|
||||
size_t wrote = 0;
|
||||
do {
|
||||
size_t towrite = nbytes - wrote;
|
||||
|
||||
r = s->output_unit->write(p, towrite);
|
||||
if (r < 0) {
|
||||
ALOG("%p - Write failed %d", s, r);
|
||||
break;
|
||||
}
|
||||
|
||||
/* AudioTrack::write is blocking when the AudioTrack is playing. When
|
||||
it's not playing, it's a non-blocking call that will return a short
|
||||
write when the buffer is full. Use a short write to indicate a good
|
||||
time to start the AudioTrack playing. */
|
||||
if (r != towrite) {
|
||||
ALOG("%p - Buffer full, starting playback", s);
|
||||
sa_stream_resume(s);
|
||||
}
|
||||
|
||||
p += r;
|
||||
wrote += r;
|
||||
} while (wrote < nbytes);
|
||||
|
||||
ALOG("%p - Wrote %u", s, nbytes);
|
||||
s->amountWritten += nbytes;
|
||||
|
||||
return r < 0 ? SA_ERROR_INVALID : SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -173,11 +261,21 @@ sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) {
|
|||
int
|
||||
sa_stream_get_write_size(sa_stream_t *s, size_t *size) {
|
||||
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
|
||||
// XXX
|
||||
/* No android API for this, so estimate based on how much we have played and
|
||||
* how much we have written. */
|
||||
*size = s->bufferSize - ((s->timePlaying * s->channels * s->rate * sizeof(int16_t) /
|
||||
MILLISECONDS_PER_SECOND) - s->amountWritten);
|
||||
|
||||
/* Available buffer space can't exceed bufferSize. */
|
||||
if (*size > s->bufferSize) {
|
||||
*size = s->bufferSize;
|
||||
}
|
||||
ALOG("%p - Write Size tp=%lld aw=%u sz=%zu", s, s->timePlaying, s->amountWritten, *size);
|
||||
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -185,11 +283,20 @@ sa_stream_get_write_size(sa_stream_t *s, size_t *size) {
|
|||
int
|
||||
sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) {
|
||||
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
|
||||
// XXX
|
||||
ALOG("%p - get position", s);
|
||||
|
||||
uint32_t framePosition;
|
||||
if (s->output_unit->getPosition(&framePosition) != NO_ERROR)
|
||||
return SA_ERROR_INVALID;
|
||||
|
||||
/* android returns number of frames, so:
|
||||
position = frames * (PCM_16_BIT == 2 bytes) * channels
|
||||
*/
|
||||
*pos = framePosition * s->channels * sizeof(int16_t);
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -197,11 +304,23 @@ sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) {
|
|||
int
|
||||
sa_stream_pause(sa_stream_t *s) {
|
||||
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
|
||||
// XXX
|
||||
s->isPaused = 1;
|
||||
|
||||
/* Update stats */
|
||||
if (s->lastStartTime != 0) {
|
||||
/* if lastStartTime is not zero, so playback has started */
|
||||
struct timespec current_time;
|
||||
clock_gettime(CLOCK_REALTIME, ¤t_time);
|
||||
int64_t ticker = current_time.tv_sec * 1000 + current_time.tv_nsec / 1000000;
|
||||
s->timePlaying += ticker - s->lastStartTime;
|
||||
}
|
||||
ALOG("%p - Pause total time playing: %lld total written: %lld", s, s->timePlaying, s->amountWritten);
|
||||
|
||||
s->output_unit->pause();
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -209,11 +328,21 @@ sa_stream_pause(sa_stream_t *s) {
|
|||
int
|
||||
sa_stream_resume(sa_stream_t *s) {
|
||||
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
|
||||
// XXX
|
||||
ALOG("%p - resume", s);
|
||||
|
||||
s->isPaused = 0;
|
||||
|
||||
/* Update stats */
|
||||
struct timespec current_time;
|
||||
clock_gettime(CLOCK_REALTIME, ¤t_time);
|
||||
int64_t ticker = current_time.tv_sec * 1000 + current_time.tv_nsec / 1000000;
|
||||
s->lastStartTime = ticker;
|
||||
|
||||
s->output_unit->start();
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -221,11 +350,36 @@ sa_stream_resume(sa_stream_t *s) {
|
|||
int
|
||||
sa_stream_drain(sa_stream_t *s)
|
||||
{
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
|
||||
// XXX
|
||||
/* This is somewhat of a hack (see bug 693131). The AudioTrack documentation
|
||||
doesn't make it clear how much data must be written before a chunk of data is
|
||||
played, and experimentation with short streams required filling the entire
|
||||
allocated buffer. To guarantee that short streams (and the end of longer
|
||||
streams) are audible, write an entire bufferSize of silence before sleeping.
|
||||
This guarantees the short write logic in sa_stream_write is hit and the
|
||||
stream is playing before sleeping. Note that the sleep duration is
|
||||
calculated from the duration of audio written before writing silence. */
|
||||
size_t available;
|
||||
sa_stream_get_write_size(s, &available);
|
||||
|
||||
void *p = calloc(1, s->bufferSize);
|
||||
sa_stream_write(s, p, s->bufferSize);
|
||||
free(p);
|
||||
|
||||
/* There is no way with the Android SDK to determine exactly how
|
||||
long to playback. So estimate and sleep for that long. */
|
||||
unsigned long long x = (s->bufferSize - available) * 1000 / s->channels / s->rate /
|
||||
sizeof(int16_t) * NANOSECONDS_IN_MILLISECOND;
|
||||
ALOG("%p - Drain - flush %u, sleep for %llu ns", s, available, x);
|
||||
|
||||
struct timespec ts = {(time_t)(x / NANOSECONDS_PER_SECOND),
|
||||
(time_t)(x % NANOSECONDS_PER_SECOND)};
|
||||
nanosleep(&ts, NULL);
|
||||
s->output_unit->flush();
|
||||
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -239,11 +393,11 @@ sa_stream_drain(sa_stream_t *s)
|
|||
int
|
||||
sa_stream_set_volume_abs(sa_stream_t *s, float vol) {
|
||||
|
||||
if (s == NULL) {
|
||||
if (s == NULL || s->output_unit == NULL) {
|
||||
return SA_ERROR_NO_INIT;
|
||||
}
|
||||
|
||||
// XXX
|
||||
s->output_unit->setVolume(vol, vol);
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Brad Lassey <blassey@mozilla.com>
|
||||
* Lucas Rocha <lucasr@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -37,120 +38,183 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.*;
|
||||
import android.database.*;
|
||||
import android.view.*;
|
||||
import android.graphics.*;
|
||||
import android.content.*;
|
||||
import android.provider.Browser;
|
||||
import android.util.Log;
|
||||
import java.util.Date;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Browser;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import java.io.*;
|
||||
import java.util.zip.*;
|
||||
import android.os.Handler;
|
||||
import org.json.*;
|
||||
import android.util.AttributeSet;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
|
||||
public class AboutHomeContent extends LinearLayout {
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class AboutHomeContent extends ScrollView {
|
||||
private static final String LOGTAG = "GeckoAboutHome";
|
||||
|
||||
private static final int NUMBER_OF_TOP_SITES_PORTRAIT = 4;
|
||||
private static final int NUMBER_OF_TOP_SITES_LANDSCAPE = 3;
|
||||
|
||||
private static final int NUMBER_OF_COLS_PORTRAIT = 2;
|
||||
private static final int NUMBER_OF_COLS_LANDSCAPE = 3;
|
||||
|
||||
private boolean mInflated;
|
||||
|
||||
private Cursor mCursor;
|
||||
UriLoadCallback mUriLoadCallback = null;
|
||||
|
||||
protected SimpleCursorAdapter mTopSitesAdapter;
|
||||
protected GridView mTopSitesGrid;
|
||||
|
||||
protected ArrayAdapter<String> mAddonsAdapter;
|
||||
protected ListView mAddonsList;
|
||||
|
||||
public interface UriLoadCallback {
|
||||
public void callback(String uriSpec);
|
||||
}
|
||||
|
||||
UriLoadCallback mUriLoadCallback = null;
|
||||
|
||||
void setUriLoadCallback(UriLoadCallback uriLoadCallback) {
|
||||
mUriLoadCallback = uriLoadCallback;
|
||||
}
|
||||
|
||||
public AboutHomeContent(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mInflated = false;
|
||||
}
|
||||
|
||||
private static final String LOGTAG = "GeckoAboutHome";
|
||||
private static final String TITLE_KEY = "title";
|
||||
private static final int NUMBER_OF_TOP_SITES = 3;
|
||||
private static final int kTileWidth = 122;
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
private Cursor mCursor;
|
||||
private Uri mUri;
|
||||
private String mTitle;
|
||||
|
||||
protected ListAdapter mGridAdapter;
|
||||
protected ArrayAdapter<String> mAddonAdapter;
|
||||
protected GridView mGrid;
|
||||
protected ListView mAddonList;
|
||||
private Handler mHandler = new Handler();
|
||||
|
||||
public void onActivityContentChanged(Activity activity) {
|
||||
mGrid = (GridView)findViewById(R.id.grid);
|
||||
if (mGrid == null)
|
||||
// HACK: Without this, the onFinishInflate is called twice
|
||||
// This issue is due to a bug when Android inflates a layout with a
|
||||
// parent. Fixed in Honeycomb
|
||||
if (mInflated)
|
||||
return;
|
||||
|
||||
mGrid.setOnItemClickListener(mGridOnClickListener);
|
||||
mInflated = true;
|
||||
|
||||
// we want to do this: mGrid.setNumColumns(GridView.AUTO_FIT); but it doesn't work
|
||||
Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
int width = display.getWidth();
|
||||
mGrid.setNumColumns((int) Math.floor(width / kTileWidth));
|
||||
mAddonList = (ListView)findViewById(R.id.recommended_addon_list);
|
||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mGrid.setAdapter(mGridAdapter);
|
||||
mTopSitesGrid = (GridView)findViewById(R.id.top_sites_grid);
|
||||
mTopSitesGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
|
||||
Cursor c = (Cursor) parent.getItemAtPosition(position);
|
||||
|
||||
String spec = c.getString(c.getColumnIndex(URLColumns.URL));
|
||||
Log.i(LOGTAG, "clicked: " + spec);
|
||||
|
||||
if (mUriLoadCallback != null)
|
||||
mUriLoadCallback.callback(spec);
|
||||
}
|
||||
});
|
||||
|
||||
mAddonsList = (ListView) findViewById(R.id.recommended_addons_list);
|
||||
|
||||
TextView allTopSitesText = (TextView) findViewById(R.id.all_top_sites_text);
|
||||
allTopSitesText.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
GeckoApp.mAppContext.showAwesomebar(AwesomeBar.Type.EDIT);
|
||||
}
|
||||
});
|
||||
|
||||
TextView allAddonsText = (TextView) findViewById(R.id.all_addons_text);
|
||||
allAddonsText.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (mUriLoadCallback != null)
|
||||
mUriLoadCallback.callback("about:addons");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private AdapterView.OnItemClickListener mGridOnClickListener = new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
|
||||
{
|
||||
onGridItemClick((GridView)parent, v, position, id);
|
||||
private int getNumberOfTopSites() {
|
||||
Configuration config = getContext().getResources().getConfiguration();
|
||||
if (config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|
||||
return NUMBER_OF_TOP_SITES_LANDSCAPE;
|
||||
else
|
||||
return NUMBER_OF_TOP_SITES_PORTRAIT;
|
||||
}
|
||||
|
||||
private int getNumberOfColumns() {
|
||||
Configuration config = getContext().getResources().getConfiguration();
|
||||
if (config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|
||||
return NUMBER_OF_COLS_LANDSCAPE;
|
||||
else
|
||||
return NUMBER_OF_COLS_PORTRAIT;
|
||||
}
|
||||
};
|
||||
|
||||
void init(final Activity activity) {
|
||||
GeckoAppShell.getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
if (mCursor != null)
|
||||
activity.stopManagingCursor(mCursor);
|
||||
|
||||
ContentResolver resolver = GeckoApp.mAppContext.getContentResolver();
|
||||
mCursor = BrowserDB.filter(resolver, "", NUMBER_OF_TOP_SITES);
|
||||
mCursor = BrowserDB.filter(resolver, "", NUMBER_OF_TOP_SITES_PORTRAIT);
|
||||
activity.startManagingCursor(mCursor);
|
||||
|
||||
onActivityContentChanged(activity);
|
||||
mAddonAdapter = new ArrayAdapter<String>(activity, R.layout.abouthome_addon_list_item);
|
||||
mTopSitesAdapter = new TopSitesCursorAdapter(activity,
|
||||
R.layout.abouthome_topsite_item,
|
||||
mCursor,
|
||||
new String[] { URLColumns.TITLE,
|
||||
URLColumns.THUMBNAIL },
|
||||
new int[] { R.id.title, R.id.thumbnail });
|
||||
|
||||
if (mAddonsAdapter == null)
|
||||
mAddonsAdapter = new ArrayAdapter<String>(activity, R.layout.abouthome_addon_row);
|
||||
|
||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
final SimpleCursorAdapter gridAdapter =
|
||||
new SimpleCursorAdapter(activity, R.layout.abouthome_grid_box, mCursor,
|
||||
new String[] { URLColumns.TITLE,
|
||||
URLColumns.FAVICON,
|
||||
URLColumns.URL,
|
||||
URLColumns.THUMBNAIL },
|
||||
new int[] {R.id.bookmark_title, R.id.bookmark_icon, R.id.bookmark_url, R.id.screenshot});
|
||||
mGrid.setAdapter(gridAdapter);
|
||||
gridAdapter.setViewBinder(new AwesomeCursorViewBinder());
|
||||
mAddonList.setAdapter(mAddonAdapter);
|
||||
mTopSitesGrid.setNumColumns(getNumberOfColumns());
|
||||
|
||||
mTopSitesGrid.setAdapter(mTopSitesAdapter);
|
||||
mTopSitesAdapter.setViewBinder(new TopSitesViewBinder());
|
||||
|
||||
mAddonsList.setAdapter(mAddonsAdapter);
|
||||
}
|
||||
});
|
||||
|
||||
readRecommendedAddons(activity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setUriLoadCallback(UriLoadCallback uriLoadCallback) {
|
||||
mUriLoadCallback = uriLoadCallback;
|
||||
}
|
||||
|
||||
public void onActivityContentChanged(Activity activity) {
|
||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mTopSitesGrid.setAdapter(mTopSitesAdapter);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
mTopSitesGrid.setNumColumns(getNumberOfColumns());
|
||||
mTopSitesAdapter.notifyDataSetChanged();
|
||||
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
InputStream getProfileRecommendedAddonsStream() {
|
||||
try {
|
||||
File profileDir = GeckoApp.mAppContext.getProfileDir();
|
||||
|
@ -172,7 +236,11 @@ public class AboutHomeContent extends LinearLayout {
|
|||
return is;
|
||||
File applicationPackage = new File(activity.getApplication().getPackageResourcePath());
|
||||
ZipFile zip = new ZipFile(applicationPackage);
|
||||
if (zip == null)
|
||||
return null;
|
||||
ZipEntry fileEntry = zip.getEntry("recommended-addons.json");
|
||||
if (fileEntry == null)
|
||||
return null;
|
||||
return zip.getInputStream(fileEntry);
|
||||
}
|
||||
|
||||
|
@ -182,6 +250,8 @@ public class AboutHomeContent extends LinearLayout {
|
|||
try {
|
||||
byte[] buf = new byte[32768];
|
||||
InputStream fileStream = getRecommendedAddonsStream(activity);
|
||||
if (fileStream == null)
|
||||
return;
|
||||
StringBuffer jsonString = new StringBuffer();
|
||||
int read = 0;
|
||||
while ((read = fileStream.read(buf, 0, 32768)) != -1) {
|
||||
|
@ -193,7 +263,7 @@ public class AboutHomeContent extends LinearLayout {
|
|||
try {
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
JSONObject jsonobj = array.getJSONObject(i);
|
||||
mAddonAdapter.add(jsonobj.getString("name"));
|
||||
mAddonsAdapter.add(jsonobj.getString("name"));
|
||||
Log.i("GeckoAddons", "addon #" + i +": " + jsonobj.getString("name"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -208,31 +278,47 @@ public class AboutHomeContent extends LinearLayout {
|
|||
});
|
||||
}
|
||||
|
||||
protected void onGridItemClick(GridView l, View v, int position, long id) {
|
||||
mCursor.moveToPosition(position);
|
||||
String spec = mCursor.getString(mCursor.getColumnIndex(URLColumns.URL));
|
||||
Log.i(LOGTAG, "clicked: " + spec);
|
||||
if (mUriLoadCallback != null)
|
||||
mUriLoadCallback.callback(spec);
|
||||
public static class TopSitesGridView extends GridView {
|
||||
public TopSitesGridView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
}
|
||||
class AwesomeCursorViewBinder implements SimpleCursorAdapter.ViewBinder {
|
||||
private static final String LOGTAG = "GeckoAwesomeCursorViewBinder";
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// This is to ensure that the GridView always has a size that shows
|
||||
// all items with no need for scrolling.
|
||||
int expandedHeightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
|
||||
MeasureSpec.AT_MOST);
|
||||
super.onMeasure(widthMeasureSpec, expandedHeightSpec);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateImage(View view, Cursor cursor, int faviconIndex) {
|
||||
byte[] b = cursor.getBlob(faviconIndex);
|
||||
ImageView favicon = (ImageView) view;
|
||||
public class TopSitesCursorAdapter extends SimpleCursorAdapter {
|
||||
public TopSitesCursorAdapter(Context context, int layout, Cursor c,
|
||||
String[] from, int[] to) {
|
||||
super(context, layout, c, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return Math.min(super.getCount(), getNumberOfTopSites());
|
||||
}
|
||||
}
|
||||
|
||||
class TopSitesViewBinder implements SimpleCursorAdapter.ViewBinder {
|
||||
private boolean updateThumbnail(View view, Cursor cursor, int thumbIndex) {
|
||||
byte[] b = cursor.getBlob(thumbIndex);
|
||||
ImageView thumbnail = (ImageView) view;
|
||||
|
||||
if (b == null) {
|
||||
favicon.setImageResource(R.drawable.favicon);
|
||||
thumbnail.setImageResource(R.drawable.abouthome_topsite_placeholder);
|
||||
} else {
|
||||
try {
|
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
|
||||
favicon.setImageBitmap(bitmap);
|
||||
thumbnail.setImageBitmap(bitmap);
|
||||
} catch (OutOfMemoryError oom) {
|
||||
Log.e(LOGTAG, "Unable to load thumbnail bitmap", oom);
|
||||
favicon.setImageResource(R.drawable.favicon);
|
||||
thumbnail.setImageResource(R.drawable.abouthome_topsite_placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,7 +327,8 @@ class AwesomeCursorViewBinder implements SimpleCursorAdapter.ViewBinder {
|
|||
|
||||
private boolean updateTitle(View view, Cursor cursor, int titleIndex) {
|
||||
String title = cursor.getString(titleIndex);
|
||||
TextView titleView = (TextView)view;
|
||||
TextView titleView = (TextView) view;
|
||||
|
||||
// Use the URL instead of an empty title for consistency with the normal URL
|
||||
// bar view - this is the equivalent of getDisplayTitle() in Tab.java
|
||||
if (title == null || title.length() == 0) {
|
||||
|
@ -253,46 +340,49 @@ class AwesomeCursorViewBinder implements SimpleCursorAdapter.ViewBinder {
|
|||
return true;
|
||||
}
|
||||
|
||||
private boolean updateUrl(View view, Cursor cursor, int urlIndex) {
|
||||
String title = cursor.getString(urlIndex);
|
||||
TextView urlView = (TextView)view;
|
||||
if (title != null) {
|
||||
int index;
|
||||
if ((index = title.indexOf("://")) != -1)
|
||||
title = title.substring(index + 3);
|
||||
if (title.startsWith("www."))
|
||||
title = title.substring(4);
|
||||
if (title.endsWith("/"))
|
||||
title = title.substring(0, title.length() -1);
|
||||
}
|
||||
urlView.setText(title);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
|
||||
int faviconIndex = cursor.getColumnIndexOrThrow(URLColumns.FAVICON);
|
||||
if (columnIndex == faviconIndex) {
|
||||
return updateImage(view, cursor, faviconIndex);
|
||||
}
|
||||
|
||||
int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE);
|
||||
if (columnIndex == titleIndex) {
|
||||
return updateTitle(view, cursor, titleIndex);
|
||||
}
|
||||
|
||||
int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
|
||||
if (columnIndex == urlIndex) {
|
||||
return updateUrl(view, cursor, urlIndex);
|
||||
}
|
||||
|
||||
int thumbIndex = cursor.getColumnIndexOrThrow(URLColumns.THUMBNAIL);
|
||||
if (columnIndex == thumbIndex) {
|
||||
return updateImage(view, cursor, thumbIndex);
|
||||
return updateThumbnail(view, cursor, thumbIndex);
|
||||
}
|
||||
|
||||
// Other columns are handled automatically
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AddonsListView extends ListView {
|
||||
public AddonsListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// This is to ensure that the ListView always has a size that shows
|
||||
// all items with no need for scrolling.
|
||||
int expandedHeightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
|
||||
MeasureSpec.AT_MOST);
|
||||
super.onMeasure(widthMeasureSpec, expandedHeightSpec);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LinkTextView extends TextView {
|
||||
public LinkTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
SpannableString content = new SpannableString(text + " \u00BB");
|
||||
content.setSpan(new UnderlineSpan(), 0, text.length(), 0);
|
||||
|
||||
super.setText(content, BufferType.SPANNABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,8 @@
|
|||
android:windowSoftInputMode="stateAlwaysVisible|adjustResize"/>
|
||||
|
||||
<activity android:name="org.mozilla.gecko.TabsTray"
|
||||
android:theme="@style/Gecko.Translucent"/>
|
||||
android:theme="@style/Gecko.Translucent"
|
||||
android:launchMode="singleTask"/>
|
||||
|
||||
<activity android:name="org.mozilla.gecko.GeckoPreferences"
|
||||
android:theme="@style/Gecko.TitleBar"
|
||||
|
@ -141,7 +142,11 @@
|
|||
|
||||
<provider android:name="org.mozilla.gecko.db.BrowserProvider"
|
||||
android:authorities="org.mozilla.gecko.providers.browser"
|
||||
android:exported="false"/>
|
||||
android:permission="org.mozilla.gecko.permissions.BROWSER_PROVIDER"/>
|
||||
|
||||
</application>
|
||||
|
||||
<permission android:name="org.mozilla.gecko.permissions.BROWSER_PROVIDER"
|
||||
android:protectionLevel="signature"/>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -84,7 +84,7 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
|
|||
mAwesomeTabs = (AwesomeBarTabs) findViewById(R.id.awesomebar_tabs);
|
||||
mAwesomeTabs.setOnUrlOpenListener(new AwesomeBarTabs.OnUrlOpenListener() {
|
||||
public void onUrlOpen(String url) {
|
||||
openUrlAndFinish(url);
|
||||
submitAndFinish(url);
|
||||
}
|
||||
|
||||
public void onSearch(String engine) {
|
||||
|
@ -95,7 +95,7 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
|
|||
mGoButton = (ImageButton) findViewById(R.id.awesomebar_button);
|
||||
mGoButton.setOnClickListener(new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
openUrlAndFinish(mText.getText().toString());
|
||||
submitAndFinish(mText.getText().toString());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -166,7 +166,7 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
|
|||
if (event.getAction() != KeyEvent.ACTION_DOWN)
|
||||
return true;
|
||||
|
||||
openUrlAndFinish(mText.getText().toString());
|
||||
submitAndFinish(mText.getText().toString());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -209,6 +209,34 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method tries to guess if the given string could be a search query or URL
|
||||
* Search examples:
|
||||
* foo
|
||||
* foo bar.com
|
||||
* foo http://bar.com
|
||||
*
|
||||
* URL examples
|
||||
* foo.com
|
||||
* foo.c
|
||||
* :foo
|
||||
* http://foo.com bar
|
||||
*/
|
||||
private boolean isSearchUrl(String text) {
|
||||
text = text.trim();
|
||||
if (text.length() == 0)
|
||||
return false;
|
||||
|
||||
int colon = text.indexOf(':');
|
||||
int dot = text.indexOf('.');
|
||||
int space = text.indexOf(' ');
|
||||
|
||||
// If a space is found before any dot or colon, we assume this is a search query
|
||||
boolean spacedOut = space > -1 && (space < colon || space < dot);
|
||||
|
||||
return spacedOut || (dot == -1 && colon == -1);
|
||||
}
|
||||
|
||||
private void updateGoButton(String text) {
|
||||
if (text.length() == 0) {
|
||||
mGoButton.setVisibility(View.GONE);
|
||||
|
@ -218,13 +246,19 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
|
|||
mGoButton.setVisibility(View.VISIBLE);
|
||||
|
||||
int imageResource = R.drawable.ic_awesomebar_go;
|
||||
if (!GeckoAppShell.canCreateFixupURI(text)) {
|
||||
if (isSearchUrl(text))
|
||||
imageResource = R.drawable.ic_awesomebar_search;
|
||||
}
|
||||
|
||||
mGoButton.setImageResource(imageResource);
|
||||
}
|
||||
|
||||
private void submitAndFinish(String url) {
|
||||
if (isSearchUrl(url))
|
||||
openSearchAndFinish(url, "__default__");
|
||||
else
|
||||
openUrlAndFinish(url);
|
||||
}
|
||||
|
||||
private void cancelAndFinish() {
|
||||
setResult(Activity.RESULT_CANCELED);
|
||||
finish();
|
||||
|
|
|
@ -165,7 +165,7 @@ public class CrashReporter extends Activity
|
|||
public void run() {
|
||||
sendReport(mPendingMinidumpFile, mExtrasStringMap, mPendingExtrasFile);
|
||||
}
|
||||
}).start();
|
||||
}, "CrashReporter Thread").start();
|
||||
}
|
||||
|
||||
public void onCloseClick(View v) { // bound via crash_reporter.xml
|
||||
|
|
|
@ -222,6 +222,9 @@ abstract public class GeckoApp
|
|||
public ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<PackageInfo>();
|
||||
|
||||
String[] getPluginDirectories() {
|
||||
// we don't support Honeycomb and later
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
return new String[0];
|
||||
|
||||
Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - start of getPluginDirectories");
|
||||
|
||||
|
@ -453,11 +456,13 @@ abstract public class GeckoApp
|
|||
MenuItem forward = aMenu.findItem(R.id.forward);
|
||||
MenuItem share = aMenu.findItem(R.id.share);
|
||||
MenuItem agentMode = aMenu.findItem(R.id.agent_mode);
|
||||
MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
|
||||
|
||||
if (tab == null) {
|
||||
bookmark.setEnabled(false);
|
||||
forward.setEnabled(false);
|
||||
share.setEnabled(false);
|
||||
saveAsPDF.setEnabled(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -478,7 +483,11 @@ abstract public class GeckoApp
|
|||
|
||||
// Don't share about:, chrome: and file: URIs
|
||||
String scheme = Uri.parse(tab.getURL()).getScheme();
|
||||
share.setEnabled(!scheme.equals("about") && !scheme.equals("chrome") && !scheme.equals("file"));
|
||||
share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") || scheme.equals("file")));
|
||||
|
||||
// Disable save as PDF for about:home and xul pages
|
||||
saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
|
||||
tab.getContentType().equals("application/vnd.mozilla.xul+xml")));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -563,21 +572,26 @@ abstract public class GeckoApp
|
|||
super.onSaveInstanceState(outState);
|
||||
if (mOwnActivityDepth > 0)
|
||||
return; // we're showing one of our own activities and likely won't get paged out
|
||||
|
||||
if (outState == null)
|
||||
outState = new Bundle();
|
||||
mRememberLastScreenRunnable.run();
|
||||
|
||||
new SessionSnapshotRunnable(null).run();
|
||||
|
||||
outState.putString(SAVED_STATE_URI, mLastUri);
|
||||
outState.putString(SAVED_STATE_TITLE, mLastTitle);
|
||||
outState.putString(SAVED_STATE_VIEWPORT, mLastViewport);
|
||||
outState.putByteArray(SAVED_STATE_SCREEN, mLastScreen);
|
||||
}
|
||||
|
||||
Runnable mRememberLastScreenRunnable = new Runnable() {;
|
||||
public void run() {
|
||||
synchronized (this) {
|
||||
if (mUserDefinedProfile)
|
||||
return;
|
||||
public class SessionSnapshotRunnable implements Runnable {
|
||||
Tab mThumbnailTab;
|
||||
SessionSnapshotRunnable(Tab thumbnailTab) {
|
||||
mThumbnailTab = thumbnailTab;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
synchronized (mSoftwareLayerClient) {
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab == null)
|
||||
return;
|
||||
|
@ -598,6 +612,10 @@ abstract public class GeckoApp
|
|||
mLastTitle = lastHistoryEntry.mTitle;
|
||||
Bitmap bitmap = mSoftwareLayerClient.getBitmap();
|
||||
if (bitmap != null) {
|
||||
// Make a thumbnail for the given tab, if it's still selected
|
||||
if (tab == mThumbnailTab)
|
||||
mThumbnailTab.updateThumbnail(bitmap);
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
|
||||
mLastScreen = bos.toByteArray();
|
||||
|
@ -606,7 +624,7 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void maybeCancelFaviconLoad(Tab tab) {
|
||||
long faviconLoadId = tab.getFaviconLoadId();
|
||||
|
@ -655,7 +673,8 @@ abstract public class GeckoApp
|
|||
tab.setFaviconLoadId(id);
|
||||
}
|
||||
|
||||
void handleLocationChange(final int tabId, final String uri) {
|
||||
void handleLocationChange(final int tabId, final String uri,
|
||||
final String documentURI, final String contentType) {
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
@ -669,6 +688,8 @@ abstract public class GeckoApp
|
|||
|
||||
String oldBaseURI = tab.getURL();
|
||||
tab.updateURL(uri);
|
||||
tab.setDocumentURI(documentURI);
|
||||
tab.setContentType(contentType);
|
||||
|
||||
String baseURI = uri;
|
||||
if (baseURI.indexOf('#') != -1)
|
||||
|
@ -836,8 +857,10 @@ abstract public class GeckoApp
|
|||
} else if (event.equals("Content:LocationChange")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final String uri = message.getString("uri");
|
||||
final String documentURI = message.getString("documentURI");
|
||||
final String contentType = message.getString("contentType");
|
||||
Log.i(LOGTAG, "URI - " + uri);
|
||||
handleLocationChange(tabId, uri);
|
||||
handleLocationChange(tabId, uri, documentURI, contentType);
|
||||
} else if (event.equals("Content:SecurityChange")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final String mode = message.getString("mode");
|
||||
|
@ -890,6 +913,11 @@ abstract public class GeckoApp
|
|||
setLaunchState(GeckoApp.LaunchState.GeckoRunning);
|
||||
GeckoAppShell.sendPendingEventsToGecko();
|
||||
connectGeckoLayerClient();
|
||||
GeckoAppShell.getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
Looper.myQueue().addIdleHandler(new UpdateIdleHandler());
|
||||
}
|
||||
});
|
||||
} else if (event.equals("ToggleChrome:Hide")) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
|
@ -1023,10 +1051,6 @@ abstract public class GeckoApp
|
|||
}
|
||||
|
||||
void handleSelectTab(int tabId) {
|
||||
Tab selTab = Tabs.getInstance().getSelectedTab();
|
||||
if (selTab != null)
|
||||
selTab.updateThumbnail(mSoftwareLayerClient.getBitmap());
|
||||
|
||||
final Tab tab = Tabs.getInstance().selectTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
@ -1084,6 +1108,9 @@ abstract public class GeckoApp
|
|||
onTabsChanged(tab);
|
||||
}
|
||||
});
|
||||
|
||||
Runnable r = new SessionSnapshotRunnable(tab);
|
||||
GeckoAppShell.getHandler().postDelayed(r, 500);
|
||||
}
|
||||
|
||||
void handleShowToast(final String message, final String duration) {
|
||||
|
@ -1106,18 +1133,17 @@ abstract public class GeckoApp
|
|||
|
||||
tab.updateTitle(title);
|
||||
|
||||
// Make the UI changes
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
loadFavicon(tab);
|
||||
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setTitle(tab.getDisplayTitle());
|
||||
tab.updateThumbnail(mSoftwareLayerClient.getBitmap());
|
||||
}
|
||||
|
||||
onTabsChanged(tab);
|
||||
}
|
||||
});
|
||||
GeckoAppShell.getHandler().postDelayed(mRememberLastScreenRunnable, 500);
|
||||
}
|
||||
|
||||
void handleTitleChanged(int tabId, String title) {
|
||||
|
@ -1251,7 +1277,13 @@ abstract public class GeckoApp
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
// StrictMode is set by defaults resource flag |enableStrictMode|.
|
||||
if (getResources().getBoolean(R.bool.enableStrictMode)) {
|
||||
enableStrictMode();
|
||||
}
|
||||
|
||||
System.loadLibrary("mozutils");
|
||||
mMainHandler = new Handler();
|
||||
Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - onCreate");
|
||||
if (savedInstanceState != null) {
|
||||
mLastUri = savedInstanceState.getString(SAVED_STATE_URI);
|
||||
|
@ -1259,11 +1291,16 @@ abstract public class GeckoApp
|
|||
mLastViewport = savedInstanceState.getString(SAVED_STATE_VIEWPORT);
|
||||
mLastScreen = savedInstanceState.getByteArray(SAVED_STATE_SCREEN);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 9) {
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectDiskReads().detectDiskWrites().detectNetwork()
|
||||
.penaltyLog().build());
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().penaltyLog().build());
|
||||
String uri = getIntent().getDataString();
|
||||
String title = uri;
|
||||
if (uri != null && uri.length() > 0) {
|
||||
mLastUri = uri;
|
||||
mLastTitle = title;
|
||||
}
|
||||
|
||||
if (mLastUri == null || mLastUri.equals("") ||
|
||||
mLastUri.equals("about:home")) {
|
||||
showAboutHome();
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -1342,8 +1379,6 @@ abstract public class GeckoApp
|
|||
if (sGREDir == null)
|
||||
sGREDir = new File(this.getApplicationInfo().dataDir);
|
||||
|
||||
mMainHandler = new Handler();
|
||||
|
||||
if (!sTryCatchAttached) {
|
||||
sTryCatchAttached = true;
|
||||
mMainHandler.post(new Runnable() {
|
||||
|
@ -1401,31 +1436,27 @@ abstract public class GeckoApp
|
|||
registerReceiver(mSmsReceiver, smsFilter);
|
||||
|
||||
final GeckoApp self = this;
|
||||
}
|
||||
|
||||
mMainHandler.postDelayed(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - pre checkLaunchState");
|
||||
|
||||
/*
|
||||
XXXX see bug 635342
|
||||
We want to disable this code if possible. It is about 145ms in runtime
|
||||
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
||||
String localeCode = settings.getString(getPackageName() + ".locale", "");
|
||||
if (localeCode != null && localeCode.length() > 0)
|
||||
GeckoAppShell.setSelectedLocale(localeCode);
|
||||
/**
|
||||
* Enable Android StrictMode checks (for supported OS versions).
|
||||
* http://developer.android.com/reference/android/os/StrictMode.html
|
||||
*/
|
||||
|
||||
if (!checkLaunchState(LaunchState.Launched)) {
|
||||
private void enableStrictMode()
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
|
||||
return;
|
||||
}
|
||||
|
||||
// it would be good only to do this if MOZ_UPDATER was defined
|
||||
long startTime = new Date().getTime();
|
||||
checkAndLaunchUpdate();
|
||||
Log.w(LOGTAG, "checking for an update took " + (new Date().getTime() - startTime) + "ms");
|
||||
}
|
||||
}, 50);
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
}
|
||||
|
||||
public void enableCameraView() {
|
||||
|
@ -1491,7 +1522,8 @@ abstract public class GeckoApp
|
|||
{
|
||||
Log.i(LOGTAG, "pause");
|
||||
|
||||
GeckoAppShell.getHandler().post(mRememberLastScreenRunnable);
|
||||
Runnable r = new SessionSnapshotRunnable(null);
|
||||
GeckoAppShell.getHandler().post(r);
|
||||
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_PAUSING));
|
||||
// The user is navigating away from this activity, but nothing
|
||||
|
@ -1668,6 +1700,21 @@ abstract public class GeckoApp
|
|||
GeckoAppShell.handleNotification(action, alertName, alertCookie);
|
||||
}
|
||||
|
||||
// it would be good only to do this if MOZ_UPDATER was defined
|
||||
private class UpdateIdleHandler implements MessageQueue.IdleHandler {
|
||||
public boolean queueIdle() {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
long startTime = new Date().getTime();
|
||||
checkAndLaunchUpdate();
|
||||
Log.w(LOGTAG, "checking for an update took " + (new Date().getTime() - startTime) + "ms");
|
||||
}
|
||||
});
|
||||
// only need to run this once.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAndLaunchUpdate() {
|
||||
Log.i(LOGTAG, "Checking for an update");
|
||||
|
||||
|
@ -2047,7 +2094,7 @@ abstract public class GeckoApp
|
|||
// we really don't care.
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}, "DNSPrefetcher Thread").start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче