merge fx-team to m-c

This commit is contained in:
Tim Taubert
2012-01-26 08:36:07 +01:00
100 changed files with 1476 additions and 1113 deletions

View File

@@ -176,7 +176,8 @@
<menuseparator class="appmenu-menuseparator"/>
<menu id="appmenu_webDeveloper"
label="&appMenuWebDeveloper.label;">
<menupopup id="appmenu_webDeveloper_popup">
<menupopup id="appmenu_webDeveloper_popup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menuitem id="appmenu_webConsole"
label="&webConsoleCmd.label;"
type="checkbox"

View File

@@ -531,7 +531,8 @@
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menupopup id="menuWebDeveloperPopup">
<menupopup id="menuWebDeveloperPopup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menuitem id="webConsole"
type="checkbox"
label="&webConsoleCmd.label;"

View File

@@ -9063,6 +9063,11 @@ var StyleEditor = {
}
};
function onWebDeveloperMenuShowing() {
document.getElementById("Tools:WebConsole").setAttribute("checked", HUDConsoleUI.getOpenHUD() != null);
}
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#ifdef XP_WIN
// Only show resizers on Windows 2000 and XP
@@ -9137,6 +9142,7 @@ var MousePosTracker = {
}
}
};
function focusNextFrame(event) {
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC;

View File

@@ -741,6 +741,11 @@ iQClass.prototype = {
if (pair.original == func) {
handler = pair.modified;
elem.iQEventData[type].splice(a, 1);
if (!elem.iQEventData[type].length) {
delete elem.iQEventData[type];
if (!Object.keys(elem.iQEventData).length)
delete elem.iQEventData;
}
break;
}
}
@@ -765,10 +770,10 @@ iQClass.prototype = {
if (!elem.iQEventData)
continue;
for (let type in elem.iQEventData) {
while (elem.iQEventData[type].length)
Object.keys(elem.iQEventData).forEach(function (type) {
while (elem.iQEventData && elem.iQEventData[type])
this.unbind(type, elem.iQEventData[type][0].original);
}
}, this);
}
return this;

View File

@@ -1552,8 +1552,6 @@ HUD_SERVICE.prototype =
this.disableAnimation(hudId);
}
chromeDocument.getElementById("Tools:WebConsole").setAttribute("checked", "true");
// Create a processing instruction for GCLIs CSS stylesheet, but only if
// we don't have one for this document. Also record the context we're
// adding this for so we know when to remove it.
@@ -1603,8 +1601,6 @@ HUD_SERVICE.prototype =
window.focus();
}
chromeDocument.getElementById("Tools:WebConsole").setAttribute("checked", "false");
// Remove this context from the list of contexts that need the GCLI CSS
// processing instruction and then remove the processing instruction if it
// isn't needed any more.

View File

@@ -337,6 +337,7 @@ if test -n "$gonkdir" ; then
AC_DEFINE(ANDROID)
AC_DEFINE(HAVE_SYS_UIO_H)
AC_DEFINE(HAVE_PTHREADS)
CROSS_COMPILE=1
MOZ_CHROME_FILE_FORMAT=omni
ZLIB_DIR=yes

View File

@@ -73,6 +73,7 @@
#include "nsGUIEvent.h"
#include "nsAsyncDOMEvent.h"
#include "nsIDOMNodeFilter.h"
#include "nsIDOMStyleSheet.h"
#include "nsDOMAttribute.h"
@@ -5024,11 +5025,15 @@ NS_IMETHODIMP
nsDocument::CreateNodeIterator(nsIDOMNode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aEntityReferenceExpansion,
PRUint8 aOptionalArgc,
nsIDOMNodeIterator **_retval)
{
*_retval = nsnull;
if (!aOptionalArgc) {
aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
}
if (!aRoot)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
@@ -5042,24 +5047,27 @@ nsDocument::CreateNodeIterator(nsIDOMNode *aRoot,
nsNodeIterator *iterator = new nsNodeIterator(root,
aWhatToShow,
aFilter,
aEntityReferenceExpansion);
aFilter);
NS_ENSURE_TRUE(iterator, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*_retval = iterator);
return NS_OK;
return NS_OK;
}
NS_IMETHODIMP
nsDocument::CreateTreeWalker(nsIDOMNode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aEntityReferenceExpansion,
PRUint8 aOptionalArgc,
nsIDOMTreeWalker **_retval)
{
*_retval = nsnull;
if (!aOptionalArgc) {
aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
}
if (!aRoot)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
@@ -5073,8 +5081,7 @@ nsDocument::CreateTreeWalker(nsIDOMNode *aRoot,
nsTreeWalker* walker = new nsTreeWalker(root,
aWhatToShow,
aFilter,
aEntityReferenceExpansion);
aFilter);
NS_ENSURE_TRUE(walker, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*_retval = walker);

View File

@@ -170,9 +170,8 @@ void nsNodeIterator::NodePointer::MoveBackward(nsINode *aParent, nsINode *aNode)
nsNodeIterator::nsNodeIterator(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aExpandEntityReferences) :
nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
nsIDOMNodeFilter *aFilter) :
nsTraversal(aRoot, aWhatToShow, aFilter),
mDetached(false),
mPointer(mRoot, true)
{
@@ -247,7 +246,7 @@ NS_IMETHODIMP nsNodeIterator::GetFilter(nsIDOMNodeFilter **aFilter)
/* readonly attribute boolean expandEntityReferences; */
NS_IMETHODIMP nsNodeIterator::GetExpandEntityReferences(bool *aExpandEntityReferences)
{
*aExpandEntityReferences = mExpandEntityReferences;
*aExpandEntityReferences = false;
return NS_OK;
}

View File

@@ -63,8 +63,7 @@ public:
nsNodeIterator(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aExpandEntityReferences);
nsIDOMNodeFilter *aFilter);
virtual ~nsNodeIterator();
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED

View File

@@ -49,12 +49,10 @@
nsTraversal::nsTraversal(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aExpandEntityReferences) :
nsIDOMNodeFilter *aFilter) :
mRoot(aRoot),
mWhatToShow(aWhatToShow),
mFilter(aFilter),
mExpandEntityReferences(aExpandEntityReferences),
mInAcceptNode(false)
{
NS_ASSERTION(aRoot, "invalid root in call to nsTraversal constructor");

View File

@@ -54,15 +54,13 @@ class nsTraversal
public:
nsTraversal(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aExpandEntityReferences);
nsIDOMNodeFilter *aFilter);
virtual ~nsTraversal();
protected:
nsCOMPtr<nsINode> mRoot;
PRUint32 mWhatToShow;
nsCOMPtr<nsIDOMNodeFilter> mFilter;
bool mExpandEntityReferences;
bool mInAcceptNode;
/*

View File

@@ -58,9 +58,8 @@
nsTreeWalker::nsTreeWalker(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aExpandEntityReferences) :
nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
nsIDOMNodeFilter *aFilter) :
nsTraversal(aRoot, aWhatToShow, aFilter),
mCurrentNode(aRoot)
{
}
@@ -127,7 +126,7 @@ NS_IMETHODIMP nsTreeWalker::GetFilter(nsIDOMNodeFilter * *aFilter)
NS_IMETHODIMP
nsTreeWalker::GetExpandEntityReferences(bool *aExpandEntityReferences)
{
*aExpandEntityReferences = mExpandEntityReferences;
*aExpandEntityReferences = false;
return NS_OK;
}

View File

@@ -63,8 +63,7 @@ public:
nsTreeWalker(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
bool aExpandEntityReferences);
nsIDOMNodeFilter *aFilter);
virtual ~nsTreeWalker();
NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeWalker)

View File

@@ -542,6 +542,7 @@ _TEST_FILES2 = \
test_bug708620.html \
file_bug708620.html \
file_bug708620-2.html \
test_bug698384.html \
$(NULL)
_CHROME_FILES = \

View File

@@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=698384
-->
<head>
<title>Test for Bug 698384</title>
<script type="text/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"
type="text/javascript"></script>
<link rel="stylesheet" type="text/css"
href="/tests/SimpleTest/test.css" />
</head>
<body onload="runTests();">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=698384">
Mozilla Bug 698384</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script type="text/javascript">
/*
Checks to see if default parameter handling is correct when 0, 1
or 2 parameters are passed.
If one is only passed, aFilter should default to null
If none are passed, aFilter should be null and aWhatToShow should
be NodeFilter.SHOW_ALL
*/
SimpleTest.waitForExplicitFinish();
var content = $('content'),
ni;
content.innerHTML = ('<span id="A"><\/span><span id="B"><\/span>'
+ '<span id="C"><\/span>');
function runTests() {
// Test NodeIterator when no optional arguments are given
ni = document.createNodeIterator(content);
is(ni.whatToShow, NodeFilter.SHOW_ALL, "whatToShow should be " +
"NodeFilter.SHOW_ALL when both " +
" optionals are not given");
is(ni.filter, null, "filter should be defaulted to null when both " +
" optionals are not given");
// Test NodeIterator when first optional is passed
ni = document.createNodeIterator(content, NodeFilter.SHOW_ELEMENT);
is(ni.filter, null, "filter should be defaulted to null when only " +
" first argument is passed");
is(ni.whatToShow, NodeFilter.SHOW_ELEMENT, "whatToShow should " +
"properly be set to NodeFilter.SHOW_ELEMENT when whatToShow is " +
"provided and filter is not");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@@ -816,7 +816,7 @@ nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener)
}
#endif
nsJSContext::GarbageCollectNow();
nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS);
nsJSContext::CycleCollectNow(aListener);
return NS_OK;

View File

@@ -2272,7 +2272,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
newInnerWindow->mChromeEventHandler = mChromeEventHandler;
}
mContext->GC();
mContext->GC(js::gcreason::SET_NEW_DOCUMENT);
mContext->DidInitializeContext();
if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
@@ -2429,7 +2429,7 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
}
if (mContext) {
mContext->GC();
mContext->GC(js::gcreason::SET_DOC_SHELL);
mContext->FinalizeContext();
mContext = nsnull;
}

View File

