Merge mozilla-central and mozilla-inbound

This commit is contained in:
Matt Brubeck 2011-12-28 11:17:19 -08:00
commit 442a1b085f
71 changed files with 1811 additions and 317 deletions

View File

@ -147,6 +147,7 @@
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_b2g.xpt
#endif
@BINPATH@/components/dom_battery.xpt
@ -396,6 +397,8 @@
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib

View File

@ -47,14 +47,7 @@ tabbrowser {
.tab-label:not([fadein]):not([pinned]),
.tab-icon-image:not([fadein]):not([pinned]),
.tab-close-button:not([fadein]):not([pinned]) {
opacity: 0 !important;
}
.tab-throbber,
.tab-label,
.tab-icon-image,
.tab-close-button {
-moz-transition: opacity 250ms;
display: none;
}
.tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {

View File

@ -398,20 +398,20 @@
<tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
<tooltip id="back-button-tooltip">
<label value="&backButton.tooltip;"/>
<label class="tooltip-label" value="&backButton.tooltip;"/>
#ifdef XP_MACOSX
<label value="&backForwardButtonMenuMac.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
#else
<label value="&backForwardButtonMenu.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
#endif
</tooltip>
<tooltip id="forward-button-tooltip">
<label value="&forwardButton.tooltip;"/>
<label class="tooltip-label" value="&forwardButton.tooltip;"/>
#ifdef XP_MACOSX
<label value="&backForwardButtonMenuMac.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
#else
<label value="&backForwardButtonMenu.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
#endif
</tooltip>
</popupset>

View File

@ -138,6 +138,7 @@
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_b2g.xpt
#endif
@BINPATH@/components/dom_battery.xpt
@ -366,6 +367,8 @@
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
@BINPATH@/components/BrowserProfileMigrators.manifest
@BINPATH@/components/ChromeProfileMigrator.js

View File

@ -70,6 +70,7 @@ components/pluginGlue.js
components/sidebar.xpt
#ifdef MOZ_B2G_RIL
components/dom_telephony.xpt
components/dom_wifi.xpt
components/dom_system_b2g.xpt
#endif
components/uconvd.dll
@ -922,6 +923,8 @@ xpicleanup@BIN_SUFFIX@
components/nsTelephonyWorker.js
components/Telephony.manifest
components/Telephony.js
components/nsWifiWorker.js
components/nsWifiWorker.manifest
#endif
components/txEXSLTRegExFunctions.js
components/Weave.js
@ -1143,6 +1146,7 @@ xpicleanup@BIN_SUFFIX@
components/dom_base.xpt
#ifdef MOZ_B2G_RIL
components/dom_telephony.xpt
components/dom_wifi.xpt
components/dom_system_b2g.xpt
#endif
components/dom_canvas.xpt

View File

@ -84,7 +84,10 @@ DIRS += \
$(NULL)
ifdef MOZ_B2G_RIL #{
DIRS += telephony
DIRS += \
telephony \
wifi \
$(NULL)
endif #}
ifdef ENABLE_TESTS

View File

@ -1035,6 +1035,14 @@ Navigator::SizeOf() const
return size;
}
void
Navigator::SetWindow(nsPIDOMWindow *aInnerWindow)
{
NS_ASSERTION(aInnerWindow->IsInnerWindow(),
"Navigator must get an inner window!");
mWindow = do_GetWeakReference(aInnerWindow);
}
} // namespace dom
} // namespace mozilla

View File

@ -103,6 +103,11 @@ public:
PRInt64 SizeOf() const;
/**
* For use during document.write where our inner window changes.
*/
void SetWindow(nsPIDOMWindow *aInnerWindow);
private:
bool IsSmsAllowed() const;
bool IsSmsSupported() const;

View File

@ -1988,7 +1988,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (aState) {
newInnerWindow = wsh->GetInnerWindow();
mInnerWindowHolder = wsh->GetInnerWindowHolder();
NS_ASSERTION(newInnerWindow, "Got a state without inner window");
} else if (thisChrome) {
newInnerWindow = new nsGlobalChromeWindow(this);
@ -2038,6 +2038,15 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
bool termFuncSet = false;
if (oldDoc == aDocument) {
// Move the navigator from the old inner window to the new one since
// this is a document.write. This is safe from a same-origin point of
// view because document.write can only be used by the same origin.
newInnerWindow->mNavigator = currentInner->mNavigator;
currentInner->mNavigator = nsnull;
if (newInnerWindow->mNavigator) {
newInnerWindow->mNavigator->SetWindow(newInnerWindow);
}
// Suspend the current context's request before Pop() resumes the old
// context's request.
JSAutoSuspendRequest asr(cx);

View File

@ -66,6 +66,7 @@ XPIDLSRCS = \
LOCAL_INCLUDES = \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/dom/telephony \
-I$(topsrcdir)/dom/wifi \
-I$(topsrcdir)/content/events/src \
$(NULL)

View File

@ -45,7 +45,11 @@
#include "nsIObserverService.h"
#include "mozilla/dom/workers/Workers.h"
#include "jstypedarray.h"
#include "nsTelephonyWorker.h"
#include "nsITelephone.h"
#include "nsWifiWorker.h"
#include "nsIWifi.h"
#include "nsThreadUtils.h"
@ -60,6 +64,7 @@ USING_WORKERS_NAMESPACE
using namespace mozilla::ipc;
static NS_DEFINE_CID(kTelephonyWorkerCID, NS_TELEPHONYWORKER_CID);
static NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
// Topic we listen to for shutdown.
#define PROFILE_BEFORE_CHANGE_TOPIC "profile-before-change"
@ -225,16 +230,6 @@ RadioManager::Init()
nsresult rv = obs->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
// The telephony worker component is a hack that gives us a global object for
// our own functions and makes creating the worker possible.
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
jsval workerval;
rv = worker->GetWorker(&workerval);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");
JSContext *cx;
rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
@ -243,30 +238,11 @@ RadioManager::Init()
return NS_ERROR_FAILURE;
}
JSObject *workerobj = JSVAL_TO_OBJECT(workerval);
rv = InitTelephone(cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, workerobj)) {
return NS_ERROR_OUT_OF_MEMORY;
}
WorkerCrossThreadDispatcher *wctd = GetWorkerCrossThreadDispatcher(cx, workerval);
if (!wctd) {
return NS_ERROR_FAILURE;
}
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
if (!wctd->PostTask(connection)) {
return NS_ERROR_UNEXPECTED;
}
// Now that we're set up, connect ourselves to the RIL thread.
mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
StartRil(receiver);
mTelephone = do_QueryInterface(worker);
NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);
rv = InitWifi(cx);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -278,6 +254,7 @@ RadioManager::Shutdown()
StopRil();
mTelephone = nsnull;
mWifi = nsnull;
mShutdown = true;
}
@ -316,6 +293,59 @@ RadioManager::GetTelephone()
return nsnull;
}
nsresult
RadioManager::InitTelephone(JSContext *cx)
{
// The telephony worker component is a hack that gives us a global object for
// our own functions and makes creating the worker possible.
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
jsval workerval;
nsresult rv = worker->GetWorker(&workerval);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");
JSObject *workerobj = JSVAL_TO_OBJECT(workerval);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, workerobj)) {
return NS_ERROR_OUT_OF_MEMORY;
}
WorkerCrossThreadDispatcher *wctd = GetWorkerCrossThreadDispatcher(cx, workerval);
if (!wctd) {
return NS_ERROR_FAILURE;
}
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
if (!wctd->PostTask(connection)) {
return NS_ERROR_UNEXPECTED;
}
// Now that we're set up, connect ourselves to the RIL thread.
mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
StartRil(receiver);
mTelephone = do_QueryInterface(worker);
NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);
return NS_OK;
}
nsresult
RadioManager::InitWifi(JSContext *cx)
{
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kWifiWorkerCID));
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
mWifi = do_QueryInterface(worker);
NS_ENSURE_TRUE(mWifi, NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMPL_ISUPPORTS1(RadioManager, nsIObserver)

View File

@ -48,7 +48,6 @@
#include "nsIObserver.h"
#include "mozilla/ipc/Ril.h"
#include "nsITelephone.h"
#define TELEPHONYRADIO_CONTRACTID "@mozilla.org/telephony/radio;1"
#define TELEPHONYRADIOINTERFACE_CONTRACTID "@mozilla.org/telephony/radio-interface;1"
@ -70,6 +69,8 @@
class nsIXPConnectJSObjectHolder;
class nsITelephone;
class nsIWifi;
BEGIN_TELEPHONY_NAMESPACE
@ -92,7 +93,11 @@ protected:
RadioManager();
~RadioManager();
nsresult InitTelephone(JSContext *cx);
nsresult InitWifi(JSContext *cx);
nsCOMPtr<nsITelephone> mTelephone;
nsCOMPtr<nsIWifi> mWifi;
bool mShutdown;
};

View File

@ -152,6 +152,7 @@ _TEST_FILES = \
devicemotion_outer.html \
devicemotion_inner.html \
test_bug698061.html \
test_bug707749.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=707749
-->
<head>
<title>Test for Bug 707749</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=707749 ">Mozilla Bug 707749 </a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 707749 **/
SimpleTest.waitForExplicitFinish();
function loaded() {
$('ifr').contentDocument.open();
$('ifr').contentDocument.close();
ok(true, "Don't throw an exception from contentDocument.open()");
SimpleTest.finish();
}
</script>
<iframe id="ifr" onload="loaded()" src="data:text/html,<script>navigator</script>"></iframe>
</pre>
</body>
</html>

70
dom/wifi/Makefile.in Normal file
View File

@ -0,0 +1,70 @@
# ***** 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 Telephony.
#
# 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):
# Ben Turner <bent.mozilla@gmail.com> (Original Author)
#
# 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 = dom
LIBRARY_NAME = domwifi_s
XPIDL_MODULE = dom_wifi
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
include $(topsrcdir)/dom/dom-config.mk
XPIDLSRCS = \
nsIWifi.idl \
$(NULL)
EXTRA_COMPONENTS = \
nsWifiWorker.js \
nsWifiWorker.manifest \
$(NULL)
EXTRA_JS_MODULES = \
libcutils.js \
libhardware_legacy.js \
libnetutils.js \
network_worker.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

13
dom/wifi/libcutils.js Normal file
View File

@ -0,0 +1,13 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
let libcutils = (function () {
let library = ctypes.open("/system/lib/libcutils.so");
return {
property_get: library.declare("property_get", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr, ctypes.char.ptr),
property_set: library.declare("property_set", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr)
};
})();

View File

@ -0,0 +1,36 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
let libhardware_legacy = (function () {
let library = ctypes.open("/system/lib/libhardware_legacy.so");
return {
// Load wifi driver, 0 on success, < 0 on failure.
load_driver: library.declare("wifi_load_driver", ctypes.default_abi, ctypes.int),
// Unload wifi driver, 0 on success, < 0 on failure.
unload_driver: library.declare("wifi_unload_driver", ctypes.default_abi, ctypes.int),
// Start supplicant, 0 on success, < 0 on failure.
start_supplicant: library.declare("wifi_start_supplicant", ctypes.default_abi, ctypes.int),
// Stop supplicant, 0 on success, < 0 on failure.
stop_supplicant: library.declare("wifi_stop_supplicant", ctypes.default_abi, ctypes.int),
// Open a connection to the supplicant, 0 on success, < 0 on failure.
connect_to_supplicant: library.declare("wifi_connect_to_supplicant", ctypes.default_abi, ctypes.int),
// Close connection to connection to the supplicant, 0 on success, < 0 on failure.
close_supplicant_connection: library.declare("wifi_close_supplicant_connection", ctypes.default_abi, ctypes.int),
// Block until a wifi event is returned, buf is the buffer, len is the max length of the buffer.
// Return value is number of bytes in buffer, or 0 if no event (no connection for instance), and < 0 on failure.
wait_for_event: library.declare("wifi_wait_for_event", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.size_t),
// Issue a command to the wifi driver. command is the command string, reply will hold the reply, reply_len contains
// the maximum reply length initially and is updated with the actual length. 0 is returned on success, < 0 on failure.
command: library.declare("wifi_command", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr, ctypes.size_t.ptr),
};
})();

