mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 725095 - Merge off-main-thread compositor from Maple. IGNORE BAD COMMIT MESSAGES
This commit is contained in:
commit
a96a6f4142
1
.hgtags
1
.hgtags
@ -78,3 +78,4 @@ bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
|
||||
0000000000000000000000000000000000000000 AURORA_BASE_20120131
|
||||
0000000000000000000000000000000000000000 AURORA_BASE_20120131
|
||||
bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
|
||||
b6627f28b7ec17e1b46a594df0f780d3a40847e4 FIREFOX_AURORA_13_BASE
|
||||
|
@ -41,6 +41,9 @@
|
||||
#include "nsAccessible.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsBindingManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccIterator
|
||||
@ -129,17 +132,21 @@ RelatedAccIterator::Next()
|
||||
|
||||
// Return related accessible for the given attribute and if the provider
|
||||
// content is in the same binding in the case of XBL usage.
|
||||
if (provider->mRelAttr == mRelAttr &&
|
||||
(!mBindingParent ||
|
||||
mBindingParent == provider->mContent->GetBindingParent())) {
|
||||
nsAccessible* related = mDocument->GetAccessible(provider->mContent);
|
||||
if (related)
|
||||
return related;
|
||||
if (provider->mRelAttr == mRelAttr) {
|
||||
nsIContent* bindingParent = provider->mContent->GetBindingParent();
|
||||
bool inScope = mBindingParent == bindingParent ||
|
||||
mBindingParent == provider->mContent;
|
||||
|
||||
// If the document content is pointed by relation then return the document
|
||||
// itself.
|
||||
if (provider->mContent == mDocument->GetContent())
|
||||
return mDocument;
|
||||
if (inScope) {
|
||||
nsAccessible* related = mDocument->GetAccessible(provider->mContent);
|
||||
if (related)
|
||||
return related;
|
||||
|
||||
// If the document content is pointed by relation then return the document
|
||||
// itself.
|
||||
if (provider->mContent == mDocument->GetContent())
|
||||
return mDocument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,18 +278,10 @@ XULDescriptionIterator::Next()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
|
||||
mCurrIdx(0)
|
||||
mCurrIdx(0), mContent(aContent)
|
||||
{
|
||||
if (!aContent->IsInDoc() ||
|
||||
!aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
|
||||
return;
|
||||
|
||||
if (aContent->IsInAnonymousSubtree()) {
|
||||
mXBLDocument = do_QueryInterface(aContent->OwnerDoc());
|
||||
mBindingParent = do_QueryInterface(aContent->GetBindingParent());
|
||||
} else {
|
||||
mDocument = aContent->OwnerDoc();
|
||||
}
|
||||
if (mContent->IsInDoc())
|
||||
mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);
|
||||
}
|
||||
|
||||
const nsDependentSubstring
|
||||
@ -324,20 +323,45 @@ IDRefsIterator::NextElem()
|
||||
nsIContent*
|
||||
IDRefsIterator::GetElem(const nsDependentSubstring& aID)
|
||||
{
|
||||
if (mXBLDocument) {
|
||||
// If content is anonymous subtree then use "anonid" attribute to get
|
||||
// elements, otherwise search elements in DOM by ID attribute.
|
||||
|
||||
nsCOMPtr<nsIDOMElement> refElm;
|
||||
mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
|
||||
NS_LITERAL_STRING("anonid"),
|
||||
aID,
|
||||
getter_AddRefs(refElm));
|
||||
nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
|
||||
return refContent;
|
||||
// Get elements in DOM tree by ID attribute if this is an explicit content.
|
||||
// In case of bound element check its anonymous subtree.
|
||||
if (!mContent->IsInAnonymousSubtree()) {
|
||||
dom::Element* refElm = mContent->OwnerDoc()->GetElementById(aID);
|
||||
if (refElm || !mContent->OwnerDoc()->BindingManager()->GetBinding(mContent))
|
||||
return refElm;
|
||||
}
|
||||
|
||||
return mDocument->GetElementById(aID);
|
||||
// If content is in anonymous subtree or an element having anonymous subtree
|
||||
// then use "anonid" attribute to get elements in anonymous subtree.
|
||||
nsCOMPtr<nsIDOMElement> refDOMElm;
|
||||
nsCOMPtr<nsIDOMDocumentXBL> xblDocument =
|
||||
do_QueryInterface(mContent->OwnerDoc());
|
||||
|
||||
// Check inside the binding the element is contained in.
|
||||
nsIContent* bindingParent = mContent->GetBindingParent();
|
||||
if (bindingParent) {
|
||||
nsCOMPtr<nsIDOMElement> bindingParentElm = do_QueryInterface(bindingParent);
|
||||
xblDocument->GetAnonymousElementByAttribute(bindingParentElm,
|
||||
NS_LITERAL_STRING("anonid"),
|
||||
aID,
|
||||
getter_AddRefs(refDOMElm));
|
||||
nsCOMPtr<dom::Element> refElm = do_QueryInterface(refDOMElm);
|
||||
if (refElm)
|
||||
return refElm;
|
||||
}
|
||||
|
||||
// Check inside the binding of the element.
|
||||
if (mContent->OwnerDoc()->BindingManager()->GetBinding(mContent)) {
|
||||
nsCOMPtr<nsIDOMElement> elm = do_QueryInterface(mContent);
|
||||
xblDocument->GetAnonymousElementByAttribute(elm,
|
||||
NS_LITERAL_STRING("anonid"),
|
||||
aID,
|
||||
getter_AddRefs(refDOMElm));
|
||||
nsCOMPtr<dom::Element> refElm = do_QueryInterface(refDOMElm);
|
||||
return refElm;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
|
@ -291,11 +291,8 @@ private:
|
||||
IDRefsIterator operator = (const IDRefsIterator&);
|
||||
|
||||
nsString mIDs;
|
||||
nsIContent* mContent;
|
||||
nsAString::index_type mCurrIdx;
|
||||
|
||||
nsIDocument* mDocument;
|
||||
nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
|
||||
nsCOMPtr<nsIDOMElement> mBindingParent;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -54,13 +54,6 @@
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
enum {
|
||||
IA2AlphaShift = 24,
|
||||
IA2RedShift = 16,
|
||||
IA2GreenShift = 8,
|
||||
IA2BlueShift = 0
|
||||
};
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
@ -130,110 +123,40 @@ __try {
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleComponent::get_foreground(IA2Color *aForeground)
|
||||
CAccessibleComponent::get_foreground(IA2Color* aForeground)
|
||||
{
|
||||
__try {
|
||||
return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("color"), aForeground);
|
||||
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
||||
if (acc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsIFrame* frame = acc->GetFrame();
|
||||
if (frame)
|
||||
*aForeground = frame->GetStyleColor()->mColor;
|
||||
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleComponent::get_background(IA2Color *aBackground)
|
||||
CAccessibleComponent::get_background(IA2Color* aBackground)
|
||||
{
|
||||
__try {
|
||||
return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("background-color"),
|
||||
aBackground);
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CAccessibleComponent::GetARGBValueFromCSSProperty(const nsAString& aPropName,
|
||||
IA2Color *aColorValue)
|
||||
{
|
||||
__try {
|
||||
*aColorValue = 0;
|
||||
|
||||
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
||||
if (acc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
||||
nsWinUtils::GetComputedStyleDeclaration(acc->GetContent());
|
||||
NS_ENSURE_STATE(styleDecl);
|
||||
nsIFrame* frame = acc->GetFrame();
|
||||
if (frame)
|
||||
*aBackground = frame->GetStyleBackground()->mBackgroundColor;
|
||||
|
||||
nsCOMPtr<nsIDOMCSSValue> cssGenericValue;
|
||||
styleDecl->GetPropertyCSSValue(aPropName, getter_AddRefs(cssGenericValue));
|
||||
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue =
|
||||
do_QueryInterface(cssGenericValue);
|
||||
if (!cssValue)
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIDOMRGBColor> rgbColor;
|
||||
nsresult rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
|
||||
if (NS_FAILED(rv) || !rgbColor)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNSRGBAColor> rgbaColor(do_QueryInterface(rgbColor));
|
||||
if (!rgbaColor)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get alpha
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> alphaValue;
|
||||
rv = rgbaColor->GetAlpha(getter_AddRefs(alphaValue));
|
||||
if (NS_FAILED(rv) || !alphaValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float alpha = 0.0;
|
||||
rv = alphaValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &alpha);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get red
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> redValue;
|
||||
rv = rgbaColor->GetRed(getter_AddRefs(redValue));
|
||||
if (NS_FAILED(rv) || !redValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float red = 0.0;
|
||||
rv = redValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &red);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get green
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> greenValue;
|
||||
rv = rgbaColor->GetGreen(getter_AddRefs(greenValue));
|
||||
if (NS_FAILED(rv) || !greenValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float green = 0.0;
|
||||
rv = greenValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &green);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get blue
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> blueValue;
|
||||
rv = rgbaColor->GetBlue(getter_AddRefs(blueValue));
|
||||
if (NS_FAILED(rv) || !blueValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float blue = 0.0;
|
||||
rv = blueValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &blue);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// compose ARGB value
|
||||
*aColorValue = (((IA2Color) blue) << IA2BlueShift) |
|
||||
(((IA2Color) green) << IA2GreenShift) |
|
||||
(((IA2Color) red) << IA2RedShift) |
|
||||
(((IA2Color) (alpha * 0xff)) << IA2AlphaShift);
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
@ -65,14 +65,6 @@ public:
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Return ARGB value for CSS property like 'color' or 'background-color'.
|
||||
*/
|
||||
HRESULT GetARGBValueFromCSSProperty(const nsAString& aPropName,
|
||||
IA2Color *aColorValue);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@ function testRelation(aIdentifier, aRelType, aRelatedIdentifiers)
|
||||
}
|
||||
}
|
||||
|
||||
ok(isFound, relatedIds[idx] + " is not a target of" + relDescr);
|
||||
ok(isFound, prettyName(relatedIds[idx]) + " is not a target of" + relDescr);
|
||||
}
|
||||
|
||||
// Check if all obtained targets are given related accessibles.
|
||||
|
@ -46,11 +46,13 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_bindings.xhtml \
|
||||
test_embeds.xul \
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_tabbrowser.xul \
|
||||
test_tree.xul \
|
||||
test_ui_modalprompt.html \
|
||||
test_update.html \
|
||||
$(NULL)
|
||||
|
||||
|
103
accessible/tests/mochitest/relations/test_bindings.xhtml
Normal file
103
accessible/tests/mochitest/relations/test_bindings.xhtml
Normal file
@ -0,0 +1,103 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>Accessible relations for bindings</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<style>
|
||||
.button {
|
||||
-moz-binding: url('#custombutton');
|
||||
}
|
||||
|
||||
.button2 {
|
||||
-moz-binding: url('#custombutton2');
|
||||
}
|
||||
</style>
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl">
|
||||
<binding id="custombutton">
|
||||
<content aria-labelledby="button.label label">
|
||||
<label xmlns="http://www.w3.org/1999/xhtml" anonid="button.label">
|
||||
anon label
|
||||
</label>
|
||||
<button xmlns="http://www.w3.org/1999/xhtml" anonid="button.button"
|
||||
aria-labelledby="button.label label">
|
||||
a button
|
||||
</button>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||
anonid="button.button2" class="button2"
|
||||
aria-labelledby="button.label"></div>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||
anonid="button.button3" class="button2"></div>
|
||||
</content>
|
||||
</binding>
|
||||
<binding id="custombutton2">
|
||||
<content aria-labelledby="button2.label">
|
||||
<label xmlns="http://www.w3.org/1999/xhtml" anonid="button2.label">
|
||||
nested anon label
|
||||
</label>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../relations.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTests()
|
||||
{
|
||||
var button = document.getElementById("button");
|
||||
var anonLabel = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.label");
|
||||
var anonButton = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.button");
|
||||
var anonButton2 = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.button2");
|
||||
var anonButton3 = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.button3");
|
||||
var anonAnonLabel = document.
|
||||
getAnonymousElementByAttribute(anonButton3, "anonid", "button2.label");
|
||||
|
||||
testRelation("label", RELATION_LABEL_FOR, button);
|
||||
testRelation(anonLabel, RELATION_LABEL_FOR, [button, anonButton, anonButton2]);
|
||||
testRelation(button, RELATION_LABELLED_BY, [anonLabel, "label"]);
|
||||
testRelation(anonButton, RELATION_LABELLED_BY, anonLabel);
|
||||
testRelation(anonButton2, RELATION_LABELLED_BY, anonLabel);
|
||||
testRelation(anonButton3, RELATION_LABELLED_BY, anonAnonLabel);
|
||||
testRelation(anonAnonLabel, RELATION_LABEL_FOR, anonButton3);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTests);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=421242"
|
||||
title="Allow relations in anonymous content for binding parent">
|
||||
Mozilla Bug 421242
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<div id="eventdump"></div>
|
||||
|
||||
<label id="label">explicit label</label>
|
||||
<div id="button" class="button"></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,95 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Modal prompts</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../relations.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../browser.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function showAlert()
|
||||
{
|
||||
this.eventSeq = [
|
||||
{
|
||||
type: EVENT_SHOW,
|
||||
match: function(aEvent)
|
||||
{
|
||||
return aEvent.accessible.role == ROLE_DIALOG;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
this.invoke = function showAlert_invoke()
|
||||
{
|
||||
window.setTimeout(
|
||||
function()
|
||||
{
|
||||
currentTabDocument().defaultView.alert("hello");
|
||||
}, 0);
|
||||
}
|
||||
|
||||
this.check = function showAlert_finalCheck(aEvent)
|
||||
{
|
||||
var dialog = aEvent.accessible.DOMNode;
|
||||
var info = dialog.ui.infoBody;
|
||||
testRelation(info, RELATION_DESCRIPTION_FOR, dialog);
|
||||
testRelation(dialog, RELATION_DESCRIBED_BY, info);
|
||||
}
|
||||
|
||||
this.getID = function showAlert_getID()
|
||||
{
|
||||
return "show alert";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true; // debug
|
||||
|
||||
var gQueue = null;
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new showAlert());
|
||||
gQueue.onFinish = function()
|
||||
{
|
||||
synthesizeKey("VK_RETURN", {}, browserWindow());
|
||||
closeBrowserWindow();
|
||||
}
|
||||
gQueue.invoke(); // will call SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
openBrowserWindow(doTests);
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body id="body">
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=661293"
|
||||
title="The tabmodalprompt dialog's prompt label doesn't get the text properly associated for accessibility">
|
||||
Mozilla Bug 661293
|
||||
</a>
|
||||
<br>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -2,41 +2,33 @@ function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var pageInfo;
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
pageInfo = BrowserPageInfo();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function loadListener() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", loadListener, true);
|
||||
|
||||
Services.obs.addObserver(observer, "page-info-dialog-loaded", false);
|
||||
pageInfo = BrowserPageInfo();
|
||||
}, true);
|
||||
content.location =
|
||||
"https://example.com/browser/browser/base/content/test/feed_tab.html";
|
||||
|
||||
function observer(win, topic, data) {
|
||||
if (topic != "page-info-dialog-loaded")
|
||||
return;
|
||||
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
Services.obs.removeObserver(observer, "page-info-dialog-loaded");
|
||||
handlePageInfo();
|
||||
}
|
||||
|
||||
function $(aId) { return pageInfo.document.getElementById(aId) };
|
||||
|
||||
function handlePageInfo() {
|
||||
var feedTab = $("feedTab");
|
||||
var feedListbox = $("feedListbox");
|
||||
|
||||
ok(feedListbox, "Feed list is null (feeds tab is broken)");
|
||||
ok(pageInfo.document.getElementById("feedTab"), "Feed tab");
|
||||
let feedListbox = pageInfo.document.getElementById("feedListbox");
|
||||
ok(feedListbox, "Feed list");
|
||||
|
||||
var feedRowsNum = feedListbox.getRowCount();
|
||||
|
||||
ok(feedRowsNum == 3, "Number of feeds listed: " +
|
||||
feedRowsNum + ", should be 3");
|
||||
|
||||
is(feedRowsNum, 3, "Number of feeds listed");
|
||||
|
||||
for (var i = 0; i < feedRowsNum; i++) {
|
||||
let feedItem = feedListbox.getItemAtIndex(i);
|
||||
ok(feedItem.getAttribute("name") == (i+1),
|
||||
"Name given: " + feedItem.getAttribute("name") + ", should be " + (i+1));
|
||||
is(feedItem.getAttribute("name"), i + 1, "Feed name");
|
||||
}
|
||||
|
||||
pageInfo.close();
|
||||
|
@ -1 +1 @@
|
||||
13.0a1
|
||||
14.0a1
|
||||
|
@ -66,6 +66,21 @@
|
||||
-moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
|
||||
}
|
||||
|
||||
#navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme) {
|
||||
border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.27) hsla(210,54%,20%,.3);
|
||||
}
|
||||
|
||||
#navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme):not([focused]):hover,
|
||||
#navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme):not([focused]):hover {
|
||||
border-color: hsla(210,54%,20%,.35) hsla(210,54%,20%,.37) hsla(210,54%,20%,.4);
|
||||
}
|
||||
|
||||
#navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme)[focused],
|
||||
#navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme)[focused] {
|
||||
border-color: hsla(206,100%,60%,.65) hsla(206,100%,55%,.65) hsla(206,100%,50%,.65);
|
||||
}
|
||||
|
||||
#sidebar-splitter {
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid #A9B7C9;
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
13.0a1
|
||||
14.0a1
|
||||
|
@ -276,12 +276,13 @@ var TestRequests = [
|
||||
// Aborted requests.
|
||||
new AbortedRequest(false),
|
||||
new AbortedRequest(true, -1),
|
||||
new AbortedRequest(true, 0),
|
||||
new AbortedRequest(true, 1000),
|
||||
new AbortedRequest(true, 5000),
|
||||
];
|
||||
|
||||
var MainThreadTestRequests = [
|
||||
new AbortedRequest(true, 0),
|
||||
new AbortedRequest(true, 1000),
|
||||
|
||||
// Synchronous requests.
|
||||
SyncRequestSettingTimeoutAfterOpen,
|
||||
SyncRequestSettingTimeoutBeforeOpen
|
||||
|
@ -326,10 +326,48 @@ is(e.view, window, "view should be window");
|
||||
document.dispatchEvent(e);
|
||||
is(receivedEvent, e, "Wrong event!");
|
||||
|
||||
// UIEvent
|
||||
// StorageEvent
|
||||
|
||||
try {
|
||||
e = new UIEvent();
|
||||
e = new StorageEvent();
|
||||
} catch(exp) {
|
||||
ex = true;
|
||||
}
|
||||
ok(ex, "First parameter is required!");
|
||||
ex = false;
|
||||
|
||||
e = new StorageEvent("hello");
|
||||
ok(e.type, "hello", "Wrong event type!");
|
||||
ok(!e.isTrusted, "Event shouldn't be trusted!");
|
||||
ok(!e.bubbles, "Event shouldn't bubble!");
|
||||
ok(!e.cancelable, "Event shouldn't be cancelable!");
|
||||
is(e.key, "", "key should be ''");
|
||||
is(e.oldValue, null, "oldValue should be null");
|
||||
is(e.newValue, null, "newValue should be null");
|
||||
is(e.url, "", "url should be ''");
|
||||
document.dispatchEvent(e);
|
||||
is(receivedEvent, e, "Wrong event!");
|
||||
|
||||
e = new StorageEvent("hello",
|
||||
{ bubbles: true, cancelable: true, key: "key",
|
||||
oldValue: "oldValue", newValue: "newValue", url: "url",
|
||||
storageArea: localStorage });
|
||||
ok(e.type, "hello", "Wrong event type!");
|
||||
ok(!e.isTrusted, "Event shouldn't be trusted!");
|
||||
ok(e.bubbles, "Event should bubble!");
|
||||
ok(e.cancelable, "Event should be cancelable!");
|
||||
is(e.key, "key", "Wrong value");
|
||||
is(e.oldValue, "oldValue", "Wrong value");
|
||||
is(e.newValue, "newValue", "Wrong value");
|
||||
is(e.url, "url", "Wrong value");
|
||||
is(e.storageArea, localStorage, "Wrong value");
|
||||
document.dispatchEvent(e);
|
||||
is(receivedEvent, e, "Wrong event!");
|
||||
|
||||
// MouseEvent
|
||||
|
||||
try {
|
||||
e = new MouseEvent();
|
||||
} catch(exp) {
|
||||
ex = true;
|
||||
}
|
||||
|
@ -567,6 +567,13 @@ Navigator::JavaEnabled(bool* aReturn)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Navigator::TaintEnabled(bool *aReturn)
|
||||
{
|
||||
*aReturn = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::RefreshMIMEArray()
|
||||
{
|
||||
|
@ -1422,9 +1422,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(GeoPositionCoords, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(GeoPositionAddress, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(GeoPositionError, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
@ -4020,10 +4017,6 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionCoords)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(GeoPositionAddress, nsIDOMGeoPositionAddress)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionAddress)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(GeoPositionError, nsIDOMGeoPositionError)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionError)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -422,7 +422,6 @@ DOMCI_CLASS(MessageEvent)
|
||||
DOMCI_CLASS(GeoGeolocation)
|
||||
DOMCI_CLASS(GeoPosition)
|
||||
DOMCI_CLASS(GeoPositionCoords)
|
||||
DOMCI_CLASS(GeoPositionAddress)
|
||||
DOMCI_CLASS(GeoPositionError)
|
||||
|
||||
DOMCI_CLASS(MozBatteryManager)
|
||||
|
@ -3161,6 +3161,44 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
|
||||
if (cs) {
|
||||
cs->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt,
|
||||
NS_LL("{ \"duration\": %llu, ")
|
||||
NS_LL("\"suspected\": %lu, ")
|
||||
NS_LL("\"visited\": { ")
|
||||
NS_LL("\"RCed\": %lu, ")
|
||||
NS_LL("\"GCed\": %lu }, ")
|
||||
NS_LL("\"collected\": { ")
|
||||
NS_LL("\"RCed\": %lu, ")
|
||||
NS_LL("\"GCed\": %lu }, ")
|
||||
NS_LL("\"waiting_for_gc\": %lu, ")
|
||||
NS_LL("\"forced_gc\": %d, ")
|
||||
NS_LL("\"forget_skippable\": { ")
|
||||
NS_LL("\"times_before_cc\": %lu, ")
|
||||
NS_LL("\"min\": %lu, ")
|
||||
NS_LL("\"max\": %lu, ")
|
||||
NS_LL("\"avg\": %lu, ")
|
||||
NS_LL("\"total\": %lu, ")
|
||||
NS_LL("\"removed\": %lu } ")
|
||||
NS_LL("}"));
|
||||
nsString json;
|
||||
json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(),
|
||||
(now - start) / PR_USEC_PER_MSEC, suspected,
|
||||
ccResults.mVisitedRefCounted, ccResults.mVisitedGCed,
|
||||
ccResults.mFreedRefCounted, ccResults.mFreedGCed,
|
||||
sCCollectedWaitingForGC,
|
||||
ccResults.mForcedGC,
|
||||
sForgetSkippableBeforeCC,
|
||||
sMinForgetSkippableTime / PR_USEC_PER_MSEC,
|
||||
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
|
||||
(sTotalForgetSkippableTime / cleanups) /
|
||||
PR_USEC_PER_MSEC,
|
||||
sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
|
||||
sRemovedPurples));
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(nsnull, "cycle-collection-statistics", json.get());
|
||||
}
|
||||
}
|
||||
sMinForgetSkippableTime = PR_UINT32_MAX;
|
||||
sMaxForgetSkippableTime = 0;
|
||||
@ -3417,12 +3455,39 @@ nsJSContext::GC(js::gcreason::Reason aReason)
|
||||
PokeGC(aReason);
|
||||
}
|
||||
|
||||
class NotifyGCEndRunnable : public nsRunnable
|
||||
{
|
||||
nsString mMessage;
|
||||
|
||||
public:
|
||||
NotifyGCEndRunnable(const nsString& aMessage) : mMessage(aMessage) {}
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotifyGCEndRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (!observerService) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const jschar oomMsg[3] = { '{', '}', 0 };
|
||||
const jschar *toSend = mMessage.get() ? mMessage.get() : oomMsg;
|
||||
observerService->NotifyObservers(nsnull, "garbage-collection-statistics", toSend);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescription &aDesc)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
|
||||
|
||||
if (aDesc.logMessage && sPostGCEventsToConsole) {
|
||||
if (aProgress == js::GC_CYCLE_END && sPostGCEventsToConsole) {
|
||||
PRTime now = PR_Now();
|
||||
PRTime delta = 0;
|
||||
if (sFirstCollectionTime) {
|
||||
@ -3432,10 +3497,11 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_STRING(kFmt, "GC(T+%.1f) %s");
|
||||
nsString msg;
|
||||
nsString msg, gcstats;
|
||||
gcstats.Adopt(aDesc.formatMessage(aRt));
|
||||
msg.Adopt(nsTextFormatter::smprintf(kFmt.get(),
|
||||
double(delta) / PR_USEC_PER_SEC,
|
||||
aDesc.logMessage));
|
||||
gcstats.get()));
|
||||
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (cs) {
|
||||
cs->LogStringMessage(msg.get());
|
||||
@ -3463,6 +3529,11 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
|
||||
sCCollectedWaitingForGC = 0;
|
||||
sCleanupSinceLastGC = false;
|
||||
|
||||
nsString json;
|
||||
json.Adopt(aDesc.formatJSON(aRt));
|
||||
nsRefPtr<NotifyGCEndRunnable> notify = new NotifyGCEndRunnable(json);
|
||||
NS_DispatchToMainThread(notify);
|
||||
|
||||
if (aDesc.isCompartment) {
|
||||
// If this is a compartment GC, restart it. We still want
|
||||
// a full GC to happen. Compartment GCs usually happen as a
|
||||
|
@ -53,7 +53,7 @@ nsWindowMemoryReporter::Init()
|
||||
NS_RegisterMemoryMultiReporter(new nsWindowMemoryReporter());
|
||||
}
|
||||
|
||||
static bool
|
||||
static void
|
||||
AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
|
||||
@ -71,21 +71,19 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
|
||||
}
|
||||
}
|
||||
|
||||
if (!uri) {
|
||||
return false;
|
||||
if (uri) {
|
||||
nsCString spec;
|
||||
uri->GetSpec(spec);
|
||||
|
||||
// A hack: replace forward slashes with '\\' so they aren't
|
||||
// treated as path separators. Users of the reporters
|
||||
// (such as about:memory) have to undo this change.
|
||||
spec.ReplaceChar('/', '\\');
|
||||
|
||||
aStr += spec;
|
||||
} else {
|
||||
aStr += NS_LITERAL_CSTRING("[system]");
|
||||
}
|
||||
|
||||
nsCString spec;
|
||||
uri->GetSpec(spec);
|
||||
|
||||
// A hack: replace forward slashes with '\\' so they aren't
|
||||
// treated as path separators. Users of the reporters
|
||||
// (such as about:memory) have to undo this change.
|
||||
spec.ReplaceChar('/', '\\');
|
||||
|
||||
aStr += spec;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
|
||||
@ -104,99 +102,68 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
||||
// cached) yet held alive by either a website or our code. The
|
||||
// latter case may be a memory leak, but not necessarily.
|
||||
//
|
||||
// For inner windows we show how much memory the window and its
|
||||
// document etc use, and we report those per URI, where the URI is
|
||||
// the document URI, if available, or the codebase of the principal
|
||||
// in the window. In the case where we're unable to find a URI we're
|
||||
// dealing with a chrome window with no document in it (or
|
||||
// somesuch), and for that we make the URI be the string "[system]".
|
||||
// For each window we show how much memory the window and its
|
||||
// document, etc, use, and we report those per URI, where the URI is
|
||||
// the document URI, if available, or the codebase of the principal in
|
||||
// the window. In the case where we're unable to find a URI we're
|
||||
// dealing with a chrome window with no document in it (or somesuch),
|
||||
// and for that we make the URI be the string "[system]".
|
||||
//
|
||||
// For outer windows we simply group them all together and just show
|
||||
// the combined count and amount of memory used, which is generally
|
||||
// a constant amount per window (since all the actual data lives in
|
||||
// the inner window).
|
||||
// Outer windows are lumped in with inner windows, because the amount
|
||||
// of memory used by outer windows is small.
|
||||
//
|
||||
// The path we give to the reporter callback for inner windows are
|
||||
// as follows:
|
||||
// The path we give to the reporter callback for "active" and "cached"
|
||||
// windows (both inner and outer) is as follows:
|
||||
//
|
||||
// explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
|
||||
// explicit/window-objects/top(<top-outer-uri>, id=<top-outer-id>)/<category>/window(<window-uri>)/...
|
||||
//
|
||||
// The path we give for "other" windows is as follows:
|
||||
//
|
||||
// explicit/window-objects/top(none)/window(<window-uri>)/...
|
||||
//
|
||||
// Where:
|
||||
// - <category> is active, cached, or other, as described above.
|
||||
// - <category> is "active" or "cached", as described above.
|
||||
// - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
|
||||
// the top outer window (i.e. tab, or top level chrome window).
|
||||
// - <top-inner-id> is the window id of the top window's inner
|
||||
// window.
|
||||
// - <id> is the window id of the inner window in question.
|
||||
// - <uri> is the URI per above description.
|
||||
// - <top-inner-uri> is the URI of the top outer window. Excepting
|
||||
// special windows (such as browser.xul or hiddenWindow.html) it's
|
||||
// what the address bar shows for the tab.
|
||||
// - <window-uri> is the URI of aWindow.
|
||||
//
|
||||
// Exposing the window ids is done to get logical grouping in
|
||||
// about:memory, and also for debuggability since one can get to the
|
||||
// nsGlobalWindow for a window id by calling the static method
|
||||
// nsGlobalWindow::GetInnerWindowWithId(id) (or
|
||||
// GetOuterWindowWithId(id) in a debugger.
|
||||
//
|
||||
// For outer windows we simply use:
|
||||
//
|
||||
// explicit/window-objects/<category>/outer-windows
|
||||
//
|
||||
// Which gives us simple counts of how many outer windows (and their
|
||||
// combined sizes) per category.
|
||||
// Exposing the top-outer-id ensures that each tab gets its own
|
||||
// sub-tree, even if multiple tabs are showing the same URI.
|
||||
|
||||
nsCAutoString windowPath("explicit/window-objects/");
|
||||
|
||||
nsIDocShell *docShell = aWindow->GetDocShell();
|
||||
|
||||
nsGlobalWindow *top = aWindow->GetTop();
|
||||
nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
|
||||
aWindow->SizeOfIncludingThis(&windowSizes);
|
||||
|
||||
if (docShell && aWindow->IsFrozen()) {
|
||||
windowPath += NS_LITERAL_CSTRING("cached/");
|
||||
} else if (docShell) {
|
||||
windowPath += NS_LITERAL_CSTRING("active/");
|
||||
windowPath += NS_LITERAL_CSTRING("top(");
|
||||
if (top) {
|
||||
AppendWindowURI(top, windowPath);
|
||||
windowPath += NS_LITERAL_CSTRING(", id=");
|
||||
windowPath.AppendInt(top->WindowID());
|
||||
} else {
|
||||
windowPath += NS_LITERAL_CSTRING("other/");
|
||||
windowPath += NS_LITERAL_CSTRING("none");
|
||||
}
|
||||
windowPath += NS_LITERAL_CSTRING(")/");
|
||||
|
||||
nsIDocShell *docShell = aWindow->GetDocShell();
|
||||
if (docShell) {
|
||||
MOZ_ASSERT(top, "'cached' or 'active' window lacks a top window");
|
||||
windowPath += aWindow->IsFrozen() ? NS_LITERAL_CSTRING("cached/")
|
||||
: NS_LITERAL_CSTRING("active/");
|
||||
} else {
|
||||
MOZ_ASSERT(!top, "'other' window has a top window");
|
||||
}
|
||||
|
||||
if (aWindow->IsInnerWindow()) {
|
||||
windowPath += NS_LITERAL_CSTRING("top=");
|
||||
windowPath += NS_LITERAL_CSTRING("window(");
|
||||
AppendWindowURI(aWindow, windowPath);
|
||||
windowPath += NS_LITERAL_CSTRING(")");
|
||||
|
||||
if (top) {
|
||||
windowPath.AppendInt(top->WindowID());
|
||||
|
||||
nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
|
||||
if (topInner) {
|
||||
windowPath += NS_LITERAL_CSTRING(" (inner=");
|
||||
windowPath.AppendInt(topInner->WindowID());
|
||||
windowPath += NS_LITERAL_CSTRING(")");
|
||||
}
|
||||
} else {
|
||||
windowPath += NS_LITERAL_CSTRING("none");
|
||||
}
|
||||
|
||||
windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
|
||||
windowPath.AppendInt(aWindow->WindowID());
|
||||
windowPath += NS_LITERAL_CSTRING(", uri=");
|
||||
|
||||
if (!AppendWindowURI(aWindow, windowPath)) {
|
||||
windowPath += NS_LITERAL_CSTRING("[system]");
|
||||
}
|
||||
|
||||
windowPath += NS_LITERAL_CSTRING(")");
|
||||
} else {
|
||||
// Combine all outer windows per section (active/cached/other) as
|
||||
// they basically never contain anything of interest, and are
|
||||
// always pretty much the same size.
|
||||
|
||||
windowPath += NS_LITERAL_CSTRING("outer-windows");
|
||||
}
|
||||
|
||||
#define REPORT(_path1, _path2, _amount, _desc) \
|
||||
#define REPORT(_pathTail, _amount, _desc) \
|
||||
do { \
|
||||
if (_amount > 0) { \
|
||||
nsCAutoString path(_path1); \
|
||||
path += _path2; \
|
||||
nsCAutoString path(windowPath); \
|
||||
path += _pathTail; \
|
||||
nsresult rv; \
|
||||
rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\
|
||||
nsIMemoryReporter::UNITS_BYTES, _amount, \
|
||||
@ -205,24 +172,27 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
REPORT(windowPath, "/dom", windowSizes.mDOM,
|
||||
nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
|
||||
aWindow->SizeOfIncludingThis(&windowSizes);
|
||||
|
||||
REPORT("/dom", windowSizes.mDOM,
|
||||
"Memory used by a window and the DOM within it.");
|
||||
aWindowTotalSizes->mDOM += windowSizes.mDOM;
|
||||
|
||||
REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets,
|
||||
REPORT("/style-sheets", windowSizes.mStyleSheets,
|
||||
"Memory used by style sheets within a window.");
|
||||
aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
|
||||
|
||||
REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas,
|
||||
REPORT("/layout/arenas", windowSizes.mLayoutArenas,
|
||||
"Memory used by layout PresShell, PresContext, and other related "
|
||||
"areas within a window.");
|
||||
aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;
|
||||
|
||||
REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets,
|
||||
REPORT("/layout/style-sets", windowSizes.mLayoutStyleSets,
|
||||
"Memory used by style sets within a window.");
|
||||
aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets;
|
||||
|
||||
REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns,
|
||||
REPORT("/layout/text-runs", windowSizes.mLayoutTextRuns,
|
||||
"Memory used for text-runs (glyph layout) in the PresShell's frame "
|
||||
"tree, within a window.");
|
||||
aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns;
|
||||
|
@ -25,7 +25,7 @@ const STORE_NAME = "contacts";
|
||||
|
||||
function ContactDB(aGlobal) {
|
||||
debug("Constructor");
|
||||
this._indexedDB = aGlobal.mozIndexedDB;
|
||||
this._global = aGlobal;
|
||||
}
|
||||
|
||||
ContactDB.prototype = {
|
||||
@ -54,7 +54,7 @@ ContactDB.prototype = {
|
||||
|
||||
let self = this;
|
||||
debug("try to open database:" + DB_NAME + " " + DB_VERSION);
|
||||
let request = this._indexedDB.open(DB_NAME, DB_VERSION);
|
||||
let request = this._global.mozIndexedDB.open(DB_NAME, DB_VERSION);
|
||||
request.onsuccess = function (event) {
|
||||
debug("Opened database:", DB_NAME, DB_VERSION);
|
||||
self.db = event.target.result;
|
||||
@ -116,6 +116,14 @@ ContactDB.prototype = {
|
||||
objectStore.createIndex("email", "properties.email", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("note", "properties.note", { unique: false, multiEntry: true });
|
||||
|
||||
objectStore.createIndex("nicknameLowerCase", "search.nickname", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("nameLowerCase", "search.name", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("familyNameLowerCase", "search.familyName", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("givenNameLowerCase", "search.givenName", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("telLowerCase", "search.tel", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("emailLowerCase", "search.email", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("noteLowerCase", "search.note", { unique: false, multiEntry: true });
|
||||
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
@ -123,7 +131,7 @@ ContactDB.prototype = {
|
||||
* Start a new transaction.
|
||||
*
|
||||
* @param txn_type
|
||||
* Type of transaction (e.g. IDBTransaction.READ_WRITE)
|
||||
* Type of transaction (e.g. "readwrite")
|
||||
* @param callback
|
||||
* Function to call when the transaction is available. It will
|
||||
* be invoked with the transaction and the 'contacts' object store.
|
||||
@ -171,7 +179,6 @@ ContactDB.prototype = {
|
||||
}, failureCb);
|
||||
},
|
||||
|
||||
// Todo: add searchfields. "Tom" should be a result with T, t, To, to...
|
||||
makeImport: function makeImport(aContact) {
|
||||
let contact = {};
|
||||
contact.properties = {
|
||||
@ -197,9 +204,33 @@ ContactDB.prototype = {
|
||||
genderIdentity: null
|
||||
};
|
||||
|
||||
contact.search = {
|
||||
name: [],
|
||||
honorificPrefix: [],
|
||||
givenName: [],
|
||||
additionalName: [],
|
||||
familyName: [],
|
||||
honorificSuffix: [],
|
||||
nickname: [],
|
||||
email: [],
|
||||
category: [],
|
||||
tel: [],
|
||||
org: [],
|
||||
note: [],
|
||||
impp: []
|
||||
};
|
||||
|
||||
for (let field in aContact.properties) {
|
||||
contact.properties[field] = aContact.properties[field];
|
||||
// Add search fields
|
||||
if (aContact.properties[field] && contact.search[field]) {
|
||||
for (let i = 0; i <= aContact.properties[field].length; i++) {
|
||||
if (aContact.properties[field][i])
|
||||
contact.search[field].push(aContact.properties[field][i].toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("contact:" + JSON.stringify(contact));
|
||||
|
||||
contact.updated = aContact.updated;
|
||||
contact.published = aContact.published;
|
||||
@ -208,7 +239,6 @@ ContactDB.prototype = {
|
||||
return contact;
|
||||
},
|
||||
|
||||
// Needed to remove searchfields
|
||||
makeExport: function makeExport(aRecord) {
|
||||
let contact = {};
|
||||
contact.properties = aRecord.properties;
|
||||
@ -234,7 +264,7 @@ ContactDB.prototype = {
|
||||
|
||||
saveContact: function saveContact(aContact, successCb, errorCb) {
|
||||
let contact = this.makeImport(aContact);
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
|
||||
this.newTxn("readwrite", function (txn, store) {
|
||||
debug("Going to update" + JSON.stringify(contact));
|
||||
|
||||
// Look up the existing record and compare the update timestamp.
|
||||
@ -263,14 +293,14 @@ ContactDB.prototype = {
|
||||
},
|
||||
|
||||
removeContact: function removeContact(aId, aSuccessCb, aErrorCb) {
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
|
||||
this.newTxn("readwrite", function (txn, store) {
|
||||
debug("Going to delete" + aId);
|
||||
store.delete(aId);
|
||||
}, aSuccessCb, aErrorCb);
|
||||
},
|
||||
|
||||
clear: function clear(aSuccessCb, aErrorCb) {
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
|
||||
this.newTxn("readwrite", function (txn, store) {
|
||||
debug("Going to clear all!");
|
||||
store.clear();
|
||||
}, aSuccessCb, aErrorCb);
|
||||
@ -297,11 +327,9 @@ ContactDB.prototype = {
|
||||
debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp + "\n");
|
||||
|
||||
let self = this;
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (txn, store) {
|
||||
if (aOptions && aOptions.filterOp == "equals") {
|
||||
this.newTxn("readonly", function (txn, store) {
|
||||
if (aOptions && (aOptions.filterOp == "equals" || aOptions.filterOp == "contains")) {
|
||||
self._findWithIndex(txn, store, aOptions);
|
||||
} else if (aOptions && aOptions.filterBy) {
|
||||
self._findWithSearch(txn, store, aOptions);
|
||||
} else {
|
||||
self._findAll(txn, store, aOptions);
|
||||
}
|
||||
@ -334,10 +362,17 @@ ContactDB.prototype = {
|
||||
if (key == "id") {
|
||||
// store.get would return an object and not an array
|
||||
request = store.getAll(options.filterValue);
|
||||
} else {
|
||||
} else if (options.filterOp == "equals") {
|
||||
debug("Getting index: " + key);
|
||||
// case sensitive
|
||||
let index = store.index(key);
|
||||
request = index.getAll(options.filterValue, options.filterLimit);
|
||||
} else {
|
||||
// not case sensitive
|
||||
let tmp = options.filterValue.toLowerCase();
|
||||
let range = this._global.IDBKeyRange.bound(tmp, tmp + "\uFFFF");
|
||||
let index = store.index(key + "LowerCase");
|
||||
request = index.getAll(range, options.filterLimit);
|
||||
}
|
||||
if (!txn.result)
|
||||
txn.result = {};
|
||||
@ -350,52 +385,6 @@ ContactDB.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// Will be replaced by _findWithIndex once all searchfields are added.
|
||||
_findWithSearch: function _findWithSearch(txn, store, options) {
|
||||
debug("_findWithSearch:" + options.filterValue + options.filterOp)
|
||||
store.getAll().onsuccess = function (event) {
|
||||
debug("Request successful." + event.target.result);
|
||||
txn.result = event.target.result.filter(function (record) {
|
||||
let properties = record.properties;
|
||||
for (let i = 0; i < options.filterBy.length; i++) {
|
||||
let field = options.filterBy[i];
|
||||
if (!properties[field])
|
||||
continue;
|
||||
let value = '';
|
||||
switch (field) {
|
||||
case "name":
|
||||
case "familyName":
|
||||
case "givenName":
|
||||
case "nickname":
|
||||
case "email":
|
||||
case "tel":
|
||||
case "note":
|
||||
value = [f for each (f in [properties[field]])].join("\n") || '';
|
||||
break;
|
||||
default:
|
||||
value = properties[field];
|
||||
debug("unknown field: " + field);
|
||||
}
|
||||
let match = false;
|
||||
switch (options.filterOp) {
|
||||
case "icontains":
|
||||
match = value.toLowerCase().indexOf(options.filterValue.toLowerCase()) != -1;
|
||||
break;
|
||||
case "contains":
|
||||
match = value.indexOf(options.filterValue) != -1;
|
||||
break;
|
||||
case "equals":
|
||||
match = value == options.filterValue;
|
||||
break
|
||||
}
|
||||
if (match)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}).map(this.makeExport.bind(this));
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
_findAll: function _findAll(txn, store, options) {
|
||||
debug("ContactDB:_findAll: " + JSON.stringify(options));
|
||||
if (!txn.result)
|
||||
|
@ -46,7 +46,7 @@ var adr2 = {
|
||||
|
||||
var properties1 = {
|
||||
name: "Testname1",
|
||||
familyName: "TestFamilyName",
|
||||
familyName: ["TestFamilyName","Wagner"],
|
||||
givenName: ["Test1","Test2"],
|
||||
nickname: "nicktest",
|
||||
tel: ["123456"],
|
||||
@ -211,6 +211,66 @@ var steps = [
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving by substring");
|
||||
var options = {filterBy: ["name"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.name.substring(0,3)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(createResult1, properties1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving by substring2");
|
||||
var options = {filterBy: ["givenName"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.givenName[0].substring(0,3)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(createResult1, properties1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving by substring3");
|
||||
var options = {filterBy: ["name", "givenName"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.givenName[0].substring(0,3)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(createResult1, properties1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving by substring3, Testing multi entry");
|
||||
var options = {filterBy: ["name", "givenName", "familyName"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.familyName[1].substring(0,3).toLowerCase()};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(createResult1, properties1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
req = mozContacts.find({});
|
||||
@ -306,7 +366,7 @@ var steps = [
|
||||
function () {
|
||||
ok(true, "Searching contacts by query");
|
||||
var options = {filterBy: ["name", "email"],
|
||||
filterOp: "icontains",
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.name[0].substring(0,4)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
@ -321,7 +381,7 @@ var steps = [
|
||||
function () {
|
||||
ok(true, "Searching contacts by query");
|
||||
var options = {filterBy: ["nickname", "email"],
|
||||
filterOp: "icontains",
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.nickname};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
@ -429,7 +489,7 @@ var steps = [
|
||||
function () {
|
||||
console.log("Searching contacts by query1");
|
||||
var options = {filterBy: ["name", "email"],
|
||||
filterOp: "icontains",
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.name[0].substring(0, 4)}
|
||||
req = mozContacts.find(options)
|
||||
req.onsuccess = function () {
|
||||
@ -444,7 +504,7 @@ var steps = [
|
||||
function () {
|
||||
ok(true, "Searching contacts by query2");
|
||||
var options = {filterBy: ["name", "email"],
|
||||
filterOp: "icontains",
|
||||
filterOp: "contains",
|
||||
filterValue: properties2.name[0].substring(0, 4)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
@ -538,9 +598,9 @@ var steps = [
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts2");
|
||||
var options = {filterBy: ["name"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties2.name[0].substring(0, 4)};
|
||||
req = mozContacts.find({});
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.name[0].substring(0, 4)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 100, "100 Entries.");
|
||||
checkContacts(createResult1, req.result[99]);
|
||||
@ -548,6 +608,20 @@ var steps = [
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts3");
|
||||
var options = {filterBy: ["name", "givenName", "tel", "email", "note"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties1.name[0].substring(0, 4),
|
||||
filterLimit: 15 };
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 15, "15 Entries.");
|
||||
checkContacts(createResult1, req.result[10]);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
req = mozContacts.clear();
|
||||
@ -588,7 +662,7 @@ var steps = [
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
var options = {filterBy: ["name"],
|
||||
filterOp: "icontains",
|
||||
filterOp: "contains",
|
||||
filterValue: properties2.name[0].substring(0, 4)};
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function () {
|
||||
|
@ -463,7 +463,7 @@ IDBCursor::GetDirection(nsAString& aDirection)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
switch(mDirection) {
|
||||
switch (mDirection) {
|
||||
case NEXT:
|
||||
aDirection.AssignLiteral("next");
|
||||
break;
|
||||
|
@ -532,7 +532,7 @@ IDBTransaction::GetMode(nsAString& aMode)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
switch(mMode) {
|
||||
switch (mMode) {
|
||||
case READ_ONLY:
|
||||
aMode.AssignLiteral("readonly");
|
||||
break;
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(e610c037-db58-4cd7-8ed3-0d7f1422b4d3)]
|
||||
[scriptable, uuid(e0737ed5-89c5-4fe3-891e-a75bf3a1bb55)]
|
||||
interface nsIDOMNavigator : nsISupports
|
||||
{
|
||||
readonly attribute DOMString appCodeName;
|
||||
@ -62,6 +62,7 @@ interface nsIDOMNavigator : nsISupports
|
||||
readonly attribute nsIDOMMozPowerManager mozPower;
|
||||
|
||||
boolean javaEnabled();
|
||||
boolean taintEnabled();
|
||||
|
||||
/**
|
||||
* Pulse the device's vibrator, if it has one. If the device does not have a
|
||||
|
@ -49,7 +49,6 @@ GRE_MODULE = 1
|
||||
XPIDLSRCS = \
|
||||
nsIDOMGeoGeolocation.idl \
|
||||
nsIDOMGeoPosition.idl \
|
||||
nsIDOMGeoPositionAddress.idl \
|
||||
nsIDOMGeoPositionCoords.idl \
|
||||
nsIDOMGeoPositionCallback.idl \
|
||||
nsIDOMGeoPositionError.idl \
|
||||
|
@ -37,13 +37,10 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
#include "nsIDOMGeoPositionCoords.idl"
|
||||
#include "nsIDOMGeoPositionAddress.idl"
|
||||
|
||||
[scriptable, uuid(23E5269F-4DD7-41C4-B52A-75918694C2DE)]
|
||||
[scriptable, uuid(dd9f7e81-0f74-4fb5-b361-37019bf60c3f)]
|
||||
interface nsIDOMGeoPosition : nsISupports
|
||||
{
|
||||
readonly attribute DOMTimeStamp timestamp;
|
||||
readonly attribute nsIDOMGeoPositionCoords coords;
|
||||
readonly attribute nsIDOMGeoPositionAddress address;
|
||||
|
||||
};
|
||||
|
@ -753,6 +753,16 @@ ContentChild::RecvDeviceMotionChanged(const long int& type,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvNeedsCalibration()
|
||||
{
|
||||
nsCOMPtr<nsIDeviceMotionUpdate> dmu =
|
||||
do_GetService(NS_DEVICE_MOTION_CONTRACTID);
|
||||
if (dmu)
|
||||
dmu->NeedsCalibration();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
|
||||
{
|
||||
|
@ -162,6 +162,8 @@ public:
|
||||
const double& x, const double& y,
|
||||
const double& z);
|
||||
|
||||
virtual bool RecvNeedsCalibration();
|
||||
|
||||
virtual bool RecvScreenSizeChanged(const gfxIntSize &size);
|
||||
|
||||
virtual bool RecvFlushMemory(const nsString& reason);
|
||||
|
@ -1291,6 +1291,12 @@ ContentParent::OnMotionChange(nsIDeviceMotionData *aDeviceData) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentParent::NeedsCalibration() {
|
||||
unused << SendNeedsCalibration();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -134,6 +134,7 @@ child:
|
||||
AddPermission(Permission permission);
|
||||
|
||||
DeviceMotionChanged(long type, double x, double y, double z);
|
||||
NeedsCalibration();
|
||||
|
||||
ScreenSizeChanged(gfxIntSize size);
|
||||
|
||||
|
@ -40,100 +40,6 @@
|
||||
#include "nsGeoPosition.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// nsGeoPositionAddress
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
nsGeoPositionAddress::nsGeoPositionAddress(const nsAString &aStreetNumber,
|
||||
const nsAString &aStreet,
|
||||
const nsAString &aPremises,
|
||||
const nsAString &aCity,
|
||||
const nsAString &aCounty,
|
||||
const nsAString &aRegion,
|
||||
const nsAString &aCountry,
|
||||
const nsAString &aPostalCode)
|
||||
: mStreetNumber(aStreetNumber)
|
||||
, mStreet(aStreet)
|
||||
, mPremises(aPremises)
|
||||
, mCity(aCity)
|
||||
, mCounty(aCounty)
|
||||
, mRegion(aRegion)
|
||||
, mCountry(aCountry)
|
||||
, mPostalCode(aPostalCode)
|
||||
{
|
||||
}
|
||||
|
||||
nsGeoPositionAddress::~nsGeoPositionAddress()
|
||||
{
|
||||
}
|
||||
|
||||
DOMCI_DATA(GeoPositionAddress, nsGeoPositionAddress)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsGeoPositionAddress)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionAddress)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionAddress)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionAddress)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionAddress)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionAddress)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetStreetNumber(nsAString & aStreetNumber)
|
||||
{
|
||||
aStreetNumber = mStreetNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetStreet(nsAString & aStreet)
|
||||
{
|
||||
aStreet = mStreet;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetPremises(nsAString & aPremises)
|
||||
{
|
||||
aPremises = mPremises;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetCity(nsAString & aCity)
|
||||
{
|
||||
aCity = mCity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetCounty(nsAString & aCounty)
|
||||
{
|
||||
aCounty = mCounty;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetRegion(nsAString & aRegion)
|
||||
{
|
||||
aRegion = mRegion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetCountry(nsAString & aCountry)
|
||||
{
|
||||
aCountry = mCountry;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPositionAddress::GetPostalCode(nsAString & aPostalCode)
|
||||
{
|
||||
aPostalCode = mPostalCode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// nsGeoPositionCoords
|
||||
////////////////////////////////////////////////////
|
||||
@ -239,11 +145,9 @@ nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
|
||||
}
|
||||
|
||||
nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
|
||||
nsIDOMGeoPositionAddress *aAddress,
|
||||
DOMTimeStamp aTimestamp) :
|
||||
mTimestamp(aTimestamp),
|
||||
mCoords(aCoords),
|
||||
mAddress(aAddress)
|
||||
mCoords(aCoords)
|
||||
{
|
||||
}
|
||||
|
||||
@ -275,11 +179,3 @@ nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords)
|
||||
NS_IF_ADDREF(*aCoords = mCoords);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress)
|
||||
{
|
||||
NS_IF_ADDREF(*aAddress = mAddress);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -43,42 +43,10 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIDOMGeoPositionAddress.h"
|
||||
#include "nsIDOMGeoPositionCoords.h"
|
||||
#include "nsIDOMGeoPosition.h"
|
||||
#include "nsString.h"
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// nsGeoPositionAddress
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
class nsGeoPositionAddress : public nsIDOMGeoPositionAddress
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMGEOPOSITIONADDRESS
|
||||
|
||||
nsGeoPositionAddress( const nsAString &aStreetNumber,
|
||||
const nsAString &aStreet,
|
||||
const nsAString &aPremises,
|
||||
const nsAString &aCity,
|
||||
const nsAString &aCounty,
|
||||
const nsAString &aRegion,
|
||||
const nsAString &aCountry,
|
||||
const nsAString &aPostalCode);
|
||||
|
||||
~nsGeoPositionAddress();
|
||||
private:
|
||||
const nsString mStreetNumber;
|
||||
const nsString mStreet;
|
||||
const nsString mPremises;
|
||||
const nsString mCity;
|
||||
const nsString mCounty;
|
||||
const nsString mRegion;
|
||||
const nsString mCountry;
|
||||
const nsString mPostalCode;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// nsGeoPositionCoords
|
||||
////////////////////////////////////////////////////
|
||||
@ -122,18 +90,12 @@ public:
|
||||
long long aTimestamp);
|
||||
|
||||
nsGeoPosition(nsIDOMGeoPositionCoords *aCoords,
|
||||
nsIDOMGeoPositionAddress *aAddress,
|
||||
DOMTimeStamp aTimestamp);
|
||||
|
||||
void SetAddress(nsIDOMGeoPositionAddress *address) {
|
||||
mAddress = address;
|
||||
}
|
||||
|
||||
private:
|
||||
~nsGeoPosition();
|
||||
long long mTimestamp;
|
||||
nsRefPtr<nsIDOMGeoPositionCoords> mCoords;
|
||||
nsRefPtr<nsIDOMGeoPositionAddress> mAddress;
|
||||
};
|
||||
|
||||
#endif /* nsGeoPosition_h */
|
||||
|
@ -41,98 +41,11 @@
|
||||
#include "nsGeoPosition.h"
|
||||
#include "nsIDOMGeoPosition.h"
|
||||
|
||||
typedef nsIDOMGeoPositionAddress *GeoPositionAddress;
|
||||
typedef nsGeoPositionCoords *GeoPositionCoords;
|
||||
typedef nsIDOMGeoPosition *GeoPosition;
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<GeoPositionAddress>
|
||||
{
|
||||
typedef GeoPositionAddress paramType;
|
||||
|
||||
// Function to serialize a geo position address
|
||||
static void Write(Message *aMsg, const paramType& aParam)
|
||||
{
|
||||
bool isNull = !aParam;
|
||||
WriteParam(aMsg, isNull);
|
||||
// If it is null, then we are done
|
||||
if (isNull) return;
|
||||
|
||||
nsString addressLine;
|
||||
|
||||
aParam->GetStreetNumber(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetStreet(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetPremises(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetCity(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetCounty(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetRegion(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetCountry(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
|
||||
aParam->GetPostalCode(addressLine);
|
||||
WriteParam(aMsg, addressLine);
|
||||
}
|
||||
|
||||
// Function to de-serialize a geoposition
|
||||
static bool Read(const Message* aMsg, void **aIter, paramType* aResult)
|
||||
{
|
||||
// Check if it is the null pointer we have transfered
|
||||
bool isNull;
|
||||
if (!ReadParam(aMsg, aIter, &isNull)) return false;
|
||||
|
||||
if (isNull) {
|
||||
*aResult = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We need somewhere to store the address before we create the object
|
||||
nsString streetNumber;
|
||||
nsString street;
|
||||
nsString premises;
|
||||
nsString city;
|
||||
nsString county;
|
||||
nsString region;
|
||||
nsString country;
|
||||
nsString postalCode;
|
||||
|
||||
// It's not important to us where it fails, but rather if it fails
|
||||
if (!(ReadParam(aMsg, aIter, &streetNumber) &&
|
||||
ReadParam(aMsg, aIter, &street ) &&
|
||||
ReadParam(aMsg, aIter, &premises ) &&
|
||||
ReadParam(aMsg, aIter, &city ) &&
|
||||
ReadParam(aMsg, aIter, &county ) &&
|
||||
ReadParam(aMsg, aIter, ®ion ) &&
|
||||
ReadParam(aMsg, aIter, &country ) &&
|
||||
ReadParam(aMsg, aIter, &postalCode ))) return false;
|
||||
|
||||
// We now have all the data
|
||||
*aResult = new nsGeoPositionAddress(streetNumber, /* aStreetNumber */
|
||||
street, /* aStreet */
|
||||
premises, /* aPremises */
|
||||
city, /* aCity */
|
||||
county, /* aCounty */
|
||||
region, /* aRegion */
|
||||
country, /* aCountry */
|
||||
postalCode /* aPostalCode */
|
||||
);
|
||||
return true;
|
||||
}
|
||||
} ;
|
||||
|
||||
template <>
|
||||
struct ParamTraits<GeoPositionCoords>
|
||||
{
|
||||
@ -235,11 +148,6 @@ struct ParamTraits<GeoPosition>
|
||||
aParam->GetCoords(getter_AddRefs(coords));
|
||||
GeoPositionCoords simpleCoords = static_cast<GeoPositionCoords>(coords.get());
|
||||
WriteParam(aMsg, simpleCoords);
|
||||
|
||||
nsCOMPtr<nsIDOMGeoPositionAddress> address;
|
||||
aParam->GetAddress(getter_AddRefs(address));
|
||||
GeoPositionAddress simpleAddress = address.get();
|
||||
WriteParam(aMsg, simpleAddress);
|
||||
}
|
||||
|
||||
// Function to de-serialize a geoposition
|
||||
@ -256,20 +164,17 @@ struct ParamTraits<GeoPosition>
|
||||
|
||||
DOMTimeStamp timeStamp;
|
||||
GeoPositionCoords coords = nsnull;
|
||||
GeoPositionAddress address;
|
||||
|
||||
// It's not important to us where it fails, but rather if it fails
|
||||
if (!( ReadParam(aMsg, aIter, &timeStamp)
|
||||
&& ReadParam(aMsg, aIter, &coords )
|
||||
&& ReadParam(aMsg, aIter, &address ))) {
|
||||
&& ReadParam(aMsg, aIter, &coords ))) {
|
||||
// note it is fine to do "delete nsnull" in case coords hasn't
|
||||
// been allocated and we will never have a case where address
|
||||
// gets allocated and we end here
|
||||
// been allocated
|
||||
delete coords;
|
||||
return false;
|
||||
}
|
||||
|
||||
*aResult = new nsGeoPosition(coords, address, timeStamp);
|
||||
*aResult = new nsGeoPosition(coords, timeStamp);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
@ -87,6 +87,9 @@ EXPORTS = \
|
||||
nsDeviceMotion.h \
|
||||
$(NULL)
|
||||
|
||||
# We fire the nsDOMDeviceAcceleration
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
|
@ -59,6 +59,7 @@ CPPSRCS = \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/src/geolocation \
|
||||
-I$(topsrcdir)/content/events/src
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -49,9 +49,13 @@ LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
EXPORT_LIBRARY = 1
|
||||
|
||||
# We fire the nsDOMDeviceAcceleration
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
CMMSRCS = \
|
||||
smslib.mm \
|
||||
nsDeviceMotionSystem.mm \
|
||||
$(NULL)
|
||||
|
||||
|
@ -42,8 +42,9 @@
|
||||
#include <sys/resource.h>
|
||||
#include <sys/vm.h>
|
||||
|
||||
#define MODEL_NAME_LENGTH 64
|
||||
static char gModelName[MODEL_NAME_LENGTH];
|
||||
#import "smslib.h"
|
||||
#define MEAN_GRAVITY 9.80665
|
||||
#define DEFAULT_SENSOR_POLL 100
|
||||
|
||||
nsDeviceMotionSystem::nsDeviceMotionSystem()
|
||||
{
|
||||
@ -53,24 +54,6 @@ nsDeviceMotionSystem::~nsDeviceMotionSystem()
|
||||
{
|
||||
}
|
||||
|
||||
// Data format returned from IOConnectMethodStructureIStructureO.
|
||||
// I am not sure what the other bits in this structure are,
|
||||
// or if there are any, but this has to be 40 bytes long or
|
||||
// the call to read fails.
|
||||
//
|
||||
// Since we make the SmsData struct larger than any members we plan to access we
|
||||
// keep track of the the size of the part of the struct we plan to access for
|
||||
// use in bounds checking.
|
||||
#define SMSDATA_PADDING_SIZE 34
|
||||
typedef struct
|
||||
{
|
||||
PRInt16 x;
|
||||
PRInt16 y;
|
||||
PRInt16 z;
|
||||
PRInt8 unknown[SMSDATA_PADDING_SIZE];
|
||||
} SmsData;
|
||||
#define SMSDATA_USED_SIZE (sizeof(SmsData) - SMSDATA_PADDING_SIZE)
|
||||
|
||||
void
|
||||
nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
@ -79,129 +62,35 @@ nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure)
|
||||
NS_ERROR("no self");
|
||||
return;
|
||||
}
|
||||
sms_acceleration accel;
|
||||
smsGetData(&accel);
|
||||
|
||||
size_t bufferLen = sizeof(SmsData);
|
||||
|
||||
void * input = malloc(bufferLen);
|
||||
void * output = malloc(bufferLen);
|
||||
|
||||
if (!input || !output)
|
||||
return;
|
||||
|
||||
memset(input, 0, bufferLen);
|
||||
memset(output, 0, bufferLen);
|
||||
|
||||
size_t structureOutputSize = bufferLen;
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
|
||||
kern_return_t result = ::IOConnectMethodStructureIStructureO(self->mSmsConnection,
|
||||
5, /* Magic number for SMCMotionSensor */
|
||||
bufferLen,
|
||||
(IOByteCount*)&structureOutputSize,
|
||||
input,
|
||||
output);
|
||||
#else
|
||||
kern_return_t result = ::IOConnectCallStructMethod((mach_port_t)self->mSmsConnection,
|
||||
5, /* Magic number for SMCMotionSensor */
|
||||
input,
|
||||
bufferLen,
|
||||
output,
|
||||
&structureOutputSize);
|
||||
#endif
|
||||
|
||||
if ((result != kIOReturnSuccess) || (structureOutputSize < SMSDATA_USED_SIZE)) {
|
||||
free(input);
|
||||
free(output);
|
||||
return;
|
||||
}
|
||||
|
||||
SmsData *data = (SmsData*) output;
|
||||
|
||||
float xf, yf, zf;
|
||||
|
||||
// we want to normalize the return result from the chip to
|
||||
// something between -1 and 1 where 0 is the balance point.
|
||||
|
||||
const int normalizeFactor = 250.5;
|
||||
|
||||
if (!strcmp(gModelName, "MacBookPro5,1")) {
|
||||
xf = ((float)data->x) / normalizeFactor;
|
||||
yf = (((float)data->y) / normalizeFactor) * -1;
|
||||
zf = ((float)data->z) / normalizeFactor;
|
||||
}
|
||||
else if (!strcmp(gModelName, "MacBookPro5,3")) {
|
||||
xf = ((float)data->y) / normalizeFactor;
|
||||
yf = (((float)data->x) / normalizeFactor) * -1;
|
||||
zf = (((float)data->z) / normalizeFactor) * -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xf = (((float)data->x) / normalizeFactor) * -1;
|
||||
yf = ((float)data->y) / normalizeFactor;
|
||||
zf = ((float)data->z) / normalizeFactor;
|
||||
}
|
||||
|
||||
free(input);
|
||||
free(output);
|
||||
|
||||
self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, xf, yf, zf );
|
||||
self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION,
|
||||
accel.x * MEAN_GRAVITY,
|
||||
accel.y * MEAN_GRAVITY,
|
||||
accel.z * MEAN_GRAVITY);
|
||||
}
|
||||
|
||||
void nsDeviceMotionSystem::Startup()
|
||||
{
|
||||
// we can fail, and that just means the caller will not see any changes.
|
||||
|
||||
mach_port_t port;
|
||||
kern_return_t result = ::IOMasterPort(MACH_PORT_NULL, &port);
|
||||
if (result != kIOReturnSuccess)
|
||||
return;
|
||||
|
||||
CFMutableDictionaryRef dict = ::IOServiceMatching("SMCMotionSensor");
|
||||
if (!dict)
|
||||
return;
|
||||
|
||||
io_iterator_t iter;
|
||||
result = ::IOServiceGetMatchingServices(port, dict, &iter);
|
||||
if (result != kIOReturnSuccess)
|
||||
return;
|
||||
|
||||
io_object_t device = ::IOIteratorNext(iter);
|
||||
|
||||
::IOObjectRelease(iter);
|
||||
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
result = ::IOServiceOpen(device, mach_task_self(), 0, &mSmsConnection);
|
||||
::IOObjectRelease(device);
|
||||
|
||||
if (result != kIOReturnSuccess)
|
||||
return;
|
||||
|
||||
mach_port_deallocate(mach_task_self(), port);
|
||||
|
||||
/* get the version of the hardware we are running on. */
|
||||
int mib[2];
|
||||
size_t len = MODEL_NAME_LENGTH;
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_MODEL;
|
||||
sysctl(mib, 2, gModelName, &len, NULL, 0);
|
||||
smsStartup(nil, nil);
|
||||
smsLoadCalibration();
|
||||
|
||||
mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (mUpdateTimer)
|
||||
mUpdateTimer->InitWithFuncCallback(UpdateHandler,
|
||||
this,
|
||||
mUpdateInterval,
|
||||
DEFAULT_SENSOR_POLL,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
void nsDeviceMotionSystem::Shutdown()
|
||||
{
|
||||
if (mSmsConnection)
|
||||
::IOServiceClose(mSmsConnection);
|
||||
|
||||
if (mUpdateTimer) {
|
||||
mUpdateTimer->Cancel();
|
||||
mUpdateTimer = nsnull;
|
||||
}
|
||||
|
||||
smsShutdown();
|
||||
}
|
||||
|
||||
|
159
dom/system/cocoa/smslib.h
Normal file
159
dom/system/cocoa/smslib.h
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* smslib.h
|
||||
*
|
||||
* SMSLib Sudden Motion Sensor Access Library
|
||||
* Copyright (c) 2010 Suitable Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Daniel Griscom
|
||||
* Suitable Systems
|
||||
* http://www.suitable.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal with the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimers.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimers in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the names of Suitable Systems nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this Software without specific prior written permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
|
||||
*
|
||||
* For more information about SMSLib, see
|
||||
* <http://www.suitable.com/tools/smslib.html>
|
||||
* or contact
|
||||
* Daniel Griscom
|
||||
* Suitable Systems
|
||||
* 1 Centre Street, Suite 204
|
||||
* Wakefield, MA 01880
|
||||
* (781) 665-0053
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define SMSLIB_VERSION "1.8"
|
||||
|
||||
#pragma mark Structure definitions
|
||||
|
||||
// Structure for specifying a 3-axis acceleration. 0.0 means "zero gravities",
|
||||
// 1.0 means "one gravity".
|
||||
typedef struct sms_acceleration {
|
||||
float x; // Right-left acceleration (positive is rightwards)
|
||||
float y; // Front-rear acceleration (positive is rearwards)
|
||||
float z; // Up-down acceleration (positive is upwards)
|
||||
} sms_acceleration;
|
||||
|
||||
// Structure for specifying a calibration.
|
||||
typedef struct sms_calibration {
|
||||
float zeros[3]; // Zero points for three axes (X, Y, Z)
|
||||
float onegs[3]; // One gravity values for three axes
|
||||
} sms_calibration;
|
||||
|
||||
#pragma mark Return value definitions
|
||||
|
||||
// These are the return values for accelStartup(), giving the
|
||||
// various stages where the most successful attempt at accessing
|
||||
// the accelerometer failed. The higher the value, the further along the
|
||||
// software progressed before failing. The options are:
|
||||
// - Didn't match model name
|
||||
#define SMS_FAIL_MODEL (-7)
|
||||
// - Failure getting dictionary matching desired services
|
||||
#define SMS_FAIL_DICTIONARY (-6)
|
||||
// - Failure getting list of services
|
||||
#define SMS_FAIL_LIST_SERVICES (-5)
|
||||
// - Failure if list of services is empty. The process generally fails
|
||||
// here if run on a machine without a Sudden Motion Sensor.
|
||||
#define SMS_FAIL_NO_SERVICES (-4)
|
||||
// - Failure if error opening device.
|
||||
#define SMS_FAIL_OPENING (-3)
|
||||
// - Failure if opened, but didn't get a connection
|
||||
#define SMS_FAIL_CONNECTION (-2)
|
||||
// - Failure if couldn't access connction using given function and size. This
|
||||
// is where the process would probably fail with a change in Apple's API.
|
||||
// Driver problems often also cause failures here.
|
||||
#define SMS_FAIL_ACCESS (-1)
|
||||
// - Success!
|
||||
#define SMS_SUCCESS (0)
|
||||
|
||||
#pragma mark Function declarations
|
||||
|
||||
// This starts up the accelerometer code, trying each possible sensor
|
||||
// specification. Note that for logging purposes it
|
||||
// takes an object and a selector; the object's selector is then invoked
|
||||
// with a single NSString as argument giving progress messages. Example
|
||||
// logging method:
|
||||
// - (void)logMessage: (NSString *)theString
|
||||
// which would be used in accelStartup's invocation thusly:
|
||||
// result = accelStartup(self, @selector(logMessage:));
|
||||
// If the object is nil, then no logging is done. Sets calibation from built-in
|
||||
// value table. Returns ACCEL_SUCCESS for success, and other (negative)
|
||||
// values for various failures (returns value indicating result of
|
||||
// most successful trial).
|
||||
int smsStartup(id logObject, SEL logSelector);
|
||||
|
||||
// This starts up the library in debug mode, ignoring the actual hardware.
|
||||
// Returned data is in the form of 1Hz sine waves, with the X, Y and Z
|
||||
// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5);
|
||||
// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0,
|
||||
// Z axes centered on 1 (calibrated) or 256 (uncalibrated).
|
||||
// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS.
|
||||
int smsDebugStartup(id logObject, SEL logSelector);
|
||||
|
||||
// Returns the current calibration values.
|
||||
void smsGetCalibration(sms_calibration *calibrationRecord);
|
||||
|
||||
// Sets the calibration, but does NOT store it as a preference. If the argument
|
||||
// is nil then the current calibration is set from the built-in value table.
|
||||
void smsSetCalibration(sms_calibration *calibrationRecord);
|
||||
|
||||
// Stores the current calibration values as a stored preference.
|
||||
void smsStoreCalibration(void);
|
||||
|
||||
// Loads the stored preference values into the current calibration.
|
||||
// Returns YES if successful.
|
||||
BOOL smsLoadCalibration(void);
|
||||
|
||||
// Deletes any stored calibration, and then takes the current calibration values
|
||||
// from the built-in value table.
|
||||
void smsDeleteCalibration(void);
|
||||
|
||||
// Fills in the accel record with calibrated acceleration data. Takes
|
||||
// 1-2ms to return a value. Returns 0 if success, error number if failure.
|
||||
int smsGetData(sms_acceleration *accel);
|
||||
|
||||
// Fills in the accel record with uncalibrated acceleration data.
|
||||
// Returns 0 if success, error number if failure.
|
||||
int smsGetUncalibratedData(sms_acceleration *accel);
|
||||
|
||||
// Returns the length of a raw block of data for the current type of sensor.
|
||||
int smsGetBufferLength(void);
|
||||
|
||||
// Takes a pointer to accelGetRawLength() bytes; sets those bytes
|
||||
// to return value from sensor. Make darn sure the buffer length is right!
|
||||
void smsGetBufferData(char *buffer);
|
||||
|
||||
// This returns an NSString describing the current calibration in
|
||||
// human-readable form. Also include a description of the machine.
|
||||
NSString *smsGetCalibrationDescription(void);
|
||||
|
||||
// Shuts down the accelerometer.
|
||||
void smsShutdown(void);
|
||||
|
937
dom/system/cocoa/smslib.mm
Normal file
937
dom/system/cocoa/smslib.mm
Normal file
@ -0,0 +1,937 @@
|
||||
/*
|
||||
* smslib.m
|
||||
*
|
||||
* SMSLib Sudden Motion Sensor Access Library
|
||||
* Copyright (c) 2010 Suitable Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Daniel Griscom
|
||||
* Suitable Systems
|
||||
* http://www.suitable.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal with the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimers.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimers in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the names of Suitable Systems nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this Software without specific prior written permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
|
||||
*
|
||||
* For more information about SMSLib, see
|
||||
* <http://www.suitable.com/tools/smslib.html>
|
||||
* or contact
|
||||
* Daniel Griscom
|
||||
* Suitable Systems
|
||||
* 1 Centre Street, Suite 204
|
||||
* Wakefield, MA 01880
|
||||
* (781) 665-0053
|
||||
*
|
||||
*/
|
||||
|
||||
#import <IOKit/IOKitLib.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <math.h>
|
||||
#import "smslib.h"
|
||||
|
||||
#pragma mark Internal structures
|
||||
|
||||
// Represents a single axis of a type of sensor.
|
||||
typedef struct axisStruct {
|
||||
int enabled; // Non-zero if axis is valid in this sensor
|
||||
int index; // Location in struct of first byte
|
||||
int size; // Number of bytes
|
||||
float zerog; // Value meaning "zero g"
|
||||
float oneg; // Change in value meaning "increase of one g"
|
||||
// (can be negative if axis sensor reversed)
|
||||
} axisStruct;
|
||||
|
||||
// Represents the configuration of a type of sensor.
|
||||
typedef struct sensorSpec {
|
||||
char *model; // Prefix of model to be tested
|
||||
char *name; // Name of device to be read
|
||||
unsigned int function; // Kernel function index
|
||||
int recordSize; // Size of record to be sent/received
|
||||
axisStruct axes[3]; // Description of three axes (X, Y, Z)
|
||||
} sensorSpec;
|
||||
|
||||
// Configuration of all known types of sensors. The configurations are
|
||||
// tried in order until one succeeds in returning data.
|
||||
// All default values are set here, but each axis' zerog and oneg values
|
||||
// may be changed to saved (calibrated) values.
|
||||
//
|
||||
// These values came from SeisMaCalibrate calibration reports. In general I've
|
||||
// found the following:
|
||||
// - All Intel-based SMSs have 250 counts per g, centered on 0, but the signs
|
||||
// are different (and in one case two axes are swapped)
|
||||
// - PowerBooks and iBooks all have sensors centered on 0, and reading
|
||||
// 50-53 steps per gravity (but with differing polarities!)
|
||||
// - PowerBooks and iBooks of the same model all have the same axis polarities
|
||||
// - PowerBook and iBook access methods are model- and OS version-specific
|
||||
//
|
||||
// So, the sequence of tests is:
|
||||
// - Try model-specific access methods. Note that the test is for a match to the
|
||||
// beginning of the model name, e.g. the record with model name "MacBook"
|
||||
// matches computer models "MacBookPro1,2" and "MacBook1,1" (and ""
|
||||
// matches any model).
|
||||
// - If no model-specific record's access fails, then try each model-independent
|
||||
// access method in order, stopping when one works.
|
||||
static const sensorSpec sensors[] = {
|
||||
// ****** Model-dependent methods ******
|
||||
// The PowerBook5,6 is one of the G4 models that seems to lose
|
||||
// SMS access until the next reboot.
|
||||
{"PowerBook5,6", "IOI2CMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, -51.5},
|
||||
{1, 2, 1, 0, -51.5}
|
||||
}
|
||||
},
|
||||
// The PowerBook5,7 is one of the G4 models that seems to lose
|
||||
// SMS access until the next reboot.
|
||||
{"PowerBook5,7", "IOI2CMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, 51.5},
|
||||
{1, 2, 1, 0, 51.5}
|
||||
}
|
||||
},
|
||||
// Access seems to be reliable on the PowerBook5,8
|
||||
{"PowerBook5,8", "PMUMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, -51.5},
|
||||
{1, 1, 1, 0, 51.5},
|
||||
{1, 2, 1, 0, -51.5}
|
||||
}
|
||||
},
|
||||
// Access seems to be reliable on the PowerBook5,9
|
||||
{"PowerBook5,9", "PMUMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, -51.5},
|
||||
{1, 2, 1, 0, -51.5}
|
||||
}
|
||||
},
|
||||
// The PowerBook6,7 is one of the G4 models that seems to lose
|
||||
// SMS access until the next reboot.
|
||||
{"PowerBook6,7", "IOI2CMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, 51.5},
|
||||
{1, 2, 1, 0, 51.5}
|
||||
}
|
||||
},
|
||||
// The PowerBook6,8 is one of the G4 models that seems to lose
|
||||
// SMS access until the next reboot.
|
||||
{"PowerBook6,8", "IOI2CMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, 51.5},
|
||||
{1, 2, 1, 0, 51.5}
|
||||
}
|
||||
},
|
||||
// MacBook Pro Core 2 Duo 17". Note the reversed Y and Z axes.
|
||||
{"MacBookPro2,1", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, 251},
|
||||
{1, 2, 2, 0, -251},
|
||||
{1, 4, 2, 0, -251}
|
||||
}
|
||||
},
|
||||
// MacBook Pro Core 2 Duo 15" AND 17" with LED backlight, introduced June '07.
|
||||
// NOTE! The 17" machines have the signs of their X and Y axes reversed
|
||||
// from this calibration, but there's no clear way to discriminate between
|
||||
// the two machines.
|
||||
{"MacBookPro3,1", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, -251},
|
||||
{1, 2, 2, 0, 251},
|
||||
{1, 4, 2, 0, -251}
|
||||
}
|
||||
},
|
||||
// ... specs?
|
||||
{"MacBook5,2", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, -251},
|
||||
{1, 2, 2, 0, 251},
|
||||
{1, 4, 2, 0, -251}
|
||||
}
|
||||
},
|
||||
// ... specs?
|
||||
{"MacBookPro5,1", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, -251},
|
||||
{1, 2, 2, 0, -251},
|
||||
{1, 4, 2, 0, 251}
|
||||
}
|
||||
},
|
||||
// ... specs?
|
||||
{"MacBookPro5,2", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, -251},
|
||||
{1, 2, 2, 0, -251},
|
||||
{1, 4, 2, 0, 251}
|
||||
}
|
||||
},
|
||||
// This is speculative, based on a single user's report. Looks like the X and Y axes
|
||||
// are swapped. This is true for no other known Appple laptop.
|
||||
{"MacBookPro5,3", "SMCMotionSensor", 5, 40, {
|
||||
{1, 2, 2, 0, -251},
|
||||
{1, 0, 2, 0, -251},
|
||||
{1, 4, 2, 0, -251}
|
||||
}
|
||||
},
|
||||
// ... specs?
|
||||
{"MacBookPro5,4", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, -251},
|
||||
{1, 2, 2, 0, -251},
|
||||
{1, 4, 2, 0, 251}
|
||||
}
|
||||
},
|
||||
// ****** Model-independent methods ******
|
||||
// Seen once with PowerBook6,8 under system 10.3.9; I suspect
|
||||
// other G4-based 10.3.* systems might use this
|
||||
{"", "IOI2CMotionSensor", 24, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, 51.5},
|
||||
{1, 2, 1, 0, 51.5}
|
||||
}
|
||||
},
|
||||
// PowerBook5,6 , PowerBook5,7 , PowerBook6,7 , PowerBook6,8
|
||||
// under OS X 10.4.*
|
||||
{"", "IOI2CMotionSensor", 21, 60, {
|
||||
{1, 0, 1, 0, 51.5},
|
||||
{1, 1, 1, 0, 51.5},
|
||||
{1, 2, 1, 0, 51.5}
|
||||
}
|
||||
},
|
||||
// PowerBook5,8 , PowerBook5,9 under OS X 10.4.*
|
||||
{"", "PMUMotionSensor", 21, 60, {
|
||||
// Each has two out of three gains negative, but it's different
|
||||
// for the different models. So, this will be right in two out
|
||||
// of three axis for either model.
|
||||
{1, 0, 1, 0, -51.5},
|
||||
{1, 1, 1, -6, -51.5},
|
||||
{1, 2, 1, 0, -51.5}
|
||||
}
|
||||
},
|
||||
// All MacBook, MacBookPro models. Hardware (at least on early MacBookPro 15")
|
||||
// is Kionix KXM52-1050 three-axis accelerometer chip. Data is at
|
||||
// http://kionix.com/Product-Index/product-index.htm. Specific MB and MBP models
|
||||
// that use this are:
|
||||
// MacBook1,1
|
||||
// MacBook2,1
|
||||
// MacBook3,1
|
||||
// MacBook4,1
|
||||
// MacBook5,1
|
||||
// MacBook6,1
|
||||
// MacBookAir1,1
|
||||
// MacBookPro1,1
|
||||
// MacBookPro1,2
|
||||
// MacBookPro4,1
|
||||
// MacBookPro5,5
|
||||
{"", "SMCMotionSensor", 5, 40, {
|
||||
{1, 0, 2, 0, 251},
|
||||
{1, 2, 2, 0, 251},
|
||||
{1, 4, 2, 0, 251}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define SENSOR_COUNT (sizeof(sensors)/sizeof(sensorSpec))
|
||||
|
||||
#pragma mark Internal prototypes
|
||||
|
||||
static int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector);
|
||||
static float getAxis(int which, int calibrated);
|
||||
static int signExtend(int value, int size);
|
||||
static NSString *getModelName(void);
|
||||
static NSString *getOSVersion(void);
|
||||
static BOOL loadCalibration(void);
|
||||
static void storeCalibration(void);
|
||||
static void defaultCalibration(void);
|
||||
static void deleteCalibration(void);
|
||||
static int prefIntRead(NSString *prefName, BOOL *success);
|
||||
static void prefIntWrite(NSString *prefName, int prefValue);
|
||||
static float prefFloatRead(NSString *prefName, BOOL *success);
|
||||
static void prefFloatWrite(NSString *prefName, float prefValue);
|
||||
static void prefDelete(NSString *prefName);
|
||||
static void prefSynchronize(void);
|
||||
// static long getMicroseconds(void);
|
||||
float fakeData(NSTimeInterval time);
|
||||
|
||||
#pragma mark Static variables
|
||||
|
||||
static int debugging = NO; // True if debugging (synthetic data)
|
||||
static io_connect_t connection; // Connection for reading accel values
|
||||
static int running = NO; // True if we successfully started
|
||||
static int sensorNum = 0; // The current index into sensors[]
|
||||
static char *serviceName; // The name of the current service
|
||||
static char *iRecord, *oRecord; // Pointers to read/write records for sensor
|
||||
static int recordSize; // Size of read/write records
|
||||
static unsigned int function; // Which kernel function should be used
|
||||
static float zeros[3]; // X, Y and Z zero calibration values
|
||||
static float onegs[3]; // X, Y and Z one-g calibration values
|
||||
|
||||
#pragma mark Defines
|
||||
|
||||
// Pattern for building axis letter from axis number
|
||||
#define INT_TO_AXIS(a) (a == 0 ? @"X" : a == 1 ? @"Y" : @"Z")
|
||||
// Name of configuration for given axis' zero (axis specified by integer)
|
||||
#define ZERO_NAME(a) [NSString stringWithFormat:@"%@-Axis-Zero", INT_TO_AXIS(a)]
|
||||
// Name of configuration for given axis' oneg (axis specified by integer)
|
||||
#define ONEG_NAME(a) [NSString stringWithFormat:@"%@-Axis-One-g", INT_TO_AXIS(a)]
|
||||
// Name of "Is calibrated" preference
|
||||
#define CALIBRATED_NAME (@"Calibrated")
|
||||
// Application domain for SeisMac library
|
||||
#define APP_ID ((CFStringRef)@"com.suitable.SeisMacLib")
|
||||
|
||||
// These #defines make the accelStartup code a LOT easier to read.
|
||||
#define LOG(message) \
|
||||
if (logObject) { \
|
||||
[logObject performSelector:logSelector withObject:message]; \
|
||||
}
|
||||
#define LOG_ARG(format, var1) \
|
||||
if (logObject) { \
|
||||
[logObject performSelector:logSelector \
|
||||
withObject:[NSString stringWithFormat:format, var1]]; \
|
||||
}
|
||||
#define LOG_2ARG(format, var1, var2) \
|
||||
if (logObject) { \
|
||||
[logObject performSelector:logSelector \
|
||||
withObject:[NSString stringWithFormat:format, var1, var2]]; \
|
||||
}
|
||||
#define LOG_3ARG(format, var1, var2, var3) \
|
||||
if (logObject) { \
|
||||
[logObject performSelector:logSelector \
|
||||
withObject:[NSString stringWithFormat:format, var1, var2, var3]]; \
|
||||
}
|
||||
|
||||
#pragma mark Function definitions
|
||||
|
||||
// This starts up the accelerometer code, trying each possible sensor
|
||||
// specification. Note that for logging purposes it
|
||||
// takes an object and a selector; the object's selector is then invoked
|
||||
// with a single NSString as argument giving progress messages. Example
|
||||
// logging method:
|
||||
// - (void)logMessage: (NSString *)theString
|
||||
// which would be used in accelStartup's invocation thusly:
|
||||
// result = accelStartup(self, @selector(logMessage:));
|
||||
// If the object is nil, then no logging is done. Sets calibation from built-in
|
||||
// value table. Returns ACCEL_SUCCESS for success, and other (negative)
|
||||
// values for various failures (returns value indicating result of
|
||||
// most successful trial).
|
||||
int smsStartup(id logObject, SEL logSelector) {
|
||||
io_iterator_t iterator;
|
||||
io_object_t device;
|
||||
kern_return_t result;
|
||||
sms_acceleration accel;
|
||||
int failure_result = SMS_FAIL_MODEL;
|
||||
|
||||
running = NO;
|
||||
debugging = NO;
|
||||
|
||||
NSString *modelName = getModelName();
|
||||
|
||||
LOG_ARG(@"Machine model: %@\n", modelName);
|
||||
LOG_ARG(@"OS X version: %@\n", getOSVersion());
|
||||
LOG_ARG(@"Accelerometer library version: %s\n", SMSLIB_VERSION);
|
||||
|
||||
for (sensorNum = 0; sensorNum < SENSOR_COUNT; sensorNum++) {
|
||||
|
||||
// Set up all specs for this type of sensor
|
||||
serviceName = sensors[sensorNum].name;
|
||||
recordSize = sensors[sensorNum].recordSize;
|
||||
function = sensors[sensorNum].function;
|
||||
|
||||
LOG_3ARG(@"Trying service \"%s\" with selector %d and %d byte record:\n",
|
||||
serviceName, function, recordSize);
|
||||
|
||||
NSString *targetName = [NSString stringWithCString:sensors[sensorNum].model
|
||||
encoding:NSMacOSRomanStringEncoding];
|
||||
LOG_ARG(@" Comparing model name to target \"%@\": ", targetName);
|
||||
if ([targetName length] == 0 || [modelName hasPrefix:targetName]) {
|
||||
LOG(@"success.\n");
|
||||
} else {
|
||||
LOG(@"failure.\n");
|
||||
// Don't need to increment failure_result.
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(@" Fetching dictionary for service: ");
|
||||
CFMutableDictionaryRef dict = IOServiceMatching(serviceName);
|
||||
|
||||
if (dict) {
|
||||
LOG(@"success.\n");
|
||||
} else {
|
||||
LOG(@"failure.\n");
|
||||
if (failure_result < SMS_FAIL_DICTIONARY) {
|
||||
failure_result = SMS_FAIL_DICTIONARY;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(@" Getting list of matching services: ");
|
||||
result = IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||
dict,
|
||||
&iterator);
|
||||
|
||||
if (result == KERN_SUCCESS) {
|
||||
LOG(@"success.\n");
|
||||
} else {
|
||||
LOG_ARG(@"failure, with return value 0x%x.\n", result);
|
||||
if (failure_result < SMS_FAIL_LIST_SERVICES) {
|
||||
failure_result = SMS_FAIL_LIST_SERVICES;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(@" Getting first device in list: ");
|
||||
device = IOIteratorNext(iterator);
|
||||
|
||||
if (device == 0) {
|
||||
LOG(@"failure.\n");
|
||||
if (failure_result < SMS_FAIL_NO_SERVICES) {
|
||||
failure_result = SMS_FAIL_NO_SERVICES;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
LOG(@"success.\n");
|
||||
LOG(@" Opening device: ");
|
||||
}
|
||||
|
||||
result = IOServiceOpen(device, mach_task_self(), 0, &connection);
|
||||
|
||||
if (result != KERN_SUCCESS) {
|
||||
LOG_ARG(@"failure, with return value 0x%x.\n", result);
|
||||
IOObjectRelease(device);
|
||||
if (failure_result < SMS_FAIL_OPENING) {
|
||||
failure_result = SMS_FAIL_OPENING;
|
||||
}
|
||||
continue;
|
||||
} else if (connection == 0) {
|
||||
LOG_ARG(@"'success', but didn't get a connection.\n", result);
|
||||
IOObjectRelease(device);
|
||||
if (failure_result < SMS_FAIL_CONNECTION) {
|
||||
failure_result = SMS_FAIL_CONNECTION;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
IOObjectRelease(device);
|
||||
LOG(@"success.\n");
|
||||
}
|
||||
LOG(@" Testing device.\n");
|
||||
|
||||
defaultCalibration();
|
||||
|
||||
iRecord = (char*) malloc(recordSize);
|
||||
oRecord = (char*) malloc(recordSize);
|
||||
|
||||
running = YES;
|
||||
result = getData(&accel, true, logObject, logSelector);
|
||||
running = NO;
|
||||
|
||||
if (result) {
|
||||
LOG_ARG(@" Failure testing device, with result 0x%x.\n", result);
|
||||
free(iRecord);
|
||||
iRecord = 0;
|
||||
free(oRecord);
|
||||
oRecord = 0;
|
||||
if (failure_result < SMS_FAIL_ACCESS) {
|
||||
failure_result = SMS_FAIL_ACCESS;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
LOG(@" Success testing device!\n");
|
||||
running = YES;
|
||||
return SMS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return failure_result;
|
||||
}
|
||||
|
||||
// This starts up the library in debug mode, ignoring the actual hardware.
|
||||
// Returned data is in the form of 1Hz sine waves, with the X, Y and Z
|
||||
// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5);
|
||||
// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0,
|
||||
// Z axes centered on 1 (calibrated) or 256 (uncalibrated).
|
||||
// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS.
|
||||
int smsDebugStartup(id logObject, SEL logSelector) {
|
||||
LOG(@"Starting up in debug mode\n");
|
||||
debugging = YES;
|
||||
return SMS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the current calibration values.
|
||||
void smsGetCalibration(sms_calibration *calibrationRecord) {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 3; x++) {
|
||||
calibrationRecord->zeros[x] = (debugging ? 0 : zeros[x]);
|
||||
calibrationRecord->onegs[x] = (debugging ? 256 : onegs[x]);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the calibration, but does NOT store it as a preference. If the argument
|
||||
// is nil then the current calibration is set from the built-in value table.
|
||||
void smsSetCalibration(sms_calibration *calibrationRecord) {
|
||||
int x;
|
||||
|
||||
if (!debugging) {
|
||||
if (calibrationRecord) {
|
||||
for (x = 0; x < 3; x++) {
|
||||
zeros[x] = calibrationRecord->zeros[x];
|
||||
onegs[x] = calibrationRecord->onegs[x];
|
||||
}
|
||||
} else {
|
||||
defaultCalibration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stores the current calibration values as a stored preference.
|
||||
void smsStoreCalibration(void) {
|
||||
if (!debugging)
|
||||
storeCalibration();
|
||||
}
|
||||
|
||||
// Loads the stored preference values into the current calibration.
|
||||
// Returns YES if successful.
|
||||
BOOL smsLoadCalibration(void) {
|
||||
if (debugging) {
|
||||
return YES;
|
||||
} else if (loadCalibration()) {
|
||||
return YES;
|
||||
} else {
|
||||
defaultCalibration();
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes any stored calibration, and then takes the current calibration values
|
||||
// from the built-in value table.
|
||||
void smsDeleteCalibration(void) {
|
||||
if (!debugging) {
|
||||
deleteCalibration();
|
||||
defaultCalibration();
|
||||
}
|
||||
}
|
||||
|
||||
// Fills in the accel record with calibrated acceleration data. Takes
|
||||
// 1-2ms to return a value. Returns 0 if success, error number if failure.
|
||||
int smsGetData(sms_acceleration *accel) {
|
||||
NSTimeInterval time;
|
||||
if (debugging) {
|
||||
usleep(1500); // Usually takes 1-2 milliseconds
|
||||
time = [NSDate timeIntervalSinceReferenceDate];
|
||||
accel->x = fakeData(time)/5;
|
||||
accel->y = fakeData(time - 1)/5;
|
||||
accel->z = fakeData(time - 2)/5 + 1.0;
|
||||
return true;
|
||||
} else {
|
||||
return getData(accel, true, nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
// Fills in the accel record with uncalibrated acceleration data.
|
||||
// Returns 0 if success, error number if failure.
|
||||
int smsGetUncalibratedData(sms_acceleration *accel) {
|
||||
NSTimeInterval time;
|
||||
if (debugging) {
|
||||
usleep(1500); // Usually takes 1-2 milliseconds
|
||||
time = [NSDate timeIntervalSinceReferenceDate];
|
||||
accel->x = fakeData(time) * 256 / 5;
|
||||
accel->y = fakeData(time - 1) * 256 / 5;
|
||||
accel->z = fakeData(time - 2) * 256 / 5 + 256;
|
||||
return true;
|
||||
} else {
|
||||
return getData(accel, false, nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the length of a raw block of data for the current type of sensor.
|
||||
int smsGetBufferLength(void) {
|
||||
if (debugging) {
|
||||
return 0;
|
||||
} else if (running) {
|
||||
return sensors[sensorNum].recordSize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a pointer to accelGetRawLength() bytes; sets those bytes
|
||||
// to return value from sensor. Make darn sure the buffer length is right!
|
||||
void smsGetBufferData(char *buffer) {
|
||||
IOItemCount iSize = recordSize;
|
||||
IOByteCount oSize = recordSize;
|
||||
kern_return_t result;
|
||||
|
||||
if (debugging || running == NO) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(iRecord, 1, iSize);
|
||||
memset(buffer, 0, oSize);
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
|
||||
const size_t InStructSize = recordSize;
|
||||
size_t OutStructSize = recordSize;
|
||||
result = IOConnectCallStructMethod(connection,
|
||||
function, // magic kernel function number
|
||||
(const void *)iRecord,
|
||||
InStructSize,
|
||||
(void *)buffer,
|
||||
&OutStructSize
|
||||
);
|
||||
#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
|
||||
result = IOConnectMethodStructureIStructureO(connection,
|
||||
function, // magic kernel function number
|
||||
iSize,
|
||||
&oSize,
|
||||
iRecord,
|
||||
buffer
|
||||
);
|
||||
#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
|
||||
|
||||
if (result != KERN_SUCCESS) {
|
||||
running = NO;
|
||||
}
|
||||
}
|
||||
|
||||
// This returns an NSString describing the current calibration in
|
||||
// human-readable form. Also include a description of the machine.
|
||||
NSString *smsGetCalibrationDescription(void) {
|
||||
BOOL success;
|
||||
NSMutableString *s = [[NSMutableString alloc] init];
|
||||
|
||||
if (debugging) {
|
||||
[s release];
|
||||
return @"Debugging!";
|
||||
}
|
||||
|
||||
[s appendString:@"---- SeisMac Calibration Record ----\n \n"];
|
||||
[s appendFormat:@"Machine model: %@\n",
|
||||
getModelName()];
|
||||
[s appendFormat:@"OS X build: %@\n",
|
||||
getOSVersion()];
|
||||
[s appendFormat:@"SeisMacLib version %s, record %d\n \n",
|
||||
SMSLIB_VERSION, sensorNum];
|
||||
[s appendFormat:@"Using service \"%s\", function index %d, size %d\n \n",
|
||||
serviceName, function, recordSize];
|
||||
if (prefIntRead(CALIBRATED_NAME, &success) && success) {
|
||||
[s appendString:@"Calibration values (from calibration):\n"];
|
||||
} else {
|
||||
[s appendString:@"Calibration values (from defaults):\n"];
|
||||
}
|
||||
[s appendFormat:@" X-Axis-Zero = %.2f\n", zeros[0]];
|
||||
[s appendFormat:@" X-Axis-One-g = %.2f\n", onegs[0]];
|
||||
[s appendFormat:@" Y-Axis-Zero = %.2f\n", zeros[1]];
|
||||
[s appendFormat:@" Y-Axis-One-g = %.2f\n", onegs[1]];
|
||||
[s appendFormat:@" Z-Axis-Zero = %.2f\n", zeros[2]];
|
||||
[s appendFormat:@" Z-Axis-One-g = %.2f\n \n", onegs[2]];
|
||||
[s appendString:@"---- End Record ----\n"];
|
||||
return s;
|
||||
}
|
||||
|
||||
// Shuts down the accelerometer.
|
||||
void smsShutdown(void) {
|
||||
if (!debugging) {
|
||||
running = NO;
|
||||
if (iRecord) free(iRecord);
|
||||
if (oRecord) free(oRecord);
|
||||
IOServiceClose(connection);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Internal functions
|
||||
|
||||
// Loads the current calibration from the stored preferences.
|
||||
// Returns true iff successful.
|
||||
BOOL loadCalibration(void) {
|
||||
BOOL thisSuccess, allSuccess;
|
||||
int x;
|
||||
|
||||
prefSynchronize();
|
||||
|
||||
if (prefIntRead(CALIBRATED_NAME, &thisSuccess) && thisSuccess) {
|
||||
// Calibrated. Set all values from saved values.
|
||||
allSuccess = YES;
|
||||
for (x = 0; x < 3; x++) {
|
||||
zeros[x] = prefFloatRead(ZERO_NAME(x), &thisSuccess);
|
||||
allSuccess &= thisSuccess;
|
||||
onegs[x] = prefFloatRead(ONEG_NAME(x), &thisSuccess);
|
||||
allSuccess &= thisSuccess;
|
||||
}
|
||||
return allSuccess;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Stores the current calibration into the stored preferences.
|
||||
static void storeCalibration(void) {
|
||||
int x;
|
||||
prefIntWrite(CALIBRATED_NAME, 1);
|
||||
for (x = 0; x < 3; x++) {
|
||||
prefFloatWrite(ZERO_NAME(x), zeros[x]);
|
||||
prefFloatWrite(ONEG_NAME(x), onegs[x]);
|
||||
}
|
||||
prefSynchronize();
|
||||
}
|
||||
|
||||
|
||||
// Sets the calibration to its default values.
|
||||
void defaultCalibration(void) {
|
||||
int x;
|
||||
for (x = 0; x < 3; x++) {
|
||||
zeros[x] = sensors[sensorNum].axes[x].zerog;
|
||||
onegs[x] = sensors[sensorNum].axes[x].oneg;
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes the stored preferences.
|
||||
static void deleteCalibration(void) {
|
||||
int x;
|
||||
|
||||
prefDelete(CALIBRATED_NAME);
|
||||
for (x = 0; x < 3; x++) {
|
||||
prefDelete(ZERO_NAME(x));
|
||||
prefDelete(ONEG_NAME(x));
|
||||
}
|
||||
prefSynchronize();
|
||||
}
|
||||
|
||||
// Read a named floating point value from the stored preferences. Sets
|
||||
// the success boolean based on, you guessed it, whether it succeeds.
|
||||
static float prefFloatRead(NSString *prefName, BOOL *success) {
|
||||
float result = 0.0f;
|
||||
|
||||
CFPropertyListRef ref = CFPreferencesCopyAppValue((CFStringRef)prefName,
|
||||
APP_ID);
|
||||
// If there isn't such a preference, fail
|
||||
if (ref == NULL) {
|
||||
*success = NO;
|
||||
return result;
|
||||
}
|
||||
CFTypeID typeID = CFGetTypeID(ref);
|
||||
// Is it a number?
|
||||
if (typeID == CFNumberGetTypeID()) {
|
||||
// Is it a floating point number?
|
||||
if (CFNumberIsFloatType((CFNumberRef)ref)) {
|
||||
// Yup: grab it.
|
||||
*success = CFNumberGetValue((__CFNumber*)ref, kCFNumberFloat32Type, &result);
|
||||
} else {
|
||||
// Nope: grab as an integer, and convert to a float.
|
||||
long num;
|
||||
if (CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &num)) {
|
||||
result = num;
|
||||
*success = YES;
|
||||
} else {
|
||||
*success = NO;
|
||||
}
|
||||
}
|
||||
// Or is it a string (e.g. set by the command line "defaults" command)?
|
||||
} else if (typeID == CFStringGetTypeID()) {
|
||||
result = (float)CFStringGetDoubleValue((CFStringRef)ref);
|
||||
*success = YES;
|
||||
} else {
|
||||
// Can't convert to a number: fail.
|
||||
*success = NO;
|
||||
}
|
||||
CFRelease(ref);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Writes a named floating point value to the stored preferences.
|
||||
static void prefFloatWrite(NSString *prefName, float prefValue) {
|
||||
CFNumberRef cfFloat = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberFloatType,
|
||||
&prefValue);
|
||||
CFPreferencesSetAppValue((CFStringRef)prefName,
|
||||
cfFloat,
|
||||
APP_ID);
|
||||
CFRelease(cfFloat);
|
||||
}
|
||||
|
||||
// Reads a named integer value from the stored preferences.
|
||||
static int prefIntRead(NSString *prefName, BOOL *success) {
|
||||
Boolean internalSuccess;
|
||||
CFIndex result = CFPreferencesGetAppIntegerValue((CFStringRef)prefName,
|
||||
APP_ID,
|
||||
&internalSuccess);
|
||||
*success = internalSuccess;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Writes a named integer value to the stored preferences.
|
||||
static void prefIntWrite(NSString *prefName, int prefValue) {
|
||||
CFPreferencesSetAppValue((CFStringRef)prefName,
|
||||
(CFNumberRef)[NSNumber numberWithInt:prefValue],
|
||||
APP_ID);
|
||||
}
|
||||
|
||||
// Deletes the named preference values.
|
||||
static void prefDelete(NSString *prefName) {
|
||||
CFPreferencesSetAppValue((CFStringRef)prefName,
|
||||
NULL,
|
||||
APP_ID);
|
||||
}
|
||||
|
||||
// Synchronizes the local preferences with the stored preferences.
|
||||
static void prefSynchronize(void) {
|
||||
CFPreferencesAppSynchronize(APP_ID);
|
||||
}
|
||||
|
||||
// Internal version of accelGetData, with logging
|
||||
int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector) {
|
||||
IOItemCount iSize = recordSize;
|
||||
IOByteCount oSize = recordSize;
|
||||
kern_return_t result;
|
||||
|
||||
if (running == NO) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(iRecord, 1, iSize);
|
||||
memset(oRecord, 0, oSize);
|
||||
|
||||
LOG_2ARG(@" Querying device: ",
|
||||
sensors[sensorNum].function, sensors[sensorNum].recordSize);
|
||||
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
|
||||
const size_t InStructSize = recordSize;
|
||||
size_t OutStructSize = recordSize;
|
||||
result = IOConnectCallStructMethod(connection,
|
||||
function, // magic kernel function number
|
||||
(const void *)iRecord,
|
||||
InStructSize,
|
||||
(void *)oRecord,
|
||||
&OutStructSize
|
||||
);
|
||||
#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
|
||||
result = IOConnectMethodStructureIStructureO(connection,
|
||||
function, // magic kernel function number
|
||||
iSize,
|
||||
&oSize,
|
||||
iRecord,
|
||||
oRecord
|
||||
);
|
||||
#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050
|
||||
|
||||
if (result != KERN_SUCCESS) {
|
||||
LOG(@"failed.\n");
|
||||
running = NO;
|
||||
return result;
|
||||
} else {
|
||||
LOG(@"succeeded.\n");
|
||||
|
||||
accel->x = getAxis(0, calibrated);
|
||||
accel->y = getAxis(1, calibrated);
|
||||
accel->z = getAxis(2, calibrated);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Given the returned record, extracts the value of the given axis. If
|
||||
// calibrated, then zero G is 0.0, and one G is 1.0.
|
||||
float getAxis(int which, int calibrated) {
|
||||
// Get various values (to make code cleaner)
|
||||
int indx = sensors[sensorNum].axes[which].index;
|
||||
int size = sensors[sensorNum].axes[which].size;
|
||||
float zerog = zeros[which];
|
||||
float oneg = onegs[which];
|
||||
// Storage for value to be returned
|
||||
int value = 0;
|
||||
|
||||
// Although the values in the returned record should have the proper
|
||||
// endianness, we still have to get it into the proper end of value.
|
||||
#if (BYTE_ORDER == BIG_ENDIAN)
|
||||
// On PowerPC processors
|
||||
memcpy(((char *)&value) + (sizeof(int) - size), &oRecord[indx], size);
|
||||
#endif
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
// On Intel processors
|
||||
memcpy(&value, &oRecord[indx], size);
|
||||
#endif
|
||||
|
||||
value = signExtend(value, size);
|
||||
|
||||
if (calibrated) {
|
||||
// Scale and shift for zero.
|
||||
return ((float)(value - zerog)) / oneg;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// Extends the sign, given the length of the value.
|
||||
int signExtend(int value, int size) {
|
||||
// Extend sign
|
||||
switch (size) {
|
||||
case 1:
|
||||
if (value & 0x00000080)
|
||||
value |= 0xffffff00;
|
||||
break;
|
||||
case 2:
|
||||
if (value & 0x00008000)
|
||||
value |= 0xffff0000;
|
||||
break;
|
||||
case 3:
|
||||
if (value & 0x00800000)
|
||||
value |= 0xff000000;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Returns the model name of the computer (e.g. "MacBookPro1,1")
|
||||
NSString *getModelName(void) {
|
||||
char model[32];
|
||||
size_t len = sizeof(model);
|
||||
int name[2] = {CTL_HW, HW_MODEL};
|
||||
NSString *result;
|
||||
|
||||
if (sysctl(name, 2, &model, &len, NULL, 0) == 0) {
|
||||
result = [NSString stringWithFormat:@"%s", model];
|
||||
} else {
|
||||
result = @"";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the current OS X version and build (e.g. "10.4.7 (build 8J2135a)")
|
||||
NSString *getOSVersion(void) {
|
||||
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:
|
||||
@"/System/Library/CoreServices/SystemVersion.plist"];
|
||||
NSString *versionString = [dict objectForKey:@"ProductVersion"];
|
||||
NSString *buildString = [dict objectForKey:@"ProductBuildVersion"];
|
||||
NSString *wholeString = [NSString stringWithFormat:@"%@ (build %@)",
|
||||
versionString, buildString];
|
||||
return wholeString;
|
||||
}
|
||||
|
||||
// Returns time within the current second in microseconds.
|
||||
// long getMicroseconds() {
|
||||
// struct timeval t;
|
||||
// gettimeofday(&t, 0);
|
||||
// return t.tv_usec;
|
||||
//}
|
||||
|
||||
// Returns fake data given the time. Range is +/-1.
|
||||
float fakeData(NSTimeInterval time) {
|
||||
long secs = lround(floor(time));
|
||||
int secsMod3 = secs % 3;
|
||||
double angle = time * 10 * M_PI * 2;
|
||||
double mag = exp(-(time - (secs - secsMod3)) * 2);
|
||||
return sin(angle) * mag;
|
||||
}
|
||||
|
@ -44,11 +44,14 @@
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIDOMDeviceOrientationEvent.h"
|
||||
#include "nsIDOMDeviceMotionEvent.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsDOMDeviceMotionEvent.h"
|
||||
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::TimeDuration;
|
||||
|
||||
// also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java
|
||||
#define DEFAULT_SENSOR_POLL 100
|
||||
|
||||
static const nsTArray<nsIDOMWindow*>::index_type NoIndex =
|
||||
nsTArray<nsIDOMWindow*>::NoIndex;
|
||||
@ -117,21 +120,16 @@ NS_IMPL_ISUPPORTS2(nsDeviceMotion, nsIDeviceMotion, nsIDeviceMotionUpdate)
|
||||
|
||||
nsDeviceMotion::nsDeviceMotion()
|
||||
: mStarted(false),
|
||||
mUpdateInterval(50), /* default to 50 ms */
|
||||
mEnabled(true)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefSrv) {
|
||||
PRInt32 value;
|
||||
nsresult rv = prefSrv->GetIntPref("device.motion.update.interval", &value);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mUpdateInterval = value;
|
||||
|
||||
bool bvalue;
|
||||
rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue);
|
||||
nsresult rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue);
|
||||
if (NS_SUCCEEDED(rv) && bvalue == false)
|
||||
mEnabled = false;
|
||||
}
|
||||
mLastDOMMotionEventTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
nsDeviceMotion::~nsDeviceMotion()
|
||||
@ -255,8 +253,10 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z)
|
||||
|
||||
if (domdoc) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
|
||||
if (type == nsIDeviceMotionData::TYPE_ACCELERATION)
|
||||
FireDOMMotionEvent(domdoc, target, x, y, z);
|
||||
if (type == nsIDeviceMotionData::TYPE_ACCELERATION ||
|
||||
type == nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION ||
|
||||
type == nsIDeviceMotionData::TYPE_GYROSCOPE )
|
||||
FireDOMMotionEvent(domdoc, target, type, x, y, z);
|
||||
else if (type == nsIDeviceMotionData::TYPE_ORIENTATION)
|
||||
FireDOMOrientationEvent(domdoc, target, x, y, z);
|
||||
}
|
||||
@ -264,6 +264,64 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeviceMotion::NeedsCalibration()
|
||||
{
|
||||
if (!mEnabled)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMArray<nsIDeviceMotionListener> listeners = mListeners;
|
||||
for (PRUint32 i = listeners.Count(); i > 0 ; ) {
|
||||
--i;
|
||||
listeners[i]->NeedsCalibration();
|
||||
}
|
||||
|
||||
nsCOMArray<nsIDOMWindow> windowListeners;
|
||||
for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) {
|
||||
windowListeners.AppendObject(mWindowListeners[i]);
|
||||
}
|
||||
|
||||
for (PRUint32 i = windowListeners.Count(); i > 0 ; ) {
|
||||
--i;
|
||||
|
||||
// check to see if this window is in the background. if
|
||||
// it is, don't send any device motion to it.
|
||||
nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(windowListeners[i]);
|
||||
if (!pwindow ||
|
||||
!pwindow->GetOuterWindow() ||
|
||||
pwindow->GetOuterWindow()->IsBackground())
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
windowListeners[i]->GetDocument(getter_AddRefs(domdoc));
|
||||
|
||||
if (domdoc) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
|
||||
FireNeedsCalibration(domdoc, target);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDeviceMotion::FireNeedsCalibration(nsIDOMDocument *domdoc,
|
||||
nsIDOMEventTarget *target)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
domdoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->InitEvent(NS_LITERAL_STRING("compassneedscalibration"), true, false);
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
|
||||
if (privateEvent)
|
||||
privateEvent->SetTrusted(true);
|
||||
|
||||
bool defaultActionEnabled = true;
|
||||
target->DispatchEvent(event, &defaultActionEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc,
|
||||
nsIDOMEventTarget *target,
|
||||
@ -300,34 +358,57 @@ nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc,
|
||||
void
|
||||
nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc,
|
||||
nsIDOMEventTarget *target,
|
||||
PRUint32 type,
|
||||
double x,
|
||||
double y,
|
||||
double z) {
|
||||
// Attempt to coalesce events
|
||||
bool fireEvent = TimeStamp::Now() > mLastDOMMotionEventTime + TimeDuration::FromMilliseconds(DEFAULT_SENSOR_POLL);
|
||||
|
||||
switch (type) {
|
||||
case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION:
|
||||
mLastAcceleration = new nsDOMDeviceAcceleration(x, y, z);
|
||||
break;
|
||||
case nsIDeviceMotionData::TYPE_ACCELERATION:
|
||||
mLastAccelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z);
|
||||
break;
|
||||
case nsIDeviceMotionData::TYPE_GYROSCOPE:
|
||||
mLastRotationRate = new nsDOMDeviceRotationRate(x, y, z);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fireEvent && (!mLastAcceleration || !mLastAccelerationIncluduingGravity || !mLastRotationRate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
bool defaultActionEnabled = true;
|
||||
domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event));
|
||||
|
||||
nsCOMPtr<nsIDOMDeviceMotionEvent> me = do_QueryInterface(event);
|
||||
|
||||
if (!me) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently acceleration as determined includes gravity.
|
||||
nsRefPtr<nsDOMDeviceAcceleration> acceleration = new nsDOMDeviceAcceleration(x, y, z);
|
||||
}
|
||||
|
||||
me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"),
|
||||
true,
|
||||
false,
|
||||
nsnull,
|
||||
acceleration,
|
||||
nsnull,
|
||||
0);
|
||||
mLastAcceleration,
|
||||
mLastAccelerationIncluduingGravity,
|
||||
mLastRotationRate,
|
||||
DEFAULT_SENSOR_POLL);
|
||||
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
|
||||
if (privateEvent)
|
||||
privateEvent->SetTrusted(true);
|
||||
|
||||
bool defaultActionEnabled = true;
|
||||
target->DispatchEvent(event, &defaultActionEnabled);
|
||||
|
||||
mLastRotationRate = nsnull;
|
||||
mLastAccelerationIncluduingGravity = nsnull;
|
||||
mLastAcceleration = nsnull;
|
||||
mLastDOMMotionEventTime = TimeStamp::Now();
|
||||
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,10 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDOMDeviceOrientationEvent.h"
|
||||
#include "nsIDOMDeviceMotionEvent.h"
|
||||
#include "nsDOMDeviceMotionEvent.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#define NS_DEVICE_MOTION_CID \
|
||||
{ 0xecba5203, 0x77da, 0x465a, \
|
||||
@ -76,6 +80,9 @@ private:
|
||||
|
||||
protected:
|
||||
|
||||
void FireNeedsCalibration(nsIDOMDocument *domdoc,
|
||||
nsIDOMEventTarget *target);
|
||||
|
||||
void FireDOMOrientationEvent(class nsIDOMDocument *domDoc,
|
||||
class nsIDOMEventTarget *target,
|
||||
double alpha,
|
||||
@ -84,15 +91,20 @@ private:
|
||||
|
||||
void FireDOMMotionEvent(class nsIDOMDocument *domDoc,
|
||||
class nsIDOMEventTarget *target,
|
||||
PRUint32 type,
|
||||
double x,
|
||||
double y,
|
||||
double z);
|
||||
|
||||
PRUint32 mUpdateInterval;
|
||||
bool mEnabled;
|
||||
|
||||
virtual void Startup() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
bool mEnabled;
|
||||
mozilla::TimeStamp mLastDOMMotionEventTime;
|
||||
nsRefPtr<nsDOMDeviceAcceleration> mLastAcceleration;
|
||||
nsRefPtr<nsDOMDeviceAcceleration> mLastAccelerationIncluduingGravity;
|
||||
nsRefPtr<nsDOMDeviceRotationRate> mLastRotationRate;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -82,4 +82,7 @@ LOCAL_INCLUDES += $(MOZ_QT_CFLAGS) \
|
||||
endif
|
||||
endif
|
||||
|
||||
# We fire the nsDOMDeviceAcceleration
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "nsDeviceMotionSystem.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#define DEFAULT_SENSOR_POLL 100
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
typedef struct {
|
||||
@ -223,7 +225,7 @@ void nsDeviceMotionSystem::Startup()
|
||||
if (mUpdateTimer)
|
||||
mUpdateTimer->InitWithFuncCallback(UpdateHandler,
|
||||
this,
|
||||
mUpdateInterval,
|
||||
DEFAULT_SENSOR_POLL,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,9 @@ LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
EXPORT_LIBRARY = 1
|
||||
|
||||
# We fire the nsDOMDeviceAcceleration
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define DEFAULT_SENSOR_POLL 100
|
||||
|
||||
////////////////////////////
|
||||
// ThinkPad
|
||||
////////////////////////////
|
||||
@ -156,7 +158,7 @@ void nsDeviceMotionSystem::Startup()
|
||||
if (mUpdateTimer)
|
||||
mUpdateTimer->InitWithFuncCallback(UpdateHandler,
|
||||
this,
|
||||
mUpdateInterval,
|
||||
DEFAULT_SENSOR_POLL,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
|
@ -164,8 +164,8 @@ Telephony::Create(nsPIDOMWindow* aOwner, nsIRadioInterfaceLayer* aRIL)
|
||||
|
||||
nsRefPtr<Telephony> telephony = new Telephony();
|
||||
|
||||
telephony->mOwner = aOwner;
|
||||
telephony->mScriptContext.swap(scriptContext);
|
||||
telephony->BindToOwner(aOwner);
|
||||
|
||||
telephony->mRIL = aRIL;
|
||||
telephony->mRILTelephonyCallback = new RILTelephonyCallback(telephony);
|
||||
|
||||
@ -328,12 +328,16 @@ Telephony::GetActive(jsval* aActive)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
nsContentUtils::WrapNative(mScriptContext->GetNativeContext(),
|
||||
mScriptContext->GetNativeGlobal(),
|
||||
mActiveCall->ToISupports(), aActive);
|
||||
nsresult rv;
|
||||
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (sc) {
|
||||
rv =
|
||||
nsContentUtils::WrapNative(sc->GetNativeContext(),
|
||||
sc->GetNativeGlobal(),
|
||||
mActiveCall->ToISupports(), aActive);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -342,17 +346,24 @@ Telephony::GetCalls(jsval* aCalls)
|
||||
{
|
||||
JSObject* calls = mCallsArray;
|
||||
if (!calls) {
|
||||
nsresult rv =
|
||||
nsTArrayToJSArray(mScriptContext->GetNativeContext(),
|
||||
mScriptContext->GetNativeGlobal(), mCalls, &calls);
|
||||
nsresult rv;
|
||||
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (sc) {
|
||||
rv =
|
||||
nsTArrayToJSArray(sc->GetNativeContext(),
|
||||
sc->GetNativeGlobal(), mCalls, &calls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mRooted) {
|
||||
NS_HOLD_JS_OBJECTS(this, Telephony);
|
||||
mRooted = true;
|
||||
if (!mRooted) {
|
||||
NS_HOLD_JS_OBJECTS(this, Telephony);
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
mCallsArray = calls;
|
||||
} else {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mCallsArray = calls;
|
||||
}
|
||||
|
||||
aCalls->setObject(*calls);
|
||||
|
@ -118,18 +118,6 @@ public:
|
||||
return mRIL;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
Owner() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
nsIScriptContext*
|
||||
ScriptContext() const
|
||||
{
|
||||
return mScriptContext;
|
||||
}
|
||||
|
||||
private:
|
||||
Telephony();
|
||||
~Telephony();
|
||||
|
@ -57,8 +57,8 @@ TelephonyCall::Create(Telephony* aTelephony, const nsAString& aNumber,
|
||||
|
||||
nsRefPtr<TelephonyCall> call = new TelephonyCall();
|
||||
|
||||
call->mOwner = aTelephony->Owner();
|
||||
call->mScriptContext = aTelephony->ScriptContext();
|
||||
call->BindToOwner(aTelephony->GetOwner());
|
||||
|
||||
call->mTelephony = aTelephony;
|
||||
call->mNumber = aNumber;
|
||||
call->mCallIndex = aCallIndex;
|
||||
|
@ -252,10 +252,9 @@ public class GeckoEvent {
|
||||
}
|
||||
}
|
||||
|
||||
public GeckoEvent(Location l, Address a) {
|
||||
public GeckoEvent(Location l) {
|
||||
mType = LOCATION_EVENT;
|
||||
mLocation = l;
|
||||
mAddress = a;
|
||||
}
|
||||
|
||||
public GeckoEvent(int imeAction, int offset, int count) {
|
||||
|
@ -580,47 +580,10 @@ class GeckoSurfaceView
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
|
||||
}
|
||||
|
||||
private class GeocoderTask extends AsyncTask<Location, Void, Void> {
|
||||
protected Void doInBackground(Location... location) {
|
||||
try {
|
||||
List<Address> addresses = mGeocoder.getFromLocation(location[0].getLatitude(),
|
||||
location[0].getLongitude(), 1);
|
||||
// grab the first address. in the future,
|
||||
// may want to expose multiple, or filter
|
||||
// for best.
|
||||
mLastGeoAddress = addresses.get(0);
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent(location[0], mLastGeoAddress));
|
||||
} catch (Exception e) {
|
||||
Log.w(LOG_FILE_NAME, "GeocoderTask "+e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// geolocation
|
||||
public void onLocationChanged(Location location)
|
||||
{
|
||||
if (mGeocoder == null)
|
||||
mGeocoder = new Geocoder(getContext(), Locale.getDefault());
|
||||
|
||||
if (mLastGeoAddress == null) {
|
||||
new GeocoderTask().execute(location);
|
||||
}
|
||||
else {
|
||||
float[] results = new float[1];
|
||||
Location.distanceBetween(location.getLatitude(),
|
||||
location.getLongitude(),
|
||||
mLastGeoAddress.getLatitude(),
|
||||
mLastGeoAddress.getLongitude(),
|
||||
results);
|
||||
// pfm value. don't want to slam the
|
||||
// geocoder with very similar values, so
|
||||
// only call after about 100m
|
||||
if (results[0] > 100)
|
||||
new GeocoderTask().execute(location);
|
||||
}
|
||||
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent(location, mLastGeoAddress));
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent(location));
|
||||
}
|
||||
|
||||
public void onProviderDisabled(String provider)
|
||||
@ -825,9 +788,6 @@ class GeckoSurfaceView
|
||||
ByteBuffer mSoftwareBuffer;
|
||||
Bitmap mSoftwareBufferCopy;
|
||||
|
||||
Geocoder mGeocoder;
|
||||
Address mLastGeoAddress;
|
||||
|
||||
final SynchronousQueue<Object> mSyncDraws = new SynchronousQueue<Object>();
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "gfxFT2FontList.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsIScreen.h"
|
||||
#include "nsIScreenManager.h"
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
@ -57,6 +59,15 @@ static FT_Library gPlatformFTLibrary = NULL;
|
||||
gfxAndroidPlatform::gfxAndroidPlatform()
|
||||
{
|
||||
FT_Init_FreeType(&gPlatformFTLibrary);
|
||||
|
||||
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
|
||||
nsCOMPtr<nsIScreen> screen;
|
||||
screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
|
||||
PRInt32 depth = 24;
|
||||
screen->GetColorDepth(&depth);
|
||||
|
||||
mOffscreenFormat = depth == 16 ? gfxASurface::ImageFormatRGB16_565 :
|
||||
gfxASurface::ImageFormatARGB32;
|
||||
}
|
||||
|
||||
gfxAndroidPlatform::~gfxAndroidPlatform()
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; }
|
||||
|
||||
virtual gfxImageFormat GetOffscreenFormat() { return gfxASurface::ImageFormatRGB16_565; }
|
||||
virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::ScaledFont>
|
||||
GetScaledFontForFont(gfxFont *aFont);
|
||||
@ -102,6 +102,9 @@ public:
|
||||
virtual bool FontHintingEnabled() MOZ_OVERRIDE;
|
||||
|
||||
FT_Library GetFTLibrary();
|
||||
|
||||
private:
|
||||
gfxImageFormat mOffscreenFormat;
|
||||
};
|
||||
|
||||
#endif /* GFX_PLATFORM_ANDROID_H */
|
||||
|
@ -54,6 +54,8 @@ enum SensorType {
|
||||
SENSOR_ORIENTATION,
|
||||
SENSOR_ACCELERATION,
|
||||
SENSOR_PROXIMITY,
|
||||
SENSOR_LINEAR_ACCELERATION,
|
||||
SENSOR_GYROSCOPE,
|
||||
NUM_SENSOR_TYPE
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "base/platform_thread.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/scoped_nsautorelease_pool.h"
|
||||
@ -51,3 +52,26 @@ void InitThreading() {
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
// static
|
||||
void PlatformThread::SetName(const char* name) {
|
||||
// pthread_setname_np is only available in 10.6 or later, so test
|
||||
// for it at runtime.
|
||||
int (*dynamic_pthread_setname_np)(const char*);
|
||||
*reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
|
||||
dlsym(RTLD_DEFAULT, "pthread_setname_np");
|
||||
if (!dynamic_pthread_setname_np)
|
||||
return;
|
||||
|
||||
// Mac OS X does not expose the length limit of the name, so
|
||||
// hardcode it.
|
||||
const int kMaxNameLength = 63;
|
||||
std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
|
||||
// pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
|
||||
// See http://crbug.com/47058
|
||||
|
||||
// The name parameter is copied thus it's safe to release it after calling.
|
||||
// Checked against the bionic implementation in bionic/libc/bionic/pthread.c
|
||||
dynamic_pthread_setname_np(shortened_name.c_str());
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,9 @@ void PlatformThread::Sleep(int duration_ms) {
|
||||
sleep_time = remaining;
|
||||
}
|
||||
|
||||
#ifndef OS_MACOSX
|
||||
// Mac is implemented in platform_thread_mac.mm.
|
||||
|
||||
// static
|
||||
void PlatformThread::SetName(const char* name) {
|
||||
// The POSIX standard does not provide for naming threads, and neither Linux
|
||||
@ -70,6 +73,7 @@ void PlatformThread::SetName(const char* name) {
|
||||
// TODO(darin): decide whether stuffing the name in TLS or other in-memory
|
||||
// structure would be useful for debugging or not.
|
||||
}
|
||||
#endif // !OS_MACOSX
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
13.0a1
|
||||
14.0a1
|
||||
|
@ -54,6 +54,210 @@
|
||||
namespace js {
|
||||
namespace gcstats {
|
||||
|
||||
/* Except for the first and last, slices of less than 12ms are not reported. */
|
||||
static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC;
|
||||
|
||||
class StatisticsSerializer
|
||||
{
|
||||
typedef Vector<char, 128, SystemAllocPolicy> CharBuffer;
|
||||
CharBuffer buf_;
|
||||
bool asJSON_;
|
||||
bool needComma_;
|
||||
bool oom_;
|
||||
|
||||
const static int MaxFieldValueLength = 128;
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
AsJSON = true,
|
||||
AsText = false
|
||||
};
|
||||
|
||||
StatisticsSerializer(Mode asJSON)
|
||||
: buf_(), asJSON_(asJSON), needComma_(false), oom_(false)
|
||||
{}
|
||||
|
||||
bool isJSON() { return asJSON_; }
|
||||
|
||||
bool isOOM() { return oom_; }
|
||||
|
||||
void endLine() {
|
||||
if (!asJSON_) {
|
||||
p("\n");
|
||||
needComma_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void extra(const char *str) {
|
||||
if (!asJSON_) {
|
||||
needComma_ = false;
|
||||
p(str);
|
||||
}
|
||||
}
|
||||
|
||||
void appendString(const char *name, const char *value) {
|
||||
put(name, value, "", true);
|
||||
}
|
||||
|
||||
void appendNumber(const char *name, const char *vfmt, const char *units, ...) {
|
||||
va_list va;
|
||||
va_start(va, units);
|
||||
append(name, vfmt, va, units);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void appendIfNonzeroMS(const char *name, double v) {
|
||||
if (asJSON_ || v)
|
||||
appendNumber(name, "%.1f", "ms", v);
|
||||
}
|
||||
|
||||
void beginObject(const char *name) {
|
||||
if (needComma_)
|
||||
pJSON(", ");
|
||||
if (asJSON_ && name) {
|
||||
putQuoted(name);
|
||||
pJSON(": ");
|
||||
}
|
||||
pJSON("{");
|
||||
needComma_ = false;
|
||||
}
|
||||
|
||||
void endObject() {
|
||||
needComma_ = false;
|
||||
pJSON("}");
|
||||
needComma_ = true;
|
||||
}
|
||||
|
||||
void beginArray(const char *name) {
|
||||
if (needComma_)
|
||||
pJSON(", ");
|
||||
if (asJSON_)
|
||||
putQuoted(name);
|
||||
pJSON(": [");
|
||||
needComma_ = false;
|
||||
}
|
||||
|
||||
void endArray() {
|
||||
needComma_ = false;
|
||||
pJSON("]");
|
||||
needComma_ = true;
|
||||
}
|
||||
|
||||
jschar *finishJSString() {
|
||||
char *buf = finishCString();
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
size_t nchars = strlen(buf);
|
||||
jschar *out = (jschar *)js_malloc(sizeof(jschar) * (nchars + 1));
|
||||
if (!out) {
|
||||
oom_ = true;
|
||||
js_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t outlen = nchars;
|
||||
bool ok = InflateStringToBuffer(NULL, buf, nchars, out, &outlen);
|
||||
js_free(buf);
|
||||
if (!ok) {
|
||||
oom_ = true;
|
||||
js_free(out);
|
||||
return NULL;
|
||||
}
|
||||
out[nchars] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
char *finishCString() {
|
||||
if (oom_)
|
||||
return NULL;
|
||||
|
||||
buf_.append('\0');
|
||||
|
||||
char *buf = buf_.extractRawBuffer();
|
||||
if (!buf)
|
||||
oom_ = true;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private:
|
||||
void append(const char *name, const char *vfmt,
|
||||
va_list va, const char *units)
|
||||
{
|
||||
char val[MaxFieldValueLength];
|
||||
JS_vsnprintf(val, MaxFieldValueLength, vfmt, va);
|
||||
put(name, val, units, false);
|
||||
}
|
||||
|
||||
void p(const char *cstr) {
|
||||
if (oom_)
|
||||
return;
|
||||
|
||||
if (!buf_.append(cstr, strlen(cstr)))
|
||||
oom_ = true;
|
||||
}
|
||||
|
||||
void p(const char c) {
|
||||
if (oom_)
|
||||
return;
|
||||
|
||||
if (!buf_.append(c))
|
||||
oom_ = true;
|
||||
}
|
||||
|
||||
void pJSON(const char *str) {
|
||||
if (asJSON_)
|
||||
p(str);
|
||||
}
|
||||
|
||||
void put(const char *name, const char *val, const char *units, bool valueIsQuoted) {
|
||||
if (needComma_)
|
||||
p(", ");
|
||||
needComma_ = true;
|
||||
|
||||
putKey(name);
|
||||
p(": ");
|
||||
if (valueIsQuoted)
|
||||
putQuoted(val);
|
||||
else
|
||||
p(val);
|
||||
if (!asJSON_)
|
||||
p(units);
|
||||
}
|
||||
|
||||
void putQuoted(const char *str) {
|
||||
pJSON("\"");
|
||||
p(str);
|
||||
pJSON("\"");
|
||||
}
|
||||
|
||||
void putKey(const char *str) {
|
||||
if (!asJSON_) {
|
||||
p(str);
|
||||
return;
|
||||
}
|
||||
|
||||
p("\"");
|
||||
const char *c = str;
|
||||
while (*c) {
|
||||
if (*c == ' ' || *c == '\t')
|
||||
p('_');
|
||||
else if (isupper(*c))
|
||||
p(tolower(*c));
|
||||
else if (*c == '+')
|
||||
p("added_");
|
||||
else if (*c == '-')
|
||||
p("removed_");
|
||||
else if (*c != '(' && *c != ')')
|
||||
p(*c);
|
||||
c++;
|
||||
}
|
||||
p("\"");
|
||||
}
|
||||
};
|
||||
|
||||
static const char *
|
||||
ExplainReason(gcreason::Reason reason)
|
||||
{
|
||||
@ -70,57 +274,36 @@ ExplainReason(gcreason::Reason reason)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::fmt(const char *f, ...)
|
||||
static double
|
||||
t(int64_t t)
|
||||
{
|
||||
va_list va;
|
||||
size_t off = strlen(buffer);
|
||||
|
||||
va_start(va, f);
|
||||
JS_vsnprintf(buffer + off, BUFFER_SIZE - off, f, va);
|
||||
va_end(va);
|
||||
return double(t) / PRMJ_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::fmtIfNonzero(const char *name, double t)
|
||||
static void
|
||||
formatPhases(StatisticsSerializer &ss, const char *name, int64_t *times)
|
||||
{
|
||||
if (t) {
|
||||
if (needComma)
|
||||
fmt(", ");
|
||||
fmt("%s: %.1f", name, t);
|
||||
needComma = true;
|
||||
}
|
||||
ss.beginObject(name);
|
||||
ss.appendIfNonzeroMS("Mark", t(times[PHASE_MARK]));
|
||||
ss.appendIfNonzeroMS("Mark Roots", t(times[PHASE_MARK_ROOTS]));
|
||||
ss.appendIfNonzeroMS("Mark Delayed", t(times[PHASE_MARK_DELAYED]));
|
||||
ss.appendIfNonzeroMS("Mark Other", t(times[PHASE_MARK_OTHER]));
|
||||
ss.appendIfNonzeroMS("Sweep", t(times[PHASE_SWEEP]));
|
||||
ss.appendIfNonzeroMS("Sweep Object", t(times[PHASE_SWEEP_OBJECT]));
|
||||
ss.appendIfNonzeroMS("Sweep String", t(times[PHASE_SWEEP_STRING]));
|
||||
ss.appendIfNonzeroMS("Sweep Script", t(times[PHASE_SWEEP_SCRIPT]));
|
||||
ss.appendIfNonzeroMS("Sweep Shape", t(times[PHASE_SWEEP_SHAPE]));
|
||||
ss.appendIfNonzeroMS("Discard Code", t(times[PHASE_DISCARD_CODE]));
|
||||
ss.appendIfNonzeroMS("Discard Analysis", t(times[PHASE_DISCARD_ANALYSIS]));
|
||||
ss.appendIfNonzeroMS("XPConnect", t(times[PHASE_XPCONNECT]));
|
||||
ss.appendIfNonzeroMS("Deallocate", t(times[PHASE_DESTROY]));
|
||||
ss.endObject();
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::formatPhases(int64_t *times)
|
||||
bool
|
||||
Statistics::formatData(StatisticsSerializer &ss)
|
||||
{
|
||||
needComma = false;
|
||||
fmtIfNonzero("mark", t(times[PHASE_MARK]));
|
||||
fmtIfNonzero("mark-roots", t(times[PHASE_MARK_ROOTS]));
|
||||
fmtIfNonzero("mark-delayed", t(times[PHASE_MARK_DELAYED]));
|
||||
fmtIfNonzero("mark-other", t(times[PHASE_MARK_OTHER]));
|
||||
fmtIfNonzero("sweep", t(times[PHASE_SWEEP]));
|
||||
fmtIfNonzero("sweep-obj", t(times[PHASE_SWEEP_OBJECT]));
|
||||
fmtIfNonzero("sweep-string", t(times[PHASE_SWEEP_STRING]));
|
||||
fmtIfNonzero("sweep-script", t(times[PHASE_SWEEP_SCRIPT]));
|
||||
fmtIfNonzero("sweep-shape", t(times[PHASE_SWEEP_SHAPE]));
|
||||
fmtIfNonzero("discard-code", t(times[PHASE_DISCARD_CODE]));
|
||||
fmtIfNonzero("discard-analysis", t(times[PHASE_DISCARD_ANALYSIS]));
|
||||
fmtIfNonzero("xpconnect", t(times[PHASE_XPCONNECT]));
|
||||
fmtIfNonzero("deallocate", t(times[PHASE_DESTROY]));
|
||||
}
|
||||
|
||||
/* Except for the first and last, slices of less than 12ms are not reported. */
|
||||
static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC;
|
||||
|
||||
const char *
|
||||
Statistics::formatData()
|
||||
{
|
||||
buffer[0] = 0x00;
|
||||
|
||||
int64_t total = 0, longest = 0;
|
||||
|
||||
for (SliceData *slice = slices.begin(); slice != slices.end(); slice++) {
|
||||
total += slice->duration();
|
||||
if (slice->duration() > longest)
|
||||
@ -130,47 +313,70 @@ Statistics::formatData()
|
||||
double mmu20 = computeMMU(20 * PRMJ_USEC_PER_MSEC);
|
||||
double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC);
|
||||
|
||||
fmt("TotalTime: %.1fms, Type: %s", t(total), compartment ? "compartment" : "global");
|
||||
fmt(", MMU(20ms): %d%%, MMU(50ms): %d%%", int(mmu20 * 100), int(mmu50 * 100));
|
||||
|
||||
if (slices.length() > 1)
|
||||
fmt(", MaxPause: %.1f", t(longest));
|
||||
ss.beginObject(NULL);
|
||||
ss.appendNumber("Total Time", "%.1f", "ms", t(total));
|
||||
ss.appendString("Type", compartment ? "compartment" : "global");
|
||||
ss.appendNumber("MMU (20ms)", "%d", "%", int(mmu20 * 100));
|
||||
ss.appendNumber("MMU (50ms)", "%d", "%", int(mmu50 * 100));
|
||||
if (slices.length() > 1 || ss.isJSON())
|
||||
ss.appendNumber("Max Pause", "%.1f", "ms", t(longest));
|
||||
else
|
||||
fmt(", Reason: %s", ExplainReason(slices[0].reason));
|
||||
ss.appendString("Reason", ExplainReason(slices[0].reason));
|
||||
if (nonincrementalReason || ss.isJSON()) {
|
||||
ss.appendString("Nonincremental Reason",
|
||||
nonincrementalReason ? nonincrementalReason : "none");
|
||||
}
|
||||
ss.appendNumber("+Chunks", "%d", "", counts[STAT_NEW_CHUNK]);
|
||||
ss.appendNumber("-Chunks", "%d", "", counts[STAT_DESTROY_CHUNK]);
|
||||
ss.endLine();
|
||||
|
||||
if (nonincrementalReason)
|
||||
fmt(", NonIncrementalReason: %s", nonincrementalReason);
|
||||
|
||||
fmt(", +chunks: %d, -chunks: %d\n", counts[STAT_NEW_CHUNK], counts[STAT_DESTROY_CHUNK]);
|
||||
|
||||
if (slices.length() > 1) {
|
||||
if (slices.length() > 1 || ss.isJSON()) {
|
||||
ss.beginArray("Slices");
|
||||
for (size_t i = 0; i < slices.length(); i++) {
|
||||
int64_t width = slices[i].duration();
|
||||
if (i != 0 && i != slices.length() - 1 && width < SLICE_MIN_REPORT_TIME &&
|
||||
!slices[i].resetReason)
|
||||
!slices[i].resetReason && !ss.isJSON())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fmt(" Slice %d @ %.1fms (Pause: %.1f, Reason: %s",
|
||||
i,
|
||||
t(slices[i].end - slices[0].start),
|
||||
t(width),
|
||||
ExplainReason(slices[i].reason));
|
||||
ss.beginObject(NULL);
|
||||
ss.extra(" ");
|
||||
ss.appendNumber("Slice", "%d", "", i);
|
||||
ss.appendNumber("Time", "%.1f", "ms", t(slices[i].end - slices[0].start));
|
||||
ss.extra(" (");
|
||||
ss.appendNumber("Pause", "%.1f", "", t(width));
|
||||
ss.appendString("Reason", ExplainReason(slices[i].reason));
|
||||
if (slices[i].resetReason)
|
||||
fmt(", Reset: %s", slices[i].resetReason);
|
||||
fmt("): ");
|
||||
formatPhases(slices[i].phaseTimes);
|
||||
fmt("\n");
|
||||
ss.appendString("Reset", slices[i].resetReason);
|
||||
ss.extra("): ");
|
||||
formatPhases(ss, "times", slices[i].phaseTimes);
|
||||
ss.endLine();
|
||||
ss.endObject();
|
||||
}
|
||||
|
||||
fmt(" Totals: ");
|
||||
ss.endArray();
|
||||
}
|
||||
ss.extra(" Totals: ");
|
||||
formatPhases(ss, "totals", phaseTimes);
|
||||
ss.endObject();
|
||||
|
||||
formatPhases(phaseTimes);
|
||||
fmt("\n");
|
||||
return !ss.isOOM();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
jschar *
|
||||
Statistics::formatMessage()
|
||||
{
|
||||
StatisticsSerializer ss(StatisticsSerializer::AsText);
|
||||
formatData(ss);
|
||||
return ss.finishJSString();
|
||||
}
|
||||
|
||||
jschar *
|
||||
Statistics::formatJSON()
|
||||
{
|
||||
StatisticsSerializer ss(StatisticsSerializer::AsJSON);
|
||||
formatData(ss);
|
||||
return ss.finishJSString();
|
||||
}
|
||||
|
||||
Statistics::Statistics(JSRuntime *rt)
|
||||
@ -179,8 +385,7 @@ Statistics::Statistics(JSRuntime *rt)
|
||||
fp(NULL),
|
||||
fullFormat(false),
|
||||
compartment(NULL),
|
||||
nonincrementalReason(NULL),
|
||||
needComma(false)
|
||||
nonincrementalReason(NULL)
|
||||
{
|
||||
PodArrayZero(phaseTotals);
|
||||
PodArrayZero(counts);
|
||||
@ -209,9 +414,13 @@ Statistics::~Statistics()
|
||||
{
|
||||
if (fp) {
|
||||
if (fullFormat) {
|
||||
buffer[0] = 0x00;
|
||||
formatPhases(phaseTotals);
|
||||
fprintf(fp, "TOTALS\n%s\n\n-------\n", buffer);
|
||||
StatisticsSerializer ss(StatisticsSerializer::AsText);
|
||||
formatPhases(ss, "", phaseTotals);
|
||||
char *msg = ss.finishCString();
|
||||
if (msg) {
|
||||
fprintf(fp, "TOTALS\n%s\n\n-------\n", msg);
|
||||
js_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (fp != stdout && fp != stderr)
|
||||
@ -219,12 +428,6 @@ Statistics::~Statistics()
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
Statistics::t(int64_t t)
|
||||
{
|
||||
return double(t) / PRMJ_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
int64_t
|
||||
Statistics::gcDuration()
|
||||
{
|
||||
@ -235,9 +438,13 @@ void
|
||||
Statistics::printStats()
|
||||
{
|
||||
if (fullFormat) {
|
||||
fprintf(fp, "GC(T+%.3fs) %s\n",
|
||||
t(slices[0].start - startupTime) / 1000.0,
|
||||
formatData());
|
||||
StatisticsSerializer ss(StatisticsSerializer::AsText);
|
||||
formatData(ss);
|
||||
char *msg = ss.finishCString();
|
||||
if (msg) {
|
||||
fprintf(fp, "GC(T+%.3fs) %s\n", t(slices[0].start - startupTime) / 1000.0, msg);
|
||||
js_free(msg);
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "%f %f %f\n",
|
||||
t(gcDuration()),
|
||||
@ -301,10 +508,8 @@ Statistics::beginSlice(JSCompartment *comp, gcreason::Reason reason)
|
||||
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback)
|
||||
(*cb)(JS_TELEMETRY_GC_REASON, reason);
|
||||
|
||||
if (GCSliceCallback cb = runtime->gcSliceCallback) {
|
||||
GCDescription desc(NULL, !!compartment);
|
||||
(*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, desc);
|
||||
}
|
||||
if (GCSliceCallback cb = runtime->gcSliceCallback)
|
||||
(*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, GCDescription(!!compartment));
|
||||
}
|
||||
|
||||
void
|
||||
@ -323,9 +528,9 @@ Statistics::endSlice()
|
||||
|
||||
if (GCSliceCallback cb = runtime->gcSliceCallback) {
|
||||
if (last)
|
||||
(*cb)(runtime, GC_CYCLE_END, GCDescription(formatData(), !!compartment));
|
||||
(*cb)(runtime, GC_CYCLE_END, GCDescription(!!compartment));
|
||||
else
|
||||
(*cb)(runtime, GC_SLICE_END, GCDescription(NULL, !!compartment));
|
||||
(*cb)(runtime, GC_SLICE_END, GCDescription(!!compartment));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ enum Stat {
|
||||
STAT_LIMIT
|
||||
};
|
||||
|
||||
static const size_t BUFFER_SIZE = 8192;
|
||||
class StatisticsSerializer;
|
||||
|
||||
struct Statistics {
|
||||
Statistics(JSRuntime *rt);
|
||||
@ -96,6 +96,9 @@ struct Statistics {
|
||||
counts[s]++;
|
||||
}
|
||||
|
||||
jschar *formatMessage();
|
||||
jschar *formatJSON();
|
||||
|
||||
private:
|
||||
JSRuntime *runtime;
|
||||
|
||||
@ -136,19 +139,12 @@ struct Statistics {
|
||||
/* Number of events of this type for this GC. */
|
||||
unsigned int counts[STAT_LIMIT];
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
bool needComma;
|
||||
|
||||
void beginGC();
|
||||
void endGC();
|
||||
|
||||
int64_t gcDuration();
|
||||
double t(int64_t t);
|
||||
void printStats();
|
||||
void fmt(const char *f, ...);
|
||||
void fmtIfNonzero(const char *name, double t);
|
||||
void formatPhases(int64_t *times);
|
||||
const char *formatData();
|
||||
bool formatData(StatisticsSerializer &ss);
|
||||
|
||||
double computeMMU(int64_t resolution);
|
||||
};
|
||||
|
@ -4284,7 +4284,7 @@ prop_iter_trace(JSTracer *trc, JSObject *obj)
|
||||
|
||||
static Class prop_iter_class = {
|
||||
"PropertyIterator",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
@ -6445,23 +6445,10 @@ JS_ClearPendingException(JSContext *cx)
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ReportPendingException(JSContext *cx)
|
||||
{
|
||||
JSBool ok;
|
||||
bool save;
|
||||
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
/*
|
||||
* Set cx->generatingError to suppress the standard error-to-exception
|
||||
* conversion done by all {js,JS}_Report* functions except for OOM. The
|
||||
* cx->generatingError flag was added to suppress recursive divergence
|
||||
* under js_ErrorToException, but it serves for our purposes here too.
|
||||
*/
|
||||
save = cx->generatingError;
|
||||
cx->generatingError = JS_TRUE;
|
||||
ok = js_ReportUncaughtException(cx);
|
||||
cx->generatingError = save;
|
||||
return ok;
|
||||
return js_ReportUncaughtException(cx);
|
||||
}
|
||||
|
||||
struct JSExceptionState {
|
||||
|
@ -120,7 +120,6 @@
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsstr.h"
|
||||
#include "jswrapper.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "methodjit/StubCalls.h"
|
||||
|
@ -827,11 +827,11 @@ struct JSContext : js::ContextFriendFields
|
||||
bool hasVersionOverride;
|
||||
|
||||
/* Exception state -- the exception member is a GC root by definition. */
|
||||
JSBool throwing; /* is there a pending exception? */
|
||||
js::Value exception; /* most-recently-thrown exception */
|
||||
JSBool throwing; /* is there a pending exception? */
|
||||
js::Value exception; /* most-recently-thrown exception */
|
||||
|
||||
/* Per-context run options. */
|
||||
unsigned runOptions; /* see jsapi.h for JSOPTION_* */
|
||||
unsigned runOptions; /* see jsapi.h for JSOPTION_* */
|
||||
|
||||
public:
|
||||
int32_t reportGranularity; /* see jsprobes.h */
|
||||
@ -841,11 +841,8 @@ struct JSContext : js::ContextFriendFields
|
||||
|
||||
js::AutoResolving *resolvingList;
|
||||
|
||||
/*
|
||||
* True if generating an error, to prevent runaway recursion.
|
||||
* NB: generatingError packs with throwing below.
|
||||
*/
|
||||
bool generatingError;
|
||||
/* True if generating an error, to prevent runaway recursion. */
|
||||
bool generatingError;
|
||||
|
||||
/* GC heap compartment. */
|
||||
JSCompartment *compartment;
|
||||
|
@ -1074,7 +1074,6 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
||||
const JSErrorFormatString *errorString;
|
||||
JSExnType exn;
|
||||
jsval tv[4];
|
||||
JSBool ok;
|
||||
JSObject *errProto, *errObject;
|
||||
JSString *messageStr, *filenameStr;
|
||||
|
||||
@ -1083,7 +1082,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
||||
*/
|
||||
JS_ASSERT(reportp);
|
||||
if (JSREPORT_IS_WARNING(reportp->flags))
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
|
||||
/* Find the exception index associated with this error. */
|
||||
errorNumber = (JSErrNum) reportp->errorNumber;
|
||||
@ -1106,19 +1105,12 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
||||
* with the given error number.
|
||||
*/
|
||||
if (exn == JSEXN_NONE)
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Prevent runaway recursion, via cx->generatingError. If an out-of-memory
|
||||
* error occurs, no exception object will be created, but we don't assume
|
||||
* that OOM is the only kind of error that subroutines of this function
|
||||
* called below might raise.
|
||||
*/
|
||||
/* Prevent infinite recursion. */
|
||||
if (cx->generatingError)
|
||||
return JS_FALSE;
|
||||
|
||||
MUST_FLOW_THROUGH("out");
|
||||
cx->generatingError = JS_TRUE;
|
||||
return false;
|
||||
AutoScopedAssign<bool> asa(&cx->generatingError, true);
|
||||
|
||||
/* Protect the newly-created strings below from nesting GCs. */
|
||||
PodArrayZero(tv);
|
||||
@ -1129,45 +1121,32 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
||||
* exception constructor name in the scope chain of the current context's
|
||||
* top stack frame, or in the global object if no frame is active.
|
||||
*/
|
||||
ok = js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto);
|
||||
if (!ok)
|
||||
goto out;
|
||||
if (!js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto))
|
||||
return false;
|
||||
tv[0] = OBJECT_TO_JSVAL(errProto);
|
||||
|
||||
errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL);
|
||||
if (!errObject) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!(errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL)))
|
||||
return false;
|
||||
tv[1] = OBJECT_TO_JSVAL(errObject);
|
||||
|
||||
messageStr = JS_NewStringCopyZ(cx, message);
|
||||
if (!messageStr) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!(messageStr = JS_NewStringCopyZ(cx, message)))
|
||||
return false;
|
||||
tv[2] = STRING_TO_JSVAL(messageStr);
|
||||
|
||||
filenameStr = JS_NewStringCopyZ(cx, reportp->filename);
|
||||
if (!filenameStr) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!(filenameStr = JS_NewStringCopyZ(cx, reportp->filename)))
|
||||
return false;
|
||||
tv[3] = STRING_TO_JSVAL(filenameStr);
|
||||
|
||||
ok = InitExnPrivate(cx, errObject, messageStr, filenameStr,
|
||||
reportp->lineno, reportp, exn);
|
||||
if (!ok)
|
||||
goto out;
|
||||
if (!InitExnPrivate(cx, errObject, messageStr, filenameStr,
|
||||
reportp->lineno, reportp, exn)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
|
||||
|
||||
/* Flag the error report passed in to indicate an exception was raised. */
|
||||
reportp->flags |= JSREPORT_EXCEPTION;
|
||||
|
||||
out:
|
||||
cx->generatingError = JS_FALSE;
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -717,6 +717,18 @@ SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
|
||||
return old;
|
||||
}
|
||||
|
||||
jschar *
|
||||
GCDescription::formatMessage(JSRuntime *rt) const
|
||||
{
|
||||
return rt->gcStats.formatMessage();
|
||||
}
|
||||
|
||||
jschar *
|
||||
GCDescription::formatJSON(JSRuntime *rt) const
|
||||
{
|
||||
return rt->gcStats.formatJSON();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
WantGCSlice(JSRuntime *rt)
|
||||
{
|
||||
|
@ -699,12 +699,14 @@ enum GCProgress {
|
||||
GC_CYCLE_END
|
||||
};
|
||||
|
||||
struct GCDescription {
|
||||
const char *logMessage;
|
||||
struct JS_FRIEND_API(GCDescription) {
|
||||
bool isCompartment;
|
||||
|
||||
GCDescription(const char *msg, bool isCompartment)
|
||||
: logMessage(msg), isCompartment(isCompartment) {}
|
||||
GCDescription(bool isCompartment)
|
||||
: isCompartment(isCompartment) {}
|
||||
|
||||
jschar *formatMessage(JSRuntime *rt) const;
|
||||
jschar *formatJSON(JSRuntime *rt) const;
|
||||
};
|
||||
|
||||
typedef void
|
||||
|
@ -6931,7 +6931,7 @@ mjit::Compiler::jsop_regexp()
|
||||
*/
|
||||
analyze::SSAUseChain *uses =
|
||||
analysis->useChain(analyze::SSAValue::PushedValue(PC - script->code, 0));
|
||||
if (uses && uses->popped && !uses->next) {
|
||||
if (uses && uses->popped && !uses->next && !reobj->global() && !reobj->sticky()) {
|
||||
jsbytecode *use = script->code + uses->offset;
|
||||
uint32_t which = uses->u.which;
|
||||
if (JSOp(*use) == JSOP_CALLPROP) {
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
@ -1,39 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
@ -1,39 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,7 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,38 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
@ -1,39 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
@ -1,39 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,38 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,40 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
@ -1,39 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user