@@ -43,6 +43,7 @@
#include "nsISupports.h"
#include "nsCOMPtr.h"
#include "nsIProgrammingLanguage.h"
#include "jsfriendapi.h"
#include "jspubtd.h"
class nsIScriptGlobalObject;
@@ -354,7 +355,7 @@ public:
*
* @return NS_OK if the method is successful
*/
virtual void GC() = 0;
virtual void GC(js::gcreason::Reason aReason) = 0;
/**
* Inform the context that a script was evaluated.

View File

@@ -203,7 +203,7 @@ nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
if (sGCOnMemoryPressure) {
nsJSContext::GarbageCollectNow(true);
nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking);
nsJSContext::CycleCollectNow();
}
return NS_OK;
@@ -1111,7 +1111,7 @@ nsJSContext::DestroyJSContext()
js_options_dot_str, this);
if (mGCOnDestruction) {
PokeGC();
PokeGC(js::gcreason::NSJSCONTEXT_DESTROY);
}
// Let xpconnect destroy the JSContext when it thinks the time is right.
@@ -3220,7 +3220,7 @@ nsJSContext::ScriptExecuted()
//static
void
nsJSContext::GarbageCollectNow(bool shrinkingGC)
nsJSContext::GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind)
{
NS_TIME_FUNCTION_MIN(1.0);
SAMPLE_LABEL("GC", "GarbageCollectNow");
@@ -3238,7 +3238,7 @@ nsJSContext::GarbageCollectNow(bool shrinkingGC)
sLoadingInProgress = false;
if (nsContentUtils::XPConnect()) {
nsContentUtils::XPConnect()->GarbageCollect(shrinkingGC);
nsContentUtils::XPConnect()->GarbageCollect(reason, gckind);
}
}
@@ -3276,7 +3276,7 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener)
// If we collected a substantial amount of cycles, poke the GC since more objects
// might be unreachable now.
if (sCCollectedWaitingForGC > 250) {
PokeGC();
PokeGC(js::gcreason::CC_WAITING);
}
PRTime now = PR_Now();
@@ -3315,7 +3315,8 @@ GCTimerFired(nsITimer *aTimer, void *aClosure)
{
NS_RELEASE(sGCTimer);
nsJSContext::GarbageCollectNow();
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason), nsGCNormal);
}
void
@@ -3359,12 +3360,12 @@ nsJSContext::LoadEnd()
// Its probably a good idea to GC soon since we have finished loading.
sLoadingInProgress = false;
PokeGC();
PokeGC(js::gcreason::LOAD_END);
}
// static
void
nsJSContext::PokeGC()
nsJSContext::PokeGC(js::gcreason::Reason aReason)
{
if (sGCTimer) {
// There's already a timer for GC'ing, just return
@@ -3380,7 +3381,7 @@ nsJSContext::PokeGC()
static bool first = true;
sGCTimer->InitWithFuncCallback(GCTimerFired, nsnull,
sGCTimer->InitWithFuncCallback(GCTimerFired, reinterpret_cast<void *>(aReason),
first
? NS_FIRST_GC_DELAY
: NS_GC_DELAY,
@@ -3473,9 +3474,9 @@ nsJSContext::KillCCTimer()
}
void
nsJSContext::GC()
nsJSContext::GC(js::gcreason::Reason aReason)
{
PokeGC();
PokeGC(aReason);
}
static void
@@ -3513,7 +3514,7 @@ DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
// probably a time of heavy activity and we want to delay
// the full GC, but we do want it to happen eventually.
if (comp) {
nsJSContext::PokeGC();
nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
// We poked the GC, so we can kill any pending CC here.
nsJSContext::KillCCTimer();

View File

@@ -41,10 +41,12 @@
#include "nsIScriptRuntime.h"
#include "nsCOMPtr.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "nsIObserver.h"
#include "nsIXPCScriptNotify.h"
#include "prtime.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIXPConnect.h"
class nsIXPConnectJSObjectHolder;
class nsRootedJSValueArray;
@@ -179,11 +181,11 @@ public:
static void LoadStart();
static void LoadEnd();
static void GarbageCollectNow(bool shrinkingGC = false);
static void GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind = nsGCNormal);
static void ShrinkGCBuffersNow();
static void CycleCollectNow(nsICycleCollectorListener *aListener = nsnull);
static void PokeGC();
static void PokeGC(js::gcreason::Reason aReason);
static void KillGCTimer();
static void PokeShrinkGCBuffers();
@@ -193,7 +195,7 @@ public:
static void MaybePokeCC();
static void KillCCTimer();
virtual void GC();
virtual void GC(js::gcreason::Reason aReason);
protected:
nsresult InitializeExternalClasses();

View File

@@ -66,7 +66,7 @@ interface nsIDOMLocation;
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
*/
[scriptable, uuid(5c3bff4d-ae7f-4c93-948c-519589672c30)]
[scriptable, uuid(d7cdd08e-1bfd-4bc3-9742-d66586781ee2)]
interface nsIDOMDocument : nsIDOMNode
{
readonly attribute nsIDOMDocumentType doctype;
@@ -118,16 +118,14 @@ interface nsIDOMDocument : nsIDOMNode
*/
nsIDOMRange createRange();
nsIDOMNodeIterator createNodeIterator(in nsIDOMNode root,
in unsigned long whatToShow,
in nsIDOMNodeFilter filter,
in boolean entityReferenceExpansion)
raises(DOMException);
nsIDOMTreeWalker createTreeWalker(in nsIDOMNode root,
in unsigned long whatToShow,
in nsIDOMNodeFilter filter,
in boolean entityReferenceExpansion)
raises(DOMException);
[optional_argc] nsIDOMNodeIterator createNodeIterator(in nsIDOMNode root,
[optional] in unsigned long whatToShow,
[optional] in nsIDOMNodeFilter filter)
raises(DOMException);
[optional_argc] nsIDOMTreeWalker createTreeWalker(in nsIDOMNode root,
[optional] in unsigned long whatToShow,
[optional] in nsIDOMNodeFilter filter)
raises(DOMException);
nsIDOMEvent createEvent(in DOMString eventType)
raises(DOMException);

View File

@@ -1,61 +0,0 @@
/* -*- Mode: IDL; 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 this file as it was released on May 1 2001.
*
* The Initial Developer of the Original Code is
* Jonas Sicking.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <sicking@bigfoot.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
interface nsIDOMNodeIterator;
interface nsIDOMNodeFilter;
interface nsIDOMTreeWalker;
[scriptable, uuid(13f236c0-47f8-11d5-b6a3-009027446e84)]
// Introduced in DOM Level 2:
interface nsIDOMDocumentTraversal : nsISupports
{
nsIDOMNodeIterator createNodeIterator(in nsIDOMNode root,
in unsigned long whatToShow,
in nsIDOMNodeFilter filter,
in boolean entityReferenceExpansion)
raises(DOMException);
nsIDOMTreeWalker createTreeWalker(in nsIDOMNode root,
in unsigned long whatToShow,
in nsIDOMNodeFilter filter,
in boolean entityReferenceExpansion)
raises(DOMException);
};

View File

@@ -44,7 +44,7 @@ interface nsIDOMNodeFilter;
[scriptable, uuid(5af83f50-c8d5-4824-be29-1aa9d640bacb)]
// Introduced in DOM Level 2:
// Introduced in DOM Level 2, updated to DOM Level 4:
interface nsIDOMNodeIterator : nsISupports
{
readonly attribute nsIDOMNode root;

View File

@@ -800,14 +800,14 @@ ContentChild::GetIndexedDBPath()
bool
ContentChild::RecvGarbageCollect()
{
nsJSContext::GarbageCollectNow();
nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
return true;
}
bool
ContentChild::RecvCycleCollect()
{
nsJSContext::GarbageCollectNow();
nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
nsJSContext::CycleCollectNow();
return true;
}

View File

@@ -634,8 +634,6 @@ nsJSONListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
nsIInputStream *aStream,
PRUint32 aOffset, PRUint32 aLength)
{
PRUint32 contentLength;
aStream->Available(&contentLength);
nsresult rv = NS_OK;
if (mNeedsConverter && mSniffBuffer.Length() < 4) {

View File

@@ -3794,10 +3794,10 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
AssertIsOnWorkerThread();
if (aShrinking) {
JS_ShrinkingGC(aCx);
js::ShrinkingGC(aCx, js::gcreason::DOM_WORKER);
}
else {
JS_GC(aCx);
js::GCForReason(aCx, js::gcreason::DOM_WORKER);
}
if (aCollectChildren) {

View File

@@ -486,7 +486,7 @@ GetTextNode(nsISelection *selection, nsEditor *editor) {
// if node is null, return it to indicate there's no text
NS_ENSURE_TRUE(node, nsnull);
// This should be the root node, walk the tree looking for text nodes
nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nsnull, true);
nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nsnull);
while (!editor->IsTextNode(selNode)) {
if (NS_FAILED(res = iter.NextNode(getter_AddRefs(selNode))) || !selNode) {
return nsnull;

View File

@@ -38,6 +38,7 @@
* ***** END LICENSE BLOCK ***** */
#include <stdio.h>
#include <ctype.h>
#include "jscntxt.h"
#include "jscrashformat.h"
@@ -52,6 +53,22 @@
namespace js {
namespace gcstats {
static const char *
ExplainReason(gcreason::Reason reason)
{
switch (reason) {
#define SWITCH_REASON(name) \
case gcreason::name: \
return #name;
GCREASONS(SWITCH_REASON)
default:
JS_NOT_REACHED("bad GC reason");
return "?";
#undef SWITCH_REASON
}
}
Statistics::ColumnInfo::ColumnInfo(const char *title, double t, double total)
: title(title)
{
@@ -117,8 +134,8 @@ Statistics::makeTable(ColumnInfo *cols)
}
Statistics::Statistics(JSRuntime *rt)
: runtime(rt)
, triggerReason(PUBLIC_API) //dummy reason to satisfy makeTable
: runtime(rt),
triggerReason(gcreason::NO_REASON)
{
PodArrayZero(counts);
PodArrayZero(totals);
@@ -178,7 +195,7 @@ struct GCCrashData
};
void
Statistics::beginGC(JSCompartment *comp, Reason reason)
Statistics::beginGC(JSCompartment *comp, gcreason::Reason reason)
{
compartment = comp;
@@ -276,7 +293,6 @@ Statistics::endGC()
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
(*cb)(JS_TELEMETRY_GC_REASON, triggerReason);
(*cb)(JS_TELEMETRY_GC_IS_COMPARTMENTAL, compartment ? 1 : 0);
(*cb)(JS_TELEMETRY_GC_IS_SHAPE_REGEN, 0);
(*cb)(JS_TELEMETRY_GC_MS, t(PHASE_GC));
(*cb)(JS_TELEMETRY_GC_MARK_MS, t(PHASE_MARK));
(*cb)(JS_TELEMETRY_GC_SWEEP_MS, t(PHASE_SWEEP));

View File

@@ -42,6 +42,7 @@
#include <string.h>
#include "jsfriendapi.h"
#include "jspubtd.h"
#include "jsutil.h"
@@ -50,32 +51,6 @@ struct JSCompartment;
namespace js {
namespace gcstats {
enum Reason {
PUBLIC_API,
MAYBEGC,
LASTCONTEXT,
DESTROYCONTEXT,
LASTDITCH,
TOOMUCHMALLOC,
ALLOCTRIGGER,
CHUNK,
SHAPE,
REFILL
};
static const int NUM_REASONS = REFILL + 1;
static inline const char *
ExplainReason(Reason r)
{
static const char *strs[] = {" API", "Maybe", "LastC", "DestC", "LastD",
"Mallc", "Alloc", "Chunk", "Shape", "Refil"};
JS_ASSERT(strcmp(strs[SHAPE], "Shape") == 0 &&
sizeof(strs) / sizeof(strs[0]) == NUM_REASONS);
return strs[r];
}
enum Phase {
PHASE_GC,
PHASE_MARK,
@@ -103,7 +78,7 @@ struct Statistics {
Statistics(JSRuntime *rt);
~Statistics();
void beginGC(JSCompartment *comp, Reason reason);
void beginGC(JSCompartment *comp, gcreason::Reason reason);
void endGC();
void beginPhase(Phase phase);
@@ -122,7 +97,7 @@ struct Statistics {
FILE *fp;
bool fullFormat;
Reason triggerReason;
gcreason::Reason triggerReason;
JSCompartment *compartment;
uint64_t phaseStarts[PHASE_LIMIT];
@@ -140,8 +115,8 @@ struct Statistics {
struct ColumnInfo {
const char *title;
char str[12];
char totalStr[12];
char str[32];
char totalStr[32];
int width;
ColumnInfo() {}
@@ -155,7 +130,8 @@ struct Statistics {
};
struct AutoGC {
AutoGC(Statistics &stats, JSCompartment *comp, Reason reason JS_GUARD_OBJECT_NOTIFIER_PARAM)
AutoGC(Statistics &stats, JSCompartment *comp, gcreason::Reason reason
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginGC(comp, reason); }
~AutoGC() { stats.endGC(); }

View File

@@ -0,0 +1,21 @@
function f(arr, b) {
var res = "";
var a;
if (b)
a = arr;
for (var i=100; i>-200; i--) {
if (i in a) {
res += i;
}
}
return res;
}
assertEq(f([1, , 2, 3], true), "320");
try {
f([1, , 2, 3], false);
assertEq(0, 1);
} catch(e) {
assertEq(e instanceof TypeError, true);
}

View File

@@ -735,6 +735,7 @@ JSRuntime::JSRuntime()
gcIsNeeded(0),
gcWeakMapList(NULL),
gcStats(thisFromCtor()),
gcTriggerReason(gcreason::NO_REASON),
gcTriggerCompartment(NULL),
gcCurrentCompartment(NULL),
gcCheckCompartment(NULL),
@@ -2857,7 +2858,7 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
JS_ASSERT(comp != cx->runtime->atomsCompartment);
js::gc::VerifyBarriers(cx, true);
js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API);
js_GC(cx, comp, GC_NORMAL, gcreason::API);
}
JS_PUBLIC_API(void)

View File

@@ -323,13 +323,13 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
#endif
if (last) {
js_GC(cx, NULL, GC_NORMAL, gcstats::LASTCONTEXT);
js_GC(cx, NULL, GC_NORMAL, gcreason::LAST_CONTEXT);
/* Take the runtime down, now that it has no contexts or atoms. */
JS_LOCK_GC(rt);
} else {
if (mode == JSDCM_FORCE_GC)
js_GC(cx, NULL, GC_NORMAL, gcstats::DESTROYCONTEXT);
js_GC(cx, NULL, GC_NORMAL, gcreason::DESTROY_CONTEXT);
else if (mode == JSDCM_MAYBE_GC)
JS_MaybeGC(cx);
@@ -1179,7 +1179,7 @@ JSContext::runningWithTrustedPrincipals() const
JS_FRIEND_API(void)
JSRuntime::onTooMuchMalloc()
{
TriggerGC(this, gcstats::TOOMUCHMALLOC);
TriggerGC(this, gcreason::TOO_MUCH_MALLOC);
}
JS_FRIEND_API(void *)

View File

@@ -318,7 +318,7 @@ struct JSRuntime
js::gcstats::Statistics gcStats;
/* The reason that an interrupt-triggered GC should be called. */
js::gcstats::Reason gcTriggerReason;
js::gcreason::Reason gcTriggerReason;
/* Pre-allocated space for the GC mark stack. */
uintptr_t gcMarkStackArray[js::MARK_STACK_LENGTH];

View File

@@ -128,9 +128,15 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj
}
JS_FRIEND_API(void)
JS_ShrinkingGC(JSContext *cx)
js::GCForReason(JSContext *cx, gcreason::Reason reason)
{
js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
js_GC(cx, NULL, GC_NORMAL, reason);
}
JS_FRIEND_API(void)
js::ShrinkingGC(JSContext *cx, gcreason::Reason reason)
{
js_GC(cx, NULL, GC_SHRINK, reason);
}
JS_FRIEND_API(void)

View File

@@ -72,9 +72,6 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj
extern JS_FRIEND_API(uint32_t)
JS_ObjectCountDynamicSlots(JSObject *obj);
extern JS_FRIEND_API(void)
JS_ShrinkingGC(JSContext *cx);
extern JS_FRIEND_API(void)
JS_ShrinkGCBuffers(JSRuntime *rt);
@@ -101,7 +98,6 @@ JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape);
enum {
JS_TELEMETRY_GC_REASON,
JS_TELEMETRY_GC_IS_COMPARTMENTAL,
JS_TELEMETRY_GC_IS_SHAPE_REGEN,
JS_TELEMETRY_GC_MS,
JS_TELEMETRY_GC_MARK_MS,
JS_TELEMETRY_GC_SWEEP_MS
@@ -572,6 +568,56 @@ GetRuntimeCompartments(JSRuntime *rt);
extern JS_FRIEND_API(size_t)
SizeOfJSContext();
#define GCREASONS(D) \
/* Reasons internal to the JS engine */ \
D(API) \
D(MAYBEGC) \
D(LAST_CONTEXT) \
D(DESTROY_CONTEXT) \
D(LAST_DITCH) \
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
D(UNUSED1) /* was CHUNK */ \
D(UNUSED2) /* was SHAPE */ \
D(UNUSED3) /* was REFILL */ \
\
/* Reasons from Firefox */ \
D(DOM_WINDOW_UTILS) \
D(COMPONENT_UTILS) \
D(MEM_PRESSURE) \
D(CC_WAITING) \
D(CC_FORCED) \
D(LOAD_END) \
D(POST_COMPARTMENT) \
D(PAGE_HIDE) \
D(NSJSCONTEXT_DESTROY) \
D(SET_NEW_DOCUMENT) \
D(SET_DOC_SHELL) \
D(DOM_UTILS) \
D(DOM_IPC) \
D(DOM_WORKER) \
D(INTER_SLICE_GC) \
D(REFRESH_FRAME)
namespace gcreason {
/* GCReasons will end up looking like JSGC_MAYBEGC */
enum Reason {
#define MAKE_REASON(name) name,
GCREASONS(MAKE_REASON)
#undef MAKE_REASON
NO_REASON,
NUM_REASONS
};
} /* namespace gcreason */
extern JS_FRIEND_API(void)
GCForReason(JSContext *cx, gcreason::Reason reason);
extern JS_FRIEND_API(void)
ShrinkingGC(JSContext *cx, gcreason::Reason reason);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeeded(JSRuntime *rt);

View File

@@ -742,7 +742,7 @@ Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
rt->gcBytes += ArenaSize;
comp->gcBytes += ArenaSize;
if (comp->gcBytes >= comp->gcTriggerBytes)
TriggerCompartmentGC(comp, gcstats::ALLOCTRIGGER);
TriggerCompartmentGC(comp, gcreason::ALLOC_TRIGGER);
return aheader;
}
@@ -1647,7 +1647,7 @@ RunLastDitchGC(JSContext *cx)
/* The last ditch GC preserves all atoms. */
AutoKeepAtoms keep(rt);
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcstats::LASTDITCH);
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcreason::LAST_DITCH);
}
/* static */ void *
@@ -2137,7 +2137,7 @@ MarkRuntime(JSTracer *trc)
}
void
TriggerGC(JSRuntime *rt, gcstats::Reason reason)
TriggerGC(JSRuntime *rt, gcreason::Reason reason)
{
JS_ASSERT(rt->onOwnerThread());
@@ -2152,7 +2152,7 @@ TriggerGC(JSRuntime *rt, gcstats::Reason reason)
}
void
TriggerCompartmentGC(JSCompartment *comp, gcstats::Reason reason)
TriggerCompartmentGC(JSCompartment *comp, gcreason::Reason reason)
{
JSRuntime *rt = comp->rt;
JS_ASSERT(!rt->gcRunning);
@@ -2198,18 +2198,18 @@ MaybeGC(JSContext *cx)
JS_ASSERT(rt->onOwnerThread());
if (rt->gcZeal()) {
js_GC(cx, NULL, GC_NORMAL, gcstats::MAYBEGC);
js_GC(cx, NULL, GC_NORMAL, gcreason::MAYBEGC);
return;
}
JSCompartment *comp = cx->compartment;
if (rt->gcIsNeeded) {
js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcreason::MAYBEGC);
return;
}
if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4)) {
js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcreason::MAYBEGC);
return;
}
@@ -2223,7 +2223,7 @@ MaybeGC(JSContext *cx)
if (rt->gcChunkAllocationSinceLastGC ||
rt->gcNumArenasFreeCommitted > FreeCommittedArenasThreshold)
{
js_GC(cx, NULL, GC_SHRINK, gcstats::MAYBEGC);
js_GC(cx, NULL, GC_SHRINK, gcreason::MAYBEGC);
} else {
rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN;
}
@@ -2966,7 +2966,7 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
}
void
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Reason reason)
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcreason::Reason reason)
{
JSRuntime *rt = cx->runtime;
JS_AbortIfWrongThread(rt);

View File

@@ -1382,11 +1382,11 @@ MarkContext(JSTracer *trc, JSContext *acx);
/* Must be called with GC lock taken. */
extern void
TriggerGC(JSRuntime *rt, js::gcstats::Reason reason);
TriggerGC(JSRuntime *rt, js::gcreason::Reason reason);
/* Must be called with GC lock taken. */
extern void
TriggerCompartmentGC(JSCompartment *comp, js::gcstats::Reason reason);
TriggerCompartmentGC(JSCompartment *comp, js::gcreason::Reason reason);
extern void
MaybeGC(JSContext *cx);
@@ -1409,7 +1409,7 @@ typedef enum JSGCInvocationKind {
/* Pass NULL for |comp| to get a full GC. */
extern void
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcstats::Reason r);
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcreason::Reason r);
namespace js {

View File

@@ -791,6 +791,20 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
return branch32(cond, extent, key.reg());
}
Jump guardElementNotHole(RegisterID elements, const Int32Key &key) {
Jump jmp;
if (key.isConstant()) {
Address slot(elements, key.index() * sizeof(Value));
jmp = guardNotHole(slot);
} else {
BaseIndex slot(elements, key.reg(), JSVAL_SCALE);
jmp = guardNotHole(slot);
}
return jmp;
}
// Load a jsval from an array slot, given a key. |objReg| is clobbered.
FastArrayLoadFails fastArrayLoad(RegisterID objReg, const Int32Key &key,
RegisterID typeReg, RegisterID dataReg) {

View File

@@ -2966,11 +2966,7 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_IN)
{
prepareStubCall(Uses(2));
INLINE_STUBCALL(stubs::In, REJOIN_PUSH_BOOLEAN);
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
jsop_in();
}
END_CASE(JSOP_IN)
@@ -7448,6 +7444,76 @@ mjit::Compiler::jsop_toid()
stubcc.rejoin(Changes(1));
}
void
mjit::Compiler::jsop_in()
{
FrameEntry *obj = frame.peek(-1);
FrameEntry *id = frame.peek(-2);
if (cx->typeInferenceEnabled() && id->isType(JSVAL_TYPE_INT32)) {
types::TypeSet *types = analysis->poppedTypes(PC, 0);
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript))
{
bool isPacked = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
if (!obj->isTypeKnown()) {
Jump guard = frame.testObject(Assembler::NotEqual, obj);
stubcc.linkExit(guard, Uses(2));
}
RegisterID dataReg = frame.copyDataIntoReg(obj);
Int32Key key = id->isConstant()
? Int32Key::FromConstant(id->getValue().toInt32())
: Int32Key::FromRegister(frame.tempRegForData(id));
masm.loadPtr(Address(dataReg, JSObject::offsetOfElements()), dataReg);
// Guard on the array's initialized length.
Jump initlenGuard = masm.guardArrayExtent(ObjectElements::offsetOfInitializedLength(),
dataReg, key, Assembler::BelowOrEqual);
// Guard to make sure we don't have a hole. Skip it if the array is packed.
MaybeJump holeCheck;
if (!isPacked)
holeCheck = masm.guardElementNotHole(dataReg, key);
masm.move(Imm32(1), dataReg);
Jump done = masm.jump();
Label falseBranch = masm.label();
initlenGuard.linkTo(falseBranch, &masm);
if (!isPacked)
holeCheck.getJump().linkTo(falseBranch, &masm);
masm.move(Imm32(0), dataReg);
done.linkTo(masm.label(), &masm);
stubcc.leave();
OOL_STUBCALL_USES(stubs::In, REJOIN_PUSH_BOOLEAN, Uses(2));
frame.popn(2);
if (dataReg != Registers::ReturnReg)
stubcc.masm.move(Registers::ReturnReg, dataReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, dataReg);
stubcc.rejoin(Changes(2));
return;
}
}
prepareStubCall(Uses(2));
INLINE_STUBCALL(stubs::In, REJOIN_PUSH_BOOLEAN);
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
}
/*
* For any locals or args which we know to be integers but are treated as
* doubles by the type inference, convert to double. These will be assumed to be

View File

@@ -753,6 +753,7 @@ private:
CompileStatus jsop_equality_obj_obj(JSOp op, jsbytecode *target, JSOp fused);
bool jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
void jsop_pos();
void jsop_in();
static inline Assembler::Condition
GetCompareCondition(JSOp op, JSOp fused)

View File

@@ -390,9 +390,15 @@ interface nsIXPCFunctionThisTranslator : nsISupports
#define NS_XPCONNECT_CID \
{ 0xcb6593e0, 0xf9b2, 0x11d2, \
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
enum nsGCType {
nsGCNormal,
nsGCShrinking,
nsGCIncremental
};
%}
[uuid(241e6db3-e018-4d99-b976-c782a05f9c77)]
[uuid(686bb1d0-4711-11e1-b86c-0800200c9a66)]
interface nsIXPConnect : nsISupports
{
%{ C++
@@ -723,8 +729,10 @@ interface nsIXPConnect : nsISupports
/**
* Trigger a JS garbage collection.
* Use a js::gcreason::Reason from jsfriendapi.h for the kind.
* Use the nsGCType enum for the kind.
*/
void GarbageCollect(in boolean shrinkingGC);
void GarbageCollect(in PRUint32 reason, in PRUint32 kind);
/**
* Define quick stubs on the given object, @a proto.

View File

@@ -3600,7 +3600,7 @@ nsXPCComponents_Utils::GetWeakReference(const JS::Value &object, JSContext *cx,
NS_IMETHODIMP
nsXPCComponents_Utils::ForceGC(JSContext *cx)
{
JS_GC(cx);
js::GCForReason(cx, js::gcreason::COMPONENT_UTILS);
return NS_OK;
}
@@ -3608,7 +3608,7 @@ nsXPCComponents_Utils::ForceGC(JSContext *cx)
NS_IMETHODIMP
nsXPCComponents_Utils::ForceShrinkingGC(JSContext *cx)
{
JS_ShrinkingGC(cx);
js::ShrinkingGC(cx, js::gcreason::COMPONENT_UTILS);
return NS_OK;
}
@@ -3636,9 +3636,9 @@ class PreciseGCRunnable : public nsRunnable
}
if (mShrinking)
JS_ShrinkingGC(mCx);
js::ShrinkingGC(mCx, js::gcreason::COMPONENT_UTILS);
else
JS_GC(mCx);
js::GCForReason(mCx, js::gcreason::COMPONENT_UTILS);
mCallback->Callback();
return NS_OK;

View File

@@ -1870,9 +1870,6 @@ AccumulateTelemetryCallback(int id, uint32_t sample)
case JS_TELEMETRY_GC_IS_COMPARTMENTAL:
Telemetry::Accumulate(Telemetry::GC_IS_COMPARTMENTAL, sample);
break;
case JS_TELEMETRY_GC_IS_SHAPE_REGEN:
Telemetry::Accumulate(Telemetry::GC_IS_SHAPE_REGEN, sample);
break;
case JS_TELEMETRY_GC_MS:
Telemetry::Accumulate(Telemetry::GC_MS, sample);
break;

View File

@@ -365,7 +365,7 @@ nsXPConnect::NeedCollect()
}
void
nsXPConnect::Collect(bool shrinkingGC)
nsXPConnect::Collect(PRUint32 reason, PRUint32 kind)
{
// We're dividing JS objects into 2 categories:
//
@@ -424,16 +424,20 @@ nsXPConnect::Collect(bool shrinkingGC)
// XPCCallContext::Init we disable the conservative scanner if that call
// has started the request on this thread.
js::AutoSkipConservativeScan ascs(cx);
if (shrinkingGC)
JS_ShrinkingGC(cx);
else
JS_GC(cx);
MOZ_ASSERT(reason < js::gcreason::NUM_REASONS);
js::gcreason::Reason gcreason = (js::gcreason::Reason)reason;
if (kind == nsGCShrinking) {
js::ShrinkingGC(cx, gcreason);
} else {
MOZ_ASSERT(kind == nsGCNormal);
js::GCForReason(cx, gcreason);
}
}
NS_IMETHODIMP
nsXPConnect::GarbageCollect(bool shrinkingGC)
nsXPConnect::GarbageCollect(PRUint32 reason, PRUint32 kind)
{
Collect(shrinkingGC);
Collect(reason, kind);
return NS_OK;
}

View File

@@ -549,7 +549,7 @@ public:
virtual nsresult FinishCycleCollection();
virtual nsCycleCollectionParticipant *ToParticipant(void *p);
virtual bool NeedCollect();
virtual void Collect(bool shrinkingGC=false);
virtual void Collect(PRUint32 reason, PRUint32 kind);
#ifdef DEBUG_CC
virtual void PrintAllReferencesTo(void *p);
#endif

View File

@@ -198,6 +198,8 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
#include "mozilla/dom/Element.h"
#include "jsfriendapi.h"
using namespace mozilla;
#ifdef NS_DEBUG
@@ -1287,7 +1289,7 @@ DocumentViewerImpl::PageHide(bool aIsUnload)
if (aIsUnload) {
// Poke the GC. The window might be collectable garbage now.
nsJSContext::PokeGC();
nsJSContext::PokeGC(js::gcreason::PAGE_HIDE);
// if Destroy() was called during OnPageHide(), mDocument is nsnull.
NS_ENSURE_STATE(mDocument);

View File

@@ -310,7 +310,7 @@ nsContentDLF::CreateInstance(const char* aCommand,
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if(pluginHost &&
NS_SUCCEEDED(pluginHost->IsPluginEnabledForType(aContentType))) {
NS_SUCCEEDED(pluginHost->IsPluginEnabledForType(aContentType, true))) {
return CreateDocument(aCommand,
aChannel, aLoadGroup,
aContainer, kPluginDocumentCID,

View File

@@ -405,6 +405,11 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
ExpandableListView exList = (ExpandableListView)list;
int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
// Check if long tap is on a header row
if (groupPosition < 0 || childPosition < 0)
return;
selectedItem = exList.getExpandableListAdapter().getChild(groupPosition, childPosition);
Map map = (Map)selectedItem;

View File

@@ -52,6 +52,9 @@ SYNC_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/java-sources.mn | t
SYNC_PP_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/preprocess-sources.mn | tr '\n' ' ';)
SYNC_THIRDPARTY_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/java-third-party-sources.mn | tr '\n' ' ';)
SYNC_RES_DRAWABLE=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-resources.mn | tr '\n' ' ';)
SYNC_RES_DRAWABLE_LDPI=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-ldpi-resources.mn | tr '\n' ' ';)
SYNC_RES_DRAWABLE_MDPI=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-mdpi-resources.mn | tr '\n' ' ';)
SYNC_RES_DRAWABLE_HDPI=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-hdpi-resources.mn | tr '\n' ' ';)
SYNC_RES_LAYOUT=$(shell cat $(topsrcdir)/mobile/android/sync/android-layout-resources.mn | tr '\n' ' ';)
SYNC_RES_VALUES=$(shell cat $(topsrcdir)/mobile/android/sync/android-values-resources.mn | tr '\n' ' ';)
SYNC_RES_XML=res/xml/sync_authenticator.xml res/xml/sync_options.xml
@@ -143,7 +146,6 @@ FENNEC_PP_JAVA_FILES = \
db/BrowserContract.java \
db/BrowserProvider.java \
SmsManager.java \
SyncPreference.java \
$(NULL)
@@ -539,6 +541,9 @@ RES_DIRS= \
res/xml \
res/anim \
res/drawable-nodpi \
res/drawable-ldpi \
res/drawable-mdpi \
res/drawable-hdpi \
res/drawable-mdpi-v8 \
res/drawable-hdpi-v8 \
res/drawable-mdpi-v9 \
@@ -576,7 +581,10 @@ $(PP_RES_XML): $(subst res/,$(srcdir)/resources/, $(PP_RES_XML).in)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
AndroidManifest.xml $(FENNEC_PP_JAVA_FILES) $(SYNC_PP_JAVA_FILES) package-name.txt: % : %.in Makefile.in
# AndroidManifest.xml includes these files, so they need to be marked as dependencies.
SYNC_MANIFEST_FRAGMENTS = $(wildcard $(topsrcdir)/mobile/android/sync/manifests/*.in)
AndroidManifest.xml $(FENNEC_PP_JAVA_FILES) $(SYNC_PP_JAVA_FILES) package-name.txt: % : %.in Makefile.in $(SYNC_MANIFEST_FRAGMENTS)
mkdir -p db sync/repositories/android
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
@@ -594,6 +602,21 @@ $(RES_DRAWABLE): $(addprefix $(topsrcdir)/,$(MOZ_ANDROID_DRAWABLES))
$(NSINSTALL) -D res/drawable
$(NSINSTALL) $^ res/drawable/
RES_DRAWABLE_LDPI = $(addprefix res/drawable-ldpi/,$(notdir $(SYNC_RES_DRAWABLE_LDPI)))
$(RES_DRAWABLE_LDPI): $(addprefix $(topsrcdir)/,$(SYNC_RES_DRAWABLE_LDPI))
$(NSINSTALL) -D res/drawable-ldpi
$(NSINSTALL) $^ res/drawable-ldpi/
RES_DRAWABLE_MDPI = $(addprefix res/drawable-mdpi/,$(notdir $(SYNC_RES_DRAWABLE_MDPI)))
$(RES_DRAWABLE_MDPI): $(addprefix $(topsrcdir)/,$(SYNC_RES_DRAWABLE_MDPI))
$(NSINSTALL) -D res/drawable-mdpi
$(NSINSTALL) $^ res/drawable-mdpi/
RES_DRAWABLE_HDPI = $(addprefix res/drawable-hdpi/,$(notdir $(SYNC_RES_DRAWABLE_HDPI)))
$(RES_DRAWABLE_HDPI): $(addprefix $(topsrcdir)/,$(SYNC_RES_DRAWABLE_HDPI))
$(NSINSTALL) -D res/drawable-hdpi
$(NSINSTALL) $^ res/drawable-hdpi/
res/values/defaults.xml: $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/res/values/defaults.xml
$(NSINSTALL) -D res/values
$(NSINSTALL) $^ res/values
@@ -607,10 +630,10 @@ $(RESOURCES): $(RES_DIRS) $(subst res/,$(srcdir)/resources/,$(RESOURCES))
$(NSINSTALL) $(subst res/,$(srcdir)/resources/,$@) $(dir $@)
R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(PP_RES_XML) res/values/defaults.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
gecko.ap_: AndroidManifest.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
gecko.ap_: AndroidManifest.xml res/drawable/sync_icon.png res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
libs:: classes.dex package-name.txt

View File

@@ -1,81 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* ***** 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 Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009-2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Nicholson <bnicholson@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* 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 ***** */
#filter substitution
package org.mozilla.gecko;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
class SyncPreference extends Preference {
private static final String FEEDS_PACKAGE_NAME = "com.android.providers.subscribedfeeds";
private static final String ACCOUNT_SYNC_CLASS_NAME = "com.android.settings.AccountSyncSettings";
private static final String ACCOUNT_KEY = "account";
private static final String FENNEC_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
private static final String FENNEC_SYNC_CLASS_NAME = "org.mozilla.gecko.sync.setup.activities.SetupSyncActivity";
private static final String FENNEC_ACCOUNT_TYPE = "org.mozilla.firefox_sync";
private Context mContext;
public SyncPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
@Override
protected void onClick() {
Intent intent = new Intent(Intent.ACTION_MAIN);
Account[] accounts = AccountManager.get(mContext).getAccountsByType(FENNEC_ACCOUNT_TYPE);
if (accounts.length > 0) {
// show sync account
// we assume there's exactly one sync account. see bugs 716906 and 710407.
intent.setComponent(new ComponentName(FEEDS_PACKAGE_NAME, ACCOUNT_SYNC_CLASS_NAME));
Account account = accounts[0];
intent.putExtra(ACCOUNT_KEY, account);
} else {
// show sync setup
intent.setComponent(new ComponentName(FENNEC_PACKAGE_NAME, FENNEC_SYNC_CLASS_NAME));
}
mContext.startActivity(intent);
}
}

