This commit is contained in:
Rob Campbell 2011-12-14 10:28:49 -04:00
Родитель 83f69bf800 54d8d54f8e
Коммит 0b84a96de6
220 изменённых файлов: 4376 добавлений и 3785 удалений

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

@ -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)

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

@ -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;

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

@ -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, &current_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, &current_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();
}
}

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