30
dom/wifi/libnetutils.js Normal file
View File

@ -0,0 +1,30 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
let libnetutils = (function () {
let library = ctypes.open("/system/lib/libnetutils.so");
return {
ifc_enable: library.declare("ifc_enable", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_disable: library.declare("ifc_disable", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_add_host_route: library.declare("ifc_add_host_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.int),
ifc_remove_host_routes: library.declare("ifc_remove_host_routes", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_set_default_route: library.declare("ifc_set_default_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.int),
ifc_get_default_route: library.declare("ifc_get_default_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_remove_default_route: library.declare("ifc_remove_default_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_reset_connections: library.declare("ifc_reset_connections", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_configure: library.declare("ifc_configure", ctypes.default_abi, ctypes.int, ctypes.char.ptr,
ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int),
dhcp_do_request: library.declare("dhcp_do_request", ctypes.default_abi, ctypes.int,
ctypes.char.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr,
ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr),
dhcp_stop: library.declare("dhcp_stop", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
dhcp_release_lease: library.declare("dhcp_release_lease", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
dhcp_get_errmsg: library.declare("dhcp_get_errmsg", ctypes.default_abi, ctypes.char.ptr),
dhcp_do_request_renew: library.declare("dhcp_do_request_renew", ctypes.default_abi, ctypes.int,
ctypes.char.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr,
ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr)
};
})();

View File

@ -0,0 +1,94 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
importScripts("libhardware_legacy.js", "libnetutils.js", "libcutils.js");
var cbuf = ctypes.char.array(4096)();
var hwaddr = ctypes.uint8_t.array(6)();
var len = ctypes.size_t();
var ints = ctypes.int.array(8)();
self.onmessage = function(e) {
var data = e.data;
var id = data.id;
var cmd = data.cmd;
switch (cmd) {
case "command":
len.value = 4096;
var ret = libhardware_legacy.command(data.request, cbuf, len.address());
dump("For command " + data.request + " ret is " + ret + "\n");
var reply = "";
if (!ret) {
var reply_len = len.value;
var str = cbuf.readString();
if (str[reply_len-1] == "\n")
--reply_len;
reply = str.substr(0, reply_len);
}
postMessage({ id: id, status: ret, reply: reply });
break;
case "wait_for_event":
var ret = libhardware_legacy.wait_for_event(cbuf, 4096);
var event = cbuf.readString().substr(0, ret.value);
postMessage({ id: id, event: event });
break;
case "ifc_enable":
case "ifc_disable":
case "ifc_remove_host_routes":
case "ifc_remove_default_route":
case "ifc_reset_connections":
case "dhcp_stop":
case "dhcp_release_lease":
var ret = libnetutils[cmd](data.ifname);
postMessage({ id: id, status: ret });
break;
case "ifc_get_default_route":
var route = libnetutils.ifc_get_default_route(data.ifname);
postMessage({ id: id, route: route });
break;
case "ifc_add_host_route":
case "ifc_set_default_route":
var ret = libnetutils[cmd](data.ifname, data.route);
postMessage({ id: id, status: ret });
break;
case "ifc_configure":
dump("WIFI: data: " + uneval(data) + "\n");
var ret = libnetutils.ifc_configure(data.ifname, data.ipaddr, data.mask, data.gateway, data.dns1, data.dns2);
postMessage({ id: id, status: ret });
break;
case "dhcp_get_errmsg":
var error = libnetutils.get_dhcp_get_errmsg();
postMessage({ id: id, error: error.readString() });
break;
case "dhcp_do_request":
case "dhcp_do_request_renew":
var ret = libnetutils[cmd](data.ifname,
ints.addressOfElement(0),
ints.addressOfElement(1),
ints.addressOfElement(2),
ints.addressOfElement(3),
ints.addressOfElement(4),
ints.addressOfElement(5),
ints.addressOfElement(6));
postMessage({ id: id, status: ret, ipaddr: ints[0], gateway: ints[1], mask: ints[2],
dns1: ints[3], dns2: ints[4], server: ints[5], lease: ints[6]});
break;
case "property_get":
var ret = libcutils.property_get(data.key, cbuf, data.defaultValue);
postMessage({ id: id, status: ret, value: cbuf.readString() });
break;
case "property_set":
var ret = libcutils.property_set(data.key, data.value);
postMessage({ id: id, status: ret });
break;
default:
var f = libhardware_legacy[cmd] || libnetutils[cmd];
var ret = f();
dump("WIFI: " + cmd + " returned: " + ret);
postMessage({ id: id, status: ret });
break;
}
}

42
dom/wifi/nsIWifi.idl Normal file
View File

@ -0,0 +1,42 @@
/* ***** 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 Telephony.
*
* 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, uuid(9DCE05BF-659C-4427-A050-0EAC3BB6C1C0)]
interface nsIWifi : nsISupports {
};

40
dom/wifi/nsWifiWorker.h Normal file
View File

@ -0,0 +1,40 @@
/* ***** 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 Telephony.
*
* 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):
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
*
* 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 ***** */
#define NS_WIFIWORKER_CID \
{ 0xA14E8977, 0xD259, 0x433A, \
{ 0xA8, 0x8D, 0x58, 0xDD, 0x44, 0x65, 0x7E, 0x5B } }

853
dom/wifi/nsWifiWorker.js Normal file
View File

@ -0,0 +1,853 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* ***** 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 Telephony.
*
* 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):
* Andreas Gal <gal@mozilla.com>
* Blake Kaplan <mrbkap@gmail.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
* 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 ***** */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const DEBUG = true; // set to false to suppress debug messages
const WIFIWORKER_CONTRACTID = "@mozilla.org/wifi/worker;1";
const WIFIWORKER_CID = Components.ID("{a14e8977-d259-433a-a88d-58dd44657e5b}");
const WIFIWORKER_WORKER = "resource://gre/modules/network_worker.js";
var WifiManager = (function() {
var controlWorker = new ChromeWorker(WIFIWORKER_WORKER);
var eventWorker = new ChromeWorker(WIFIWORKER_WORKER);
// Callbacks to invoke when a reply arrives from the controlWorker.
var controlCallbacks = Object.create(null);
var idgen = 0;
function controlMessage(obj, callback) {
var id = idgen++;
obj.id = id;
if (callback)
controlCallbacks[id] = callback;
controlWorker.postMessage(obj);
}
function onerror(e) {
// It is very important to call preventDefault on the event here.
// If an exception is thrown on the worker, it bubbles out to the
// component that created it. If that component doesn't have an
// onerror handler, the worker will try to call the error reporter
// on the context it was created on. However, That doesn't work
// for component contexts and can result in crashes. This onerror
// handler has to make sure that it calls preventDefault on the
// incoming event.
e.preventDefault();
var worker = (this === controlWorker) ? "control" : "event";
debug("Got an error from the " + worker + " worker: " + e.filename +
":" + e.lineno + ": " + e.message + "\n");
}
controlWorker.onerror = onerror;
eventWorker.onerror = onerror;
controlWorker.onmessage = function(e) {
var data = e.data;
var id = data.id;
var callback = controlCallbacks[id];
if (callback) {
callback(data);
delete controlCallbacks[id];
}
};
// Polling the status worker
var recvErrors = 0;
eventWorker.onmessage = function(e) {
// process the event and tell the event worker to listen for more events
if (handleEvent(e.data.event))
waitForEvent();
};
function waitForEvent() {
eventWorker.postMessage({ cmd: "wait_for_event" });
}
// Commands to the control worker
function voidControlMessage(cmd, callback) {
controlMessage({ cmd: cmd }, function (data) {
callback(data.status);
});
}
function loadDriver(callback) {
voidControlMessage("load_driver", callback);
}
function unloadDriver(callback) {
voidControlMessage("unload_driver", callback);
}
function startSupplicant(callback) {
voidControlMessage("start_supplicant", callback);
}
function stopSupplicant(callback) {
voidControlMessage("stop_supplicant", callback);
}
function connectToSupplicant(callback) {
voidControlMessage("connect_to_supplicant", callback);
}
function closeSupplicantConnection(callback) {
voidControlMessage("close_supplicant_connection", callback);
}
function doCommand(request, callback) {
controlMessage({ cmd: "command", request: request }, callback);
}
function doIntCommand(request, callback) {
doCommand(request, function(data) {
callback(data.status ? -1 : (data.reply|0));
});
}
function doBooleanCommand(request, expected, callback) {
doCommand(request, function(data) {
callback(data.status ? false : (data.reply == expected));
});
}
function doStringCommand(request, callback) {
doCommand(request, function(data) {
callback(data.status ? null : data.reply);
});
}
function listNetworksCommand(callback) {
doStringCommand("LIST_NETWORKS", callback);
}
function addNetworkCommand(callback) {
doIntCommand("ADD_NETWORK", callback);
}
function setNetworkVariableCommand(netId, name, value, callback) {
doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value, "OK", callback);
}
function getNetworkVariableCommand(netId, name, callback) {
doStringCommand("GET_NETWORK " + netId + " " + name, callback);
}
function removeNetworkCommand(netId, callback) {
doBooleanCommand("REMOVE_NETWORK " + netId, callback);
}
function enableNetworkCommand(netId, disableOthers, callback) {
doBooleanCommand((disableOthers ? "SELECT_NETWORK " : "ENABLE_NETWORK ") + netId, "OK", callback);
}
function disableNetworkCommand(netId, callback) {
doBooleanCommand("DISABLE_NETWORK " + netId, "OK", callback);
}
function statusCommand(callback) {
doStringCommand("STATUS", callback);
}
function pingCommand(callback) {
doBooleanCommand("PING", "PONG", callback);
}
function scanResultsCommand(callback) {
doStringCommand("SCAN_RESULTS", callback);
}
function disconnectCommand(callback) {
doBooleanCommand("DISCONNECT", "OK", callback);
}
function reconnectCommand(callback) {
doBooleanCommand("RECONNECT", "OK", callback);
}
function reassociateCommand(callback) {
doBooleanCommand("REASSOCIATE", "OK", callback);
}
var scanModeActive = false;
function doSetScanModeCommand(setActive, callback) {
doBooleanCommand(setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE", "OK", callback);
}
function scanCommand(forceActive, callback) {
if (forceActive && !scanModeActive) {
doSetScanModeCommand(true, function(ok) {
ok && doBooleanCommand("SCAN", "OK", function(ok) {
ok && doSetScanModeCommand(false, callback);
});
});
return;
}
doBooleanCommand("SCAN", "OK", callback);
}
function setScanModeCommand(setActive, callback) {
sScanModeActive = setActive;
doSetScanModeCommand(setActive, callback);
}
function startDriverCommand(callback) {
doBooleanCommand("DRIVER START", "OK");
}
function stopDriverCommand(callback) {
doBooleanCommand("DRIVER STOP", "OK");
}
function startPacketFiltering(callback) {
doBooleanCommand("DRIVER RXFILTER-ADD 0", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-ADD 1", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-ADD 3", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-START", "OK", callback)
});
});
});
}
function stopPacketFiltering(callback) {
doBooleanCommand("DRIVER RXFILTER-STOP", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 3", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 1", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 0", "OK", callback)
});
});
});
}
function doGetRssiCommand(cmd, callback) {
doCommand(cmd, function(data) {
var rssi = -200;
if (!data.status) {
// If we are associating, the reply is "OK".
var reply = data.reply;
if (reply != "OK") {
// Format is: <SSID> rssi XX". SSID can contain spaces.
var offset = reply.lastIndexOf("rssi ");
if (offset != -1)
rssi = reply.substr(offset + 5) | 0;
}
}
callback(rssi);
});
}
function getRssiCommand(callback) {
doGetRssiCommand("DRIVER RSSI", callback);
}
function getRssiApproxCommand(callback) {
doGetRssiCommand("DRIVER RSSI-APPROX", callback);
}
function getLinkSpeedCommand(callback) {
doStringCommand("DRIVER LINKSPEED", function(reply) {
if (reply)
reply = reply.split()[1] | 0; // Format: LinkSpeed XX
callback(reply);
});
}
function getMacAddressCommand(callback) {
doStringCommand("DRIVER MACADDR", function(reply) {
if (reply)
reply = reply.split(" ")[2]; // Format: Macaddr = XX.XX.XX.XX.XX.XX
callback(reply);
});
}
function setPowerModeCommand(mode, callback) {
doBooleanCommand("DRIVER POWERMODE " + mode, "OK", callback);
}
function getPowerModeCommand(callback) {
doStringCommand("DRIVER GETPOWER", function(reply) {
if (reply)
reply = (reply.split()[2]|0); // Format: powermode = XX
callback(reply);
});
}
function setNumAllowedChannelsCommand(numChannels, callback) {
doBooleanCommand("DRIVER SCAN-CHANNELS " + numChannels, "OK", callback);
}
function getNumAllowedChannelsCommand(callback) {
doStringCommand("DRIVER SCAN-CHANNELS", function(reply) {
if (reply)
reply = (reply.split()[2]|0); // Format: Scan-Channels = X
callback(reply);
});
}
function setBluetoothCoexistenceModeCommand(mode, callback) {
doBooleanCommand("DRIVER BTCOEXMODE " + mode, "OK", callback);
}
function setBluetoothCoexistenceScanModeCommand(mode, callback) {
doBooleanCommand("DRIVER BTCOEXSCAN-" + (mode ? "START" : "STOP"), "OK", callback);
}
function saveConfigCommand(callback) {
// Make sure we never write out a value for AP_SCAN other than 1
doBooleanCommand("AP_SCAN 1", "OK", function(ok) {
doBooleanCommand("SAVE_CONFIG", "OK", callback);
});
}
function reloadConfigCommand(callback) {
doBooleanCommand("RECONFIGURE", "OK", callback);
}
function setScanResultHandlingCommand(mode, callback) {
doBooleanCommand("AP_SCAN " + mode, "OK", callback);
}
function addToBlacklistCommand(bssid, callback) {
doBooleanCommand("BLACKLIST " + bssid, "OK", callback);
}
function clearBlacklistCommand(callback) {
doBooleanCommand("BLACKLIST clear", "OK", callback);
}
function setSuspendOptimizationsCommand(enabled, callback) {
doBooleanCommand("DRIVER SETSUSPENDOPT " + (enabled ? 0 : 1), "OK", callback);
}
function getProperty(key, defaultValue, callback) {
controlMessage({ cmd: "property_get", key: key, defaultValue: defaultValue }, function(data) {
callback(data.status < 0 ? null : data.value);
});
}
function setProperty(key, value, callback) {
controlMessage({ cmd: "property_set", key: key, value: value }, function(data) {
callback(!data.status);
});
}
function enableInterface(ifname, callback) {
controlMessage({ cmd: "ifc_enable", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function disableInterface(ifname, callback) {
controlMessage({ cmd: "ifc_disable", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function addHostRoute(ifname, route, callback) {
controlMessage({ cmd: "ifc_add_host_route", ifname: ifname, route: route }, function(data) {
callback(!data.status);
});
}
function removeHostRoutes(ifname, callback) {
controlMessage({ cmd: "ifc_remove_host_routes", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function setDefaultRoute(ifname, route, callback) {
controlMessage({ cmd: "ifc_set_default_route", ifname: ifname, route: route }, function(data) {
callback(!data.status);
});
}
function getDefaultRoute(ifname, callback) {
controlMessage({ cmd: "ifc_get_default_route", ifname: ifname }, function(data) {
callback(!data.route);
});
}
function removeDefaultRoute(ifname, callback) {
controlMessage({ cmd: "ifc_remove_default_route", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function resetConnections(ifname, callback) {
controlMessage({ cmd: "ifc_reset_connections", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function runDhcp(ifname, callback) {
controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
callback(data.status ? null : data);
});
}
function stopDhcp(ifname, callback) {
controlMessage({ cmd: "dhcp_stop", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function releaseDhcpLease(ifname, callback) {
controlMessage({ cmd: "dhcp_release_lease", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function getDhcpError(callback) {
controlMessage({ cmd: "dhcp_get_errmsg" }, function(data) {
callback(data.error);
});
}
function configureInterface(ifname, ipaddr, mask, gateway, dns1, dns2, callback) {
controlMessage({ cmd: "ifc_configure", ifname: ifname,
ipaddr: ipaddr, mask: mask, gateway: gateway,
dns1: dns1, dns2: dns2}, function(data) {
callback(!data.status);
});
}
function runDhcpRenew(ifname, callback) {
controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
callback(data.status ? null : data);
});
}
var manager = {};
function notify(eventName, eventObject) {
var handler = manager["on" + eventName];
if (handler) {
if (!eventObject)
eventObject = ({});
handler.call(eventObject);
}
}
// try to connect to the supplicant
var connectTries = 0;
var retryTimer = null;
function connectCallback(ok) {
if (ok === 0) {
// tell the event worker to start waiting for events
retryTimer = null;
waitForEvent();
notify("supplicantconnection");
return;
}
if (connectTries++ < 3) {
// try again in 5 seconds
if (!retryTimer)
retryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
retryTimer.initWithCallback(function(timer) {
connectToSupplicant(connectCallback);
}, 5000, Ci.nsITimer.TYPE_ONE_SHOT);
return;
}
retryTimer = null;
notify("supplicantlost");
}
manager.start = function() {
connectToSupplicant(connectCallback);
}
var supplicantStatesMap = ["DISCONNECTED", "INACTIVE", "SCANNING", "ASSOCIATING",
"FOUR_WAY_HANDSHAKE", "GROUP_HANDSHAKE", "COMPLETED",
"DORMANT", "UNINITIALIZED"];
var driverEventMap = { STOPPED: "driverstopped", STARTED: "driverstarted", HANGED: "driverhung" };
// handle events sent to us by the event worker
function handleEvent(event) {
debug("Event coming in: " + event);
if (event.indexOf("CTRL-EVENT-") !== 0) {
debug("Got weird event, possibly not doing anything.");
if (event.indexOf("WPA:") == 0 &&
event.indexOf("pre-shared key may be incorrect") != -1) {
notify("passwordmaybeincorrect");
}
return true;
}
var eventData = event.substr(0, event.indexOf(" ") + 1);
if (eventData.indexOf("CTRL-EVENT-STATE-CHANGE") === 0) {
// Parse the event data
var fields = {};
var tokens = eventData.split(" ");
for (var n = 0; n < tokens.length; ++n) {
var kv = tokens[n].split("=");
if (kv.length === 2)
fields[kv[0]] = kv[1];
}
if (!("state" in fields))
return true;
fields.state = supplicantStatesMap[fields.state];
notify("statechange", fields);
return true;
}
if (eventData.indexOf("CTRL-EVENT-DRIVER-STATE") === 0) {
var handlerName = driverEventMap[eventData];
if (handlerName)
notify(handlerName);
return true;
}
if (eventData.indexOf("CTRL-EVENT-TERMINATING") === 0) {
// If the monitor socket is closed, we have already stopped the
// supplicant and we can stop waiting for more events and
// simply exit here (we don't have to notify).
if (eventData.indexOf("connection closed") !== -1)
return false;
// As long we haven't seen too many recv errors yet, we
// will keep going for a bit longer
if (eventData.indexOf("recv error") !== -1 && ++recvErrors < 10)
return true;
notify("supplicantlost");
return false;
}
if (eventData.indexOf("CTRL-EVENT-DISCONNECTED") === 0) {
notify("statechange", { state: "DISCONNECTED" });
return true;
}
if (eventData.indexOf("CTRL-EVENT-CONNECTED") === 0) {
// Format: CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]
var bssid = eventData.split(" ")[4];
var id = eventData.substr(eventData.indexOf("id=")).split(" ")[0];
notify("statechange", { state: "CONNECTED", BSSID: bssid, id: id });
return true;
}
if (eventData.indexOf("CTRL-EVENT-SCAN-RESULTS") === 0) {
debug("Notifying of scn results available");
notify("scanresultsavailable");
return true;
}
// unknown event
return true;
}
// Initial state
var airplaneMode = false;
// Public interface of the wifi service
manager.setWifiEnabled = function(enable, callback) {
var targetState = enable ? "ENABLED" : "DISABLED";
if (enable == targetState)
return true;
if (enable && airplaneMode)
return false;
if (enable) {
loadDriver(function (ok) {
(ok === 0) ? startSupplicant(callback) : callback(-1);
});
} else {
stopSupplicant(function (ok) {
(ok === 0) ? unloadDriver(callback) : callback(-1);
});
}
}
manager.disconnect = disconnectCommand;
manager.reconnect = reconnectCommand;
manager.reassociate = reassociateCommand;
var networkConfigurationFields = ["ssid", "bssid", "psk", "wep_key0", "wep_key1", "wep_key2", "wep_key3",
"wep_tx_keyidx", "priority", "key_mgmt", "scan_ssid"];
manager.getNetworkConfiguration = function(config, callback) {
var netId = config.netId;
var done = 0;
for (var n = 0; n < networkConfigurationFields; ++n) {
var fieldName = networkConfigurationFields[n];
getNetworkVariableCommand(netId, fieldName, function(value) {
config[fieldName] = value;
if (++done == networkConfigurationFields.length)
callback(config);
});
}
}
manager.setNetworkConfiguration = function(config, callback) {
var netId = config.netId;
var done = 0;
var errors = 0;
for (var n = 0; n < networkConfigurationFields.length; ++n) {
var fieldName = networkConfigurationFields[n];
if (!(fieldName in config)) {
++done;
} else {
setNetworkVariableCommand(netId, fieldName, config[fieldName], function(ok) {
if (!ok)
++errors;
if (++done == networkConfigurationFields.length)
callback(errors == 0);
});
}
}
// If config didn't contain any of the fields we want, don't lose the error callback
if (done == networkConfigurationFields.length)
callback(false);
}
manager.getConfiguredNetworks = function(callback) {
listNetworksCommand(function (reply) {
var networks = {};
var done = 0;
var errors = 0;
var lines = reply.split("\n");
for (var n = 1; n < lines.length; ++n) {
var result = lines[n].split("\t");
var netId = result[0];
var config = networks[netId] = { netId: netId };
switch (result[3]) {
case "[CURRENT]":
config.status = "CURRENT";
break;
case "[DISABLED]":
config.status = "DISABLED";
break;
default:
config.status = "ENABLED";
break;
}
manager.getNetworkConfiguration(config, function (ok) {
if (!ok)
++errors;
if (++done == lines.length - 1) {
if (errors) {
// If an error occured, delete the new netId
removeNetworkCommand(netId, function() {
callback(null);
});
} else {
callback(networks);
}
}
});
}
});
}
manager.addNetwork = function(config, callback) {
addNetworkCommand(function (netId) {
config.netId = netId;
manager.setNetworkConfiguration(config, callback);
});
}
manager.updateNetwork = function(config, callback) {
manager.setNetworkConfiguration(config, callback);
}
manager.removeNetwork = function(netId, callback) {
removeNetworkCommand(netId, callback);
}
function ipToString(n) {
return String((n & (0xff << 24)) >> 24) + "." +
((n & (0xff << 16)) >> 16) + "." +
((n & (0xff << 8)) >> 8) + "." +
((n & (0xff << 0)) >> 0);
}
manager.enableNetwork = function(netId, disableOthers, callback) {
getProperty("wifi.interface", "tiwlan0", function (ifname) {
if (!ifname) {
callback(false);
return;
}
enableInterface(ifname, function (ok) {
if (!ok) {
callback(false);
return;
}
enableNetworkCommand(netId, disableOthers, function (ok) {
if (!ok) {
disableInterface(ifname, function () {
callback(false);
});
return;
}
runDhcp(ifname, function (data) {
debug("After running dhcp, got data: " + uneval(data));
if (!data) {
disableInterface(ifname, function() {
callback(false);
});
return;
}
setProperty("net.dns1", ipToString(data.dns1), function(ok) {
if (!ok) {
callback(false);
return;
}
getProperty("net.dnschange", "0", function(value) {
if (value === null) {
callback(false);
return;
}
setProperty("net.dnschange", String(Number(value) + 1), function(ok) {
callback(ok);
});
});
});
});
});
});
});
}
manager.disableNetwork = function(netId, callback) {
disableNetworkCommand(netId, callback);
}
manager.getMacAddress = getMacAddressCommand;
manager.getScanResults = scanResultsCommand;
return manager;
})();
function nsWifiWorker() {
WifiManager.onsupplicantconnection = function() {
debug("Connected to supplicant");
WifiManager.getMacAddress(function (mac) {
debug("Got mac: " + mac);
});
}
WifiManager.onsupplicantlost = function() {
debug("Couldn't connect to supplicant");
}
var networks = Object.create(null);
WifiManager.onscanresultsavailable = function() {
debug("Scan results are available! Asking for them.");
if (networks["Mozilla Guest"])
return;
WifiManager.getScanResults(function(r) {
let lines = r.split("\n");
// NB: Skip the header line.
let added = !("Mozilla Guest" in networks);
for (let i = 1; i < lines.length; ++i) {
// bssid / frequency / signal level / flags / ssid
var match = /([\S]+)\s+([\S]+)\s+([\S]+)\s+(\[[\S]+\])?\s+(.*)/.exec(lines[i])
if (match)
networks[match[5]] = match[1];
else
debug("Match didn't find anything for: " + lines[i]);
}
if (("Mozilla Guest" in networks) && added) {
debug("Mozilla Guest exists in networks, trying to connect!");
var config = Object.create(null);
config["ssid"] = '"Mozilla Guest"';
//config["bssid"] = '"' + networks["Mozilla Guest"] + '"';
config["key_mgmt"] = "NONE";
config["scan_ssid"] = 1;
WifiManager.addNetwork(config, function (ok) {
if (ok) {
WifiManager.enableNetwork(config.netId, false, function (ok) {
if (ok)
debug("Enabled the network!");
else
debug("Failed to enable the network :(");
});
} else {
debug("Failed to add the network :(");
}
});
}
});
}
WifiManager.setWifiEnabled(true, function (ok) {
if (ok === 0)
WifiManager.start();
else
debug("Couldn't start Wifi");
});
debug("Wifi starting");
}
nsWifiWorker.prototype = {
classID: WIFIWORKER_CID,
classInfo: XPCOMUtils.generateCI({classID: WIFIWORKER_CID,
contractID: WIFIWORKER_CONTRACTID,
classDescription: "WifiWorker",
interfaces: [Ci.nsIRadioWorker,
Ci.nsIWifi]}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioWorker,
Ci.nsIWifi]),
setWifiEnabled: function(enable) {
WifiManager.setWifiEnabled(enable, function (ok) {
debug(ok);
});
},
// This is a bit ugly, but works. In particular, this depends on the fact
// that RadioManager never actually tries to get the worker from us.
get worker() { throw "Not implemented"; },
shutdown: function() {
this.setWifiEnabled(false);
}
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([nsWifiWorker]);
let debug;
if (DEBUG) {
debug = function (s) {
dump("-*- nsWifiWorker component: " + s + "\n");
};
} else {
debug = function (s) {};
}

View File

@ -0,0 +1 @@
component {a14e8977-d259-433a-a88d-58dd44657e5b} nsWifiWorker.js

View File

@ -7334,8 +7334,10 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ok = EmitUnary(cx, bce, pn);
break;
case PNK_INC:
case PNK_DEC:
case PNK_PREINCREMENT:
case PNK_PREDECREMENT:
case PNK_POSTINCREMENT:
case PNK_POSTDECREMENT:
ok = EmitIncOrDec(cx, bce, pn);
break;

View File

@ -41,6 +41,8 @@
#ifndef ParseMaps_h__
#define ParseMaps_h__
#include "mozilla/Attributes.h"
#include "ds/InlineMap.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@ -267,8 +269,8 @@ class AtomDecls
JSContext *cx;
AtomDOHMap *map;
AtomDecls(const AtomDecls &other);
void operator=(const AtomDecls &other);
AtomDecls(const AtomDecls &other) MOZ_DELETE;
void operator=(const AtomDecls &other) MOZ_DELETE;
AtomDeclNode *allocNode(Definition *defn);

View File

@ -75,8 +75,10 @@ enum ParseNodeKind {
PNK_STAR,
PNK_DIV,
PNK_MOD,
PNK_INC,
PNK_DEC,
PNK_PREINCREMENT,
PNK_POSTINCREMENT,
PNK_PREDECREMENT,
PNK_POSTDECREMENT,
PNK_DOT,
PNK_LB,
PNK_RB,
@ -347,8 +349,10 @@ enum ParseNodeKind {
* PNK_VOID,
* PNK_NOT,
* PNK_BITNOT
* PNK_INC, unary pn_kid: MEMBER expr
* PNK_DEC
* PNK_PREINCREMENT, unary pn_kid: MEMBER expr
* PNK_POSTINCREMENT,
* PNK_PREDECREMENT,
* PNK_POSTDECREMENT
* PNK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
* pn_count: 1 + N (where N is number of args)
* ctor is a MEMBER expr

View File

@ -4780,7 +4780,7 @@ Parser::assignExpr()
return ParseNode::newBinaryOrAppend(kind, op, lhs, rhs, tc);
}
static ParseNode *
static bool
SetLvalKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, ParseNode *kid,
const char *name)
{
@ -4795,25 +4795,24 @@ SetLvalKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, Parse
!kid->isKind(PNK_LB))
{
ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_BAD_OPERAND, name);
return NULL;
return false;
}
if (!CheckStrictAssignment(cx, tc, kid))
return NULL;
return false;
pn->pn_kid = kid;
return kid;
return true;
}
static const char incop_name_str[][10] = {"increment", "decrement"};
static JSBool
SetIncOpKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, ParseNode *kid,
TokenKind tt, JSBool preorder)
TokenKind tt, bool preorder)
{
JSOp op;
kid = SetLvalKid(cx, ts, tc, pn, kid, incop_name_str[tt == TOK_DEC]);
if (!kid)
return JS_FALSE;
if (!SetLvalKid(cx, ts, tc, pn, kid, incop_name_str[tt == TOK_DEC]))
return false;
switch (kid->getKind()) {
case PNK_NAME:
op = (tt == TOK_INC)
@ -4885,13 +4884,13 @@ Parser::unaryExpr()
case TOK_INC:
case TOK_DEC:
pn = UnaryNode::create((tt == TOK_INC) ? PNK_INC : PNK_DEC, tc);
pn = UnaryNode::create((tt == TOK_INC) ? PNK_PREINCREMENT : PNK_PREDECREMENT, tc);
if (!pn)
return NULL;
pn2 = memberExpr(JS_TRUE);
if (!pn2)
return NULL;
if (!SetIncOpKid(context, &tokenStream, tc, pn, pn2, tt, JS_TRUE))
if (!SetIncOpKid(context, &tokenStream, tc, pn, pn2, tt, true))
return NULL;
pn->pn_pos.end = pn2->pn_pos.end;
break;
@ -4954,11 +4953,11 @@ Parser::unaryExpr()
if (tokenStream.onCurrentLine(pn->pn_pos)) {
tt = tokenStream.peekTokenSameLine(TSF_OPERAND);
if (tt == TOK_INC || tt == TOK_DEC) {
(void) tokenStream.getToken();
pn2 = UnaryNode::create((tt == TOK_INC) ? PNK_INC : PNK_DEC, tc);
tokenStream.consumeKnownToken(tt);
pn2 = UnaryNode::create((tt == TOK_INC) ? PNK_POSTINCREMENT : PNK_POSTDECREMENT, tc);
if (!pn2)
return NULL;
if (!SetIncOpKid(context, &tokenStream, tc, pn2, pn, tt, JS_FALSE))
if (!SetIncOpKid(context, &tokenStream, tc, pn2, pn, tt, false))
return NULL;
pn2->pn_pos.begin = pn->pn_pos.begin;
pn = pn2;
@ -6821,13 +6820,22 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
pn2 = ParseNode::newBinaryOrAppend(PNK_COLON, op, pn3, pn2, tc);
goto skip;
}
case TOK_STRING:
case TOK_STRING: {
atom = tokenStream.currentToken().atom();
pn3 = NullaryNode::create(PNK_STRING, tc);
if (!pn3)
return NULL;
pn3->pn_atom = atom;
uint32_t index;
if (atom->isIndex(&index)) {
pn3 = NullaryNode::create(PNK_NUMBER, tc);
if (!pn3)
return NULL;
pn3->pn_dval = index;
} else {
pn3 = NullaryNode::create(PNK_STRING, tc);
if (!pn3)
return NULL;
pn3->pn_atom = atom;
}
break;
}
case TOK_RC:
goto end_obj_init;
default:

View File

@ -38,11 +38,13 @@
*
* ***** END LICENSE BLOCK ***** */
/* JS execution context. */
#ifndef jscntxt_h___
#define jscntxt_h___
/*
* JS execution context.
*/
#include "mozilla/Attributes.h"
#include <string.h>
#include "jsfriendapi.h"
@ -1406,10 +1408,9 @@ class AutoGCRooter {
OBJVECTOR = -16 /* js::AutoObjectVector */
};
private:
/* No copy or assignment semantics. */
AutoGCRooter(AutoGCRooter &ida);
void operator=(AutoGCRooter &ida);
private:
AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
void operator=(AutoGCRooter &ida) MOZ_DELETE;
};
/* FIXME(bug 332648): Move this into a public header. */
@ -1618,9 +1619,8 @@ class AutoIdArray : private AutoGCRooter {
JSIdArray * idArray;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
/* No copy or assignment semantics. */
AutoIdArray(AutoIdArray &ida);
void operator=(AutoIdArray &ida);
AutoIdArray(AutoIdArray &ida) MOZ_DELETE;
void operator=(AutoIdArray &ida) MOZ_DELETE;
};
/* The auto-root for enumeration object and its state. */
@ -1797,7 +1797,8 @@ class AutoReleasePtr {
void *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoReleasePtr operator=(const AutoReleasePtr &other);
AutoReleasePtr(const AutoReleasePtr &other) MOZ_DELETE;
AutoReleasePtr operator=(const AutoReleasePtr &other) MOZ_DELETE;
public:
explicit AutoReleasePtr(JSContext *cx, void *ptr
@ -1817,7 +1818,8 @@ class AutoReleaseNullablePtr {
void *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other);
AutoReleaseNullablePtr(const AutoReleaseNullablePtr &other) MOZ_DELETE;
AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other) MOZ_DELETE;
public:
explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr

View File

@ -38,9 +38,12 @@
*
* ***** END LICENSE BLOCK ***** */
/* JS Mark-and-Sweep Garbage Collector. */
#include "mozilla/Attributes.h"
#include "mozilla/Util.h"
/*
* JS Mark-and-Sweep Garbage Collector.
*
* This GC allocates fixed-sized things with sizes up to GC_NBYTES_MAX (see
* jsgc.h). It allocates from a special GC arena pool with each arena allocated
* using malloc. It uses an ideally parallel array of flag bytes to hold the
@ -51,8 +54,6 @@
#include <math.h>
#include <string.h> /* for memset used when DEBUG */
#include "mozilla/Util.h"
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h"
@ -473,42 +474,16 @@ ChunkPool::get(JSRuntime *rt)
/* Must be called either during the GC or with the GC lock taken. */
inline void
ChunkPool::put(JSRuntime *rt, Chunk *chunk)
ChunkPool::put(Chunk *chunk)
{
JS_ASSERT(this == &rt->gcChunkPool);
size_t initialAge = 0;
#ifdef JS_THREADSAFE
/*
* When we have not yet started the background finalization, we must keep
* empty chunks until we are done with all the sweeping and finalization
* that cannot be done in the background even if shouldShrink() is true.
* This way we can safely call IsAboutToBeFinalized and Cell::isMarked for
* finalized GC things in empty chunks. So we only release the chunk if we
* are called from the background thread.
*/
if (rt->gcHelperThread.sweeping()) {
if (rt->gcHelperThread.shouldShrink()) {
Chunk::release(rt, chunk);
return;
}
/*
* Set the age to one as we expire chunks early during the background
* sweep so this chunk already survived one GC cycle.
*/
initialAge = 1;
}
#endif
chunk->info.age = initialAge;
chunk->info.age = 0;
chunk->info.next = emptyChunkListHead;
emptyChunkListHead = chunk;
emptyCount++;
}
/* Must be called either during the GC or with the GC lock taken. */
void
Chunk *
ChunkPool::expire(JSRuntime *rt, bool releaseAll)
{
JS_ASSERT(this == &rt->gcChunkPool);
@ -519,6 +494,7 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
* without emptying the list, the older chunks will stay at the tail
* and are more likely to reach the max age.
*/
Chunk *freeList = NULL;
for (Chunk **chunkp = &emptyChunkListHead; *chunkp; ) {
JS_ASSERT(emptyCount);
Chunk *chunk = *chunkp;
@ -528,7 +504,9 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
if (releaseAll || chunk->info.age == MAX_EMPTY_CHUNK_AGE) {
*chunkp = chunk->info.next;
--emptyCount;
Chunk::release(rt, chunk);
chunk->prepareToBeFreed(rt);
chunk->info.next = freeList;
freeList = chunk;
} else {
/* Keep the chunk but increase its age. */
++chunk->info.age;
@ -536,6 +514,7 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
}
}
JS_ASSERT_IF(releaseAll, !emptyCount);
return freeList;
}
JS_FRIEND_API(int64_t)
@ -570,12 +549,36 @@ Chunk::allocate(JSRuntime *rt)
Chunk::release(JSRuntime *rt, Chunk *chunk)
{
JS_ASSERT(chunk);
JS_ASSERT(rt->gcNumArenasFreeCommitted >= chunk->info.numArenasFreeCommitted);
rt->gcNumArenasFreeCommitted -= chunk->info.numArenasFreeCommitted;
rt->gcStats.count(gcstats::STAT_DESTROY_CHUNK);
chunk->prepareToBeFreed(rt);
FreeChunk(chunk);
}
static void
FreeChunkList(Chunk *chunkListHead)
{
while (Chunk *chunk = chunkListHead) {
JS_ASSERT(!chunk->info.numArenasFreeCommitted);
chunkListHead = chunk->info.next;
FreeChunk(chunk);
}
}
inline void
Chunk::prepareToBeFreed(JSRuntime *rt)
{
JS_ASSERT(rt->gcNumArenasFreeCommitted >= info.numArenasFreeCommitted);
rt->gcNumArenasFreeCommitted -= info.numArenasFreeCommitted;
rt->gcStats.count(gcstats::STAT_DESTROY_CHUNK);
#ifdef DEBUG
/*
* Let FreeChunkList detect a missing prepareToBeFreed call before it
* frees chunk.
*/
info.numArenasFreeCommitted = 0;
#endif
}
void
Chunk::init()
{
@ -723,6 +726,17 @@ Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
return aheader;
}
inline void
Chunk::addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader)
{
JS_ASSERT(!aheader->allocated());
aheader->next = info.freeArenasHead;
info.freeArenasHead = aheader;
++info.numArenasFreeCommitted;
++info.numArenasFree;
++rt->gcNumArenasFreeCommitted;
}
void
Chunk::releaseArena(ArenaHeader *aheader)
{
@ -749,11 +763,7 @@ Chunk::releaseArena(ArenaHeader *aheader)
JS_ATOMIC_ADD(&comp->gcBytes, -int32_t(ArenaSize));
aheader->setAsNotAllocated();
aheader->next = info.freeArenasHead;
info.freeArenasHead = aheader;
++info.numArenasFreeCommitted;
++info.numArenasFree;
++rt->gcNumArenasFreeCommitted;
addArenaToFreeList(rt, aheader);
if (info.numArenasFree == 1) {
JS_ASSERT(!info.prevp);
@ -764,7 +774,7 @@ Chunk::releaseArena(ArenaHeader *aheader)
} else {
rt->gcChunkSet.remove(this);
removeFromAvailableList();
rt->gcChunkPool.put(rt, this);
rt->gcChunkPool.put(this);
}
}
@ -1172,7 +1182,7 @@ js_FinishGC(JSRuntime *rt)
* Finish the pool after the background thread stops in case it was doing
* the background sweeping.
*/
rt->gcChunkPool.expire(rt, true);
FreeChunkList(rt->gcChunkPool.expire(rt, true));
#ifdef DEBUG
if (!rt->gcRootsHash.empty())
@ -2195,12 +2205,99 @@ MaybeGC(JSContext *cx)
}
}
} /* namespace js */
static void
DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp)
{
Chunk *chunk = *availableListHeadp;
if (!chunk)
return;
/*
* Decommit is expensive so we avoid holding the GC lock while calling it.
*
* We decommit from the tail of the list to minimize interference with the
* main thread that may start to allocate things at this point.
*/
JS_ASSERT(chunk->info.prevp == availableListHeadp);
while (Chunk *next = chunk->info.next) {
JS_ASSERT(next->info.prevp == &chunk->info.next);
chunk = next;
}
for (;;) {
while (chunk->info.numArenasFreeCommitted != 0) {
/*
* The arena that is been decommitted outside the GC lock must not
* be available for allocations either via the free list or via
* the decommittedArenas bitmap. For that we just fetch the arena
* from the free list before the decommit and then mark it as free
* and decommitted when we retake the GC lock.
*
* We also must make sure that the aheader is not accessed again
* after we decommit the arena.
*/
ArenaHeader *aheader = chunk->fetchNextFreeArena(rt);
size_t arenaIndex = Chunk::arenaIndex(aheader->arenaAddress());
bool ok;
{
AutoUnlockGC unlock(rt);
ok = DecommitMemory(aheader->getArena(), ArenaSize);
}
if (ok) {
++chunk->info.numArenasFree;
chunk->decommittedArenas.set(arenaIndex);
} else {
chunk->addArenaToFreeList(rt, aheader);
}
if (rt->gcChunkAllocationSinceLastGC) {
/*
* The allocator thread has started to get new chunks. We should stop
* to avoid decommitting arenas in just allocated chunks.
*/
return;
}
}
/*
* prevp becomes null when the allocator thread consumed all chunks from
* the available list.
*/
JS_ASSERT_IF(chunk->info.prevp, *chunk->info.prevp == chunk);
if (chunk->info.prevp == availableListHeadp || !chunk->info.prevp)
break;
/*
* prevp exists and is not the list head. It must point to the next
* field of the previous chunk.
*/
chunk = chunk->getPrevious();
}
}
static void
DecommitArenas(JSRuntime *rt)
{
DecommitArenasFromAvailableList(rt, &rt->gcSystemAvailableChunkListHead);
DecommitArenasFromAvailableList(rt, &rt->gcUserAvailableChunkListHead);
}
/* Must be called with the GC lock taken. */
static void
ExpireChunksAndArenas(JSRuntime *rt, bool shouldShrink)
{
if (Chunk *toFree = rt->gcChunkPool.expire(rt, shouldShrink)) {
AutoUnlockGC unlock(rt);
FreeChunkList(toFree);
}
if (shouldShrink)
DecommitArenas(rt);
}
#ifdef JS_THREADSAFE
namespace js {
bool
GCHelperThread::init()
{
@ -2286,7 +2383,7 @@ GCHelperThread::threadLoop()
break;
JS_ASSERT(chunk->info.numArenasFreeCommitted == ArenasPerChunk);
rt->gcNumArenasFreeCommitted += ArenasPerChunk;
rt->gcChunkPool.put(rt, chunk);
rt->gcChunkPool.put(chunk);
} while (state == ALLOCATING && rt->gcChunkPool.wantBackgroundAllocation(rt));
if (state == ALLOCATING)
state = IDLE;
@ -2375,42 +2472,40 @@ GCHelperThread::doSweep()
{
JS_ASSERT(context);
/*
* Expire the chunks released during the GC so they will be available to
* the rest of the system immediately.
*/
rt->gcChunkPool.expire(rt, shouldShrink());
{
AutoUnlockGC unlock(rt);
AutoUnlockGC unlock(rt);
/*
* We must finalize in the insert order, see comments in
* finalizeObjects.
*/
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
ArenaLists::backgroundFinalize(context, *i);
finalizeVector.resize(0);
/*
* We must finalize in the insert order, see comments in
* finalizeObjects.
*/
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
ArenaLists::backgroundFinalize(context, *i);
finalizeVector.resize(0);
context = NULL;
context = NULL;
if (freeCursor) {
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
freeElementsAndArray(array, freeCursor);
freeCursor = freeCursorEnd = NULL;
} else {
JS_ASSERT(!freeCursorEnd);
if (freeCursor) {
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
freeElementsAndArray(array, freeCursor);
freeCursor = freeCursorEnd = NULL;
} else {
JS_ASSERT(!freeCursorEnd);
}
for (void ***iter = freeVector.begin(); iter != freeVector.end(); ++iter) {
void **array = *iter;
freeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
}
freeVector.resize(0);
}
for (void ***iter = freeVector.begin(); iter != freeVector.end(); ++iter) {
void **array = *iter;
freeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
}
freeVector.resize(0);
ExpireChunksAndArenas(rt, shouldShrink());
}
} /* namespace js */
#endif /* JS_THREADSAFE */
} /* namespace js */
static bool
ReleaseObservedTypes(JSContext *cx)
{
@ -2426,43 +2521,6 @@ ReleaseObservedTypes(JSContext *cx)
return releaseTypes;
}
static void
DecommitFreePages(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
Chunk *chunk = r.front();
ArenaHeader *aheader = chunk->info.freeArenasHead;
/*
* In the non-failure case, the list will be gone at the end of
* the loop. In the case where we fail, we relink all failed
* decommits into a new list on freeArenasHead.
*/
chunk->info.freeArenasHead = NULL;
while (aheader) {
/* Store aside everything we will need after decommit. */
ArenaHeader *next = aheader->next;
bool success = DecommitMemory(aheader, ArenaSize);
if (!success) {
aheader->next = chunk->info.freeArenasHead;
chunk->info.freeArenasHead = aheader;
continue;
}
size_t arenaIndex = Chunk::arenaIndex(aheader->arenaAddress());
chunk->decommittedArenas.set(arenaIndex);
--chunk->info.numArenasFreeCommitted;
--rt->gcNumArenasFreeCommitted;
aheader = next;
}
}
}
static void
SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
{
@ -2656,11 +2714,8 @@ SweepPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind)
* use IsAboutToBeFinalized().
* This is done on the GCHelperThread if JS_THREADSAFE is defined.
*/
rt->gcChunkPool.expire(rt, gckind == GC_SHRINK);
ExpireChunksAndArenas(rt, gckind == GC_SHRINK);
#endif
if (gckind == GC_SHRINK)
DecommitFreePages(cx);
}
{
@ -2782,9 +2837,8 @@ class AutoGCSession {
private:
JSContext *context;
/* Disable copy constructor or assignments */
AutoGCSession(const AutoGCSession&);
void operator=(const AutoGCSession&);
AutoGCSession(const AutoGCSession&) MOZ_DELETE;
void operator=(const AutoGCSession&) MOZ_DELETE;
};
/*

View File

@ -598,23 +598,23 @@ struct ChunkInfo {
*
* For the mark bitmap, we know that each arena will use a fixed number of full
* bytes: ArenaBitmapBytes. The full size of the header data is this number
* multiplied by the eventual number of arenas we have in the header. We,
* multiplied by the eventual number of arenas we have in the header. We,
* conceptually, distribute this header data among the individual arenas and do
* not include it in the header. This way we do not have to worry about its
* not include it in the header. This way we do not have to worry about its
* variable size: it gets attached to the variable number we are computing.
*
* For the decommitted arena bitmap, we only have 1 bit per arena, so this
* technique will not work. Instead, we observe that we do not have enough
* header info to fill 8 full arenas: it is currently 4 on 64bit, less on
* header info to fill 8 full arenas: it is currently 4 on 64bit, less on
* 32bit. Thus, with current numbers, we need 64 bytes for decommittedArenas.
* This will not become 63 bytes unless we double the data required in the
* header. Therefore, we just compute the number of bytes required to track
* This will not become 63 bytes unless we double the data required in the
* header. Therefore, we just compute the number of bytes required to track
* every possible arena and do not worry about slop bits, since there are too
* few to usefully allocate.
*
* To actually compute the number of arenas we can allocate in a chunk, we
* divide the amount of available space less the header info (not including
* the mark bitmap which is distributed into the arena size) by the size of
* the mark bitmap which is distributed into the arena size) by the size of
* the arena (with the mark bitmap bytes it uses).
*/
const size_t BytesPerArenaWithHeader = ArenaSize + ArenaBitmapBytes;
@ -749,6 +749,21 @@ struct Chunk {
/* Must be called with the GC lock taken. */
static inline void release(JSRuntime *rt, Chunk *chunk);
static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead);
/* Must be called with the GC lock taken. */
inline void prepareToBeFreed(JSRuntime *rt);
/*
* Assuming that the info.prevp points to the next field of the previous
* chunk in a doubly-linked list, get that chunk.
*/
Chunk *getPrevious() {
JS_ASSERT(info.prevp);
uintptr_t prevAddress = reinterpret_cast<uintptr_t>(info.prevp);
JS_ASSERT((prevAddress & ChunkMask) == offsetof(Chunk, info.next));
return reinterpret_cast<Chunk *>(prevAddress - offsetof(Chunk, info.next));
}
private:
inline void init();
@ -757,8 +772,11 @@ struct Chunk {
jsuint findDecommittedArenaOffset();
ArenaHeader* fetchNextDecommittedArena();
public:
/* Unlink and return the freeArenasHead. */
inline ArenaHeader* fetchNextFreeArena(JSRuntime *rt);
inline void addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader);
};
JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize);
@ -782,10 +800,13 @@ class ChunkPool {
inline Chunk *get(JSRuntime *rt);
/* Must be called either during the GC or with the GC lock taken. */
inline void put(JSRuntime *rt, Chunk *chunk);
inline void put(Chunk *chunk);
/* Must be called either during the GC or with the GC lock taken. */
void expire(JSRuntime *rt, bool releaseAll);
/*
* Return the list of chunks that can be released outside the GC lock.
* Must be called either during the GC or with the GC lock taken.
*/
Chunk *expire(JSRuntime *rt, bool releaseAll);
/* Must be called either during the GC or with the GC lock taken. */
JS_FRIEND_API(int64_t) countCleanDecommittedArenas(JSRuntime *rt);
@ -1720,7 +1741,7 @@ struct GCMarker : public JSTracer {
void drainMarkStack();
inline void processMarkStackTop();
void pushObject(JSObject *obj) {
pushTaggedPtr(ObjectTag, obj);
}

View File

@ -41,6 +41,7 @@
#ifndef jsonparser_h___
#define jsonparser_h___
#include "mozilla/Attributes.h"
#include "mozilla/RangedPtr.h"
#include "jscntxt.h"
@ -51,6 +52,9 @@
*/
class JSONParser
{
JSONParser(const JSONParser &other) MOZ_DELETE;
void operator=(const JSONParser &other) MOZ_DELETE;
public:
enum ErrorHandling { RaiseError, NoError };
enum ParsingMode { StrictJSON, LegacyJSON };

View File

@ -2432,15 +2432,22 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
return leftAssociate(pn, dst);
}
case PNK_INC:
case PNK_DEC:
case PNK_PREINCREMENT:
case PNK_PREDECREMENT:
{
bool incr = pn->isKind(PNK_INC);
bool prefix = pn->getOp() >= JSOP_INCNAME && pn->getOp() <= JSOP_DECELEM;
bool inc = pn->isKind(PNK_PREINCREMENT);
Value expr;
return expression(pn->pn_kid, &expr) &&
builder.updateExpression(expr, incr, prefix, &pn->pn_pos, dst);
builder.updateExpression(expr, inc, true, &pn->pn_pos, dst);
}
case PNK_POSTINCREMENT:
case PNK_POSTDECREMENT:
{
bool inc = pn->isKind(PNK_POSTINCREMENT);
Value expr;
return expression(pn->pn_kid, &expr) &&
builder.updateExpression(expr, inc, false, &pn->pn_pos, dst);
}
case PNK_ASSIGN:

View File

@ -48,6 +48,9 @@
* of rooting things that might lose their newborn root due to subsequent GC
* allocations in the same native method.
*/
#include "mozilla/Attributes.h"
#include <stdlib.h>
#include <string.h>
#include "jstypes.h"
@ -1358,8 +1361,8 @@ class RegExpPair
*/
class RegExpGuard
{
RegExpGuard(const RegExpGuard &);
void operator=(const RegExpGuard &);
RegExpGuard(const RegExpGuard &) MOZ_DELETE;
void operator=(const RegExpGuard &) MOZ_DELETE;
JSContext *cx;
RegExpPair rep;

View File

@ -40,6 +40,8 @@
#ifndef jsstrinlines_h___
#define jsstrinlines_h___
#include "mozilla/Attributes.h"
#include "jsatom.h"
#include "jsstr.h"
@ -76,6 +78,9 @@ class StringBuffer
JSContext *context() const { return cb.allocPolicy().context(); }
jschar *extractWellSized();
StringBuffer(const StringBuffer &other) MOZ_DELETE;
void operator=(const StringBuffer &other) MOZ_DELETE;
public:
explicit inline StringBuffer(JSContext *cx);
bool reserve(size_t len);
@ -243,6 +248,9 @@ class RopeBuilder {
JSContext *cx;
JSString *res;
RopeBuilder(const RopeBuilder &other) MOZ_DELETE;
void operator=(const RopeBuilder &other) MOZ_DELETE;
public:
RopeBuilder(JSContext *cx)
: cx(cx), res(cx->runtime->emptyString)

View File

@ -44,6 +44,8 @@
#ifndef jsutil_h___
#define jsutil_h___
#include "mozilla/Attributes.h"
#include "js/Utility.h"
/* Forward declarations. */
@ -223,8 +225,8 @@ class AutoRefCount
JSContext *const cx;
RefCountable *obj;
AutoRefCount(const AutoRefCount &);
void operator=(const AutoRefCount &);
AutoRefCount(const AutoRefCount &other) MOZ_DELETE;
void operator=(const AutoRefCount &other) MOZ_DELETE;
public:
explicit AutoRefCount(JSContext *cx)

View File

@ -1125,8 +1125,10 @@ FrameState::frameSlot(ActiveFrame *a, const FrameEntry *fe) const
}
inline JSC::MacroAssembler::Address
FrameState::addressForInlineReturn() const
FrameState::addressForInlineReturn()
{
if (a->callee_->isTracked())
discardFe(a->callee_);
return addressOf(a->callee_);
}

View File

@ -877,7 +877,7 @@ class FrameState
Address addressForDataRemat(const FrameEntry *fe) const;
// Inside an inline frame, the address for the return value in the caller.
Address addressForInlineReturn() const;
Address addressForInlineReturn();
inline StateRemat dataRematInfo(const FrameEntry *fe) const;

View File

@ -2333,16 +2333,9 @@ DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
static JSBool
DumpStats(JSContext *cx, uintN argc, jsval *vp)
{
uintN i;
JSString *str;
jsid id;
JSObject *obj2;
JSProperty *prop;
Value value;
jsval *argv = JS_ARGV(cx, vp);
for (i = 0; i < argc; i++) {
str = JS_ValueToString(cx, argv[i]);
for (uintN i = 0; i < argc; i++) {
JSString *str = JS_ValueToString(cx, argv[i]);
if (!str)
return JS_FALSE;
argv[i] = STRING_TO_JSVAL(str);
@ -2354,24 +2347,10 @@ DumpStats(JSContext *cx, uintN argc, jsval *vp)
} else if (JS_FlatStringEqualsAscii(flatStr, "global")) {
DumpScope(cx, cx->globalObject, stdout);
} else {
if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
return JS_FALSE;
JSObject *obj;
if (!js_FindProperty(cx, id, false, &obj, &obj2, &prop))
return JS_FALSE;
if (prop) {
if (!obj->getGeneric(cx, id, &value))
return JS_FALSE;
}
if (!prop || !value.isObjectOrNull()) {
fputs("js: invalid stats argument ", gErrFile);
JS_FileEscapedString(gErrFile, str, 0);
putc('\n', gErrFile);
continue;
}
obj = value.toObjectOrNull();
if (obj)
DumpScope(cx, obj, stdout);
fputs("js: invalid stats argument ", gErrFile);
JS_FileEscapedString(gErrFile, str, 0);
putc('\n', gErrFile);
continue;
}
}
JS_SET_RVAL(cx, vp, JSVAL_VOID);
@ -4117,7 +4096,7 @@ static const char *const shell_help_messages[] = {
" Interface to JS_DumpHeap with output sent to file",
"dumpObject() Dump an internal representation of an object",
"notes([fun]) Show source notes for functions",
"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
"stats([string ...]) Dump 'atom' or 'global' stats",
"findReferences(target)\n"
" Walk the entire heap, looking for references to |target|, and return a\n"
" \"references object\" describing what we found.\n"

View File

@ -99,16 +99,14 @@ namespace workers {
template <class T, class AllocPolicy>
class Queue {
private:
typedef Vector<T, 4, AllocPolicy> Vec;
Vec v1;
Vec v2;
Vec *front;
Vec *back;
// Queue is not copyable.
Queue(const Queue &);
Queue & operator=(const Queue &);
Queue(const Queue &) MOZ_DELETE;
Queue & operator=(const Queue &) MOZ_DELETE;
public:
Queue() : front(&v1), back(&v2) {}

View File

@ -41,6 +41,8 @@
#ifndef BooleanObject_h___
#define BooleanObject_h___
#include "mozilla/Attributes.h"
#include "jsbool.h"
namespace js {
@ -80,8 +82,8 @@ class BooleanObject : public ::JSObject
::js_InitBooleanClass(JSContext *cx, JSObject *global);
private:
BooleanObject();
BooleanObject &operator=(const BooleanObject &bo);
BooleanObject() MOZ_DELETE;
BooleanObject &operator=(const BooleanObject &bo) MOZ_DELETE;
};
} // namespace js

View File

@ -41,6 +41,8 @@
#ifndef GlobalObject_h___
#define GlobalObject_h___
#include "mozilla/Attributes.h"
#include "jsarray.h"
#include "jsbool.h"
#include "jsfun.h"
@ -90,6 +92,9 @@ class Debugger;
* again if its property is deleted and readded).
*/
class GlobalObject : public ::JSObject {
GlobalObject(const GlobalObject &other) MOZ_DELETE;
void operator=(const GlobalObject &other) MOZ_DELETE;
/*
* Count of slots to store built-in constructors, prototypes, and initial
* visible properties for the constructors.

View File

@ -41,6 +41,8 @@
#ifndef NumberObject_h___
#define NumberObject_h___
#include "mozilla/Attributes.h"
#include "jsnum.h"
namespace js {
@ -80,8 +82,8 @@ class NumberObject : public ::JSObject
::js_InitNumberClass(JSContext *cx, JSObject *global);
private:
NumberObject();
NumberObject &operator=(const NumberObject &so);
NumberObject() MOZ_DELETE;
NumberObject &operator=(const NumberObject &so) MOZ_DELETE;
};
} // namespace js

View File

@ -41,6 +41,8 @@
#ifndef RegExpObject_h__
#define RegExpObject_h__
#include "mozilla/Attributes.h"
#include <stddef.h>
#include "jsobj.h"
@ -200,8 +202,8 @@ class RegExpObject : public ::JSObject
*/
Shape *assignInitialShape(JSContext *cx);
RegExpObject();
RegExpObject &operator=(const RegExpObject &reo);
RegExpObject() MOZ_DELETE;
RegExpObject &operator=(const RegExpObject &reo) MOZ_DELETE;
}; /* class RegExpObject */
/* Either builds a new RegExpObject or re-initializes an existing one. */

View File

@ -41,6 +41,8 @@
#ifndef StringObject_h___
#define StringObject_h___
#include "mozilla/Attributes.h"
#include "jsobj.h"
#include "jsstr.h"
@ -95,8 +97,8 @@ class StringObject : public ::JSObject
Shape *assignInitialShape(JSContext *cx);
private:
StringObject();
StringObject &operator=(const StringObject &so);
StringObject() MOZ_DELETE;
StringObject &operator=(const StringObject &so) MOZ_DELETE;
};
} // namespace js

View File

@ -965,10 +965,20 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
// See bug 384168.
*aGlobal = global;
if (!JS_ExecuteScriptVersion(cx, global, script, NULL, JSVERSION_LATEST)) {
uint32 oldopts = JS_GetOptions(cx);
JS_SetOptions(cx, oldopts |
(exception ? JSOPTION_DONT_REPORT_UNCAUGHT : 0));
bool ok = JS_ExecuteScriptVersion(cx, global, script, NULL, JSVERSION_LATEST);
JS_SetOptions(cx, oldopts);
if (!ok) {
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: failed to execute %s\n", nativePath.get());
#endif
if (exception) {
JS_GetPendingException(cx, exception);
JS_ClearPendingException(cx);
}
*aGlobal = nsnull;
return NS_ERROR_FAILURE;
}

View File

@ -0,0 +1 @@
Components.utils.import("resource://test/syntax_error.jsm");

View File

@ -0,0 +1,10 @@
function run_test()
{
try {
Components.utils.import("resource://test/importer.jsm");
do_check_true(false, "import should not succeed.");
} catch (x) {
do_check_neq(x.fileName.indexOf("syntax_error.jsm"), -1);
do_check_eq(x.lineNumber, 1);
}
}

View File

@ -14,6 +14,7 @@ tail =
[test_bug_442086.js]
[test_file.js]
[test_import.js]
[test_import_fail.js]
[test_js_weak_references.js]
[test_reflect_parse.js]
[test_localeCompare.js]

View File

@ -4590,6 +4590,9 @@ nsLayoutUtils::IsContainerForFontSizeInflation(const nsIFrame *aFrame)
* them, so they and their anonymous content should also not be a
* container.
*
* However, because we can't reliably compute sizes across XUL during
* reflow, any XUL frame with a XUL parent is always a container.
*
* There are contexts where it would be nice if some blocks didn't
* count as a container, so that, for example, an indented quotation
* didn't end up with a smaller font size. However, it's hard to
@ -4597,9 +4600,12 @@ nsLayoutUtils::IsContainerForFontSizeInflation(const nsIFrame *aFrame)
* thing to count as a container, so we don't try, and blocks are
* always containers.
*/
bool isInline = aFrame->GetStyleDisplay()->mDisplay ==
NS_STYLE_DISPLAY_INLINE ||
aFrame->GetContent()->IsInNativeAnonymousSubtree();
bool isInline = (aFrame->GetStyleDisplay()->mDisplay ==
NS_STYLE_DISPLAY_INLINE ||
(aFrame->GetContent() &&
aFrame->GetContent()->IsInNativeAnonymousSubtree())) &&
!(aFrame->IsBoxFrame() && aFrame->GetParent() &&
aFrame->GetParent()->IsBoxFrame());
NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) || isInline,
"line participants must not be containers");
NS_ASSERTION(aFrame->GetType() != nsGkAtoms::bulletFrame || isInline,
@ -4628,10 +4634,26 @@ nsLayoutUtils::InflationMinFontSizeFor(const nsHTMLReflowState &aReflowState)
#ifdef DEBUG
{
const nsHTMLReflowState *rs = &aReflowState;
const nsIFrame *f = aReflowState.frame;
nsIFrame *f = aReflowState.frame;
for (; rs; rs = rs->parentReflowState, f = f->GetParent()) {
NS_ABORT_IF_FALSE(rs->frame == f,
"reflow state parentage must match frame parentage");
nsIScrollableFrame *sf;
NS_ABORT_IF_FALSE(rs->parentReflowState ||
IsContainerForFontSizeInflation(f) ||
// OK if NS_FRAME_IN_REFLOW is not set on
// (non-null) parent, since its ancestors have a
// real size. (Do we set NS_FRAME_IN_REFLOW
// correctly for xul?)
!(f->GetParent()->GetStateBits() &
NS_FRAME_IN_REFLOW) ||
// ugly exception, but ok because the
// child is a container
(f->GetType() == nsGkAtoms::scrollFrame &&
(sf = do_QueryFrame(f)) &&
(IsContainerForFontSizeInflation(
sf->GetScrolledFrame()))),
"must hit container at top of reflow state chain");
}
}
#endif

View File

@ -5818,7 +5818,28 @@ PresShell::HandleEvent(nsIFrame *aFrame,
return NS_OK;
if (presShell != this) {
return presShell->HandleEvent(presShell->GetRootFrame(), aEvent, true, aEventStatus);
nsIFrame* frame = presShell->GetRootFrame();
if (!frame) {
if (aEvent->message == NS_QUERY_TEXT_CONTENT ||
NS_IS_CONTENT_COMMAND_EVENT(aEvent)) {
return NS_OK;
}
nsIView* view = presShell->GetViewManager()->GetRootView();
while (view && !view->GetFrame()) {
view = view->GetParent();
}
if (view) {
frame = view->GetFrame();
}
}
if (!frame)
return NS_OK;
nsCOMPtr<nsIPresShell> shell = frame->PresContext()->GetPresShell();
return shell->HandleEvent(frame, aEvent, true, aEventStatus);
}
}
}

View File

@ -381,6 +381,7 @@ _BROWSER_FILES = \
_INFLATION_REFTEST_FILES = \
$(shell find $(srcdir)/font-inflation/ -name '*.html' -o -name '*.xhtml') \
$(srcdir)/../../reftests/webm-video/black140x100.webm \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,2 @@
<!DOCTYPE HTML>
<video src="black140x100.webm"></video>

View File

@ -46,6 +46,7 @@ var gTests = [
"== css-transform-1.html css-transform-1-ref.html",
"== css-transform-2.html css-transform-2-ref.html",
"== container-with-clamping.html container-with-clamping-ref.html",
"!= video-1.html about:blank", // crashtest
];
// Maintain a reference count of how many things we're waiting for until

View File

@ -154,6 +154,7 @@
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_b2g.xpt
#endif
@BINPATH@/components/dom_battery.xpt
@ -398,6 +399,8 @@
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib

View File

@ -104,10 +104,12 @@ test_asyncNULLFallback()
"SELECT NULL"
), getter_AddRefs(stmt));
nsRefPtr<Spinner> asyncSpin(new Spinner());
nsCOMPtr<mozIStoragePendingStatement> pendingStmt;
do_check_true(NS_SUCCEEDED(stmt->ExecuteAsync(asyncSpin, getter_AddRefs(pendingStmt))));
do_check_true(NS_SUCCEEDED(stmt->ExecuteAsync(nsnull, getter_AddRefs(pendingStmt))));
do_check_true(pendingStmt);
stmt->Finalize();
nsRefPtr<Spinner> asyncSpin(new Spinner());
db->AsyncClose(asyncSpin);
asyncSpin->SpinUntilCompleted();
}

View File

@ -334,7 +334,16 @@ function _execute_test() {
// possible that this will mask an NS_ERROR_ABORT that happens after a
// do_check failure though.
if (!_quit || e != Components.results.NS_ERROR_ABORT) {
msg = "TEST-UNEXPECTED-FAIL | (xpcshell/head.js) | " + e;
msg = "TEST-UNEXPECTED-FAIL | ";
if ('fileName' in e) {
msg += e.fileName;
if ('lineNumber' in e) {
msg += ":" + e.lineNumber;
}
} else {
msg += "xpcshell/head.js";
}
msg += " | " + e;
if (e.stack) {
_dump(msg + " - See following stack:\n");
_dump_exception_stack(e.stack);

View File

@ -74,7 +74,7 @@ function run_test()
do_check_eq(1180493839859230, stmt.getInt64(3));
do_check_eq(1180493839859230, stmt.getInt64(4));
do_check_eq(1, stmt.getInt32(5));
stmt.reset();
stmt.finalize();
cleanup();
}

View File

@ -54,6 +54,7 @@ function run_test()
// Check that the column exists (statement should not throw)
stmt = dbConn.createStatement("SELECT referrer FROM moz_downloads");
stmt.finalize();
// now we check the entries
stmt = dbConn.createStatement(
@ -70,7 +71,7 @@ function run_test()
do_check_eq(1180493839859230, stmt.getInt64(4));
do_check_eq(1, stmt.getInt32(5));
do_check_true(stmt.getIsNull(6));
stmt.reset();
stmt.finalize();
cleanup();
}

View File

@ -55,6 +55,7 @@ function run_test()
// Check that the column exists (statement should not throw)
stmt = dbConn.createStatement("SELECT entityID FROM moz_downloads");
stmt.finalize();
// now we check the entries
stmt = dbConn.createStatement(
@ -72,7 +73,7 @@ function run_test()
do_check_eq(1, stmt.getInt32(5));
do_check_eq("http://www.mozilla.com/en-US/products/download.html?product=firefox-2.0.0.6&os=osx&lang=en-US",stmt.getUTF8String(6));
do_check_true(stmt.getIsNull(7));
stmt.reset();
stmt.finalize();
cleanup();
}

View File

@ -71,7 +71,7 @@ function run_test()
do_check_eq("http://www.mozilla.com/en-US/products/download.html?product=firefox-2.0.0.6&os=osx&lang=en-US",stmt.getUTF8String(6));
do_check_true(stmt.getIsNull(7));
do_check_true(stmt.getIsNull(8));
stmt.reset();
stmt.finalize();
cleanup();
}

View File

@ -73,7 +73,7 @@ function run_test()
do_check_true(stmt.getIsNull(8));
do_check_eq(0, stmt.getInt64(9));
do_check_eq(-1, stmt.getInt64(10));
stmt.reset();
stmt.finalize();
cleanup();
}

View File

@ -41,6 +41,7 @@ do_load_httpd_js();
do_get_profile();
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
var downloadUtils = { };
XPCOMUtils.defineLazyServiceGetter(downloadUtils,
@ -188,3 +189,7 @@ XPCOMUtils.defineLazyGetter(this, "Services", function() {
// Disable alert service notifications
Services.prefs.setBoolPref("browser.download.manager.showAlertOnComplete", false);
do_register_cleanup(function() {
Services.obs.notifyObservers(null, "quit-application", null);
});

View File

@ -81,6 +81,7 @@ function add_download_to_db(aStartTimeInRange, aEndTimeInRange, aState)
stmt.params.endTime = aEndTimeInRange ? END_TIME - 1 : END_TIME + 1;
stmt.params.state = aState;
stmt.execute();
stmt.finalize();
return id++;
}
@ -108,6 +109,7 @@ function check_existence(aIDs, aExpected)
checkFunc(stmt.executeStep());
stmt.reset();
}
stmt.finalize();
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -137,7 +137,6 @@ FormHistory.prototype = {
this.messageManager.addMessageListener("FormHistory:FormSubmitEntries", this);
// Add observers
Services.obs.addObserver(this, "profile-change-teardown", true);
Services.obs.addObserver(this, "profile-before-change", true);
Services.obs.addObserver(this, "idle-daily", true);
Services.obs.addObserver(this, "formhistory-expire-now", true);
@ -403,10 +402,7 @@ FormHistory.prototype = {
this.expireOldEntries();
break;
case "profile-before-change":
// FIXME (bug 696486): close the connection in here.
break;
case "profile-change-teardown":
this._dbFinalize();
this._dbClose();
break;
default:
this.log("Oops! Unexpected notification: " + topic);
@ -869,15 +865,22 @@ FormHistory.prototype = {
},
/**
* _dbFinalize
* _dbClose
*
* Finalize all statements to allow closing the connection correctly.
* Finalize all statements and close the connection.
*/
_dbFinalize : function FH__dbFinalize() {
_dbClose : function FH__dbClose() {
for each (let stmt in this.dbStmts) {
stmt.finalize();
}
this.dbStmts = {};
if (this.dbConnection !== undefined) {
try {
this.dbConnection.close();
} catch (e) {
Components.utils.reportError(e);
}
}
},
/*
@ -895,16 +898,7 @@ FormHistory.prototype = {
let backupFile = this.dbFile.leafName + ".corrupt";
storage.backupDatabaseFile(this.dbFile, backupFile);
this._dbFinalize();
if (this.dbConnection !== undefined) {
try {
this.dbConnection.close();
} catch (e) {
Components.utils.reportError(e);
}
}
this._dbClose();
this.dbFile.remove(false);
}
};

View File

@ -153,6 +153,10 @@ function run_test()
do_check_eq(gDownloadLastDir.file.path, dir3.path);
// cleanup
Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService)
.notifyObservers(null, "quit-application", null);
prefsService.clearUserPref("browser.privatebrowsing.keep_current_session");
[dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
}

View File

@ -352,11 +352,12 @@ INNER_MAKE_PACKAGE = \
$(ZIPALIGN) -f -v 4 $(_ABS_DIST)/gecko.apk $(PACKAGE)
INNER_UNMAKE_PACKAGE = \
mkdir $(MOZ_PKG_DIR) && \
cd $(MOZ_PKG_DIR) && \
pushd $(MOZ_PKG_DIR) && \
$(UNZIP) $(UNPACKAGE) && \
mv lib/$(ABI_DIR)/libmozutils.so . && \
mv lib/$(ABI_DIR)/*plugin-container* $(MOZ_CHILD_PROCESS_NAME) && \
rm -rf lib/$(ABI_DIR)
rm -rf lib/$(ABI_DIR) && \
popd
endif
ifeq ($(MOZ_PKG_FORMAT),DMG)
ifndef _APPNAME

View File

@ -111,7 +111,7 @@ ah_crap_handler(int signum)
signum);
printf("Stack:\n");
NS_StackWalk(PrintStackFrame, 2, nsnull);
NS_StackWalk(PrintStackFrame, 2, nsnull, 0);
printf("Sleeping for %d seconds.\n",_gdb_sleep_duration);
printf("Type 'gdb %s %d' to attach your debugger to this thread.\n",

View File

@ -962,7 +962,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort)
/* Walk the stack, even if stacks_enabled is false. We do this to
check if we must set immediate_abort. */
info->entries = 0;
rv = NS_StackWalk(stack_callback, skip, info);
rv = NS_StackWalk(stack_callback, skip, info, 0);
*immediate_abort = rv == NS_ERROR_UNEXPECTED;
if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) {
t->suppress_tracing--;
@ -997,7 +997,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort)
/* skip == 0 means |backtrace| should show up, so don't use skip + 1 */
/* NB: this call is repeated below if the buffer is too small */
info->entries = 0;
rv = NS_StackWalk(stack_callback, skip, info);
rv = NS_StackWalk(stack_callback, skip, info, 0);
*immediate_abort = rv == NS_ERROR_UNEXPECTED;
if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) {
t->suppress_tracing--;
@ -1021,7 +1021,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort)
/* and call NS_StackWalk again */
info->entries = 0;
NS_StackWalk(stack_callback, skip, info);
NS_StackWalk(stack_callback, skip, info, 0);
/* same stack */
PR_ASSERT(info->entries * 2 == new_stack_buffer_size);

View File

@ -133,7 +133,7 @@ my_malloc_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
// stack shows up as having two pthread_cond_wait$UNIX2003 frames.
const char *name = OnSnowLeopardOrLater() ? "new_sem_from_pool" :
"pthread_cond_wait$UNIX2003";
NS_StackWalk(stack_callback, 0, const_cast<char*>(name));
NS_StackWalk(stack_callback, 0, const_cast<char*>(name), 0);
}
void
@ -802,7 +802,7 @@ WalkStackThread(void* aData)
EXPORT_XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure)
void *aClosure, uintptr_t aThread)
{
MOZ_ASSERT(gCriticalAddress.mInit);
HANDLE myProcess, myThread;
@ -812,6 +812,13 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
if (!EnsureImageHlpInitialized())
return false;
HANDLE targetThread;
if (aThread) {
targetThread = reinterpret_cast<HANDLE> (aThread);
} else {
targetThread = ::GetCurrentThread();
}
// Have to duplicate handle to get a real handle.
if (!::DuplicateHandle(::GetCurrentProcess(),
::GetCurrentProcess(),
@ -822,7 +829,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
return NS_ERROR_FAILURE;
}
if (!::DuplicateHandle(::GetCurrentProcess(),
::GetCurrentThread(),
targetThread,
::GetCurrentProcess(),
&myThread,
THREAD_ALL_ACCESS, FALSE, 0)) {
@ -1481,9 +1488,10 @@ cs_operate(int (*operate_func)(void *, void *), void * usrarg)
EXPORT_XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure)
void *aClosure, uintptr_t aThread)
{
MOZ_ASSERT(gCriticalAddress.mInit);
MOZ_ASSERT(!aThread);
struct my_user_args args;
if (!initialized)
@ -1561,9 +1569,10 @@ extern void *__libc_stack_end; // from ld-linux.so
EXPORT_XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure)
void *aClosure, uintptr_t aThread)
{
MOZ_ASSERT(gCriticalAddress.mInit);
MOZ_ASSERT(!aThread);
// Stack walking code courtesy Kipp's "leaky".
// Get the frame pointer
@ -1639,9 +1648,10 @@ unwind_callback (struct _Unwind_Context *context, void *closure)
EXPORT_XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure)
void *aClosure, uintptr_t aThread)
{
MOZ_ASSERT(gCriticalAddress.mInit);
MOZ_ASSERT(!aThread);
unwind_info info;
info.callback = aCallback;
info.skip = aSkipFrames + 1;
@ -1717,9 +1727,10 @@ NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
EXPORT_XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure)
void *aClosure, uintptr_t aThread)
{
MOZ_ASSERT(gCriticalAddress.mInit);
MOZ_ASSERT(!aThread);
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -43,6 +43,7 @@
/* WARNING: This file is intended to be included from C or C++ files. */
#include "nscore.h"
#include <mozilla/StdInt.h>
PR_BEGIN_EXTERN_C
@ -58,6 +59,10 @@ typedef void
* the first callback will be for the caller of
* NS_StackWalk.
* @param aClosure Caller-supplied data passed through to aCallback.
* @param aThread The thread for which the stack is to be retrieved.
* Passing null causes us to walk the stack of the
* current thread. On Windows, this is a thread HANDLE.
* It is currently not supported on any other platform.
*
* Returns NS_ERROR_NOT_IMPLEMENTED on platforms where it is
* unimplemented.
@ -70,7 +75,7 @@ typedef void
*/
XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure);
void *aClosure, uintptr_t aThread);
typedef struct {
/*

View File

@ -883,7 +883,7 @@ static void PrintStackFrame(void *aPC, void *aClosure)
void
nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
{
NS_StackWalk(PrintStackFrame, 2, aStream);
NS_StackWalk(PrintStackFrame, 2, aStream, 0);
}
//----------------------------------------------------------------------