View File

@@ -182,6 +182,7 @@ public class BrowserProvider extends ContentProvider {
// Images
URI_MATCHER.addURI(BrowserContract.AUTHORITY, "images", IMAGES);
URI_MATCHER.addURI(BrowserContract.AUTHORITY, "images/#", IMAGES_ID);
map = IMAGES_PROJECTION_MAP;
map.put(Images._ID, Images._ID);

View File

@@ -69,7 +69,6 @@
<!ENTITY pref_font_size_large "Large">
<!ENTITY pref_font_size_xlarge "Extra Large">
<!ENTITY pref_use_master_password "Use master password">
<!ENTITY pref_sync "Sync">
<!ENTITY quit "Quit">

View File

@@ -6,13 +6,18 @@
<!-- Main titles. -->
<!ENTITY sync.app.name.label '&syncBrand.fullName.label;'>
<!ENTITY sync.title.connect.label 'Connect to &syncBrand.shortName.label;'>
<!ENTITY sync.title.adddevice.label 'Add a &syncBrand.fullName.label; Account'>
<!ENTITY sync.title.pair.label 'Pair a Device'>
<!-- J-PAKE Key Screen -->
<!ENTITY sync.subtitle.connect.label 'To activate your new device, select “Set up &syncBrand.shortName.label;” on the device.'>
<!ENTITY sync.subtitle.header.label 'Enter this code on your computer'>
<!ENTITY sync.subtitle.connectlocation.label 'Select “&sync.title.pair.label;” in the &syncBrand.shortName.label; section of your desktop Firefox options.'>
<!ENTITY sync.subtitle.pair.label 'To activate, select “Pair a device” on your other device.'>
<!ENTITY sync.pin.default.label '...\n...\n...\n'>
<!ENTITY sync.pin.oneline.label '...'>
<!ENTITY sync.link.show.label 'Show me how.'>
<!ENTITY sync.link.advancedsetup.label 'Advanced setup...'>
<!ENTITY sync.link.nodevice.label 'I don\&apos;t have the device with me…'>
<!-- J-PAKE Waiting Screen -->

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#000000" />
<stroke android:width="1dp" android:color="#FFFFFF" />
<padding
android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp" />
</shape>

View File

@@ -1,23 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/account_top"
style="@style/SyncTop">
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_connect" />
</LinearLayout>
<ScrollView
style="@style/SyncLayout" >
android:id="@+id/account_content"
style="@style/SyncLayout"
android:layout_below="@id/account_top"
android:layout_above="@+id/account_bottom">
<LinearLayout
style="@style/SyncLayout" >
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_connect" />
<View
style="@style/SyncViewLine" />
style="@style/SyncLayout.Vertical"
android:padding="20dp" >
<TextView
style="@style/SyncTextItem"
android:text="@string/sync_subtitle_account" />
android:text="@string/sync_subtitle_account"
android:layout_marginBottom="10dp" />
<EditText android:id="@+id/usernameInput"
style="@style/SyncEditItem"
@@ -43,26 +51,26 @@
style="@style/SyncEditItem"
android:visibility="gone"
android:hint="@string/sync_input_server" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button
style="@style/SyncButtonCommon"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
<Button
android:id="@+id/accountConnectButton"
style="@style/SyncButtonCommon"
android:onClick="connectClickHandler"
android:clickable="false"
android:enabled="false"
android:text="@string/sync_button_connect" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</TableLayout>
<LinearLayout
android:id="@id/account_bottom"
style="@style/SyncBottom"
android:orientation="horizontal" >
<Button
style="@style/SyncButton"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
<Button
style="@style/SyncButton"
android:id="@+id/accountConnectButton"
android:onClick="connectClickHandler"
android:clickable="false"
android:enabled="false"
android:text="@string/sync_button_connect" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,65 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/setup_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
android:id="@+id/setup_title"
style="@style/SyncTextTitle"
android:text="@string/sync_title_connect" />
</LinearLayout>
<ScrollView
style="@style/SyncLayout" >
style="@style/SyncLayout"
android:fillViewport="true"
android:layout_below="@id/setup_top"
android:layout_above="@+id/setup_bottom" >
<LinearLayout
style="@style/SyncLayout" >
<RelativeLayout
style="@style/SyncLayout.Vertical"
android:layout_height="fill_parent"
android:padding="15dp" >
<TextView
android:id="@+id/setup_title"
style="@style/SyncTextTitle"
android:text="@string/sync_title_connect" />
<View
android:layout_width="wrap_content"
android:layout_height="2dp"
android:background="#FFFFFF" />
android:id="@+id/setup_header"
style="@style/SyncTextItem"
android:gravity="left"
android:layout_marginTop="15dp"
android:text="@string/sync_subtitle_header"
android:textStyle="bold" />
<TextView
android:id="@+id/setup_subtitle"
style="@style/SyncTextItem"
android:layout_below="@id/setup_header"
android:gravity="left"
android:layout_marginTop="2dp"
android:text="@string/sync_subtitle_connect" />
<TextView
android:id="@+id/setup_subtitle"
style="@style/SyncTextItem"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="@string/sync_subtitle_pair" />
<TextView
style="@style/SyncLinkItem"
android:onClick="showClickHandler"
android:text="@string/sync_link_show" />
android:id="@+id/setup_showme"
style="@style/SyncLinkItem"
android:layout_below="@id/setup_subtitle"
android:layout_marginTop="2dp"
android:onClick="showClickHandler"
android:text="@string/sync_link_show" />
<LinearLayout
style="@style/SyncTextItem"
android:orientation="vertical" >
<TextView
android:id="@+id/text_pin"
style="@style/SyncTextItem"
android:text="@string/sync_pin_default"
android:textSize="40dp" />
style="@style/SyncLayout"
android:layout_below="@id/setup_showme"
android:paddingTop="30dp"
android:paddingLeft="-15dp"
android:orientation="vertical" >
<TextView
android:id="@+id/text_pin1"
style="@style/SyncPinText" />
<TextView
android:id="@+id/text_pin2"
style="@style/SyncPinText" />
<TextView
android:id="@+id/text_pin3"
style="@style/SyncPinText" />
</LinearLayout>
<TextView
android:id="@+id/link_nodevice"
style="@style/SyncLinkItem"
android:onClick="manualClickHandler"
android:text="@string/sync_link_nodevice" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<Button
style="@style/SyncButtonCommon"
android:layout_marginTop="10dp"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</LinearLayout>
</LinearLayout>
android:id="@+id/link_nodevice"
style="@style/SyncLinkItem"
android:layout_alignParentBottom="true"
android:gravity="center"
android:paddingBottom="5dp"
android:onClick="manualClickHandler"
android:text="@string/sync_link_advancedsetup" />
</RelativeLayout>
</ScrollView>
</TableLayout>
<LinearLayout
android:id="@id/setup_bottom"
style="@style/SyncBottom"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,41 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_fail" />
<View
style="@style/SyncViewLine" />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/failure_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_fail" />
</LinearLayout>
<TextView
style="@style/SyncTextItem"
android:text="@string/sync_subtitle_fail" />
<TextView
style="@style/SyncTextItem"
android:layout_below="@id/failure_top"
android:layout_above="@+id/failure_bottom"
android:padding="20dp"
android:text="@string/sync_subtitle_fail" />
<LinearLayout
android:id="@id/failure_bottom"
style="@style/SyncBottom"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="tryAgainClickHandler"
android:text="@string/sync_button_tryagain" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
style="@style/SyncButtonCommon"
android:onClick="tryAgainClickHandler"
android:text="@string/sync_button_tryagain" />
<Button
style="@style/SyncButtonCommon"
android:onClick="manualClickHandler"
android:text="@string/sync_button_manual" />
</LinearLayout>
<Button
style="@style/SyncButtonCommon"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</LinearLayout>
</TableLayout>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="manualClickHandler"
android:text="@string/sync_button_manual" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,23 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_connect" />
<View
style="@style/SyncViewLine" />
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateOnly="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp" />
<TextView
style="@style/SyncTextItem"
android:text="@string/sync_jpake_subtitle_waiting" />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/waiting_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_connect" />
</LinearLayout>
<ProgressBar
android:id="@+id/waiting_content1"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/waiting_top"
android:indeterminateOnly="true"
android:layout_marginTop="40dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"/>
<TextView
style="@style/SyncTextItem"
android:gravity="center"
android:layout_below="@id/waiting_content1"
android:text="@string/sync_jpake_subtitle_waiting" />
<LinearLayout
style="@style/SyncBottom">
<Button
style="@style/SyncButtonCommon"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</TableLayout>
style="@style/SyncButton"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,18 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/internet_top"
style="@style/SyncTop">
<ImageView
style="@style/SyncTopIcon" />
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_fail" />
<View
style="@style/SyncViewLine"/>
<TextView
style="@style/SyncTextItem"
android:text="@string/sync_subtitle_nointernet" />
style="@style/SyncTextTitle"
android:text="@string/sync_title_fail" />
</LinearLayout>
<TextView
style="@style/SyncTextItem"
android:layout_below="@id/internet_top"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="@string/sync_subtitle_nointernet" />
<LinearLayout
style="@style/SyncBottom" >
<Button
style="@style/SyncButtonCommon"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_ok" />
</TableLayout>
style="@style/SyncButton"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_ok" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,28 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/pair_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon" />
<TextView
android:id="@+id/setup_title"
style="@style/SyncTextTitle"
android:text="@string/sync_title_pair" />
</LinearLayout>
<ScrollView
style="@style/SyncLayout" >
style="@style/SyncLayout"
android:layout_below="@id/pair_top"
android:layout_above="@+id/pair_bottom" >
<LinearLayout
style="@style/SyncLayout" >
<TextView
android:id="@+id/setup_title"
style="@style/SyncTextTitle"
android:text="@string/sync_title_pair" />
<View
style="@style/SyncViewLine" />
style="@style/SyncLayout.Vertical"
android:gravity="center"
android:padding="10dp" >
<TextView
android:id="@+id/setup_subtitle"
style="@style/SyncTextItem"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:text="@string/sync_subtitle_connect" />
<TextView
style="@style/SyncLinkItem"
android:layout_marginBottom="10dp"
android:onClick="showClickHandler"
android:text="@string/sync_link_show" />
@@ -32,16 +40,16 @@
android:gravity="center"
android:orientation="vertical" >
<EditText
android:id="@+id/pair_row1"
style="@style/SyncEditPin" />
<EditText
android:id="@+id/pair_row2"
style="@style/SyncEditPin" />
<EditText
android:id="@+id/pair_row3"
style="@style/SyncEditPin"
android:imeOptions="actionDone" />
<EditText
android:id="@+id/pair_row1"
style="@style/SyncEditPin" />
<EditText
android:id="@+id/pair_row2"
style="@style/SyncEditPin" />
<EditText
android:id="@+id/pair_row3"
style="@style/SyncEditPin"
android:imeOptions="actionDone" />
</LinearLayout>
<LinearLayout
@@ -54,31 +62,28 @@
<TextView
style="@style/SyncTextItem"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_margin="10dp"
android:text="@string/sync_pair_tryagain"
android:textSize="10dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<Button
style="@style/SyncButtonCommon"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
<Button
android:id="@+id/pair_button_connect"
style="@style/SyncButtonCommon"
android:onClick="connectClickHandler"
android:clickable="false"
android:enabled="false"
android:text="@string/sync_button_connect" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</TableLayout>
<LinearLayout
android:id="@id/pair_bottom"
style="@style/SyncBottom"
android:orientation="horizontal" >
<Button
style="@style/SyncButton"
android:onClick="cancelClickHandler"
android:text="@string/sync_button_cancel" />
<Button
android:id="@+id/pair_button_connect"
style="@style/SyncButton"
android:onClick="connectClickHandler"
android:clickable="false"
android:enabled="false"
android:text="@string/sync_button_connect" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,38 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncTextFrame" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SyncLayout" >
<LinearLayout
android:id="@+id/success_top"
style="@style/SyncTop" >
<ImageView
style="@style/SyncTopIcon"/>
<TextView
style="@style/SyncTextTitle"
android:text="@string/sync_title_success" />
<View style="@style/SyncViewLine" />
<TextView
android:id="@+id/setup_success_subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="@string/sync_subtitle_success" />
style="@style/SyncTextTitle"
android:text="@string/sync_title_success" />
</LinearLayout>
<TextView
android:id="@+id/setup_success_subtitle"
style="@style/SyncTextItem"
android:gravity="left"
android:padding="20dp"
android:layout_below="@id/success_top"
android:text="@string/sync_subtitle_success" />
<LinearLayout
style="@style/SyncBottom" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="settingsClickHandler"
android:text="@string/sync_settings" />
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
<TextView
android:id="@+id/link_pair"
style="@style/SyncLinkItem"
android:layout_gravity="center|bottom"
android:onClick="pairClickHandler"
android:text="@string/sync_title_pair" />
</TableLayout>
style="@style/SyncButton"
android:onClick="settingsClickHandler"
android:text="@string/sync_settings" />
</LinearLayout>
</RelativeLayout>

View File

@@ -1,34 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="SyncLayout" parent="@android:style/Widget">
<item name="android:layout_width">wrap_content</item>
<style name="SyncLayout">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:gravity">center</item>
</style>
<style name="SyncLayout.Vertical" parent="@style/SyncLayout">
<item name="android:orientation">vertical</item>
</style>
<style name="SyncLayout.Horizontal" parent="@style/SyncLayout">
<item name="android:orientation">horizontal</item>
</style>
<!-- TextView Styles -->
<style name="SyncTextFrame" parent="@android:style/TextAppearance">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:layout_gravity">center</item>
<item name="android:padding">20dp</item>
<item name="android:orientation">vertical</item>
<item name="android:background">#82818A</item>
</style>
<style name="SyncTextItem" parent="@android:style/TextAppearance.Medium">
<item name="android:gravity">center</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:textSize">15dp</item>
</style>
<style name="SyncLinkItem" parent="SyncTextItem">
<item name="android:clickable">true</item>
<item name="android:textColor">#99CCFF</item>
<item name="android:textColor">#ACC4D5</item>
</style>
<style name="SyncTextTitle" parent="@style/SyncTextItem">
<item name="android:gravity">center</item>
<item name="android:paddingBottom">10dp</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:paddingLeft">4dp</item>
<item name="android:gravity">left</item>
<item name="android:textSize">20dp</item>
</style>
<!-- EditView Styles -->
@@ -44,16 +47,48 @@
<item name="android:maxLength">4</item>
<item name="android:imeOptions">actionNext</item>
</style>
<!-- Misc Styles -->
<style name="SyncButtonCommon">
<!-- Theme Styles -->
<style name="SyncTheme" parent="@android:style/Theme.NoTitleBar"/>
<style name="SyncTop">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">left</item>
<item name="android:orientation">horizontal</item>
<item name="android:layout_alignParentTop">true</item>
<item name="android:background">@android:drawable/bottom_bar</item>
</style>
<style name="SyncBottom">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:layout_alignParentBottom">true</item>
<item name="android:background">@android:drawable/bottom_bar</item>
</style>
<style name="SyncButton" parent="@android:style/Widget.Button">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
</style>
<!-- Text Display Styles -->
<style name="SyncPinText" parent="@android:style/Widget.TextView">
<item name="android:layout_width">130sp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_marginBottom">5dp</item>
<item name="android:gravity">center</item>
<item name="android:background">@drawable/pin_background</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">35sp</item>
<item name="android:text">@string/sync_pin_default</item>
</style>
<style name="SyncTopIcon">
<item name="android:src">@drawable/sync_ic_launcher</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="SyncViewLine">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">2dp</item>
<item name="android:paddingTop">5dp</item>
<item name="android:paddingBottom">10dp</item>
<item name="android:background">#FFFFFF</item>
<item name="android:paddingTop">2dp</item>
<item name="android:paddingLeft">4dp</item>
</style>
</resources>

View File

@@ -7,8 +7,9 @@
<org.mozilla.gecko.LinkPreference android:title="@string/pref_about_firefox"
url="about:" />
<org.mozilla.gecko.SyncPreference android:title="@string/pref_sync"
android:persistent="false" />
<!-- TODO: Default Search Engine -->
<!-- TODO: Sync -->
</PreferenceCategory>

View File

@@ -74,7 +74,6 @@
<string name="pref_font_size_medium">&pref_font_size_medium;</string>
<string name="pref_font_size_large">&pref_font_size_large;</string>
<string name="pref_font_size_xlarge">&pref_font_size_xlarge;</string>
<string name="pref_sync">&pref_sync;</string>
<string name="reload">&reload;</string>
<string name="forward">&forward;</string>

View File

@@ -63,9 +63,9 @@ public class SyncConfiguration implements CredentialsSource {
this.editor = config.getEditor();
}
@Override
public void apply() {
this.editor.apply();
// Android <=r8 SharedPreferences.Editor does not contain apply() for overriding.
this.editor.commit();
}
@Override

View File

@@ -41,7 +41,6 @@ package org.mozilla.gecko.sync;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;
@@ -128,8 +127,10 @@ public class Utils {
totalLength += array.length;
}
byte[] result = Arrays.copyOf(first, totalLength);
byte[] result = new byte[totalLength];
int offset = first.length;
System.arraycopy(first, 0, result, 0, offset);
for (byte[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);

View File

@@ -40,7 +40,6 @@ package org.mozilla.gecko.sync.crypto;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@@ -98,7 +97,9 @@ public class HKDF {
T = Utils.concatAll(T, Tn);
}
return Arrays.copyOfRange(T, 0, len);
byte[] result = new byte[len];
System.arraycopy(T, 0, result, 0, len);
return result;
}
/*

View File

@@ -19,7 +19,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chenxia Liu <liuche@mozilla.com>
* Chenxia Liu <liuche@mozilla.com>
* Richard Newman <rnewman@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -52,49 +53,49 @@ import org.mozilla.gecko.sync.crypto.KeyBundle;
import android.util.Log;
public class JPakeCrypto {
private static final String LOG_TAG = "JpakeCrypto";
private static final String LOG_TAG = "JPakeCrypto";
/*
* Primes P and Q, and generator G - from original Mozilla jpake
* Primes P and Q, and generator G - from original Mozilla J-PAKE
* implementation.
*/
public static final BigInteger P = new BigInteger(
"90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C"
+ "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F"
+ "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1"
+ "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B"
+ "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394"
+ "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0"
+ "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E"
+ "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D"
+ "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F"
+ "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D"
+ "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E"
+ "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73",
16);
public static final BigInteger P = new BigInteger(
"90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" +
"7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" +
"009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
"29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" +
"6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" +
"87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
"E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" +
"BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" +
"AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
"B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" +
"597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" +
"C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73",
16);
public static final BigInteger Q = new BigInteger(
"CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D",
16);
public static final BigInteger Q = new BigInteger(
"CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D",
16);
public static final BigInteger G = new BigInteger(
"5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37"
+ "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB"
+ "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1"
+ "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8"
+ "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17"
+ "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C"
+ "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3"
+ "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B"
+ "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8"
+ "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828"
+ "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33"
+ "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B",
16);
public static final BigInteger G = new BigInteger(
"5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" +
"F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" +
"805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
"F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" +
"A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" +
"A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
"4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" +
"9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" +
"9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
"E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" +
"E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" +
"787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B",
16);
/**
*
* Round 1 of JPAKE protocol.
* Round 1 of J-PAKE protocol.
* Generate x1, x2, and ZKP for other party.
*
* @param mySignerId
@@ -118,7 +119,7 @@ public class JPakeCrypto {
}
/**
* Round 2 of JPAKE protocol.
* Round 2 of J-PAKE protocol.
* Generate A and ZKP for A.
* Verify ZKP from other party. Does not check for replay ZKP.
*
@@ -135,9 +136,9 @@ public class JPakeCrypto {
public static void round2(String secret, JPakeParty jp,
JPakeNumGenerator gen) throws Gx4IsOneException, IncorrectZkpException {
Log.d(LOG_TAG, "round2 started");
Log.d(LOG_TAG, "round2 started.");
if (jp.gx4 == BigInteger.ONE) {
if (BigInteger.ONE.compareTo(jp.gx4) == 0) {
throw new Gx4IsOneException();
}
@@ -159,11 +160,11 @@ public class JPakeCrypto {
jp.thisZkpA = createZkp(y1, y2, a, jp.signerId, gen);
jp.thisA = a;
Log.d(LOG_TAG, "round2 finished");
Log.d(LOG_TAG, "round2 finished.");
}
/**
* Final round of JPAKE protocol.
* Final round of J-PAKE protocol.
*
* @param b
* @param zkp
@@ -174,7 +175,7 @@ public class JPakeCrypto {
*/
public static KeyBundle finalRound(String secret, JPakeParty jp)
throws IncorrectZkpException {
Log.d(LOG_TAG, "final round started");
Log.d(LOG_TAG, "Final round started.");
BigInteger gb = jp.gx1.multiply(jp.gx2).mod(P).multiply(jp.gx3)
.mod(P);
checkZkp(gb, jp.otherA, jp.otherZkpA);
@@ -188,7 +189,7 @@ public class JPakeCrypto {
byte[] hmac = new byte[32];
generateKeyAndHmac(k, enc, hmac);
Log.d(LOG_TAG, "final round finished; returning key");
Log.d(LOG_TAG, "Final round finished; returning key.");
return new KeyBundle(enc, hmac);
}
@@ -198,8 +199,7 @@ public class JPakeCrypto {
try {
Mac hmacSha256;
hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key,
"HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key, "HmacSHA256");
hmacSha256.init(secret_key);
result = hmacSha256.doFinal(data);
} catch (GeneralSecurityException e) {
@@ -243,14 +243,18 @@ public class JPakeCrypto {
// Check parameters of zkp, and compare to computed hash. These shouldn't
// fail.
if (gx.compareTo(BigInteger.ZERO) < 1) {// g^x > 1
Log.e(LOG_TAG, "g^x > 1 fails");
Log.e(LOG_TAG, "g^x > 1 fails.");
throw new IncorrectZkpException();
} else if (gx.compareTo(P.subtract(BigInteger.ONE)) > -1) { // g^x < p-1
Log.e(LOG_TAG, "g^x < p-1 fails");
}
if (gx.compareTo(P.subtract(BigInteger.ONE)) > -1) { // g^x < p-1
Log.e(LOG_TAG, "g^x < p-1 fails.");
throw new IncorrectZkpException();
} else if (gx.modPow(Q, P).compareTo(BigInteger.ONE) != 0) {
Log.e(LOG_TAG, "g^x^q % p = 1 fails");
} else if (zkp.gr.compareTo(g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P)) != 0) {
}
if (gx.modPow(Q, P).compareTo(BigInteger.ONE) != 0) {
Log.e(LOG_TAG, "g^x^q % p = 1 fails.");
throw new IncorrectZkpException();
}
if (zkp.gr.compareTo(g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P)) != 0) {
// b = r-h*x ==> g^r = g^b*g^x^(h)
Log.i(LOG_TAG, "gb*g(xh) = "
+ g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P).toString(16));
@@ -260,11 +264,10 @@ public class JPakeCrypto {
Log.d(LOG_TAG, "g^(xh) = " + gx.modPow(h, P).toString(16));
Log.d(LOG_TAG, "gx = " + gx.toString(16));
Log.d(LOG_TAG, "h = " + h.toString(16));
Log.e(LOG_TAG, "zkp calculation incorrect");
Log.e(LOG_TAG, "zkp calculation incorrect.");
throw new IncorrectZkpException();
} else {
Log.d(LOG_TAG, "*** ZKP SUCCESS ***");
}
Log.d(LOG_TAG, "*** ZKP SUCCESS ***");
}
/*

View File

@@ -50,6 +50,7 @@ import android.util.Log;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.HttpVersion;
import ch.boye.httpclientandroidlib.auth.Credentials;
import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials;
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
@@ -157,6 +158,7 @@ public class BaseResource implements Resource {
HttpConnectionParams.setConnectionTimeout(params, delegate.connectionTimeout());
HttpConnectionParams.setSoTimeout(params, delegate.socketTimeout());
HttpProtocolParams.setContentCharset(params, charset);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
delegate.addHeaders(request, client);
}
@@ -182,8 +184,7 @@ public class BaseResource implements Resource {
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", 443, sf));
schemeRegistry.register(new Scheme("http", 80, new PlainSocketFactory()));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(
schemeRegistry);
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry);
connManager = cm;
return cm;
}

View File

@@ -173,7 +173,7 @@ public class SyncStorageRequest implements Resource {
}
}
public static String USER_AGENT = "Firefox AndroidSync 0.2";
public static String USER_AGENT = "Firefox AndroidSync 0.3";
protected SyncResourceDelegate resourceDelegate;
public SyncStorageRequestDelegate delegate;
protected BaseResource resource;

View File

@@ -43,19 +43,59 @@ import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import android.util.Log;
import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory;
import ch.boye.httpclientandroidlib.params.HttpParams;
public class TLSSocketFactory extends SSLSocketFactory {
private static final String LOG_TAG = "TLSSocketFactory";
private static final String[] DEFAULT_CIPHER_SUITES = new String[] {
"SSL_RSA_WITH_RC4_128_SHA", // "RC4_SHA"
};
private static final String[] DEFAULT_PROTOCOLS = new String[] {
"SSLv3",
"TLSv1"
};
// Guarded by `this`.
private static String[] cipherSuites = DEFAULT_CIPHER_SUITES;
public TLSSocketFactory(SSLContext sslContext) {
super(sslContext);
}
/**
* Attempt to specify the cipher suites to use for a connection. If
* setting fails (as it will on Android 2.2, because the wrong names
* are in use to specify ciphers), attempt to set the defaults.
*
* We store the list of cipher suites in `cipherSuites`, which
* avoids this fallback handling having to be executed more than once.
*
* This method is synchronized to ensure correct use of that member.
*
* See Bug 717691 for more details.
*
* @param socket
* The SSLSocket on which to operate.
*/
public static synchronized void setEnabledCipherSuites(SSLSocket socket) {
try {
socket.setEnabledCipherSuites(cipherSuites);
} catch (IllegalArgumentException e) {
cipherSuites = socket.getSupportedCipherSuites();
Log.d(LOG_TAG, "Setting enabled cipher suites failed: " + e.getMessage());
Log.d(LOG_TAG, "Using " + cipherSuites.length + " supported suites.");
socket.setEnabledCipherSuites(cipherSuites);
}
}
@Override
public Socket createSocket(HttpParams params) throws IOException {
SSLSocket socket = (SSLSocket) super.createSocket(params);
socket.setEnabledProtocols(new String[] { "SSLv3", "TLSv1" });
socket.setEnabledCipherSuites(new String[] { "SSL_RSA_WITH_RC4_128_SHA" });
socket.setEnabledProtocols(DEFAULT_PROTOCOLS);
setEnabledCipherSuites(socket);
return socket;
}

View File

@@ -82,6 +82,7 @@ public class AccountActivity extends AccountAuthenticatorActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.SyncTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.sync_account);
mContext = getApplicationContext();
@@ -132,7 +133,7 @@ public class AccountActivity extends AccountAuthenticatorActivity {
}
public void cancelClickHandler(View target) {
moveTaskToBack(true);
finish();
}
/*

View File

@@ -50,6 +50,7 @@ public class SetupFailureActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.SyncTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.sync_setup_failure);
mContext = this.getApplicationContext();

View File

@@ -44,15 +44,18 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.TextView;
public class SetupSuccessActivity extends Activity {
private final static String LOG_TAG = "SetupSuccessActivity";
private TextView setupSubtitle;
private Context mContext;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.SyncTheme);
super.onCreate(savedInstanceState);
mContext = getApplicationContext();
Bundle extras = this.getIntent().getExtras();
@@ -68,7 +71,7 @@ public class SetupSuccessActivity extends Activity {
/* Click Handlers */
public void settingsClickHandler(View target) {
Intent intent = new Intent("android.settings.SYNC_SETTINGS");
Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
startActivity(intent);
finish();

View File

@@ -53,6 +53,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
@@ -79,7 +80,9 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
private TextView setupTitleView;
private TextView setupNoDeviceLinkTitleView;
private TextView setupSubtitleView;
private TextView pinTextView;
private TextView pinTextView1;
private TextView pinTextView2;
private TextView pinTextView3;
private JPakeClient jClient;
// Android context.
@@ -94,6 +97,7 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.SyncTheme);
Log.i(LOG_TAG, "Called SetupSyncActivity.onCreate.");
super.onCreate(savedInstanceState);
@@ -134,9 +138,14 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
return;
}
}
// Display toast for "Only one account supported."
// Display toast for "Only one account supported." and redirect to account management.
Toast toast = Toast.makeText(mContext, R.string.sync_notification_oneaccount, Toast.LENGTH_LONG);
toast.show();
Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
startActivity(intent);
finish();
}
@@ -202,20 +211,23 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
}
// Format PIN for display.
int charPerLine = pin.length() / 3;
String prettyPin = pin.substring(0, charPerLine) + "\n";
prettyPin += pin.substring(charPerLine, 2 * charPerLine) + "\n";
prettyPin += pin.substring(2 * charPerLine, pin.length());
final String pin1 = pin.substring(0, charPerLine);
final String pin2 = pin.substring(charPerLine, 2 * charPerLine);
final String pin3 = pin.substring(2 * charPerLine, pin.length());
final String toDisplay = prettyPin;
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView view = pinTextView;
if (view == null) {
TextView view1 = pinTextView1;
TextView view2 = pinTextView2;
TextView view3 = pinTextView3;
if (view1 == null || view2 == null || view3 == null) {
Log.w(LOG_TAG, "Couldn't find view to display PIN.");
return;
}
view.setText(toDisplay);
view1.setText(pin1);
view2.setText(pin2);
view3.setText(pin3);
}
});
}
@@ -475,7 +487,9 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity {
setupTitleView = ((TextView) findViewById(R.id.setup_title));
setupSubtitleView = (TextView) findViewById(R.id.setup_subtitle);
setupNoDeviceLinkTitleView = (TextView) findViewById(R.id.link_nodevice);
pinTextView = ((TextView) findViewById(R.id.text_pin));
pinTextView1 = ((TextView) findViewById(R.id.text_pin1));
pinTextView2 = ((TextView) findViewById(R.id.text_pin2));
pinTextView3 = ((TextView) findViewById(R.id.text_pin3));
// UI checks.
if (setupTitleView == null) {

View File

@@ -6,7 +6,7 @@ mk_add_options AUTOCONF=autoconf213
ac_cv_visibility_pragma=no
ac_add_options --disable-install-strip
ac_add_options --disable-installer
ac_add_options --enable-application=mobile/android
# Nightlies only since this has a cost in performance

View File

@@ -0,0 +1 @@
mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png

View File

@@ -0,0 +1 @@
mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png

View File

@@ -0,0 +1 @@
mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png

View File

@@ -1,4 +1,2 @@
mobile/android/base/resources/drawable/pin_background.xml
mobile/android/base/resources/drawable/sync_icon.png
mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png

View File

@@ -1,13 +1,14 @@
<string name="sync_app_name">&sync.app.name.label;</string>
<string name="sync_title_connect">&sync.title.connect.label;</string>
<string name="sync_title_connect">&sync.title.adddevice.label;</string>
<string name="sync_title_pair">&sync.title.pair.label;</string>
<!-- J-PAKE PIN Screen -->
<string name="sync_subtitle_connect">&sync.subtitle.connect.label;</string>
<string name="sync_subtitle_header">&sync.subtitle.header.label;</string>
<string name="sync_subtitle_connect">&sync.subtitle.connectlocation.label;</string>
<string name="sync_subtitle_pair">&sync.subtitle.pair.label;</string>
<string name="sync_pin_default">&sync.pin.default.label;</string>
<string name="sync_link_show">&sync.link.show.label;</string>
<string name="sync_link_nodevice">&sync.link.nodevice.label;</string>
<string name="sync_pin_default">&sync.pin.oneline.label;</string>
<string name="sync_link_show"><u>&sync.link.show.label;</u></string>
<string name="sync_link_advancedsetup"><u>&sync.link.advancedsetup.label;</u></string>
<!-- J-PAKE Waiting Screen -->

View File

@@ -6,7 +6,7 @@ mk_add_options AUTOCONF=autoconf213
ac_cv_visibility_pragma=no
ac_add_options --disable-install-strip
ac_add_options --disable-installer
ac_add_options --enable-application=mobile
# Nightlies only since this has a cost in performance

View File

@@ -586,7 +586,6 @@ nsSocketOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *countWrit
PRInt32 n = PR_Write(fd, buf, count);
SOCKET_LOG((" PR_Write returned [n=%d]\n", n));
NS_ASSERTION(n != 0, "unexpected return value");
nsresult rv;
{

View File

@@ -915,6 +915,8 @@ nsCompressOutputStreamWrapper::Write(const char * buf,
while (mZstream.avail_in > 0) {
zerr = deflate(&mZstream, Z_NO_FLUSH);
if (zerr == Z_STREAM_ERROR) {
deflateEnd(&mZstream);
mStreamInitialized = PR_FALSE;
return NS_ERROR_FAILURE;
}
// Note: Z_BUF_ERROR is non-fatal and sometimes expected here.
@@ -924,6 +926,8 @@ nsCompressOutputStreamWrapper::Write(const char * buf,
if (mZstream.avail_out == 0) {
rv = WriteBuffer();
if (NS_FAILED(rv)) {
deflateEnd(&mZstream);
mStreamInitialized = PR_FALSE;
return rv;
}
}

View File

@@ -851,6 +851,8 @@ SpdySession::HandleSynReply(SpdySession *self)
return NS_OK;
}
self->mFrameDataStream->UpdateTransportReadEvents(self->mFrameDataSize);
if (!self->mFrameDataStream->SetFullyOpen()) {
// "If an endpoint receives multiple SYN_REPLY frames for the same active
// stream ID, it must drop the stream, and send a RST_STREAM for the
@@ -1128,6 +1130,9 @@ SpdySession::HandleHeaders(SpdySession *self)
// this is actually not legal in the HTTP mapping of SPDY. All
// headers are in the syn or syn reply. Log and ignore it.
// in v3 this will be legal and we must remember to note
// NS_NET_STATUS_RECEIVING_FROM from it
LOG3(("SpdySession::HandleHeaders %p HEADERS for Stream 0x%X. "
"They are ignored in the HTTP/SPDY mapping.",
self, streamID));
@@ -1148,29 +1153,6 @@ SpdySession::HandleWindowUpdate(SpdySession *self)
return NS_OK;
}
// Used for the hashtable enumeration to propogate OnTransportStatus events
struct transportStatus
{
nsITransport *transport;
nsresult status;
PRUint64 progress;
};
static PLDHashOperator
StreamTransportStatus(nsAHttpTransaction *key,
nsAutoPtr<SpdyStream> &stream,
void *closure)
{
struct transportStatus *status =
static_cast<struct transportStatus *>(closure);
stream->Transaction()->OnTransportStatus(status->transport,
status->status,
status->progress);
return PL_DHASH_NEXT;
}
//-----------------------------------------------------------------------------
// nsAHttpTransaction. It is expected that nsHttpConnection is the caller
// of these methods
@@ -1183,21 +1165,47 @@ SpdySession::OnTransportStatus(nsITransport* aTransport,
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
// nsHttpChannel synthesizes progress events in OnDataAvailable
if (aStatus == nsISocketTransport::STATUS_RECEIVING_FROM)
return;
switch (aStatus) {
// These should appear only once, deliver to the first
// transaction on the session.
case NS_NET_STATUS_RESOLVING_HOST:
case NS_NET_STATUS_RESOLVED_HOST:
case NS_NET_STATUS_CONNECTING_TO:
case NS_NET_STATUS_CONNECTED_TO:
{
SpdyStream *target = mStreamIDHash.Get(1);
if (target)
target->Transaction()->OnTransportStatus(aTransport, aStatus, aProgress);
break;
}
// STATUS_SENDING_TO is handled by SpdyStream
if (aStatus == nsISocketTransport::STATUS_SENDING_TO)
return;
default:
// The other transport events are ignored here because there is no good
// way to map them to the right transaction in spdy. Instead, the events
// are generated again from the spdy code and passed directly to the
// correct transaction.
struct transportStatus status;
status.transport = aTransport;
status.status = aStatus;
status.progress = aProgress;
// NS_NET_STATUS_SENDING_TO:
// This is generated by the socket transport when (part) of
// a transaction is written out
//
// There is no good way to map it to the right transaction in spdy,
// so it is ignored here and generated separately when the SYN_STREAM
// is sent from SpdyStream::TransmitFrame
mStreamTransactionHash.Enumerate(StreamTransportStatus, &status);
// NS_NET_STATUS_WAITING_FOR:
// Created by nsHttpConnection when the request has been totally sent.
// There is no good way to map it to the right transaction in spdy,
// so it is ignored here and generated separately when the same
// condition is complete in SpdyStream when there is no more
// request body left to be transmitted.
// NS_NET_STATUS_RECEIVING_FROM
// Generated in spdysession whenever we read a data frame or a syn_reply
// that can be attributed to a particular stream/transaction
break;
}
}
// ReadSegments() is used to write data to the network. Generally, HTTP
@@ -1675,6 +1683,7 @@ SpdySession::OnWriteSegment(char *buf,
mFrameDataRead += *countWritten;
mFrameDataStream->UpdateTransportReadEvents(*countWritten);
if ((mFrameDataRead == mFrameDataSize) && !mFrameDataLast)
ChangeDownstreamState(BUFFERING_FRAME_HEADER);

View File

@@ -75,6 +75,7 @@ SpdyStream::SpdyStream(nsAHttpTransaction *httpTransaction,
mSentFinOnData(0),
mRecvdFin(0),
mFullyOpen(0),
mSentWaitingFor(0),
mTxInlineFrameAllocation(SpdySession::kDefaultBufferSize),
mTxInlineFrameSize(0),
mTxInlineFrameSent(0),
@@ -82,7 +83,9 @@ SpdyStream::SpdyStream(nsAHttpTransaction *httpTransaction,
mTxStreamFrameSent(0),
mZlib(compressionContext),
mRequestBodyLen(0),
mPriority(priority)
mPriority(priority),
mTotalSent(0),
mTotalRead(0)
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@@ -458,6 +461,36 @@ SpdyStream::ParseHttpRequestHeaders(const char *buf,
return NS_OK;
}
void
SpdyStream::UpdateTransportReadEvents(PRUint32 count)
{
mTotalRead += count;
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_RECEIVING_FROM,
mTotalRead);
}
void
SpdyStream::UpdateTransportSendEvents(PRUint32 count)
{
mTotalSent += count;
if (mUpstreamState != SENDING_FIN_STREAM)
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_SENDING_TO,
mTotalSent);
if (!mSentWaitingFor && !mRequestBodyLen &&
mTxInlineFrameSent == mTxInlineFrameSize &&
mTxStreamFrameSent == mTxStreamFrameSize) {
mSentWaitingFor = 1;
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_WAITING_FOR,
LL_ZERO);
}
}
nsresult
SpdyStream::TransmitFrame(const char *buf,
PRUint32 *countUsed)
@@ -538,16 +571,11 @@ SpdyStream::TransmitFrame(const char *buf,
SpdySession::LogIO(mSession, this, "Writing from Transaction Buffer",
buf + offset, transmittedCount);
if (mUpstreamState == SENDING_REQUEST_BODY) {
mTransaction->OnTransportStatus(mSocketTransport,
nsISocketTransport::STATUS_SENDING_TO,
transmittedCount);
}
*countUsed += transmittedCount;
avail -= transmittedCount;
offset += transmittedCount;
mTxStreamFrameSent += transmittedCount;
UpdateTransportSendEvents(transmittedCount);
}
if (!avail) {

View File

@@ -89,6 +89,9 @@ public:
void SetRecvdFin(bool aStatus) { mRecvdFin = aStatus ? 1 : 0; }
bool RecvdFin() { return mRecvdFin; }
void UpdateTransportSendEvents(PRUint32 count);
void UpdateTransportReadEvents(PRUint32 count);
// The zlib header compression dictionary defined by SPDY,
// and hooks to the mozilla allocator for zlib to use.
static const char *kDictionary;
@@ -171,6 +174,9 @@ private:
// Flag is set after syn reply received
PRUint32 mFullyOpen : 1;
// Flag is set after the WAITING_FOR Transport event has been generated
PRUint32 mSentWaitingFor : 1;
// The InlineFrame and associated data is used for composing control
// frames and data frame headers.
nsAutoArrayPtr<char> mTxInlineFrame;
@@ -200,6 +206,9 @@ private:
// based on nsISupportsPriority definitions
PRInt32 mPriority;
// For Progress Events
PRUint64 mTotalSent;
PRUint64 mTotalRead;
};
}} // namespace mozilla::net

View File

@@ -75,7 +75,6 @@ HISTOGRAM(CYCLE_COLLECTOR_TIME_BETWEEN, 1, 120, 50, EXPONENTIAL, "Time spent in
*/
HISTOGRAM(GC_REASON, 1, 20, 20, LINEAR, "Reason (enum value) for initiating a GC")
HISTOGRAM_BOOLEAN(GC_IS_COMPARTMENTAL, "Is it a compartmental GC?")
HISTOGRAM_BOOLEAN(GC_IS_SHAPE_REGEN, "Is it a shape regenerating GC?")
HISTOGRAM(GC_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC (ms)")
HISTOGRAM(GC_MARK_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC mark phase (ms)")
HISTOGRAM(GC_SWEEP_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC sweep phase (ms)")

View File

@@ -137,6 +137,42 @@ function getSimpleMeasurements() {
return ret;
}
/**
* Read the update channel from defaults only. We do this to ensure that
* the channel is tightly coupled with the application and does not apply
* to other installations of the application that may use the same profile.
*/
function getUpdateChannel() {
var channel = "default";
var prefName;
var prefValue;
var defaults = Services.prefs.getDefaultBranch(null);
try {
channel = defaults.getCharPref("app.update.channel");
} catch (e) {
// use default when pref not found
}
try {
var partners = Services.prefs.getChildList("app.partner.");
if (partners.length) {
channel += "-cck";
partners.sort();
for each (prefName in partners) {
prefValue = Services.prefs.getCharPref(prefName);
channel += "-" + prefValue;
}
}
}
catch (e) {
Cu.reportError(e);
}
return channel;
}
function TelemetryPing() {}
TelemetryPing.prototype = {
@@ -231,7 +267,8 @@ TelemetryPing.prototype = {
appVersion: ai.version,
appName: ai.name,
appBuildID: ai.appBuildID,
platformBuildID: ai.platformBuildID,
appUpdateChannel: getUpdateChannel(),
platformBuildID: ai.platformBuildID
};
// sysinfo fields are not always available, get what we can.

View File

@@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- 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
*
@@ -214,8 +214,17 @@ static const char kOOMAllocationSizeParameter[] = "OOMAllocationSize=";
static const int kOOMAllocationSizeParameterLen =
sizeof(kOOMAllocationSizeParameter)-1;
static const char kAvailablePageFileParameter[] = "AvailablePageFile=";
static const int kAvailablePageFileParameterLen =
sizeof(kAvailablePageFileParameter)-1;
static const char kAvailablePhysicalMemoryParameter[] = "AvailablePhysicalMemory=";
static const int kAvailablePhysicalMemoryParameterLen =
sizeof(kAvailablePhysicalMemoryParameter)-1;
// this holds additional data sent via the API
static Mutex* crashReporterAPILock;
static Mutex* notesFieldLock;
static AnnotationTable* crashReporterAPIData_Hash;
static nsCString* crashReporterAPIData = nsnull;
static nsCString* notesField = nsnull;
@@ -454,34 +463,31 @@ bool MinidumpCallback(const XP_CHAR* dump_path,
&nBytes, NULL);
WriteFile(hFile, "\n", 1, &nBytes, NULL);
}
// Try to get some information about memory.
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
if (GlobalMemoryStatusEx(&statex)) {
char buffer[128];
int bufferLen;
WriteFile(hFile, kSysMemoryParameter,
kSysMemoryParameterLen, &nBytes, NULL);
ltoa(statex.dwMemoryLoad, buffer, 10);
bufferLen = strlen(buffer);
WriteFile(hFile, buffer, bufferLen,
&nBytes, NULL);
WriteFile(hFile, "\n", 1, &nBytes, NULL);
WriteFile(hFile, kTotalVirtualMemoryParameter,
kTotalVirtualMemoryParameterLen, &nBytes, NULL);
_ui64toa(statex.ullTotalVirtual, buffer, 10);
bufferLen = strlen(buffer);
WriteFile(hFile, buffer, bufferLen,
&nBytes, NULL);
WriteFile(hFile, "\n", 1, &nBytes, NULL);
WriteFile(hFile, kAvailableVirtualMemoryParameter,
kAvailableVirtualMemoryParameterLen, &nBytes, NULL);
_ui64toa(statex.ullAvailVirtual, buffer, 10);
bufferLen = strlen(buffer);
WriteFile(hFile, buffer, bufferLen,
&nBytes, NULL);
#define WRITE_STATEX_FIELD(field, paramName, conversionFunc) \
WriteFile(hFile, k##paramName##Parameter, \
k##paramName##ParameterLen, &nBytes, NULL); \
conversionFunc(statex.field, buffer, 10); \
bufferLen = strlen(buffer); \
WriteFile(hFile, buffer, bufferLen, &nBytes, NULL); \
WriteFile(hFile, "\n", 1, &nBytes, NULL);
WRITE_STATEX_FIELD(dwMemoryLoad, SysMemory, ltoa);
WRITE_STATEX_FIELD(ullTotalVirtual, TotalVirtualMemory, _ui64toa);
WRITE_STATEX_FIELD(ullAvailVirtual, AvailableVirtualMemory, _ui64toa);
WRITE_STATEX_FIELD(ullAvailPageFile, AvailablePageFile, _ui64toa);
WRITE_STATEX_FIELD(ullAvailPhys, AvailablePhysicalMemory, _ui64toa);
#undef WRITE_STATEX_FIELD
}
if (oomAllocationSizeBufferLen) {
WriteFile(hFile, kOOMAllocationSizeParameter,
kOOMAllocationSizeParameterLen, &nBytes, NULL);
@@ -657,6 +663,8 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory,
NS_ASSERTION(!crashReporterAPILock, "Shouldn't have a lock yet");
crashReporterAPILock = new Mutex("crashReporterAPILock");
NS_ASSERTION(!notesFieldLock, "Shouldn't have a lock yet");
notesFieldLock = new Mutex("notesFieldLock");
crashReporterAPIData_Hash =
new nsDataHashtable<nsCStringHashKey,nsCString>();
@@ -1086,6 +1094,9 @@ nsresult UnsetExceptionHandler()
delete crashReporterAPILock;
crashReporterAPILock = nsnull;
delete notesFieldLock;
notesFieldLock = nsnull;
delete crashReporterAPIData;
crashReporterAPIData = nsnull;
@@ -1255,6 +1266,10 @@ nsresult AppendAppNotesToCrashReport(const nsACString& data)
return NS_ERROR_INVALID_ARG;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!NS_IsMainThread()) {
NS_ERROR("Cannot call AnnotateCrashReport in child processes from non-main thread.");
return NS_ERROR_FAILURE;
}
PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter();
if (!reporter) {
EnqueueDelayedNote(new DelayedNote(data));
@@ -1274,6 +1289,8 @@ nsresult AppendAppNotesToCrashReport(const nsACString& data)
return NS_OK;
}
MutexAutoLock lock(*notesFieldLock);
notesField->Append(data);
return AnnotateCrashReport(NS_LITERAL_CSTRING("Notes"), *notesField);
}

View File

@@ -66,11 +66,12 @@ bool GetMinidumpPath(nsAString& aPath);
nsresult SetMinidumpPath(const nsAString& aPath);
// AnnotateCrashReport may be called from any thread in a chrome process,
// but may only be called from the main thread in a content process.
// AnnotateCrashReport and AppendAppNotesToCrashReport may be called from any
// thread in a chrome process, but may only be called from the main thread in
// a content process.
nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
nsresult AppendAppNotesToCrashReport(const nsACString& data);
nsresult SetRestartArgs(int argc, char** argv);
nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
const nsACString& aBuildID);

View File

@@ -6,9 +6,13 @@ function run_test()
}
var is_win7_or_newer = false;
var is_windows = false;
var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"]
.getService(Components.interfaces.nsIHttpProtocolHandler);
var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/);
if (match) {
is_windows = true;
}
if (match && (parseInt(match[1]) > 6 ||
parseInt(match[1]) == 6 && parseInt(match[2]) >= 1)) {
is_win7_or_newer = true;
@@ -22,6 +26,12 @@ function run_test()
do_check_true('CrashTime' in extra);
do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_THREAD_LIST_STREAM));
do_check_true(CrashTestUtils.dumpHasInstructionPointerMemory(mdump.path));
if (is_windows) {
['SystemMemoryUsePercentage', 'TotalVirtualMemory', 'AvailableVirtualMemory',
'AvailablePageFile', 'AvailablePhysicalMemory'].forEach(function(prop) {
do_check_true(extra[prop].toString().match(/^\d+$/));
});
}
if (is_win7_or_newer)
do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM));
});

View File

@@ -425,6 +425,7 @@ OS_LIBS += \
-lmedia \
-lhardware_legacy \
-lhardware \
-lutils \
$(NULL)
endif

View File

@@ -42,7 +42,6 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <signal.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
@@ -53,6 +52,7 @@
#include "nscore.h"
#include "mozilla/FileUtils.h"
#include "mozilla/Mutex.h"
#include "mozilla/Services.h"
#include "nsAppShell.h"
#include "nsGkAtoms.h"
@@ -61,26 +61,9 @@
#include "nsWindow.h"
#include "android/log.h"
#ifndef ABS_MT_TOUCH_MAJOR
// Taken from include/linux/input.h
// XXX update the bionic input.h so we don't have to do this!
#define ABS_X 0x00
#define ABS_Y 0x01
// ...
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
#define SYN_MT_REPORT 2
#endif
#include "ui/EventHub.h"
#include "ui/InputReader.h"
#include "ui/InputDispatcher.h"
#define LOG(args...) \
__android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
@@ -93,6 +76,7 @@
#endif
using namespace mozilla;
using namespace android;
bool gDrawRequest = false;
static nsAppShell *gAppShell = NULL;
@@ -123,21 +107,15 @@ pipeHandler(int fd, FdHandler *data)
} while (len > 0);
}
static
PRUint64 timevalToMS(const struct timeval &time)
{
return time.tv_sec * 1000 + time.tv_usec / 1000;
}
static void
sendMouseEvent(PRUint32 msg, struct timeval& time, int x, int y)
sendMouseEvent(PRUint32 msg, uint64_t timeMs, int x, int y)
{
nsMouseEvent event(true, msg, NULL,
nsMouseEvent::eReal, nsMouseEvent::eNormal);
event.refPoint.x = x;
event.refPoint.y = y;
event.time = timevalToMS(time);
event.time = timeMs;
event.isShift = false;
event.isControl = false;
event.isMeta = false;
@@ -152,64 +130,64 @@ sendMouseEvent(PRUint32 msg, struct timeval& time, int x, int y)
static nsEventStatus
sendKeyEventWithMsg(PRUint32 keyCode,
PRUint32 msg,
const timeval &time,
uint64_t timeMs,
PRUint32 flags)
{
nsKeyEvent event(true, msg, NULL);
event.keyCode = keyCode;
event.time = timevalToMS(time);
event.time = timeMs;
event.flags |= flags;
return nsWindow::DispatchInputEvent(event);
}
static void
sendKeyEvent(PRUint32 keyCode, bool down, const timeval &time)
sendKeyEvent(PRUint32 keyCode, bool down, uint64_t timeMs)
{
nsEventStatus status =
sendKeyEventWithMsg(keyCode, down ? NS_KEY_DOWN : NS_KEY_UP, time, 0);
sendKeyEventWithMsg(keyCode, down ? NS_KEY_DOWN : NS_KEY_UP, timeMs, 0);
if (down) {
sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, time,
sendKeyEventWithMsg(keyCode, NS_KEY_PRESS, timeMs,
status == nsEventStatus_eConsumeNoDefault ?
NS_EVENT_FLAG_NO_DEFAULT : 0);
}
}
static void
sendSpecialKeyEvent(nsIAtom *command, const timeval &time)
sendSpecialKeyEvent(nsIAtom *command, uint64_t timeMs)
{
nsCommandEvent event(true, nsGkAtoms::onAppCommand, command, NULL);
event.time = timevalToMS(time);
event.time = timeMs;
nsWindow::DispatchInputEvent(event);
}
static void
maybeSendKeyEvent(int keyCode, bool pressed, const timeval& time)
maybeSendKeyEvent(int keyCode, bool pressed, uint64_t timeMs)
{
switch (keyCode) {
case KEY_BACK:
sendKeyEvent(NS_VK_ESCAPE, pressed, time);
sendKeyEvent(NS_VK_ESCAPE, pressed, timeMs);
break;
case KEY_MENU:
if (!pressed)
sendSpecialKeyEvent(nsGkAtoms::Menu, time);
sendSpecialKeyEvent(nsGkAtoms::Menu, timeMs);
break;
case KEY_SEARCH:
if (pressed)
sendSpecialKeyEvent(nsGkAtoms::Search, time);
sendSpecialKeyEvent(nsGkAtoms::Search, timeMs);
break;
case KEY_HOME:
sendKeyEvent(NS_VK_HOME, pressed, time);
sendKeyEvent(NS_VK_HOME, pressed, timeMs);
break;
case KEY_POWER:
sendKeyEvent(NS_VK_SLEEP, pressed, time);
sendKeyEvent(NS_VK_SLEEP, pressed, timeMs);
break;
case KEY_VOLUMEUP:
if (pressed)
sendSpecialKeyEvent(nsGkAtoms::VolumeUp, time);
sendSpecialKeyEvent(nsGkAtoms::VolumeUp, timeMs);
break;
case KEY_VOLUMEDOWN:
if (pressed)
sendSpecialKeyEvent(nsGkAtoms::VolumeDown, time);
sendSpecialKeyEvent(nsGkAtoms::VolumeDown, timeMs);
break;
default:
VERBOSE_LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d",
@@ -217,35 +195,139 @@ maybeSendKeyEvent(int keyCode, bool pressed, const timeval& time)
}
}
static void
maybeSendKeyEvent(const input_event& e)
struct UserInputData {
uint64_t timeMs;
enum {
MOTION_DATA,
KEY_DATA
} type;
int32_t action;
int32_t flags;
int32_t metaState;
union {
struct {
int32_t keyCode;
int32_t scanCode;
} key;
struct {
PointerCoords coords;
} motion;
};
};
class GeckoInputReaderPolicy : public InputReaderPolicyInterface {
public:
GeckoInputReaderPolicy() {}
virtual bool getDisplayInfo(int32_t displayId,
int32_t* width, int32_t* height, int32_t* orientation);
virtual bool filterTouchEvents();
virtual bool filterJumpyTouchEvents();
virtual nsecs_t getVirtualKeyQuietTime();
virtual void getVirtualKeyDefinitions(const String8& deviceName,
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions);
virtual void getInputDeviceCalibration(const String8& deviceName,
InputDeviceCalibration& outCalibration);
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
protected:
virtual ~GeckoInputReaderPolicy() {}
};
class GeckoInputDispatcher : public InputDispatcherInterface {
public:
GeckoInputDispatcher()
: mQueueLock("GeckoInputDispatcher::mQueueMutex")
{}
virtual void dump(String8& dump);
// Called on the main thread
virtual void dispatchOnce();
// notify* methods are called on the InputReaderThread
virtual void notifyConfigurationChanged(nsecs_t eventTime);
virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime);
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
virtual void notifySwitch(nsecs_t when,
int32_t switchCode, int32_t switchValue, uint32_t policyFlags);
virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
virtual void setFocusedApplication(const InputApplication* inputApplication);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
protected:
virtual ~GeckoInputDispatcher() {}
private:
// mQueueLock should generally be locked while using mEventQueue.
// UserInputData is pushed on on the InputReaderThread and
// popped and dispatched on the main thread.
mozilla::Mutex mQueueLock;
std::queue<UserInputData> mEventQueue;
};
// GeckoInputReaderPolicy
bool
GeckoInputReaderPolicy::getDisplayInfo(int32_t displayId,
int32_t* width,
int32_t* height,
int32_t* orientation)
{
if (e.type != EV_KEY) {
VERBOSE_LOG("Got unknown key event type. type 0x%04x code 0x%04x value %d",
e.type, e.code, e.value);
return;
}
// 0 is the default displayId. We only support one display
if (displayId)
return false;
if (e.value != 0 && e.value != 1) {
VERBOSE_LOG("Got unknown key event value. type 0x%04x code 0x%04x value %d",
e.type, e.code, e.value);
return;
}
bool pressed = e.value == 1;
maybeSendKeyEvent(e.code, pressed, e.time);
if (width)
*width = gScreenBounds.width;
if (height)
*height = gScreenBounds.height;
if (orientation)
*orientation = ROTATION_0;
return true;
}
static void
configureVButtons(FdHandler& data)
bool
GeckoInputReaderPolicy::filterTouchEvents()
{
return false;
}
bool
GeckoInputReaderPolicy::filterJumpyTouchEvents()
{
return false;
}
nsecs_t
GeckoInputReaderPolicy::getVirtualKeyQuietTime()
{
return 0;
}
void
GeckoInputReaderPolicy::getVirtualKeyDefinitions(const String8& deviceName,
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions)
{
outVirtualKeyDefinitions.clear();
char vbuttonsPath[PATH_MAX];
snprintf(vbuttonsPath, sizeof(vbuttonsPath),
"/sys/board_properties/virtualkeys.%s",
data.name);
deviceName.string());
ScopedClose fd(open(vbuttonsPath, O_RDONLY));
if (0 > fd.mFd) {
LOG("No vbuttons for mt device %s", data.name);
LOG("No vbuttons for mt device %s", deviceName.string());
return;
}
@@ -263,31 +345,23 @@ configureVButtons(FdHandler& data)
config[nread] = '\0';
LOG("Device %s has vbutton config '%s'", data.name, config);
LOG("Device %s has vbutton config '%s'", deviceName.string(), config);
char* startStr = config;
for (size_t i = 0; i < FdHandler::kMaxVButtons; ++i) {
FdHandler::VButton& vbutton = data.vbuttons[i];
char* token;
char* state;
char* first = config;
char* magic;
char* state;
while ((magic = strtok_r(first, ":", &state))) {
// XXX not clear what "0x01" is ... maybe a version
// number? See InputManager.java.
if (!(token = strtok_r(startStr, ":", &state)) ||
strcmp(token, "0x01")) {
if (strcmp(magic, "0x01")) {
LOG(" magic 0x01 tag missing");
break;
}
startStr = NULL;
first = NULL;
if (!(token = strtok_r(NULL, ":", &state))) {
LOG(" failed to read keycode");
break;
}
vbutton.keyCode = atoi(token);
const char *centerX, *centerY, *width, *height;
if (!((centerX = strtok_r(NULL, ":", &state)) &&
const char *scanCode, *centerX, *centerY, *width, *height;
if (!((scanCode = strtok_r(NULL, ":", &state)) &&
(centerX = strtok_r(NULL, ":", &state)) &&
(centerY = strtok_r(NULL, ":", &state)) &&
(width = strtok_r(NULL, ":", &state)) &&
(height = strtok_r(NULL, ":", &state)))) {
@@ -299,247 +373,194 @@ configureVButtons(FdHandler& data)
// space. That means the values in /sys/board_config make
// assumptions about how the raw input events are mapped
// ... le sigh.
nsIntRect rect;
rect.width = atoi(width);
rect.height = atoi(height);
rect.x = atoi(centerX) - rect.width / 2;
rect.y = atoi(centerY) - rect.height / 2;
vbutton.buttonRect = rect;
VirtualKeyDefinition def;
def.scanCode = atoi(scanCode);
def.centerX = atoi(centerX);
def.centerY = atoi(centerY);
def.width = atoi(width);
def.height = atoi(height);
outVirtualKeyDefinitions.push(def);
LOG(" configured vbutton code=%d at <x=%d,y=%d,w=%d,h=%d>",
vbutton.keyCode, rect.x, rect.y, rect.width, rect.height);
def.scanCode, def.centerX, def.centerY, def.width, def.height);
}
}
static bool
calibrateMultitouchDevice(FdHandler& data)
void
GeckoInputReaderPolicy::getInputDeviceCalibration(const String8& deviceName, InputDeviceCalibration& outCalibration)
{
if (data.calibrated)
return true;
if (gScreenBounds.IsEmpty()) {
// The framebuffer hasn't been initialized yet. We *could*
// force it to be initialized here, but that's another patch.
LOG("Deferring multitouch calibrate, fb not ready");
return false;
}
struct input_absinfo xInfo, yInfo;
if (0 > ioctl(data.fd, EVIOCGABS(ABS_MT_POSITION_X), &xInfo) ||
0 > ioctl(data.fd, EVIOCGABS(ABS_MT_POSITION_Y), &yInfo)) {
LOG("Couldn't get absinfo for multitouch axes");
return false;
}
LOG("Input coordinate bounds: xmin=%d, xmax=%d, ymin=%d, ymax=%d",
xInfo.minimum, xInfo.maximum, yInfo.minimum, yInfo.maximum);
data.inputMinX = xInfo.minimum;
data.inputMinY = yInfo.minimum;
data.inputToScreenScaleX =
float(gScreenBounds.width) / float(xInfo.maximum - xInfo.minimum);
data.inputToScreenScaleY =
float(gScreenBounds.height) / float(yInfo.maximum - yInfo.minimum);
configureVButtons(data);
data.calibrated = true;
return true;
outCalibration.clear();
}
static void
multitouchHandler(int fd, FdHandler *data)
void
GeckoInputReaderPolicy::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames)
{
if (!calibrateMultitouchDevice(*data))
return;
// The Linux's input documentation (Documentation/input/input.txt)
// says that we'll always read a multiple of sizeof(input_event) bytes here.
input_event events[16];
int event_count = read(fd, events, sizeof(events));
if (event_count < 0) {
LOG("Error reading in multitouchHandler");
return;
}
MOZ_ASSERT(event_count % sizeof(input_event) == 0);
event_count /= sizeof(struct input_event);
for (int i = 0; i < event_count; i++) {
input_event *event = &events[i];
if (event->type == EV_ABS) {
if (data->mtState == FdHandler::MT_IGNORE)
continue;
if (data->mtState == FdHandler::MT_START)
data->mtState = FdHandler::MT_COLLECT;
switch (event->code) {
case ABS_MT_TOUCH_MAJOR:
data->mtMajor = event->value;
break;
case ABS_MT_TOUCH_MINOR:
case ABS_MT_WIDTH_MAJOR:
case ABS_MT_WIDTH_MINOR:
case ABS_MT_ORIENTATION:
case ABS_MT_TOOL_TYPE:
case ABS_MT_BLOB_ID:
case ABS_MT_TRACKING_ID:
case ABS_MT_PRESSURE:
break;
case ABS_MT_POSITION_X:
data->mtX = data->inputXToScreenX(event->value);
break;
case ABS_MT_POSITION_Y:
data->mtY = data->inputYToScreenY(event->value);
break;
default:
VERBOSE_LOG("Got unknown mt event type 0x%04x with code 0x%04x and value %d",
event->type, event->code, event->value);
break;
}
} else if (event->type == EV_SYN) {
switch (event->code) {
case SYN_MT_REPORT:
if (data->mtState == FdHandler::MT_COLLECT)
data->mtState = FdHandler::MT_IGNORE;
break;
case SYN_REPORT:
if (!data->mtMajor || data->mtState == FdHandler::MT_START) {
data->mtDown = false;
if (data->keyCode) {
maybeSendKeyEvent(data->keyCode, data->mtDown,
event->time);
data->keyCode = 0;
} else {
sendMouseEvent(NS_MOUSE_BUTTON_UP, event->time,
data->mtX, data->mtY);
}
} else if (!data->mtDown) {
int x = data->mtX, y = data->mtY;
bool isKeyEvent = false;
if (!gScreenBounds.Contains(x, y)) {
// Off-screen mt down. Should be a vbutton.
for (size_t i = 0; i < FdHandler::kMaxVButtons; ++i) {
const FdHandler::VButton& vbutton = data->vbuttons[i];
if (vbutton.buttonRect.IsEmpty())
break;
if (vbutton.buttonRect.Contains(x, y)) {
isKeyEvent = true;
data->keyCode = vbutton.keyCode;
break;
}
}
}
data->mtDown = true;
if (isKeyEvent) {
maybeSendKeyEvent(data->keyCode, data->mtDown,
event->time);
} else {
sendMouseEvent(NS_MOUSE_BUTTON_DOWN, event->time,
data->mtX, data->mtY);
}
} else if (!data->keyCode) {
sendMouseEvent(NS_MOUSE_MOVE, event->time,
data->mtX, data->mtY);
data->mtDown = true;
}
data->mtState = FdHandler::MT_START;
break;
default:
VERBOSE_LOG("Got unknown mt event type 0x%04x with code 0x%04x and value %d",
event->type, event->code, event->value);
}
} else
VERBOSE_LOG("Got unknown mt event type 0x%04x with code 0x%04x and value %d",
event->type, event->code, event->value);
}
outExcludedDeviceNames.clear();
}
static void
singleTouchHandler(int fd, FdHandler *data)
// GeckoInputDispatcher
void
GeckoInputDispatcher::dump(String8& dump)
{
// The Linux's input documentation (Documentation/input/input.txt)
// says that we'll always read a multiple of sizeof(input_event) bytes here.
input_event events[16];
int event_count = read(fd, events, sizeof(events));
if (event_count < 0) {
LOG("Error reading in singleTouchHandler");
return;
}
void
GeckoInputDispatcher::dispatchOnce()
{
UserInputData data;
{
MutexAutoLock lock(mQueueLock);
if (mEventQueue.empty())
return;
data = mEventQueue.front();
mEventQueue.pop();
if (!mEventQueue.empty())
gAppShell->NotifyNativeEvent();
}
MOZ_ASSERT(event_count % sizeof(input_event) == 0);
event_count /= sizeof(struct input_event);
for (int i = 0; i < event_count; i++) {
input_event *event = &events[i];
if (event->type == EV_KEY) {
switch (event->code) {
case BTN_TOUCH:
data->mtDown = event->value;
break;
default:
maybeSendKeyEvent(*event);
}
} else if (event->type == EV_ABS) {
switch (event->code) {
case ABS_X:
data->mtX = event->value;
break;
case ABS_Y:
data->mtY = event->value;
break;
default:
LOG("Got unknown st abs event type 0x%04x with code 0x%04x and value %d",
event->type, event->code, event->value);
}
} else if (event->type == EV_SYN) {
if (data->mtState == FdHandler::MT_START) {
MOZ_ASSERT(data->mtDown);
sendMouseEvent(NS_MOUSE_BUTTON_DOWN, event->time,
data->mtX, data->mtY);
data->mtState = FdHandler::MT_COLLECT;
} else if (data->mtDown) {
MOZ_ASSERT(data->mtDown);
sendMouseEvent(NS_MOUSE_MOVE, event->time,
data->mtX, data->mtY);
} else {
MOZ_ASSERT(!data->mtDown);
sendMouseEvent(NS_MOUSE_BUTTON_UP, event->time,
data->mtX, data->mtY);
data->mtDown = false;
data->mtState = FdHandler::MT_START;
}
switch (data.type) {
case UserInputData::MOTION_DATA: {
PRUint32 msg;
switch (data.action) {
case AMOTION_EVENT_ACTION_DOWN:
msg = NS_MOUSE_BUTTON_DOWN;
break;
case AMOTION_EVENT_ACTION_MOVE:
msg = NS_MOUSE_MOVE;
break;
case AMOTION_EVENT_ACTION_UP:
msg = NS_MOUSE_BUTTON_UP;
break;
}
sendMouseEvent(msg,
data.timeMs,
data.motion.coords.x,
data.motion.coords.y);
break;
}
case UserInputData::KEY_DATA:
maybeSendKeyEvent(data.key.scanCode,
data.action == AKEY_EVENT_ACTION_DOWN,
data.timeMs);
break;
}
}
static void
keyHandler(int fd, FdHandler *data)
void
GeckoInputDispatcher::notifyConfigurationChanged(nsecs_t eventTime)
{
input_event events[16];
ssize_t bytesRead = read(fd, events, sizeof(events));
if (bytesRead < 0) {
LOG("Error reading in keyHandler");
return;
}
static uint64_t
nanosecsToMillisecs(nsecs_t nsecs)
{
return nsecs / 1000000;
}
void
GeckoInputDispatcher::notifyKey(nsecs_t eventTime,
int32_t deviceId,
int32_t source,
uint32_t policyFlags,
int32_t action,
int32_t flags,
int32_t keyCode,
int32_t scanCode,
int32_t metaState,
nsecs_t downTime)
{
UserInputData data;
data.timeMs = nanosecsToMillisecs(eventTime);
data.type = UserInputData::KEY_DATA;
data.action = action;
data.flags = flags;
data.metaState = metaState;
data.key.keyCode = keyCode;
data.key.scanCode = scanCode;
{
MutexAutoLock lock(mQueueLock);
mEventQueue.push(data);
}
MOZ_ASSERT(bytesRead % sizeof(input_event) == 0);
gAppShell->NotifyNativeEvent();
}
for (unsigned int i = 0; i < bytesRead / sizeof(struct input_event); i++) {
const input_event &e = events[i];
if (e.type == EV_SYN) {
// Ignore this event; it just signifies that a key was pressed.
continue;
}
maybeSendKeyEvent(e);
void
GeckoInputDispatcher::notifyMotion(nsecs_t eventTime,
int32_t deviceId,
int32_t source,
uint32_t policyFlags,
int32_t action,
int32_t flags,
int32_t metaState,
int32_t edgeFlags,
uint32_t pointerCount,
const int32_t* pointerIds,
const PointerCoords* pointerCoords,
float xPrecision,
float yPrecision,
nsecs_t downTime)
{
UserInputData data;
data.timeMs = nanosecsToMillisecs(eventTime);
data.type = UserInputData::MOTION_DATA;
data.action = action;
data.flags = flags;
data.metaState = metaState;
data.motion.coords = *pointerCoords;
{
MutexAutoLock lock(mQueueLock);
mEventQueue.push(data);
}
gAppShell->NotifyNativeEvent();
}
void
GeckoInputDispatcher::notifySwitch(nsecs_t when,
int32_t switchCode,
int32_t switchValue,
uint32_t policyFlags)
{
}
int32_t
GeckoInputDispatcher::injectInputEvent(const InputEvent* event,
int32_t injectorPid,
int32_t injectorUid,
int32_t syncMode,
int32_t timeoutMillis)
{
return INPUT_EVENT_INJECTION_SUCCEEDED;
}
void
GeckoInputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows)
{
}
void
GeckoInputDispatcher::setFocusedApplication(const InputApplication* inputApplication)
{
}
void
GeckoInputDispatcher::setInputDispatchMode(bool enabled, bool frozen)
{
}
status_t
GeckoInputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
bool monitor)
{
return OK;
}
status_t
GeckoInputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel)
{
return OK;
}
nsAppShell::nsAppShell()
@@ -551,6 +572,9 @@ nsAppShell::nsAppShell()
nsAppShell::~nsAppShell()
{
status_t result = mReaderThread->requestExitAndWait();
if (result)
LOG("Could not stop reader thread - %d", result);
gAppShell = NULL;
}
@@ -569,52 +593,15 @@ nsAppShell::Init()
rv = AddFdHandler(signalfds[0], pipeHandler, "");
NS_ENSURE_SUCCESS(rv, rv);
DIR *dir = opendir("/dev/input");
NS_ENSURE_TRUE(dir, NS_ERROR_UNEXPECTED);
mEventHub = new EventHub();
mReaderPolicy = new GeckoInputReaderPolicy();
mDispatcher = new GeckoInputDispatcher();
#define IS_BIT_SET(bit, flags) (flags[bit >> 3] & (1 << (bit & 0x7)))
struct dirent *entry;
while ((entry = readdir(dir))) {
char entryName[64];
char entryPath[MAXPATHLEN];
if (snprintf(entryPath, sizeof(entryPath),
"/dev/input/%s", entry->d_name) < 0) {
LOG("Couldn't generate path while enumerating input devices!");
continue;
}
int fd = open(entryPath, O_RDONLY);
if (ioctl(fd, EVIOCGNAME(sizeof(entryName)), entryName) >= 0)
LOG("Found device %s - %s", entry->d_name, entryName);
else
continue;
FdHandlerCallback handlerFunc = NULL;
char flags[(NS_MAX(ABS_MAX, KEY_MAX) + 1) / 8];
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 &&
IS_BIT_SET(ABS_MT_POSITION_X, flags)) {
LOG("Found multitouch input device");
handlerFunc = multitouchHandler;
} else if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(flags)), flags) >= 0 &&
IS_BIT_SET(ABS_X, flags)) {
LOG("Found single touch input device");
handlerFunc = singleTouchHandler;
} else if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(flags)), flags) >= 0) {
LOG("Found key input device");
handlerFunc = keyHandler;
}
// Register the handler, if we have one.
if (!handlerFunc)
continue;
rv = AddFdHandler(fd, handlerFunc, entryName);
if (NS_FAILED(rv))
LOG("Failed to add fd to epoll fd");
}
mReader = new InputReader(mEventHub, mReaderPolicy, mDispatcher);
mReaderThread = new InputReaderThread(mReader);
status_t result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
NS_ENSURE_FALSE(result, NS_ERROR_UNEXPECTED);
return rv;
}
@@ -655,6 +642,8 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
for (int i = 0; i < event_count; i++)
mHandlers[events[i].data.u32].run();
mDispatcher->dispatchOnce();
// NativeEventCallback always schedules more if it needs it
// so we can coalesce these.
// See the implementation in nsBaseAppShell.cpp for more info

View File

@@ -38,10 +38,15 @@
#ifndef nsAppShell_h
#define nsAppShell_h
#include <queue>
#include "mozilla/Mutex.h"
#include "nsBaseAppShell.h"
#include "nsRect.h"
#include "nsTArray.h"
#include "utils/RefBase.h"
namespace mozilla {
bool ProcessNextEvent();
void NotifyEvent();
@@ -55,10 +60,6 @@ typedef void(*FdHandlerCallback)(int, FdHandler *);
class FdHandler {
public:
FdHandler()
: mtState(MT_START)
, keyCode(0)
, mtDown(false)
, calibrated(false)
{
memset(name, 0, sizeof(name));
}
@@ -66,57 +67,21 @@ public:
int fd;
char name[64];
FdHandlerCallback func;
enum mtStates {
MT_START,
MT_COLLECT,
MT_IGNORE
} mtState;
int mtX, mtY;
int mtMajor;
int keyCode;
bool mtDown;
// FIXME/bug 712973: we should be using libui here instead of
// recreating all that logic ourselves. Please don't extend the
// hacks here further than what's below.
bool calibrated;
// Multitouch events are delivered to us in "input space", which
// is a coordinate space defined by the multitouch device driver.
// The coordinate space has top-left at P_min = <inputMinX,
// inputMinY> when in normal-portrait orientation. The input
// device and the screen might have different resolutions. The
// resolution difference is Scale = <inputToScreenScaleX,
// inputToScreenScaleY>. So going from input to screen space
// (when in normal portrait orientation) is an affine transform
// defined by
//
// P_screen = Scale * (P_input - P_min)
//
int inputMinX, inputMinY;
float inputToScreenScaleX, inputToScreenScaleY;
// Some touch devices use virtual buttons instead of hardware
// buttons. When the device uses vbuttons, we convert touch
// events into key events of type |keyCode| when the start of the
// touch is within |buttonRect|. |buttonRect| must be disjoint
// from the screen rect.
static const size_t kMaxVButtons = 4;
struct VButton {
nsIntRect buttonRect; // in screen space
int keyCode;
} vbuttons[kMaxVButtons];
void run()
{
func(fd, this);
}
int inputXToScreenX(int inputX) {
return inputToScreenScaleX * (inputX - inputMinX);
}
int inputYToScreenY(int inputY) {
return inputToScreenScaleY * (inputY - inputMinY);
}
};
namespace android {
class EventHub;
class InputReader;
class InputReaderThread;
}
class GeckoInputReaderPolicy;
class GeckoInputDispatcher;
class nsAppShell : public nsBaseAppShell {
public:
nsAppShell();
@@ -138,6 +103,12 @@ private:
// This is somewhat racy but is perfectly safe given how the callback works
bool mNativeCallbackRequest;
nsTArray<FdHandler> mHandlers;
android::sp<android::EventHub> mEventHub;
android::sp<GeckoInputReaderPolicy> mReaderPolicy;
android::sp<GeckoInputDispatcher> mDispatcher;
android::sp<android::InputReader> mReader;
android::sp<android::InputReaderThread> mReaderThread;
};
#endif /* nsAppShell_h */

View File

@@ -47,6 +47,7 @@
#include "nsAppShellSingleton.h"
#include "nsScreenManagerGonk.h"
#include "nsIdleServiceGonk.h"
#include "nsTransferable.h"
#include "nsHTMLFormatConverter.h"
#include "nsXULAppAPI.h"
@@ -55,6 +56,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerGonk)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceGonk)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
NS_DEFINE_NAMED_CID(NS_WINDOW_CID);
@@ -62,6 +64,7 @@ NS_DEFINE_NAMED_CID(NS_CHILD_CID);
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_WINDOW_CID, false, NULL, nsWindowConstructor },
@@ -70,6 +73,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerGonkConstructor },
{ &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor },
{ &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceGonkConstructor },
{ &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor },
{ NULL }
};
@@ -80,6 +84,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
{ "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
{ "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
{ "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
{ NULL }
};

View File

@@ -2823,7 +2823,7 @@ nsCycleCollector::GCIfNeeded(bool aForceGC)
// rt->Collect() must be called from the main thread,
// because it invokes XPCJSRuntime::GCCallback(cx, JSGC_BEGIN)
// which returns false if not in the main thread.
rt->Collect();
rt->Collect(js::gcreason::CC_FORCED, nsGCNormal);
#ifdef COLLECT_TIME_DEBUG
printf("cc: GC() took %lldms\n", (PR_Now() - start) / PR_USEC_PER_MSEC);
#endif

View File

@@ -106,9 +106,10 @@ struct nsCycleCollectionJSRuntime : public nsCycleCollectionLanguageRuntime
virtual bool NeedCollect() = 0;
/**
* Runs the JavaScript GC.
* Runs the JavaScript GC. |reason| is a gcreason::Reason from jsfriendapi.h.
* |kind| is a nsGCType from nsIXPConnect.idl.
*/
virtual void Collect(bool shrinkingGC = false) = 0;
virtual void Collect(PRUint32 reason, PRUint32 kind) = 0;
};
#ifdef DEBUG

View File

@@ -3,7 +3,6 @@ export JAVA_HOME=/d/jdk1.6.0_14
ac_add_options --enable-application=xulrunner
ac_add_options --enable-jemalloc
ac_add_options --disable-installer
ac_add_options --disable-tests
mk_add_options MOZ_MAKE_FLAGS=-j1

View File

@@ -6,7 +6,6 @@ export JAVA_HOME=/d/jdk1.6.0_14
ac_add_options --enable-application=xulrunner
ac_add_options --enable-jemalloc
ac_add_options --disable-installer
ac_add_options --disable-tests
mk_add_options MOZ_MAKE_FLAGS=-j1