From f99b55852b0a08d57fcb5c0ea1cd04f2202416f6 Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Mon, 26 Mar 2012 21:05:09 -0700 Subject: [PATCH 001/113] Bug 720679 - 'Crash @ WorkerPrivate::CancelAllTimeouts while closing Firefox'. r=khuey. --- dom/workers/WorkerPrivate.cpp | 34 +++++++++++++++++++----- dom/workers/test/Makefile.in | 2 ++ dom/workers/test/clearTimeouts_worker.js | 12 +++++++++ dom/workers/test/test_clearTimeouts.html | 30 +++++++++++++++++++++ 4 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 dom/workers/test/clearTimeouts_worker.js create mode 100644 dom/workers/test/test_clearTimeouts.html diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 934ba10a73c..667db0b560d 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3164,6 +3164,8 @@ WorkerPrivate::NotifyFeatures(JSContext* aCx, Status aStatus) void WorkerPrivate::CancelAllTimeouts(JSContext* aCx) { + AssertIsOnWorkerThread(); + if (mTimerRunning) { NS_ASSERTION(mTimer, "Huh?!"); NS_ASSERTION(!mTimeouts.IsEmpty(), "Huh?!"); @@ -3176,13 +3178,19 @@ WorkerPrivate::CancelAllTimeouts(JSContext* aCx) mTimeouts[index]->mCanceled = true; } - RunExpiredTimeouts(aCx); + if (!RunExpiredTimeouts(aCx)) { + JS_ReportPendingException(aCx); + } - mTimer = nsnull; + mTimerRunning = false; } - else { +#ifdef DEBUG + else if (!mRunningExpiredTimeouts) { NS_ASSERTION(mTimeouts.IsEmpty(), "Huh?!"); } +#endif + + mTimer = nsnull; } PRUint32 @@ -3511,8 +3519,15 @@ WorkerPrivate::SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp, currentStatus = mStatus; } - if (currentStatus > Running) { + // It's a script bug if setTimeout/setInterval are called from a close handler + // so throw an exception. + if (currentStatus == Closing) { JS_ReportError(aCx, "Cannot schedule timeouts from the close handler!"); + } + + // If the worker is trying to call setTimeout/setInterval and the parent + // thread has initiated the close process then just silently fail. + if (currentStatus >= Closing) { return false; } @@ -3655,6 +3670,7 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) return true; } + NS_ASSERTION(mTimer, "Must have a timer!"); NS_ASSERTION(!mTimeouts.IsEmpty(), "Should have some work to do!"); bool retval = true; @@ -3719,12 +3735,16 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) } } + NS_ASSERTION(mRunningExpiredTimeouts, "Someone changed this!"); + // Reschedule intervals. - if (info->mIsInterval) { + if (info->mIsInterval && !info->mCanceled) { PRUint32 timeoutIndex = mTimeouts.IndexOf(info); NS_ASSERTION(timeoutIndex != PRUint32(-1), "Should still be in the main list!"); + // This is nasty but we have to keep the old nsAutoPtr from deleting the + // info we're about to re-add. mTimeouts[timeoutIndex].forget(); mTimeouts.RemoveElementAt(timeoutIndex); @@ -3755,8 +3775,8 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) } } - // Signal the parent that we're no longer using timeouts or reschedule the - // timer. + // Either signal the parent that we're no longer using timeouts or reschedule + // the timer. if (mTimeouts.IsEmpty()) { if (!ModifyBusyCountFromWorker(aCx, false)) { retval = false; diff --git a/dom/workers/test/Makefile.in b/dom/workers/test/Makefile.in index efe31ede1d3..f577afd6bae 100644 --- a/dom/workers/test/Makefile.in +++ b/dom/workers/test/Makefile.in @@ -56,6 +56,8 @@ _TEST_FILES = \ test_atob.html \ atob_worker.js \ test_blobWorkers.html \ + test_clearTimeouts.html \ + clearTimeouts_worker.js \ test_close.html \ close_worker.js \ test_closeOnGC.html \ diff --git a/dom/workers/test/clearTimeouts_worker.js b/dom/workers/test/clearTimeouts_worker.js new file mode 100644 index 00000000000..b471515b3ec --- /dev/null +++ b/dom/workers/test/clearTimeouts_worker.js @@ -0,0 +1,12 @@ +var count = 0; +function timerFunction() { + if (++count == 30) { + close(); + postMessage("ready"); + while (true) { } + } +} + +for (var i = 0; i < 10; i++) { + setInterval(timerFunction, 500); +} diff --git a/dom/workers/test/test_clearTimeouts.html b/dom/workers/test/test_clearTimeouts.html new file mode 100644 index 00000000000..5a6e83e5205 --- /dev/null +++ b/dom/workers/test/test_clearTimeouts.html @@ -0,0 +1,30 @@ + + + + + Test for DOM Worker Threads + + + + +

+ +
+
+
+ + From 10f76a25264aae9f8d0df4d89e7ddaa5f6538e05 Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Mon, 26 Mar 2012 22:37:16 -0700 Subject: [PATCH 002/113] Bug 708187: Disable caching of font inflation inside of BuildTextRunsScanner to prevent bleeding of bad values. [r=dbaron] --- .../consecutive-inline-ref.html | 29 ++++++ .../font-inflation/consecutive-inline.html | 29 ++++++ .../tests/test_font_inflation_reftests.html | 1 + layout/generic/nsTextFrame.h | 13 +-- layout/generic/nsTextFrameThebes.cpp | 88 ++++++++++++------- 5 files changed, 119 insertions(+), 41 deletions(-) create mode 100644 layout/base/tests/font-inflation/consecutive-inline-ref.html create mode 100644 layout/base/tests/font-inflation/consecutive-inline.html diff --git a/layout/base/tests/font-inflation/consecutive-inline-ref.html b/layout/base/tests/font-inflation/consecutive-inline-ref.html new file mode 100644 index 00000000000..5ce96342182 --- /dev/null +++ b/layout/base/tests/font-inflation/consecutive-inline-ref.html @@ -0,0 +1,29 @@ + + + +
+ HelloWorldz +
diff --git a/layout/base/tests/font-inflation/consecutive-inline.html b/layout/base/tests/font-inflation/consecutive-inline.html new file mode 100644 index 00000000000..3eee4b37707 --- /dev/null +++ b/layout/base/tests/font-inflation/consecutive-inline.html @@ -0,0 +1,29 @@ + + + +
+ HelloWorldz +
\ No newline at end of file diff --git a/layout/base/tests/test_font_inflation_reftests.html b/layout/base/tests/test_font_inflation_reftests.html index 99c1f8c5f8f..52dd4b517f4 100644 --- a/layout/base/tests/test_font_inflation_reftests.html +++ b/layout/base/tests/test_font_inflation_reftests.html @@ -68,6 +68,7 @@ var gTests = [ "== preformatted-text.html preformatted-text-ref.html", "== fixed-height-body.html fixed-height-body-ref.html", "== fixed-height-body-child.html fixed-height-body-child-ref.html", + "== consecutive-inline.html consecutive-inline-ref.html", ]; // Maintain a reference count of how many things we're waiting for until diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 21660dc9f7c..e9962a75633 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -284,10 +284,10 @@ public: void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, nsIFrame::InlineMinWidthData *aData, - float aInflation, TextRunType aTextRunType); + TextRunType aTextRunType); void AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, InlinePrefWidthData *aData, - float aInflation, TextRunType aTextRunType); + TextRunType aTextRunType); /** * Calculate the horizontal bounds of the grapheme clusters that fit entirely @@ -385,7 +385,6 @@ public: * Acquires the text run for this content, if necessary. * @param aWhichTextRun indicates whether to get an inflated or non-inflated * text run - * @param aInflation the text inflation scale * @param aReferenceContext the rendering context to use as a reference for * creating the textrun, if available (if not, we'll create one which will * just be slower) @@ -398,18 +397,10 @@ public: * content offset */ gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun, - float aInflation, gfxContext* aReferenceContext = nsnull, nsIFrame* aLineContainer = nsnull, const nsLineList::iterator* aLine = nsnull, PRUint32* aFlowEndInTextRun = nsnull); - // Since we can't reference |this| in default arguments: - gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun) { - return EnsureTextRun(aWhichTextRun, - (aWhichTextRun == eInflated) - ? GetFontSizeInflation() : 1.0f); - } - gfxTextRun* GetTextRun(TextRunType aWhichTextRun) { if (aWhichTextRun == eInflated || !HasFontSizeInflation()) diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 71ea612501d..e3bd79942d0 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -779,12 +779,10 @@ IsAllWhitespace(const nsTextFragment* aFrag, bool aAllowNewline) class BuildTextRunsScanner { public: BuildTextRunsScanner(nsPresContext* aPresContext, gfxContext* aContext, - nsIFrame* aLineContainer, nsTextFrame::TextRunType aWhichTextRun, - float aInflation) : + nsIFrame* aLineContainer, nsTextFrame::TextRunType aWhichTextRun) : mCurrentFramesAllSameTextRun(nsnull), mContext(aContext), mLineContainer(aLineContainer), - mInflation(aInflation), mBidiEnabled(aPresContext->BidiEnabled()), mSkipIncompleteTextRuns(false), mWhichTextRun(aWhichTextRun), @@ -840,7 +838,7 @@ public: */ gfxTextRun* BuildTextRunForFrames(void* aTextBuffer); bool SetupLineBreakerContext(gfxTextRun *aTextRun); - void AssignTextRun(gfxTextRun* aTextRun); + void AssignTextRun(gfxTextRun* aTextRun, float aInflation); nsTextFrame* GetNextBreakBeforeFrame(PRUint32* aIndex); enum SetupBreakSinksFlags { SBS_DOUBLE_BYTE = (1 << 0), @@ -949,7 +947,6 @@ private: // mMaxTextLength is an upper bound on the size of the text in all mapped frames // The value PR_UINT32_MAX represents overflow; text will be discarded PRUint32 mMaxTextLength; - float mInflation; bool mDoubleByteText; bool mBidiEnabled; bool mStartOfLine; @@ -1151,17 +1148,21 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState * General routine for building text runs. This is hairy because of the need * to build text runs that span content nodes. * - * @param aForFrameLine the line containing aForFrame; if null, we'll figure - * out the line (slowly) + * @param aContext The gfxContext we're using to construct this text run. + * @param aForFrame The nsTextFrame for which we're building this text run. * @param aLineContainer the line container containing aForFrame; if null, - * we'll walk the ancestors to find it. It's required to be non-null when - * aForFrameLine is non-null. + * we'll walk the ancestors to find it. It's required to be non-null + * when aForFrameLine is non-null. + * @param aForFrameLine the line containing aForFrame; if null, we'll figure + * out the line (slowly) + * @param aWhichTextRun The type of text run we want to build. If font inflation + * is enabled, this will be eInflated, otherwise it's eNotInflated. */ static void BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame, nsIFrame* aLineContainer, const nsLineList::iterator* aForFrameLine, - nsTextFrame::TextRunType aWhichTextRun, float aInflation) + nsTextFrame::TextRunType aWhichTextRun) { NS_ASSERTION(aForFrame || aLineContainer, "One of aForFrame or aLineContainer must be set!"); @@ -1185,7 +1186,7 @@ BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame, nsPresContext* presContext = aLineContainer->PresContext(); BuildTextRunsScanner scanner(presContext, aContext, aLineContainer, - aWhichTextRun, aInflation); + aWhichTextRun); nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aLineContainer); @@ -1875,7 +1876,40 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) // Now build the textrun nsTextFrame* firstFrame = mMappedFlows[0].mStartFrame; - gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame, mInflation); + float fontInflation; + if (mWhichTextRun == nsTextFrame::eNotInflated) { + fontInflation = 1.0f; + } else { + nsPresContext* presContext = firstFrame->PresContext(); + nsLayoutUtils::WidthDetermination widthDeter = nsLayoutUtils::eNotInReflow; + + if (presContext->PresShell()->IsReflowLocked()) { + widthDeter = nsLayoutUtils::eInReflow; + } + +#ifdef DEBUG + if (widthDeter == nsLayoutUtils::eInReflow) { + // Make sure that the font inflation container is correct. + nsIFrame* inflationContainer = nsnull; + for (nsIFrame* f = firstFrame; f; f = f->GetParent()) { + if (nsLayoutUtils::IsContainerForFontSizeInflation(f)) { + inflationContainer = f; + break; + } + } + + // FIXME: When we support variable width containers (e.g. for regions or + // differing-width columns, we should revisit this assertion. + NS_ASSERTION(inflationContainer->GetFirstInFlow() == + presContext->mCurrentInflationContainer->GetFirstInFlow(), + "Current inflation container for text frame is wrong"); + } +#endif // #ifdef DEBUG + + fontInflation = nsLayoutUtils::FontSizeInflationFor(firstFrame, widthDeter); + } + + gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame, fontInflation); if (!fontGroup) { DestroyUserData(userDataToDestroy); return nsnull; @@ -2022,7 +2056,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) // Actually wipe out the textruns associated with the mapped frames and associate // those frames with this text run. - AssignTextRun(textRun); + AssignTextRun(textRun, fontInflation); return textRun; } @@ -2288,7 +2322,7 @@ FindFlowForContent(TextRunUserData* aUserData, nsIContent* aContent) } void -BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) +BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun, float aInflation) { PRUint32 i; for (i = 0; i < mMappedFlows.Length(); ++i) { @@ -2361,7 +2395,7 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) } #endif } - f->SetTextRun(aTextRun, mWhichTextRun, mInflation); + f->SetTextRun(aTextRun, mWhichTextRun, aInflation); } // Set this bit now; we can't set it any earlier because // f->ClearTextRun() might clear it out. @@ -2371,7 +2405,6 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) gfxSkipCharsIterator nsTextFrame::EnsureTextRun(TextRunType aWhichTextRun, - float aInflation, gfxContext* aReferenceContext, nsIFrame* aLineContainer, const nsLineList::iterator* aLine, @@ -2388,8 +2421,7 @@ nsTextFrame::EnsureTextRun(TextRunType aWhichTextRun, ctx = GetReferenceRenderingContext(this, nsnull); } if (ctx) { - BuildTextRuns(ctx, this, aLineContainer, aLine, aWhichTextRun, - aInflation); + BuildTextRuns(ctx, this, aLineContainer, aLine, aWhichTextRun); } textRun = GetTextRun(aWhichTextRun); if (!textRun) { @@ -6574,13 +6606,12 @@ void nsTextFrame::MarkIntrinsicWidthsDirty() void nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, nsIFrame::InlineMinWidthData *aData, - float aInflation, TextRunType aTextRunType) { PRUint32 flowEndInTextRun; gfxContext* ctx = aRenderingContext->ThebesContext(); gfxSkipCharsIterator iter = - EnsureTextRun(aTextRunType, aInflation, ctx, aData->lineContainer, + EnsureTextRun(aTextRunType, ctx, aData->lineContainer, aData->line, &flowEndInTextRun); gfxTextRun *textRun = GetTextRun(aTextRunType); if (!textRun) @@ -6728,8 +6759,7 @@ nsTextFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext, } // This will process all the text frames that share the same textrun as f. - f->AddInlineMinWidthForFlow(aRenderingContext, aData, - inflation, trtype); + f->AddInlineMinWidthForFlow(aRenderingContext, aData, trtype); lastTextRun = f->GetTextRun(trtype); } } @@ -6740,13 +6770,12 @@ nsTextFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext, void nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, nsIFrame::InlinePrefWidthData *aData, - float aInflation, TextRunType aTextRunType) { PRUint32 flowEndInTextRun; gfxContext* ctx = aRenderingContext->ThebesContext(); gfxSkipCharsIterator iter = - EnsureTextRun(aTextRunType, aInflation, ctx, aData->lineContainer, + EnsureTextRun(aTextRunType, ctx, aData->lineContainer, aData->line, &flowEndInTextRun); gfxTextRun *textRun = GetTextRun(aTextRunType); if (!textRun) @@ -6861,8 +6890,7 @@ nsTextFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext, } // This will process all the text frames that share the same textrun as f. - f->AddInlinePrefWidthForFlow(aRenderingContext, aData, - inflation, trtype); + f->AddInlinePrefWidthForFlow(aRenderingContext, aData, trtype); lastTextRun = f->GetTextRun(trtype); } } @@ -7322,7 +7350,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, // Find the length of the first-letter. We need a textrun for this. // REVIEW: maybe-bogus inflation should be ok (fixed below) gfxSkipCharsIterator iter = - EnsureTextRun(nsTextFrame::eInflated, GetFontSizeInflation(), ctx, + EnsureTextRun(nsTextFrame::eInflated, ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun); @@ -7375,7 +7403,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, } gfxSkipCharsIterator iter = - EnsureTextRun(nsTextFrame::eInflated, fontSizeInflation, ctx, + EnsureTextRun(nsTextFrame::eInflated, ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun); NS_ABORT_IF_FALSE(GetFontSizeInflation() == fontSizeInflation, @@ -7387,7 +7415,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, // preformatted newline was encountered, and prev-in-flow frames have // consumed all the text of the textrun. We need a new textrun. ClearTextRuns(); - iter = EnsureTextRun(nsTextFrame::eInflated, fontSizeInflation, ctx, + iter = EnsureTextRun(nsTextFrame::eInflated, ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun); } @@ -7737,7 +7765,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsRenderingContext* aRC) gfxContext* ctx = aRC->ThebesContext(); gfxSkipCharsIterator start = - EnsureTextRun(nsTextFrame::eInflated, GetFontSizeInflation(), ctx); + EnsureTextRun(nsTextFrame::eInflated, ctx); NS_ENSURE_TRUE(mTextRun, result); PRUint32 trimmedStart = start.GetSkippedOffset(); From 943497857afad97ea9f9040446464c9c52043605 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 27 Mar 2012 09:27:45 +0300 Subject: [PATCH 003/113] Bug 739033 - Allow external View Source editor code live dangerously. r=smaug. --- parser/html/nsHtml5Module.cpp | 1 + parser/html/nsHtml5TreeOpExecutor.cpp | 26 +++++++++++++++++++++++++- parser/html/nsHtml5TreeOpExecutor.h | 5 +++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/parser/html/nsHtml5Module.cpp b/parser/html/nsHtml5Module.cpp index e9e38dc7e23..54b4670afdf 100644 --- a/parser/html/nsHtml5Module.cpp +++ b/parser/html/nsHtml5Module.cpp @@ -74,6 +74,7 @@ nsHtml5Module::InitializeStatics() nsHtml5TreeBuilder::initializeStatics(); nsHtml5UTF16Buffer::initializeStatics(); nsHtml5StreamParser::InitializeStatics(); + nsHtml5TreeOpExecutor::InitializeStatics(); #ifdef DEBUG sNsHtml5ModuleInitialized = true; #endif diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 463a844162a..ac8be1ec59f 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -61,6 +61,7 @@ #include "mozilla/Util.h" // DebugOnly #include "sampler.h" #include "nsIScriptError.h" +#include "mozilla/Preferences.h" using namespace mozilla; @@ -121,7 +122,8 @@ nsHtml5TreeOpExecutor::WillParse() NS_IMETHODIMP nsHtml5TreeOpExecutor::WillBuildModel(nsDTDMode aDTDMode) { - if (mDocShell && !GetDocument()->GetScriptGlobalObject()) { + if (mDocShell && !GetDocument()->GetScriptGlobalObject() && + !IsExternalViewSource()) { // Not loading as data but script global object not ready return MarkAsBroken(NS_ERROR_DOM_INVALID_STATE_ERR); } @@ -969,6 +971,27 @@ nsHtml5TreeOpExecutor::GetViewSourceBaseURI() return mViewSourceBaseURI; } +//static +void +nsHtml5TreeOpExecutor::InitializeStatics() +{ + mozilla::Preferences::AddBoolVarCache(&sExternalViewSource, + "view_source.editor.external"); +} + +bool +nsHtml5TreeOpExecutor::IsExternalViewSource() +{ + if (!sExternalViewSource) { + return false; + } + bool isViewSource = false; + if (mDocumentURI) { + mDocumentURI->SchemeIs("view-source", &isViewSource); + } + return isViewSource; +} + // Speculative loading already_AddRefed @@ -1060,3 +1083,4 @@ PRUint32 nsHtml5TreeOpExecutor::sAppendBatchExaminations = 0; PRUint32 nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop = 0; PRUint32 nsHtml5TreeOpExecutor::sTimesFlushLoopInterrupted = 0; #endif +bool nsHtml5TreeOpExecutor::sExternalViewSource = false; diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index 86c4176e9b4..dfb06757d33 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -85,6 +85,7 @@ class nsHtml5TreeOpExecutor : public nsContentSink, NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) private: + static bool sExternalViewSource; #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH static PRUint32 sAppendBatchMaxSize; static PRUint32 sAppendBatchSlotsExamined; @@ -446,9 +447,13 @@ class nsHtml5TreeOpExecutor : public nsContentSink, void SetSpeculationBase(const nsAString& aURL); + static void InitializeStatics(); + private: nsHtml5Parser* GetParser(); + bool IsExternalViewSource(); + /** * Get a nsIURI for an nsString if the URL hasn't been preloaded yet. */ From aad2ed2d73a2a81545d67001f29bcd04d7618d9c Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 27 Mar 2012 09:27:45 +0300 Subject: [PATCH 004/113] Bug 731162 - Zap nsIParser::Parse(const nsAString&, ...). r=smaug. --- content/html/document/src/nsHTMLDocument.cpp | 15 ++++--- parser/htmlparser/public/nsIParser.h | 9 +--- parser/htmlparser/src/nsParser.cpp | 44 +++++--------------- parser/htmlparser/src/nsParser.h | 19 ++++----- 4 files changed, 27 insertions(+), 60 deletions(-) diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 8d6c5197412..c8e25d9f499 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -134,6 +134,7 @@ #include "nsMimeTypes.h" #include "nsIRequest.h" #include "nsHtml5TreeOpExecutor.h" +#include "nsHtml5Parser.h" using namespace mozilla; using namespace mozilla::dom; @@ -1644,8 +1645,8 @@ nsHTMLDocument::Close() } ++mWriteLevel; - nsresult rv = mParser->Parse(EmptyString(), nsnull, - GetContentTypeInternal(), true); + nsresult rv = (static_cast(mParser.get()))->Parse( + EmptyString(), nsnull, GetContentTypeInternal(), true); --mWriteLevel; // XXX Make sure that all the document.written content is @@ -1764,13 +1765,11 @@ nsHTMLDocument::WriteCommon(JSContext *cx, // since the concatenation of strings costs more than we like. And // why pay that price when we don't need to? if (aNewlineTerminate) { - rv = mParser->Parse(aText + new_line, - key, GetContentTypeInternal(), - false); + rv = (static_cast(mParser.get()))->Parse( + aText + new_line, key, GetContentTypeInternal(), false); } else { - rv = mParser->Parse(aText, - key, GetContentTypeInternal(), - false); + rv = (static_cast(mParser.get()))->Parse( + aText, key, GetContentTypeInternal(), false); } --mWriteLevel; diff --git a/parser/htmlparser/public/nsIParser.h b/parser/htmlparser/public/nsIParser.h index 76a86ed5f36..7d41ccc7b1b 100644 --- a/parser/htmlparser/public/nsIParser.h +++ b/parser/htmlparser/public/nsIParser.h @@ -59,8 +59,8 @@ #include "nsParserBase.h" #define NS_IPARSER_IID \ -{ 0xd064f0d6, 0x44e3, 0x4366, \ - { 0xa7, 0x05, 0xcf, 0x7a, 0x91, 0x26, 0x14, 0xb6 } } +{ 0x2c4ad90a, 0x740e, 0x4212, \ + { 0xba, 0x3f, 0xfe, 0xac, 0xda, 0x4b, 0x92, 0x9e } } // {41421C60-310A-11d4-816F-000064657374} #define NS_IDEBUG_DUMP_CONTENT_IID \ @@ -219,11 +219,6 @@ class nsIParser : public nsParserBase { nsIRequestObserver* aListener = nsnull, void* aKey = 0, nsDTDMode aMode = eDTDMode_autodetect) = 0; - NS_IMETHOD Parse(const nsAString& aSourceBuffer, - void* aKey, - const nsACString& aMimeType, - bool aLastCall, - nsDTDMode aMode = eDTDMode_autodetect) = 0; NS_IMETHOD Terminate(void) = 0; diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp index e5df9d28ecf..b70a3d56a68 100644 --- a/parser/htmlparser/src/nsParser.cpp +++ b/parser/htmlparser/src/nsParser.cpp @@ -1297,19 +1297,14 @@ nsParser::Parse(nsIURI* aURL, } /** - * Call this method if all you want to do is parse 1 string full of HTML text. - * In particular, this method should be called by the DOM when it has an HTML - * string to feed to the parser in real-time. + * Used by XML fragment parsing below. * * @param aSourceBuffer contains a string-full of real content - * @param aMimeType tells us what type of content to expect in the given string */ -NS_IMETHODIMP +nsresult nsParser::Parse(const nsAString& aSourceBuffer, void* aKey, - const nsACString& aMimeType, - bool aLastCall, - nsDTDMode aMode) + bool aLastCall) { nsresult result = NS_OK; @@ -1327,11 +1322,6 @@ nsParser::Parse(const nsAString& aSourceBuffer, return result; } - // Hack to pass on to the dtd the caller's desire to - // parse a fragment without worrying about containment rules - if (aMode == eDTDMode_fragment) - mCommand = eViewFragment; - // Maintain a reference to ourselves so we don't go away // till we're completely done. nsCOMPtr kungFuDeathGrip(this); @@ -1354,7 +1344,8 @@ nsParser::Parse(const nsAString& aSourceBuffer, eAutoDetectResult theStatus = eUnknownDetect; - if (mParserContext && mParserContext->mMimeType == aMimeType) { + if (mParserContext && + mParserContext->mMimeType.EqualsLiteral("application/xml")) { // Ref. Bug 90379 NS_ASSERTION(mDTD, "How come the DTD is null?"); @@ -1390,13 +1381,8 @@ nsParser::Parse(const nsAString& aSourceBuffer, // end fix for 40143 pc->mContextType=CParserContext::eCTString; - pc->SetMimeType(aMimeType); - if (pc->mPrevContext && aMode == eDTDMode_autodetect) { - // Preserve the DTD mode from the last context, bug 265814. - pc->mDTDMode = pc->mPrevContext->mDTDMode; - } else { - pc->mDTDMode = aMode; - } + pc->SetMimeType(NS_LITERAL_CSTRING("application/xml")); + pc->mDTDMode = eDTDMode_full_standards; mUnusedInput.Truncate(); @@ -1454,9 +1440,7 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer, // pass false for the aLastCall parameter. result = Parse(theContext, (void*)&theContext, - NS_LITERAL_CSTRING("application/xml"), - false, - eDTDMode_full_standards); + false); if (NS_FAILED(result)) { mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED; return result; @@ -1478,18 +1462,14 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer, if (theCount == 0) { result = Parse(aSourceBuffer, &theContext, - NS_LITERAL_CSTRING("application/xml"), - true, - eDTDMode_full_standards); + true); fragSink->DidBuildContent(); } else { // Add an end tag chunk, so expat will read the whole source buffer, // and not worry about ']]' etc. result = Parse(aSourceBuffer + NS_LITERAL_STRING("DidBuildContent(); if (NS_SUCCEEDED(result)) { @@ -1514,9 +1494,7 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer, result = Parse(endContext, &theContext, - NS_LITERAL_CSTRING("application/xml"), - true, - eDTDMode_full_standards); + true); } } diff --git a/parser/htmlparser/src/nsParser.h b/parser/htmlparser/src/nsParser.h index 1635b1d9617..3454a26dd81 100644 --- a/parser/htmlparser/src/nsParser.h +++ b/parser/htmlparser/src/nsParser.h @@ -186,18 +186,6 @@ class nsParser : public nsIParser, void* aKey = 0, nsDTDMode aMode = eDTDMode_autodetect); - /** - * @update gess5/11/98 - * @param anHTMLString contains a string-full of real HTML - * @param appendTokens tells us whether we should insert tokens inline, or append them. - * @return TRUE if all went well -- FALSE otherwise - */ - NS_IMETHOD Parse(const nsAString& aSourceBuffer, - void* aKey, - const nsACString& aContentType, - bool aLastCall, - nsDTDMode aMode = eDTDMode_autodetect); - /** * This method needs documentation */ @@ -433,6 +421,13 @@ private: */ bool DidTokenize(bool aIsFinalChunk = false); + /** + * Pushes XML fragment parsing data to expat without an input stream. + */ + nsresult Parse(const nsAString& aSourceBuffer, + void* aKey, + bool aLastCall); + protected: //********************************************* // And now, some data members... From d8d5c35fdbfcf9465eebe3c27224a58abc2f8bfe Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Mon, 26 Mar 2012 23:49:50 -0700 Subject: [PATCH 005/113] Bug 739457 - Don't decode images when you load a link in a background tab. r=joe --- content/base/src/nsImageLoadingContent.cpp | 36 ++++++++-------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index ec6fceb45e3..d143502928f 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -314,42 +314,32 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest, mCurrentRequestNeedsResetAnimation = false; } - // We just loaded all the data we're going to get. If we haven't done an - // initial paint, we want to make sure the image starts decoding for 2 - // reasons: + // We just loaded all the data we're going to get. If we're visible and + // haven't done an initial paint (*), we want to make sure the image starts + // decoding immediately, for two reasons: // // 1) This image is sitting idle but might need to be decoded as soon as we // start painting, in which case we've wasted time. // // 2) We want to block onload until all visible images are decoded. We do this - // by blocking onload until all in progress decodes get at least one frame + // by blocking onload until all in-progress decodes get at least one frame // decoded. However, if all the data comes in while painting is suppressed // (ie, before the initial paint delay is finished), we fire onload without // doing a paint first. This means that decode-on-draw images don't start // decoding, so we can't wait for them to finish. See bug 512435. + // + // (*) IsPaintingSuppressed returns false if we haven't gotten the initial + // reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed. + // It's possible for painting to be suppressed for reasons other than the + // initial paint delay (for example, being in the bfcache), but we probably + // aren't loading images in those situations. - // We can only do this if we have a presshell nsIDocument* doc = GetOurDocument(); nsIPresShell* shell = doc ? doc->GetShell() : nsnull; - if (shell) { - // We need to figure out whether to kick off decoding - bool doRequestDecode = false; + if (shell && shell->IsVisible() && + (!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) { - // If we haven't got the initial reflow yet, IsPaintingSuppressed actually - // returns false - if (!shell->DidInitialReflow()) - doRequestDecode = true; - - // Figure out if painting is suppressed. Note that it's possible for painting - // to be suppressed for reasons other than the initial paint delay (for - // example - being in the bfcache), but we probably aren't loading images in - // those situations. - if (shell->IsPaintingSuppressed()) - doRequestDecode = true; - - // If we're requesting a decode, do it - if (doRequestDecode) - mCurrentRequest->RequestDecode(); + mCurrentRequest->RequestDecode(); } // Fire the appropriate DOM event. From a9082ae14388e02c111a8164a6133141ee55e331 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 27 Mar 2012 16:29:51 +0900 Subject: [PATCH 006/113] Bug 656225 - XUL listbox accessible tree doens't get updated, r=tbsaunde, bz --- accessible/tests/mochitest/role.js | 1 + .../tests/mochitest/treeupdate/Makefile.in | 1 + .../mochitest/treeupdate/test_listbox.xul | 180 ++++++++++++++++++ layout/base/nsCSSFrameConstructor.cpp | 12 +- layout/xul/base/src/nsListBoxBodyFrame.cpp | 13 ++ 5 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 accessible/tests/mochitest/treeupdate/test_listbox.xul diff --git a/accessible/tests/mochitest/role.js b/accessible/tests/mochitest/role.js index 006f2fdfc83..0b2c1bd8a09 100644 --- a/accessible/tests/mochitest/role.js +++ b/accessible/tests/mochitest/role.js @@ -53,6 +53,7 @@ const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR; const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE; const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON; const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON; +const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION; const ROLE_ROW = nsIAccessibleRole.ROLE_ROW; const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER; const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR; diff --git a/accessible/tests/mochitest/treeupdate/Makefile.in b/accessible/tests/mochitest/treeupdate/Makefile.in index cd3181bba6f..c15fddca4a2 100644 --- a/accessible/tests/mochitest/treeupdate/Makefile.in +++ b/accessible/tests/mochitest/treeupdate/Makefile.in @@ -57,6 +57,7 @@ _TEST_FILES =\ test_imagemap.html \ test_list_editabledoc.html \ test_list.html \ + test_listbox.xul \ test_menu.xul \ test_menubutton.xul \ test_recreation.html \ diff --git a/accessible/tests/mochitest/treeupdate/test_listbox.xul b/accessible/tests/mochitest/treeupdate/test_listbox.xul new file mode 100644 index 00000000000..862b4dde85a --- /dev/null +++ b/accessible/tests/mochitest/treeupdate/test_listbox.xul @@ -0,0 +1,180 @@ + + + + + + + + + + + + Mozilla Bug 656225 + +
+

+ +
+      
+ + + + + + + + + +
+ +
+ diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 6b020b6e5cd..845856f3259 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -10551,7 +10551,7 @@ nsCSSFrameConstructor::CreateListBoxContent(nsPresContext* aPresContext, nsIFrame* newFrame = frameItems.FirstChild(); *aNewFrame = newFrame; - if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) { + if (newFrame) { // Notify the parent frame if (aIsAppend) rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems); @@ -10560,6 +10560,16 @@ nsCSSFrameConstructor::CreateListBoxContent(nsPresContext* aPresContext, } EndUpdate(); + +#ifdef ACCESSIBILITY + if (newFrame) { + nsAccessibilityService* accService = nsIPresShell::AccService(); + if (accService) { + accService->ContentRangeInserted(mPresShell, aChild->GetParent(), + aChild, aChild->GetNextSibling()); + } + } +#endif } return rv; diff --git a/layout/xul/base/src/nsListBoxBodyFrame.cpp b/layout/xul/base/src/nsListBoxBodyFrame.cpp index 566a9c60a71..e3806183c94 100644 --- a/layout/xul/base/src/nsListBoxBodyFrame.cpp +++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp @@ -70,6 +70,10 @@ #include "nsChildIterator.h" #include "nsRenderingContext.h" +#ifdef ACCESSIBILITY +#include "nsAccessibilityService.h" +#endif + /////////////// nsListScrollSmoother ////////////////// /* A mediator used to smooth out scrolling. It works by seeing if @@ -1515,6 +1519,15 @@ nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState, return; } +#ifdef ACCESSIBILITY + nsAccessibilityService* accService = nsIPresShell::AccService(); + if (accService) { + nsIContent* content = aFrame->GetContent(); + accService->ContentRemoved(PresContext()->PresShell(), content->GetParent(), + content); + } +#endif + mFrames.RemoveFrame(aFrame); if (mLayoutManager) mLayoutManager->ChildrenRemoved(this, aState, aFrame); From 0a8698663389713c363c1b0082348852fede0c7d Mon Sep 17 00:00:00 2001 From: Michal Novotny Date: Tue, 27 Mar 2012 10:20:54 +0200 Subject: [PATCH 007/113] Bug 649194 - Abort when the cache IO thread can't be created --- netwerk/cache/nsCacheService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index cf2509a2ca2..617bed5daa5 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -1186,7 +1186,7 @@ nsCacheService::Init() nsresult rv = NS_NewThread(getter_AddRefs(mCacheIOThread)); if (NS_FAILED(rv)) { - NS_WARNING("Can't create cache IO thread"); + NS_RUNTIMEABORT("Can't create cache IO thread"); } rv = nsDeleteDir::Init(); From 5db503d729fb4aa3e8cbf337d71207f82117205c Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 19 Mar 2012 19:22:59 -0700 Subject: [PATCH 008/113] Bug 737570 - Fix handling of overwritten arguments via non-toplevel function statement named 'arguments' (r=waldo) --HG-- extra : rebase_source : 91a45e78412a86f647375485fcd038505a134f0d --- js/src/frontend/BytecodeEmitter.h | 4 ++ js/src/frontend/Parser.cpp | 44 +++++++++++-------- .../testFunctionStatementNamedArguments.js | 10 +++++ 3 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 37cc6607fdd..eb54a2dace4 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -443,6 +443,10 @@ struct TreeContext { /* tree context for semantic checks */ flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS)); } + void noteLocalOverwritesArguments() { + flags |= TCF_FUN_LOCAL_ARGUMENTS; + } + void noteArgumentsNameUse(ParseNode *node) { JS_ASSERT(inFunction()); JS_ASSERT(node->isKind(PNK_NAME)); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index e40b0023be8..52c7120d0aa 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1638,15 +1638,6 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind if (funtc.flags & TCF_FUN_HEAVYWEIGHT) { fun->flags |= JSFUN_HEAVYWEIGHT; outertc->flags |= TCF_FUN_HEAVYWEIGHT; - } else { - /* - * If this function is not at body level of a program or function (i.e. - * it is a function statement that is not a direct child of a program - * or function), then our enclosing function, if any, must be - * heavyweight. - */ - if (!bodyLevel && kind == Statement) - outertc->flags |= TCF_FUN_HEAVYWEIGHT; } JSOp op = JSOP_NOP; @@ -1663,6 +1654,10 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind JS_ASSERT(!outertc->inStrictMode()); op = JSOP_DEFFUN; outertc->noteMightAliasLocals(); + outertc->noteHasExtensibleScope(); + outertc->flags |= TCF_FUN_HEAVYWEIGHT; + if (fun->atom == context->runtime->atomState.argumentsAtom) + outertc->noteLocalOverwritesArguments(); } } @@ -1850,9 +1845,12 @@ Parser::statements() if (tc->atBodyLevel()) { pn->pn_xflags |= PNX_FUNCDEFS; } else { + /* + * General deoptimization was done in functionDef, here we just + * need to tell TOK_LC in Parser::statement to add braces. + */ + JS_ASSERT(tc->hasExtensibleScope()); tc->flags |= TCF_HAS_FUNCTION_STMT; - /* Function statements extend the Call object at runtime. */ - tc->noteHasExtensibleScope(); } } pn->append(next); @@ -2431,7 +2429,8 @@ NoteLValue(JSContext *cx, ParseNode *pn, TreeContext *tc, unsigned dflag = PND_A */ JSAtom *lname = pn->pn_atom; if (lname == cx->runtime->atomState.argumentsAtom) { - tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); + tc->flags |= TCF_FUN_HEAVYWEIGHT; + tc->noteLocalOverwritesArguments(); tc->countArgumentsUse(pn); } else if (tc->inFunction() && lname == tc->fun()->atom) { tc->flags |= TCF_FUN_HEAVYWEIGHT; @@ -2452,8 +2451,10 @@ BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, TreeContext * */ JS_ASSERT(pn->isKind(PNK_NAME)); atom = pn->pn_atom; - if (atom == cx->runtime->atomState.argumentsAtom) - tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); + if (atom == cx->runtime->atomState.argumentsAtom) { + tc->flags |= TCF_FUN_HEAVYWEIGHT; + tc->noteLocalOverwritesArguments(); + } data->pn = pn; if (!data->binder(cx, data, atom, tc)) @@ -4423,8 +4424,10 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va if (tc->inFunction() && name == context->runtime->atomState.argumentsAtom) { tc->noteArgumentsNameUse(pn2); - if (!blockObj) - tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); + if (!blockObj) { + tc->flags |= TCF_FUN_HEAVYWEIGHT; + tc->noteLocalOverwritesArguments(); + } } } } while (tokenStream.matchToken(TOK_COMMA)); @@ -6081,7 +6084,8 @@ Parser::qualifiedSuffix(ParseNode *pn) return NULL; /* This qualifiedSuffice may refer to 'arguments'. */ - tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); + tc->flags |= TCF_FUN_HEAVYWEIGHT; + tc->noteLocalOverwritesArguments(); /* Left operand of :: must be evaluated if it is an identifier. */ if (pn->isOp(JSOP_QNAMEPART)) @@ -6127,7 +6131,8 @@ Parser::qualifiedIdentifier() return NULL; if (tokenStream.matchToken(TOK_DBLCOLON)) { /* Hack for bug 496316. Slowing down E4X won't make it go away, alas. */ - tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); + tc->flags |= TCF_FUN_HEAVYWEIGHT; + tc->noteLocalOverwritesArguments(); pn = qualifiedSuffix(pn); } return pn; @@ -6642,7 +6647,8 @@ Parser::propertyQualifiedIdentifier() JS_ASSERT(tokenStream.peekToken() == TOK_DBLCOLON); /* Deoptimize QualifiedIdentifier properties to avoid tricky analysis. */ - tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS); + tc->flags |= TCF_FUN_HEAVYWEIGHT; + tc->noteLocalOverwritesArguments(); PropertyName *name = tokenStream.currentToken().name(); ParseNode *node = NameNode::create(PNK_NAME, name, tc); diff --git a/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js b/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js new file mode 100644 index 00000000000..967ab3e938b --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js @@ -0,0 +1,10 @@ +var g; +function foo(b) { + if (b) + function arguments() {}; + return arguments; +} + +var a = foo(true); +assertEq(typeof a, "function"); +assertEq(a.name, "arguments"); From 2679471c4587a12868cdc5352a8d63bb2ad64ef5 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 20 Mar 2012 11:18:37 -0700 Subject: [PATCH 009/113] Bug 737552 - Remove 'funargs' (r=jimb) --HG-- extra : rebase_source : 768b5b36503747a7ab95cc745439be4c36e64168 --- js/src/frontend/BytecodeEmitter.h | 209 +++++++++++++-------------- js/src/frontend/ParseNode.h | 54 +------ js/src/frontend/Parser.cpp | 93 +----------- js/src/frontend/SemanticAnalysis.cpp | 208 -------------------------- js/src/frontend/SemanticAnalysis.h | 4 +- js/src/jsval.h | 4 - 6 files changed, 116 insertions(+), 456 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index eb54a2dace4..b03ee2ff33b 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -161,126 +161,127 @@ struct StmtInfo { #define SET_STATEMENT_TOP(stmt, top) \ ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1)) -#define TCF_COMPILING 0x01 /* TreeContext is BytecodeEmitter */ -#define TCF_IN_FUNCTION 0x02 /* parsing inside function body */ -#define TCF_RETURN_EXPR 0x04 /* function has 'return expr;' */ -#define TCF_RETURN_VOID 0x08 /* function has 'return;' */ -#define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */ -#define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */ -#define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */ -#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function may contain a local named arguments */ -#define TCF_FUN_USES_ARGUMENTS 0x100 /* function uses arguments except as a - parameter name */ -#define TCF_FUN_HEAVYWEIGHT 0x200 /* function needs Call object per call */ -#define TCF_FUN_IS_GENERATOR 0x400 /* parsed yield statement in function */ -#define TCF_FUN_USES_OWN_NAME 0x800 /* named function expression that uses its - own name */ -#define TCF_HAS_FUNCTION_STMT 0x1000 /* block contains a function statement */ -#define TCF_GENEXP_LAMBDA 0x2000 /* flag lambda from generator expression */ -#define TCF_COMPILE_N_GO 0x4000 /* compile-and-go mode of script, can - optimize name references based on scope - chain */ -#define TCF_NO_SCRIPT_RVAL 0x8000 /* API caller does not want result value - from global script */ -/* - * Set when parsing a declaration-like destructuring pattern. This - * flag causes PrimaryExpr to create PN_NAME parse nodes for variable - * references which are not hooked into any definition's use chain, - * added to any tree context's AtomList, etc. etc. CheckDestructuring - * will do that work later. - * - * The comments atop CheckDestructuring explain the distinction - * between assignment-like and declaration-like destructuring - * patterns, and why they need to be treated differently. - */ -#define TCF_DECL_DESTRUCTURING 0x10000 +JS_ENUM_HEADER(TreeContextFlags, uint32_t) +{ + /* TreeContext is BytecodeEmitter */ + TCF_COMPILING = 0x1, -/* - * This function/global/eval code body contained a Use Strict Directive. Treat - * certain strict warnings as errors, and forbid the use of 'with'. See also - * TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and JSREPORT_STRICT_ERROR. - */ -#define TCF_STRICT_MODE_CODE 0x20000 + /* parsing inside function body */ + TCF_IN_FUNCTION = 0x2, -/* bits 0x40000 and 0x80000 are unused */ + /* function has 'return expr;' */ + TCF_RETURN_EXPR = 0x4, -/* - * "Module pattern", i.e., a lambda that is immediately applied and the whole - * of an expression statement. - */ -#define TCF_FUN_MODULE_PATTERN 0x200000 + /* function has 'return;' */ + TCF_RETURN_VOID = 0x8, -/* - * Flag to prevent a non-escaping function from being optimized into a null - * closure (i.e., a closure that needs only its global object for free variable - * resolution), because this function contains a closure that needs one or more - * scope objects surrounding it (i.e., a Call object for an outer heavyweight - * function). See bug 560234. - */ -#define TCF_FUN_ENTRAINS_SCOPES 0x400000 + /* parsing init expr of for; exclude 'in' */ + TCF_IN_FOR_INIT = 0x10, -/* The function calls 'eval'. */ -#define TCF_FUN_CALLS_EVAL 0x800000 + /* function has parameter named arguments */ + TCF_FUN_PARAM_ARGUMENTS = 0x20, -/* The function mutates a positional (non-destructuring) parameter. */ -#define TCF_FUN_MUTATES_PARAMETER 0x1000000 + /* function may contain a local named arguments */ + TCF_FUN_LOCAL_ARGUMENTS = 0x40, -/* - * Compiling an eval() script. - */ -#define TCF_COMPILE_FOR_EVAL 0x2000000 + /* function uses arguments except as a parameter name */ + TCF_FUN_USES_ARGUMENTS = 0x80, -/* - * The function or a function that encloses it may define new local names - * at runtime through means other than calling eval. - */ -#define TCF_FUN_MIGHT_ALIAS_LOCALS 0x4000000 + /* function needs Call object per call */ + TCF_FUN_HEAVYWEIGHT = 0x100, -/* - * The script contains singleton initialiser JSOP_OBJECT. - */ -#define TCF_HAS_SINGLETONS 0x8000000 + /* parsed yield statement in function */ + TCF_FUN_IS_GENERATOR = 0x200, -/* - * Some enclosing scope is a with-statement or E4X filter-expression. - */ -#define TCF_IN_WITH 0x10000000 + /* named function expression that uses its own name */ + TCF_FUN_USES_OWN_NAME = 0x400, -/* - * This function does something that can extend the set of bindings in its - * call objects --- it does a direct eval in non-strict code, or includes a - * function statement (as opposed to a function definition). - * - * This flag is *not* inherited by enclosed or enclosing functions; it - * applies only to the function in whose flags it appears. - */ -#define TCF_FUN_EXTENSIBLE_SCOPE 0x20000000 + /* block contains a function statement */ + TCF_HAS_FUNCTION_STMT = 0x800, -/* - * The caller is JS_Compile*Script*. - */ -#define TCF_NEED_SCRIPT_GLOBAL 0x40000000 + /* flag lambda from generator expression */ + TCF_GENEXP_LAMBDA = 0x1000, -/* - * Flags to check for return; vs. return expr; in a function. - */ -#define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID) + /* script can optimize name references based on scope chain */ + TCF_COMPILE_N_GO = 0x2000, + + /* API caller does not want result value from global script */ + TCF_NO_SCRIPT_RVAL = 0x4000, + + /* + * Set when parsing a declaration-like destructuring pattern. This flag + * causes PrimaryExpr to create PN_NAME parse nodes for variable references + * which are not hooked into any definition's use chain, added to any tree + * context's AtomList, etc. etc. CheckDestructuring will do that work + * later. + * + * The comments atop CheckDestructuring explain the distinction between + * assignment-like and declaration-like destructuring patterns, and why + * they need to be treated differently. + */ + TCF_DECL_DESTRUCTURING = 0x8000, + + /* + * This function/global/eval code body contained a Use Strict Directive. + * Treat certain strict warnings as errors, and forbid the use of 'with'. + * See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and + * JSREPORT_STRICT_ERROR. + */ + TCF_STRICT_MODE_CODE = 0x10000, + + /* The function calls 'eval'. */ + TCF_FUN_CALLS_EVAL = 0x20000, + + /* The function mutates a positional (non-destructuring) parameter. */ + TCF_FUN_MUTATES_PARAMETER = 0x40000, + + /* Compiling an eval() script. */ + TCF_COMPILE_FOR_EVAL = 0x100000, + + /* + * The function or a function that encloses it may define new local names + * at runtime through means other than calling eval. + */ + TCF_FUN_MIGHT_ALIAS_LOCALS = 0x200000, + + /* The script contains singleton initialiser JSOP_OBJECT. */ + TCF_HAS_SINGLETONS = 0x400000, + + /* Some enclosing scope is a with-statement or E4X filter-expression. */ + TCF_IN_WITH = 0x800000, + + /* + * This function does something that can extend the set of bindings in its + * call objects --- it does a direct eval in non-strict code, or includes a + * function statement (as opposed to a function definition). + * + * This flag is *not* inherited by enclosed or enclosing functions; it + * applies only to the function in whose flags it appears. + */ + TCF_FUN_EXTENSIBLE_SCOPE = 0x1000000, + + /* The caller is JS_Compile*Script*. */ + TCF_NEED_SCRIPT_GLOBAL = 0x2000000 + +} JS_ENUM_FOOTER(TreeContextFlags); + +/* Flags to check for return; vs. return expr; in a function. */ +static const uint32_t TCF_RETURN_FLAGS = TCF_RETURN_EXPR | TCF_RETURN_VOID; /* * Sticky deoptimization flags to propagate from FunctionBody. */ -#define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \ - TCF_FUN_USES_ARGUMENTS | \ - TCF_FUN_PARAM_ARGUMENTS | \ - TCF_FUN_LOCAL_ARGUMENTS | \ - TCF_FUN_HEAVYWEIGHT | \ - TCF_FUN_IS_GENERATOR | \ - TCF_FUN_USES_OWN_NAME | \ - TCF_FUN_CALLS_EVAL | \ - TCF_FUN_MIGHT_ALIAS_LOCALS | \ - TCF_FUN_MUTATES_PARAMETER | \ - TCF_STRICT_MODE_CODE | \ - TCF_FUN_EXTENSIBLE_SCOPE) +static const uint32_t TCF_FUN_FLAGS = TCF_FUN_USES_ARGUMENTS | + TCF_FUN_PARAM_ARGUMENTS | + TCF_FUN_LOCAL_ARGUMENTS | + TCF_FUN_HEAVYWEIGHT | + TCF_FUN_IS_GENERATOR | + TCF_FUN_USES_OWN_NAME | + TCF_FUN_CALLS_EVAL | + TCF_FUN_MIGHT_ALIAS_LOCALS | + TCF_FUN_MUTATES_PARAMETER | + TCF_STRICT_MODE_CODE | + TCF_FUN_EXTENSIBLE_SCOPE; struct BytecodeEmitter; @@ -453,8 +454,6 @@ struct TreeContext { /* tree context for semantic checks */ JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom); countArgumentsUse(node); flags |= TCF_FUN_USES_ARGUMENTS; - if (funbox) - funbox->node->pn_dflags |= PND_FUNARG; } /* diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 875b877d4a2..17ed30807fe 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -765,15 +765,14 @@ struct ParseNode { #define PND_GVAR 0x40 /* gvar binding, can't close over because it could be deleted */ #define PND_PLACEHOLDER 0x80 /* placeholder definition for lexdep */ -#define PND_FUNARG 0x100 /* downward or upward funarg usage */ -#define PND_BOUND 0x200 /* bound to a stack or global slot */ -#define PND_DEOPTIMIZED 0x400 /* former pn_used name node, pn_lexdef +#define PND_BOUND 0x100 /* bound to a stack or global slot */ +#define PND_DEOPTIMIZED 0x200 /* former pn_used name node, pn_lexdef still valid, but this use no longer optimizable via an upvar opcode */ -#define PND_CLOSED 0x800 /* variable is closed over */ +#define PND_CLOSED 0x400 /* variable is closed over */ /* Flags to propagate from uses to definition. */ -#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED) +#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED) /* PN_LIST pn_xflags bits. */ #define PNX_STRCAT 0x01 /* PNK_ADD list has string term */ @@ -816,7 +815,6 @@ struct ParseNode { bool isPlaceholder() const { return test(PND_PLACEHOLDER); } bool isDeoptimized() const { return test(PND_DEOPTIMIZED); } bool isAssigned() const { return test(PND_ASSIGNED); } - bool isFunArg() const { return test(PND_FUNARG); } bool isClosed() const { return test(PND_CLOSED); } /* @@ -833,9 +831,6 @@ struct ParseNode { */ bool isTopLevel() const { return test(PND_TOPLEVEL); } - /* Defined below, see after struct Definition. */ - void setFunArg(); - void become(ParseNode *pn2); void clear(); @@ -1431,26 +1426,6 @@ void DumpParseTree(ParseNode *pn, int indent = 0); * When the compiler unwinds from the outermost tc, tc->lexdeps contains the * definition nodes with use chains for all free variables. These are either * global variables or reference errors. - * - * We analyze whether a binding is initialized, whether the bound names is ever - * assigned apart from its initializer, and if the bound name definition or use - * is in a direct child of a block. These PND_* flags allow a subset dominance - * computation telling whether an initialized var dominates its uses. An inner - * function using only such outer vars (and formal parameters) can be optimized - * into a flat closure. See JSOP_{GET,CALL}DSLOT. - * - * Another important subset dominance relation: ... { var x = ...; ... x ... } - * where x is not assigned after initialization and not used outside the block. - * This style is common in the absence of 'let'. Even though the var x is not - * at top level, we can tell its initialization dominates all uses cheaply, - * because the above one-pass algorithm sees the definition before any uses, - * and because all uses are contained in the same block as the definition. - * - * We also analyze function uses to flag upward/downward funargs. If a lambda - * post-dominates each of its upvars' sole, inevitable (i.e. not hidden behind - * conditions or within loops or the like) initialization or assignment; then - * we can optimize the lambda as a flat closure (after Chez Scheme's display - * closures). */ #define dn_uses pn_link @@ -1528,7 +1503,7 @@ ParseNode::test(unsigned flag) const { JS_ASSERT(pn_defn || pn_arity == PN_FUNC || pn_arity == PN_NAME); #ifdef DEBUG - if ((flag & (PND_ASSIGNED | PND_FUNARG)) && pn_defn && !(pn_dflags & flag)) { + if ((flag & PND_ASSIGNED) && pn_defn && !(pn_dflags & flag)) { for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) { JS_ASSERT(!pn->pn_defn); JS_ASSERT(!(pn->pn_dflags & flag)); @@ -1538,25 +1513,6 @@ ParseNode::test(unsigned flag) const return !!(pn_dflags & flag); } -inline void -ParseNode::setFunArg() -{ - /* - * pn_defn NAND pn_used must be true, per this chart: - * - * pn_defn pn_used - * 0 0 anonymous function used implicitly, e.g. by - * hidden yield in a genexp - * 0 1 a use of a definition or placeholder - * 1 0 a definition or placeholder - * 1 1 error: this case must not be possible - */ - JS_ASSERT(!(pn_defn & pn_used)); - if (pn_used) - pn_lexdef->pn_dflags |= PND_FUNARG; - pn_dflags |= PND_FUNARG; -} - inline void LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc) { diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 52c7120d0aa..48b0eee57ba 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1070,32 +1070,11 @@ LeaveFunction(ParseNode *fn, TreeContext *funtc, PropertyName *funName = NULL, dn->pn_cookie.set(funtc->staticLevel, UpvarCookie::CALLEE_SLOT); dn->pn_dflags |= PND_BOUND; - /* - * If this named function expression uses its own name other - * than to call itself, flag this function specially. - */ - if (dn->isFunArg()) - funbox->tcflags |= TCF_FUN_USES_OWN_NAME; + funbox->tcflags |= TCF_FUN_USES_OWN_NAME; foundCallee = 1; continue; } - if (!(funbox->tcflags & TCF_FUN_SETS_OUTER_NAME) && - dn->isAssigned()) { - /* - * Make sure we do not fail to set TCF_FUN_SETS_OUTER_NAME if - * any use of dn in funtc assigns. See NoteLValue for the easy - * backward-reference case; this is the hard forward-reference - * case where we pay a higher price. - */ - for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { - if (pnu->isAssigned() && pnu->pn_blockid >= funtc->bodyid) { - funbox->tcflags |= TCF_FUN_SETS_OUTER_NAME; - break; - } - } - } - Definition *outer_dn = tc->decls.lookupFirst(atom); /* @@ -1381,23 +1360,13 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind return NULL; pn->pn_body = NULL; pn->pn_cookie.makeFree(); - - /* - * If this is a function expression, mark this function as escaping (as a - * "funarg") unless it is immediately applied (we clear PND_FUNARG if so -- - * see memberExpr). - * - * Treat function sub-statements (those not at body level of a function or - * program) as escaping funargs, since we can't statically analyze their - * definitions and uses. - */ - bool bodyLevel = tc->atBodyLevel(); - pn->pn_dflags = (kind == Expression || !bodyLevel) ? PND_FUNARG : 0; + pn->pn_dflags = 0; /* * Record names for function statements in tc->decls so we know when to * avoid optimizing variable references that might name a function. */ + bool bodyLevel = tc->atBodyLevel(); if (kind == Statement) { if (Definition *dn = tc->decls.lookupFirst(funName)) { Definition::Kind dn_kind = dn->kind(); @@ -2411,9 +2380,6 @@ NoteLValue(JSContext *cx, ParseNode *pn, TreeContext *tc, unsigned dflag = PND_A } dn->pn_dflags |= dflag; - - if (dn->pn_cookie.isFree() || dn->frameLevel() < tc->staticLevel) - tc->flags |= TCF_FUN_SETS_OUTER_NAME; } pn->pn_dflags |= dflag; @@ -3923,18 +3889,7 @@ Parser::expressionStatement() pn->pn_pos = pn2->pn_pos; pn->pn_kid = pn2; - switch (pn2->getKind()) { - case PNK_LP: - /* - * Flag lambdas immediately applied as statements as instances of - * the JS "module pattern". See CheckForImmediatelyAppliedLambda. - */ - if (pn2->pn_head->isKind(PNK_FUNCTION) && - !pn2->pn_head->pn_funbox->node->isFunArg()) { - pn2->pn_head->pn_funbox->tcflags |= TCF_FUN_MODULE_PATTERN; - } - break; - case PNK_ASSIGN: + if (pn2->getKind() == PNK_ASSIGN) { /* * Keep track of all apparent methods created by assignments such * as this.foo = function (...) {...} in a function that could end @@ -3951,8 +3906,6 @@ Parser::expressionStatement() pn2->pn_right->pn_link = tc->funbox->methods; tc->funbox->methods = pn2->pn_right; } - break; - default:; } /* Check termination of this primitive statement. */ @@ -5605,7 +5558,7 @@ Parser::generatorExpr(ParseNode *kid) return NULL; genfn->setOp(JSOP_LAMBDA); JS_ASSERT(!genfn->pn_body); - genfn->pn_dflags = PND_FUNARG; + genfn->pn_dflags = 0; { TreeContext *outertc = tc; @@ -5714,21 +5667,6 @@ Parser::argumentList(ParseNode *listNode) return JS_TRUE; } -/* Check for an immediately-applied (new'ed) lambda and clear PND_FUNARG. */ -static ParseNode * -CheckForImmediatelyAppliedLambda(ParseNode *pn) -{ - if (pn->isKind(PNK_FUNCTION)) { - JS_ASSERT(pn->isArity(PN_FUNC)); - - FunctionBox *funbox = pn->pn_funbox; - JS_ASSERT((funbox->function())->flags & JSFUN_LAMBDA); - if (!(funbox->tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME))) - pn->pn_dflags &= ~PND_FUNARG; - } - return pn; -} - ParseNode * Parser::memberExpr(JSBool allowCallSyntax) { @@ -5745,7 +5683,6 @@ Parser::memberExpr(JSBool allowCallSyntax) ParseNode *ctorExpr = memberExpr(JS_FALSE); if (!ctorExpr) return NULL; - ctorExpr = CheckForImmediatelyAppliedLambda(ctorExpr); lhs->setOp(JSOP_NEW); lhs->initList(ctorExpr); lhs->pn_pos.begin = ctorExpr->pn_pos.begin; @@ -5919,7 +5856,6 @@ Parser::memberExpr(JSBool allowCallSyntax) return NULL; nextMember->setOp(JSOP_CALL); - lhs = CheckForImmediatelyAppliedLambda(lhs); if (lhs->isOp(JSOP_NAME)) { if (lhs->pn_atom == context->runtime->atomState.evalAtom) { /* Select JSOP_EVAL and flag tc as heavyweight. */ @@ -6728,31 +6664,12 @@ Parser::identifierName(bool afterDoubleDot) dn = MakePlaceholder(node, tc); if (!dn || !tc->lexdeps->add(p, name, dn)) return NULL; - - /* - * In case this is a forward reference to a function, - * we pessimistically set PND_FUNARG if the next token - * is not a left parenthesis. - * - * If the definition eventually parsed into dn is not a - * function, this flag won't hurt, and if we do parse a - * function with pn's name, then the PND_FUNARG flag is - * necessary for safe context->display-based optimiza- - * tion of the closure's static link. - */ - if (tokenStream.peekToken() != TOK_LP) - dn->pn_dflags |= PND_FUNARG; } } JS_ASSERT(dn->isDefn()); LinkUseToDef(node, dn, tc); - /* Here we handle the backward function reference case. */ - if (tokenStream.peekToken() != TOK_LP) - dn->pn_dflags |= PND_FUNARG; - - node->pn_dflags |= (dn->pn_dflags & PND_FUNARG); if (stmt && stmt->type == STMT_WITH) node->pn_dflags |= PND_DEOPTIMIZED; } diff --git a/js/src/frontend/SemanticAnalysis.cpp b/js/src/frontend/SemanticAnalysis.cpp index de7901a41ba..b30a661bf99 100644 --- a/js/src/frontend/SemanticAnalysis.cpp +++ b/js/src/frontend/SemanticAnalysis.cpp @@ -126,211 +126,6 @@ CleanFunctionList(ParseNodeAllocator *allocator, FunctionBox **funboxHead) } } -/* - * Mark as funargs any functions that reach up to one or more upvars across an - * already-known funarg. The parser will flag the o_m lambda as a funarg in: - * - * function f(o, p) { - * o.m = function o_m(a) { - * function g() { return p; } - * function h() { return a; } - * return g() + h(); - * } - * } - * - * but without this extra marking phase, function g will not be marked as a - * funarg since it is called from within its parent scope. But g reaches up to - * f's parameter p, so if o_m escapes f's activation scope, g does too and - * cannot assume that p's stack slot is still alive. In contast function h - * neither escapes nor uses an upvar "above" o_m's level. - * - * If function g itself contained lambdas that contained non-lambdas that reach - * up above its level, then those non-lambdas would have to be marked too. This - * process is potentially exponential in the number of functions, but generally - * not so complex. But it can't be done during a single recursive traversal of - * the funbox tree, so we must use a work queue. - * - * Return the minimal "skipmin" for funbox and its siblings. This is the delta - * between the static level of the bodies of funbox and its peers (which must - * be funbox->level + 1), and the static level of the nearest upvar among all - * the upvars contained by funbox and its peers. If there are no upvars, return - * FREE_STATIC_LEVEL. Thus this function never returns 0. - */ -static unsigned -FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue) -{ - unsigned allskipmin = UpvarCookie::FREE_LEVEL; - - do { - ParseNode *fn = funbox->node; - JS_ASSERT(fn->isArity(PN_FUNC)); - int fnlevel = level; - - /* - * An eval can leak funbox, functions along its ancestor line, and its - * immediate kids. Since FindFunArgs uses DFS and the parser propagates - * TCF_FUN_HEAVYWEIGHT bottom up, funbox's ancestor function nodes have - * already been marked as funargs by this point. Therefore we have to - * flag only funbox->node and funbox->kids' nodes here. - * - * Generators need to be treated in the same way. Even if the value - * of a generator function doesn't escape, anything defined or referred - * to inside the generator can escape through a call to the generator. - * We could imagine doing static analysis to track the calls and see - * if any iterators or values returned by iterators escape, but that - * would be hard, so instead we just assume everything might escape. - */ - if (funbox->tcflags & (TCF_FUN_HEAVYWEIGHT | TCF_FUN_IS_GENERATOR)) { - fn->setFunArg(); - for (FunctionBox *kid = funbox->kids; kid; kid = kid->siblings) - kid->node->setFunArg(); - } - - /* - * Compute in skipmin the least distance from fun's static level up to - * an upvar, whether used directly by fun, or indirectly by a function - * nested in fun. - */ - unsigned skipmin = UpvarCookie::FREE_LEVEL; - ParseNode *pn = fn->pn_body; - - if (pn->isKind(PNK_UPVARS)) { - AtomDefnMapPtr &upvars = pn->pn_names; - JS_ASSERT(upvars->count() != 0); - - for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) { - Definition *defn = r.front().value(); - Definition *lexdep = defn->resolve(); - - if (!lexdep->isFreeVar()) { - unsigned upvarLevel = lexdep->frameLevel(); - - if (int(upvarLevel) <= fnlevel) - fn->setFunArg(); - - unsigned skip = (funbox->level + 1) - upvarLevel; - if (skip < skipmin) - skipmin = skip; - } - } - } - - /* - * If this function escapes, whether directly (the parser detects such - * escapes) or indirectly (because this non-escaping function uses an - * upvar that reaches across an outer function boundary where the outer - * function escapes), enqueue it for further analysis, and bump fnlevel - * to trap any non-escaping children. - */ - if (fn->isFunArg()) { - queue->push(funbox); - fnlevel = int(funbox->level); - } - - /* - * Now process the current function's children, and recalibrate their - * cumulative skipmin to be relative to the current static level. - */ - if (funbox->kids) { - unsigned kidskipmin = FindFunArgs(funbox->kids, fnlevel, queue); - - JS_ASSERT(kidskipmin != 0); - if (kidskipmin != UpvarCookie::FREE_LEVEL) { - --kidskipmin; - if (kidskipmin != 0 && kidskipmin < skipmin) - skipmin = kidskipmin; - } - } - - /* - * Finally, after we've traversed all of the current function's kids, - * minimize allskipmin against our accumulated skipmin. Minimize across - * funbox and all of its siblings, to compute our return value. - */ - if (skipmin != UpvarCookie::FREE_LEVEL) { - if (skipmin < allskipmin) - allskipmin = skipmin; - } - } while ((funbox = funbox->siblings) != NULL); - - return allskipmin; -} - -static bool -MarkFunArgs(JSContext *cx, FunctionBox *funbox, uint32_t functionCount) -{ - FunctionBoxQueue queue; - if (!queue.init(functionCount)) { - js_ReportOutOfMemory(cx); - return false; - } - - FindFunArgs(funbox, -1, &queue); - while ((funbox = queue.pull()) != NULL) { - ParseNode *fn = funbox->node; - JS_ASSERT(fn->isFunArg()); - - ParseNode *pn = fn->pn_body; - if (pn->isKind(PNK_UPVARS)) { - AtomDefnMapPtr upvars = pn->pn_names; - JS_ASSERT(!upvars->empty()); - - for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) { - Definition *defn = r.front().value(); - Definition *lexdep = defn->resolve(); - - if (!lexdep->isFreeVar() && - !lexdep->isFunArg() && - (lexdep->kind() == Definition::FUNCTION || - lexdep->isOp(JSOP_CALLEE))) { - /* - * Mark this formerly-Algol-like function as an escaping - * function (i.e., as a funarg), because it is used from - * another funarg. - * - * Progress is guaranteed because we set the funarg flag - * here, which suppresses revisiting this function (thanks - * to the !lexdep->isFunArg() test just above). - */ - lexdep->setFunArg(); - - FunctionBox *afunbox; - if (lexdep->isOp(JSOP_CALLEE)) { - /* - * A named function expression will not appear to be a - * funarg if it is immediately applied. However, if its - * name is used in an escaping function nested within - * it, then it must become flagged as a funarg again. - * See bug 545980. - */ - afunbox = funbox; - unsigned calleeLevel = lexdep->pn_cookie.level(); - unsigned staticLevel = afunbox->level + 1U; - while (staticLevel != calleeLevel) { - afunbox = afunbox->parent; - --staticLevel; - } - JS_ASSERT(afunbox->level + 1U == calleeLevel); - afunbox->node->setFunArg(); - } else { - afunbox = lexdep->pn_funbox; - } - queue.push(afunbox); - - /* - * Walk over nested functions again, now that we have - * changed the level across which it is unsafe to access - * upvars using the runtime dynamic link (frame chain). - */ - if (afunbox->kids) - FindFunArgs(afunbox->kids, afunbox->level, &queue); - } - } - } - } - return true; -} - static void FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32_t *tcflags) { @@ -347,7 +142,6 @@ FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32_t *tcflags) funbox->tcflags |= TCF_FUN_HEAVYWEIGHT; break; } - funbox->tcflags |= TCF_FUN_ENTRAINS_SCOPES; } if (!funbox && (*tcflags & TCF_IN_FUNCTION)) @@ -473,8 +267,6 @@ frontend::AnalyzeFunctions(TreeContext *tc) CleanFunctionList(&tc->parser->allocator, &tc->functionList); if (!tc->functionList) return true; - if (!MarkFunArgs(tc->parser->context, tc->functionList, tc->parser->functionCount)) - return false; if (!MarkExtensibleScopeDescendants(tc->parser->context, tc->functionList, false)) return false; bool isDirectEval = !!tc->parser->callerFrame; diff --git a/js/src/frontend/SemanticAnalysis.h b/js/src/frontend/SemanticAnalysis.h index c4783a85e74..87f0d18a0a1 100644 --- a/js/src/frontend/SemanticAnalysis.h +++ b/js/src/frontend/SemanticAnalysis.h @@ -48,8 +48,8 @@ namespace frontend { /* * For each function in the compilation unit given by tc, decide whether the - * function is a full closure, a null closure, or a flat closure, and set the - * heavyweight bit if necessary. + * function is a full closure or a null closure and set JSFunction flags + * accordingly. */ bool AnalyzeFunctions(TreeContext *tc); diff --git a/js/src/jsval.h b/js/src/jsval.h index 974724b4b6b..3a0c9f79f68 100644 --- a/js/src/jsval.h +++ b/js/src/jsval.h @@ -115,13 +115,9 @@ JSDOUBLE_IS_INT32(double d, int32_t* pi) #if defined(_MSC_VER) # define JS_ENUM_HEADER(id, type) enum id : type -# define JS_ENUM_MEMBER(id, type, value) id = (type)value, -# define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value # define JS_ENUM_FOOTER(id) #else # define JS_ENUM_HEADER(id, type) enum id -# define JS_ENUM_MEMBER(id, type, value) id = (type)value, -# define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value # define JS_ENUM_FOOTER(id) __attribute__((packed)) #endif From dc718f1471d6809939bf2cfa07274f421497cfdc Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 26 Mar 2012 22:08:03 -0700 Subject: [PATCH 010/113] Bug 739494 - rm JSOP_DEFLOCALFUN (r=bhackett) --HG-- extra : rebase_source : bb055d312548d6f04096e2320838addfbffd65fc --- js/src/frontend/BytecodeEmitter.cpp | 25 ++++++++--------------- js/src/jsanalyze.cpp | 4 +--- js/src/jsanalyze.h | 3 --- js/src/jsinfer.cpp | 18 +++-------------- js/src/jsinterp.cpp | 31 +---------------------------- js/src/jsopcode.cpp | 16 ++++++++++++++- js/src/jsopcode.tbl | 12 +++-------- js/src/methodjit/Compiler.cpp | 25 ----------------------- js/src/methodjit/StubCalls.cpp | 29 --------------------------- js/src/methodjit/StubCalls.h | 2 -- 10 files changed, 31 insertions(+), 134 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 5fb844d5acb..23cd4ac5d05 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -967,22 +967,6 @@ EmitRegExp(JSContext *cx, uint32_t index, BytecodeEmitter *bce) return EmitIndex32(cx, JSOP_REGEXP, index, bce); } -static bool -EmitSlotObjectOp(JSContext *cx, JSOp op, unsigned slot, uint32_t index, BytecodeEmitter *bce) -{ - JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTOBJECT); - - ptrdiff_t off = EmitN(cx, bce, op, SLOTNO_LEN + UINT32_INDEX_LEN); - if (off < 0) - return false; - - jsbytecode *pc = bce->code(off); - SET_SLOTNO(pc, slot); - pc += SLOTNO_LEN; - SET_UINT32_INDEX(pc, index); - return true; -} - static bool EmitArguments(JSContext *cx, BytecodeEmitter *bce) { @@ -5054,7 +5038,14 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) { return false; } - return EmitSlotObjectOp(cx, JSOP_DEFLOCALFUN, slot, index, bce); + + if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0) + return false; + if (!EmitIndexOp(cx, JSOP_LAMBDA, index, bce)) + return false; + EMIT_UINT16_IMM_OP(JSOP_SETLOCAL, slot); + if (Emit1(cx, bce, JSOP_POP) < 0) + return false; } return true; diff --git a/js/src/jsanalyze.cpp b/js/src/jsanalyze.cpp index ecd13bd4c8e..6b10ab34ecf 100644 --- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -540,7 +540,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx) case JSOP_ARGUMENTS: case JSOP_THROW: case JSOP_EXCEPTION: - case JSOP_DEFLOCALFUN: case JSOP_LAMBDA: case JSOP_DEBUGGER: case JSOP_FUNCALL: @@ -829,8 +828,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx) case JSOP_SETARG: case JSOP_SETLOCAL: - case JSOP_SETLOCALPOP: - case JSOP_DEFLOCALFUN: { + case JSOP_SETLOCALPOP: { uint32_t slot = GetBytecodeSlot(script, pc); if (!slotEscapes(slot)) killVariable(cx, lifetimes[slot], offset, saved, savedCount); diff --git a/js/src/jsanalyze.h b/js/src/jsanalyze.h index 46aa1734681..80b87d56ef5 100644 --- a/js/src/jsanalyze.h +++ b/js/src/jsanalyze.h @@ -258,7 +258,6 @@ ExtendedDef(jsbytecode *pc) case JSOP_ARGDEC: case JSOP_SETLOCAL: case JSOP_SETLOCALPOP: - case JSOP_DEFLOCALFUN: case JSOP_INCLOCAL: case JSOP_DECLOCAL: case JSOP_LOCALINC: @@ -387,7 +386,6 @@ static inline uint32_t GetBytecodeSlot(JSScript *script, jsbytecode *pc) case JSOP_CALLLOCAL: case JSOP_SETLOCAL: case JSOP_SETLOCALPOP: - case JSOP_DEFLOCALFUN: case JSOP_INCLOCAL: case JSOP_DECLOCAL: case JSOP_LOCALINC: @@ -411,7 +409,6 @@ BytecodeUpdatesSlot(JSOp op) case JSOP_SETARG: case JSOP_SETLOCAL: case JSOP_SETLOCALPOP: - case JSOP_DEFLOCALFUN: case JSOP_INCARG: case JSOP_DECARG: case JSOP_ARGINC: diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 597ee346d30..6481afa9806 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3752,24 +3752,12 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, break; case JSOP_LAMBDA: - case JSOP_DEFFUN: - case JSOP_DEFLOCALFUN: { - unsigned off = op == JSOP_DEFLOCALFUN ? SLOTNO_LEN : 0; - JSObject *obj = script->getObject(GET_UINT32_INDEX(pc + off)); + case JSOP_DEFFUN: { + JSObject *obj = script->getObject(GET_UINT32_INDEX(pc)); TypeSet *res = NULL; - if (op == JSOP_LAMBDA) { + if (op == JSOP_LAMBDA) res = &pushed[0]; - } else if (op == JSOP_DEFLOCALFUN) { - uint32_t slot = GetBytecodeSlot(script, pc); - if (trackSlot(slot)) { - res = &pushed[0]; - } else { - /* Should not see 'let' vars here. */ - JS_ASSERT(slot < TotalSlots(script)); - res = TypeScript::SlotTypes(script, slot); - } - } if (res) { if (script->hasGlobal()) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 37b966a174b..01725b82710 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1713,6 +1713,7 @@ ADD_EMPTY_CASE(JSOP_UNUSED24) ADD_EMPTY_CASE(JSOP_UNUSED25) ADD_EMPTY_CASE(JSOP_UNUSED26) ADD_EMPTY_CASE(JSOP_UNUSED27) +ADD_EMPTY_CASE(JSOP_UNUSED28) ADD_EMPTY_CASE(JSOP_CONDSWITCH) ADD_EMPTY_CASE(JSOP_TRY) #if JS_HAS_XML_SUPPORT @@ -3147,36 +3148,6 @@ BEGIN_CASE(JSOP_DEFFUN) } END_CASE(JSOP_DEFFUN) -BEGIN_CASE(JSOP_DEFLOCALFUN) -{ - /* - * Define a local function (i.e., one nested at the top level of another - * function), parented by the current scope chain, stored in a local - * variable slot that the compiler allocated. This is an optimization over - * JSOP_DEFFUN that avoids requiring a call object for the outer function's - * activation. - */ - JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc + SLOTNO_LEN)); - JS_ASSERT(fun->isInterpreted()); - - JSObject *parent; - if (fun->isNullClosure()) { - parent = ®s.fp()->scopeChain(); - } else { - parent = GetScopeChain(cx, regs.fp()); - if (!parent) - goto error; - } - JSObject *obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent); - if (!obj) - goto error; - - JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto()); - - regs.fp()->varSlot(GET_SLOTNO(regs.pc)) = ObjectValue(*obj); -} -END_CASE(JSOP_DEFLOCALFUN) - BEGIN_CASE(JSOP_LAMBDA) { /* Load the specified function object literal. */ diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index c96d04b0946..fdc914be3a5 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -4786,8 +4786,22 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) break; } #endif /* JS_HAS_GENERATOR_EXPRS */ - /* FALL THROUGH */ + else if (sn && SN_TYPE(sn) == SRC_CONTINUE) { + /* + * Local function definitions have a lambda;setlocal;pop + * triple (annotated with SRC_CONTINUE) in the function + * prologue and a nop (annotated with SRC_FUNCDEF) at the + * actual position where the function definition should + * syntactically appear. + */ + LOCAL_ASSERT(pc[JSOP_LAMBDA_LENGTH] == JSOP_SETLOCAL); + LOCAL_ASSERT(pc[JSOP_LAMBDA_LENGTH + JSOP_SETLOCAL_LENGTH] == JSOP_POP); + len = JSOP_LAMBDA_LENGTH + JSOP_SETLOCAL_LENGTH + JSOP_POP_LENGTH; + todo = -2; + break; + } + /* Otherwise, this is a lambda expression. */ fun = jp->script->getFunction(GET_UINT32_INDEX(pc)); { /* diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 2f1167b84a4..4ab727d38f3 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -364,15 +364,9 @@ OPDEF(JSOP_PICK, 133, "pick", NULL, 2, 0, 0, 0, JOF_UINT8| OPDEF(JSOP_TRY, 134,"try", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, 0, JOF_BYTE) -OPDEF(JSOP_UNUSED26, 136,"unused20", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_UNUSED27, 137,"unused21", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* - * Define a local function object as a local variable. - * The local variable's slot number is the first immediate two-byte operand. - * The function object's atom index is the second immediate operand. - */ -OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL, 7, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT) +OPDEF(JSOP_UNUSED26, 136,"unused26", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED27, 137,"unused27", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED28, 138,"unused28", NULL, 1, 0, 0, 0, JOF_BYTE) /* Extended jumps. */ OPDEF(JSOP_UNUSED4, 139,"unused4", NULL, 1, 0, 0, 0, JOF_BYTE) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index f4be4ccbf5a..1c1a31c6ed4 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -3115,31 +3115,6 @@ mjit::Compiler::generateMethod() frame.syncAndForgetEverything(); END_CASE(JSOP_TRY) - BEGIN_CASE(JSOP_DEFLOCALFUN) - { - uint32_t slot = GET_SLOTNO(PC); - JSFunction *fun = script->getFunction(GET_UINT32_INDEX(PC + SLOTNO_LEN)); - - /* - * The liveness analysis will report that the value in |slot| is - * defined at the start of this opcode. However, we don't actually - * fill it in until the stub returns. This will cause a problem if - * we GC inside the stub. So we write a safe value here so that the - * GC won't crash. - */ - markUndefinedLocal(PC - script->code, slot); - - prepareStubCall(Uses(0)); - masm.move(ImmPtr(fun), Registers::ArgReg1); - INLINE_STUBCALL(stubs::DefLocalFun, REJOIN_DEFLOCALFUN); - frame.takeReg(Registers::ReturnReg); - frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg); - frame.storeLocal(slot, true); - frame.pop(); - updateVarType(); - } - END_CASE(JSOP_DEFLOCALFUN) - BEGIN_CASE(JSOP_RETRVAL) emitReturn(NULL); fallthrough = false; diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index fd56f46fb33..d04589fb39b 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -981,35 +981,6 @@ stubs::InitElem(VMFrame &f, uint32_t last) } } -JSObject * JS_FASTCALL -stubs::DefLocalFun(VMFrame &f, JSFunction *fun) -{ - /* - * Define a local function (i.e., one nested at the top level of another - * function), parented by the current scope chain, stored in a local - * variable slot that the compiler allocated. This is an optimization over - * JSOP_DEFFUN that avoids requiring a call object for the outer function's - * activation. - */ - JS_ASSERT(fun->isInterpreted()); - - JSObject *parent; - if (fun->isNullClosure()) { - parent = &f.fp()->scopeChain(); - } else { - parent = GetScopeChain(f.cx, f.fp()); - if (!parent) - THROWV(NULL); - } - JSObject *obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, parent); - if (!obj) - THROWV(NULL); - - JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global()); - - return obj; -} - void JS_FASTCALL stubs::RegExp(VMFrame &f, JSObject *regex) { diff --git a/js/src/methodjit/StubCalls.h b/js/src/methodjit/StubCalls.h index 93f90ab2957..7ce9b5d629a 100644 --- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -135,8 +135,6 @@ JSBool JS_FASTCALL In(VMFrame &f); void JS_FASTCALL DefVarOrConst(VMFrame &f, PropertyName *name); void JS_FASTCALL SetConst(VMFrame &f, PropertyName *name); template void JS_FASTCALL DefFun(VMFrame &f, JSFunction *fun); -JSObject * JS_FASTCALL DefLocalFun(VMFrame &f, JSFunction *fun); -JSObject * JS_FASTCALL DefLocalFun_FC(VMFrame &f, JSFunction *fun); void JS_FASTCALL RegExp(VMFrame &f, JSObject *regex); JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun); JSObject * JS_FASTCALL LambdaJoinableForInit(VMFrame &f, JSFunction *fun); From 852a07ccfb407f66036ccf42a9444cfe44988fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 27 Mar 2012 07:12:44 -0400 Subject: [PATCH 011/113] Bug 683975. Set PATH when building stage2. r=rail. --- build/unix/build-toolchain/build-gcc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/unix/build-toolchain/build-gcc.py b/build/unix/build-toolchain/build-gcc.py index fda17dfee57..6befa33e7c2 100755 --- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -265,9 +265,9 @@ build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True) stage1_tool_inst_dir = stage1_dir + '/inst' stage2_dir = build_dir + '/stage2' -build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline", - "CXX" : stage1_tool_inst_dir + "/bin/g++", - "AR" : stage1_tool_inst_dir + "/bin/ar", +build_one_stage({"PATH" : stage1_tool_inst_dir + "/bin:/bin:/usr/bin", + "CC" : "gcc -fgnu89-inline", + "CXX" : "g++", "RANLIB" : "true" }, stage2_dir, False) From 2919615e28de6c3d9a19a9e1cc18a3bb227a592f Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Tue, 27 Mar 2012 08:47:14 -0400 Subject: [PATCH 012/113] Bug 738976 - java.lang.NullPointerException at org.mozilla.gecko.db.LocalBrowserDB.updateFaviconForUrl r=blassey --- mobile/android/base/db/LocalBrowserDB.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index 1dfc21137b3..e0dc8b78eb7 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -593,6 +593,8 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface { public void updateFaviconForUrl(ContentResolver cr, String uri, BitmapDrawable favicon) { Bitmap bitmap = favicon.getBitmap(); + if (bitmap == null) + return; ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); From bdb1945255c9fb272465d35328508f333a9ac772 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Tue, 27 Mar 2012 15:28:14 +0200 Subject: [PATCH 013/113] Bug 737846 - Ensure favicons service doesn't add unwanted pages to history. r=dietrich --- .../components/places/AsyncFaviconHelpers.cpp | 34 ++------- .../components/places/mozIAsyncFavicons.idl | 4 +- .../components/places/nsFaviconService.cpp | 5 +- .../components/places/nsIFaviconService.idl | 7 +- .../places/tests/chrome/Makefile.in | 3 +- .../places/tests/chrome/history_post.sjs | 6 ++ .../tests/chrome/test_favicon_annotations.xul | 45 ++++++++--- .../places/tests/chrome/test_history_post.xul | 67 +++++++++++++++++ .../tests/favicons/test_expireAllFavicons.js | 43 ++++------- .../places/tests/favicons/test_favicons.js | 9 +++ .../favicons/test_favicons_conversions.js | 36 ++++----- .../test_setAndFetchFaviconForPage.js | 7 +- ...test_setAndFetchFaviconForPage_failures.js | 75 ++++++++++++------- .../components/places/tests/head_common.js | 58 ++++++++++++++ .../places/tests/inline/head_autocomplete.js | 23 ------ .../inline/test_autocomplete_functional.js | 75 ++++--------------- .../places/tests/inline/test_typed.js | 26 ++----- 17 files changed, 300 insertions(+), 223 deletions(-) create mode 100644 toolkit/components/places/tests/chrome/history_post.sjs create mode 100644 toolkit/components/places/tests/chrome/test_history_post.xul diff --git a/toolkit/components/places/AsyncFaviconHelpers.cpp b/toolkit/components/places/AsyncFaviconHelpers.cpp index 6b78f327b3c..a371370ddd3 100644 --- a/toolkit/components/places/AsyncFaviconHelpers.cpp +++ b/toolkit/components/places/AsyncFaviconHelpers.cpp @@ -794,37 +794,15 @@ AsyncAssociateIconToPage::Run() NS_ENSURE_SUCCESS(rv, rv); } - // If the page does not have an id, try to insert a new one. + // If the page does not have an id, don't try to insert a new one, cause we + // don't know where the page comes from. Not doing so we may end adding + // a page that otherwise we'd explicitly ignore, like a POST or an error page. if (mPage.id == 0) { - nsCOMPtr stmt = mDB->GetStatement( - "INSERT INTO moz_places (url, rev_host, hidden, favicon_id, frecency, guid) " - "VALUES (:page_url, :rev_host, 1, :favicon_id, 0, GENERATE_GUID()) " - ); - NS_ENSURE_STATE(stmt); - mozStorageStatementScoper scoper(stmt); - rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mPage.spec); - NS_ENSURE_SUCCESS(rv, rv); - // The rev_host can be null. - if (mPage.revHost.IsEmpty()) { - rv = stmt->BindNullByName(NS_LITERAL_CSTRING("rev_host")); - } - else { - rv = stmt->BindStringByName(NS_LITERAL_CSTRING("rev_host"), mPage.revHost); - } - NS_ENSURE_SUCCESS(rv, rv); - rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("favicon_id"), mIcon.id); - NS_ENSURE_SUCCESS(rv, rv); - rv = stmt->Execute(); - NS_ENSURE_SUCCESS(rv, rv); - - // Get the new id and GUID. - rv = FetchPageInfo(mDB, mPage); - NS_ENSURE_SUCCESS(rv, rv); - - mIcon.status |= ICON_STATUS_ASSOCIATED; + return NS_OK; } + // Otherwise just associate the icon to the page, if needed. - else if (mPage.iconId != mIcon.id) { + if (mPage.iconId != mIcon.id) { nsCOMPtr stmt; if (mPage.id) { stmt = mDB->GetStatement( diff --git a/toolkit/components/places/mozIAsyncFavicons.idl b/toolkit/components/places/mozIAsyncFavicons.idl index bec46bc575d..063b82d6dc2 100644 --- a/toolkit/components/places/mozIAsyncFavicons.idl +++ b/toolkit/components/places/mozIAsyncFavicons.idl @@ -60,8 +60,8 @@ interface mozIAsyncFavicons : nsISupports * cache we won't do anything unless aForceReload is true, in which case * we'll try to reload the favicon. * - * This function will only save favicons for "good" URIs, as defined by what - * gets added to history or is a bookmark. For "bad" URIs, this function + * This function will only save favicons for pages that are already stored in + * the database, like visited pages or bookmarks. For any other URIs, it * will succeed but do nothing. This function will also ignore the error * page favicon URI (see FAVICON_ERRORPAGE_URL below). * diff --git a/toolkit/components/places/nsFaviconService.cpp b/toolkit/components/places/nsFaviconService.cpp index b7c9229f387..faab6ab3d8d 100644 --- a/toolkit/components/places/nsFaviconService.cpp +++ b/toolkit/components/places/nsFaviconService.cpp @@ -320,8 +320,11 @@ nsFaviconService::SetFaviconUrlForPage(nsIURI* aPageURI, nsIURI* aFaviconURI) // Now, link our icon entry with the page. PRInt64 pageId; nsCAutoString guid; - rv = history->GetOrCreateIdForPage(aPageURI, &pageId, guid); + rv = history->GetIdForPage(aPageURI, &pageId, guid); NS_ENSURE_SUCCESS(rv, rv); + if (!pageId) { + return NS_ERROR_NOT_AVAILABLE; + } nsCOMPtr stmt = mDB->GetStatement( "UPDATE moz_places SET favicon_id = :icon_id WHERE id = :page_id" diff --git a/toolkit/components/places/nsIFaviconService.idl b/toolkit/components/places/nsIFaviconService.idl index d0bf066b233..8eb0a70f3f7 100644 --- a/toolkit/components/places/nsIFaviconService.idl +++ b/toolkit/components/places/nsIFaviconService.idl @@ -50,9 +50,9 @@ interface nsIFaviconService : nsISupports * * Will create an entry linking the favicon URI to the page, regardless * of whether we have data for that icon. You can populate it later with - * SetFaviconData. However, remember that any favicons not associated with a - * visited web page, a bookmark, or a "place:" URI, will be removed during - * expiration runs. + * SetFaviconData. However, remember that favicons must only be associated + * with a visited web page, a bookmark, or a "place:" URI. Trying to + * associate the icon to any other page will throw. * * This will send out history pageChanged notification if the new favicon has * any data and it's different from the old associated favicon. This means @@ -63,6 +63,7 @@ interface nsIFaviconService : nsISupports * URI of the page whose favicon is being set. * @param aFaviconURI * URI of the favicon to associate with the page. + * @throws NS_ERROR_NOT_AVAILABLE if aPageURI doesn't exist in the database. */ void setFaviconUrlForPage(in nsIURI aPageURI, in nsIURI aFaviconURI); diff --git a/toolkit/components/places/tests/chrome/Makefile.in b/toolkit/components/places/tests/chrome/Makefile.in index d29f83e5f08..1756361fc7c 100644 --- a/toolkit/components/places/tests/chrome/Makefile.in +++ b/toolkit/components/places/tests/chrome/Makefile.in @@ -61,6 +61,8 @@ _CHROME_FILES = \ test_favicon_annotations.xul \ test_303567.xul \ test_381357.xul \ + test_history_post.xul \ + history_post.sjs \ test_reloadLivemarks.xul \ $(NULL) @@ -69,4 +71,3 @@ libs:: $(_HTTP_FILES) libs:: $(_CHROME_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir) - diff --git a/toolkit/components/places/tests/chrome/history_post.sjs b/toolkit/components/places/tests/chrome/history_post.sjs new file mode 100644 index 00000000000..3c86aad7bc7 --- /dev/null +++ b/toolkit/components/places/tests/chrome/history_post.sjs @@ -0,0 +1,6 @@ +function handleRequest(request, response) +{ + response.setStatusLine("1.0", 200, "OK"); + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.write("Ciao"); +} diff --git a/toolkit/components/places/tests/chrome/test_favicon_annotations.xul b/toolkit/components/places/tests/chrome/test_favicon_annotations.xul index 8db5686bd0d..bad9a1f9d2c 100644 --- a/toolkit/components/places/tests/chrome/test_favicon_annotations.xul +++ b/toolkit/components/places/tests/chrome/test_favicon_annotations.xul @@ -135,6 +135,7 @@ function loadNextTest() function test() { + SimpleTest.waitForExplicitFinish(); let db = Cc["@mozilla.org/browser/nav-history-service;1"]. getService(Ci.nsPIPlacesDatabase). DBConnection; @@ -148,19 +149,39 @@ function test() return ios.newURI(aSpec, null, null); }; - // Set the favicon data. Note that the "moz-anno:" protocol requires the - // favicon to be stored in the database, but the replaceFaviconDataFromDataURL - // function will not save the favicon unless it is associated with a page. - // Thus, we must associate the icon with a page explicitly in order for it to - // be visible through the protocol. - fs.replaceFaviconDataFromDataURL(uri(testURIs[1]), expectedURIs[1], - (Date.now() + 60 * 60 * 24 * 1000) * 1000); - fs.setAndFetchFaviconForPage(uri("http://example.com/favicon_annotations"), - uri(testURIs[1]), true); + let pageURI = uri("http://example.com/favicon_annotations"); + let history = Cc["@mozilla.org/browser/history;1"] + .getService(Ci.mozIAsyncHistory); + history.updatePlaces( + { + uri: pageURI, + visits: [{ transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED, + visitDate: Date.now() * 1000 + }], + }, + { + handleError: function UP_handleError() { + ok(false, "Unexpected error in adding visit."); + }, + handleResult: function () {}, + handleCompletion: function UP_handleCompletion() { + // Set the favicon data. Note that the "moz-anno:" protocol requires + // the favicon to be stored in the database, but the + // replaceFaviconDataFromDataURL function will not save the favicon + // unless it is associated with a page. Thus, we must associate the + // icon with a page explicitly in order for it to be visible through + // the protocol. + fs.replaceFaviconDataFromDataURL(uri(testURIs[1]), expectedURIs[1], + (Date.now() + 60 * 60 * 24 * 1000) * 1000); + fs.setAndFetchFaviconForPage(pageURI, uri(testURIs[1]), true); + + // And start our test process. + loadNextTest(); + } + } + }); + - // And start our test process. - loadNextTest(); - SimpleTest.waitForExplicitFinish(); } ]]> diff --git a/toolkit/components/places/tests/chrome/test_history_post.xul b/toolkit/components/places/tests/chrome/test_history_post.xul new file mode 100644 index 00000000000..95c7c037469 --- /dev/null +++ b/toolkit/components/places/tests/chrome/test_history_post.xul @@ -0,0 +1,67 @@ + + + + + + + + + + -
- -
- -
-
-
- - diff --git a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js index e46fcf6bec2..192d49adfc0 100644 --- a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js +++ b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js @@ -704,6 +704,18 @@ SpecialPowersAPI.prototype = { listener, false); }, + getFormFillController: function(window) { + return Components.classes["@mozilla.org/satchel/form-fill-controller;1"] + .getService(Components.interfaces.nsIFormFillController); + }, + attachFormFillControllerTo: function(window) { + this.getFormFillController() + .attachToBrowser(this._getDocShell(window), + this._getAutoCompletePopup(window)); + }, + detachFormFillControllerFrom: function(window) { + this.getFormFillController().detachFromBrowser(this._getDocShell(window)); + }, isBackButtonEnabled: function(window) { return !this._getTopChromeWindow(window).document .getElementById("Browser:Back") diff --git a/toolkit/content/tests/chrome/Makefile.in b/toolkit/content/tests/chrome/Makefile.in index 85e6d1eea8f..8dbbd40b337 100644 --- a/toolkit/content/tests/chrome/Makefile.in +++ b/toolkit/content/tests/chrome/Makefile.in @@ -89,6 +89,9 @@ _TEST_FILES = findbar_window.xul \ test_autocomplete4.xul \ test_autocomplete5.xul \ test_autocomplete_delayOnPaste.xul \ + file_autocomplete_with_composition.js \ + test_autocomplete_with_composition_on_input.html \ + test_autocomplete_with_composition_on_textbox.xul \ test_keys.xul \ window_keys.xul \ test_showcaret.xul \ diff --git a/toolkit/content/tests/chrome/file_autocomplete_with_composition.js b/toolkit/content/tests/chrome/file_autocomplete_with_composition.js new file mode 100644 index 00000000000..3acb744d2a5 --- /dev/null +++ b/toolkit/content/tests/chrome/file_autocomplete_with_composition.js @@ -0,0 +1,633 @@ +// nsDoTestsForAutoCompleteWithComposition tests autocomplete with composition. +// Users must include SimpleTest.js and EventUtils.js. + +function nsDoTestsForAutoCompleteWithComposition(aDescription, + aWindow, + aTarget, + aAutoCompleteController, + aIsFunc, + aGetTargetValueFunc, + aOnFinishFunc) +{ + this._description = aDescription; + this._window = aWindow; + this._target = aTarget; + this._controller = aAutoCompleteController; + + this._is = aIsFunc; + this._getTargetValue = aGetTargetValueFunc; + this._onFinish = aOnFinishFunc; + + this._target.focus(); + + this._DefaultCompleteDefaultIndex = + this._controller.input.completeDefaultIndex; + + this._doTests(); +} + +nsDoTestsForAutoCompleteWithComposition.prototype = { + _window: null, + _target: null, + _controller: null, + _DefaultCompleteDefaultIndex: false, + _description: "", + + _is: null, + _getTargetValue: function () { return "not initialized"; }, + _onFinish: null, + + _doTests: function () + { + if (++this._testingIndex == this._tests.length) { + this._controller.input.completeDefaultIndex = + this._DefaultCompleteDefaultIndex; + this._onFinish(); + return; + } + + var test = this._tests[this._testingIndex]; + if (this._controller.input.completeDefaultIndex != test.completeDefaultIndex) { + this._controller.input.completeDefaultIndex = test.completeDefaultIndex; + } + test.execute(this._window); + + var timeout = this._controller.input.timeout + 10; + this._waitResult(timeout); + }, + + _waitResult: function (aTimes) + { + var obj = this; + if (aTimes-- > 0) { + setTimeout(function () { obj._waitResult(aTimes); }, 0); + } else { + setTimeout(function () { obj._checkResult(); }, 0); + } + }, + + _checkResult: function () + { + var test = this._tests[this._testingIndex]; + this._is(this._getTargetValue(), test.value, + this._description + ", " + test.description + ": value"); + this._is(this._controller.searchString, test.searchString, + this._description + ", " + test.description +": searchString"); + this._is(this._controller.input.popupOpen, test.popup, + this._description + ", " + test.description + ": popupOpen"); + this._doTests(); + }, + + _testingIndex: -1, + _tests: [ + // Simple composition when popup hasn't been shown. + // The autocomplete popup should not be shown during composition, but + // after compositionend, the popup should be shown. + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow); + synthesizeText( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow); + synthesizeText( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "compositionend should open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "Mo" }, aWindow); + synthesizeKey("VK_ENTER", { type: "keyup" }, aWindow); + }, popup: true, value: "Mo", searchString: "Mo" + }, + // If composition starts when popup is shown, the compositionstart event + // should cause closing the popup. + { description: "compositionstart should close the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("z", { type: "keydown" }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "z" }, aWindow); + synthesizeText( + { "composition": + { "string": "z", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "Moz", searchString: "Mo" + }, + { description: "compositionupdate shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "zi" }, aWindow); + synthesizeText( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mo" + }, + { description: "compositionend should research the result and open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 2, "length": 0 } + }); + synthesizeComposition({ type: "compositionend", data: "zi" }, aWindow); + synthesizeKey("VK_ENTER", { type: "keyup" }, aWindow); + }, popup: true, value: "Mozi", searchString: "Mozi" + }, + // If composition is cancelled, the value shouldn't be changed. + { description: "compositionstart should reclose the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("l", { type: "keydown" }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "l" }, aWindow); + synthesizeText( + { "composition": + { "string": "l", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozil", searchString: "Mozi" + }, + { description: "compositionupdate shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "ll" }, aWindow); + synthesizeText( + { "composition": + { "string": "ll", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozill", searchString: "Mozi" + }, + { description: "empty compositionupdate shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow); + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mozi" + }, + { description: "cancled compositionend should reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "" }, aWindow); + synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow); + }, popup: true, value: "Mozi", searchString: "Mozi" + }, + // But if composition replaces some characters and canceled, the search + // string should be the latest value. + { description: "compositionstart with selected string should close the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_LEFT", { shiftKey: true }, aWindow); + synthesizeKey("VK_LEFT", { shiftKey: true }, aWindow); + synthesizeKey("z", { type: "keydown" }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "z" }, aWindow); + synthesizeText( + { "composition": + { "string": "z", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "Moz", searchString: "Mozi" + }, + { description: "compositionupdate shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "ll" }, aWindow); + synthesizeText( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mozi" + }, + { description: "empty compositionupdate shouldn't reopen the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow); + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "Mozi" + }, + { description: "canceled compositionend should seach the result with the latest value", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "" }, aWindow); + synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow); + }, popup: true, value: "Mo", searchString: "Mo" + }, + //If all characters are removed, the popup should be closed. + { description: "the value becomes empty by backspace, the popup should be closed", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + }, popup: false, value: "", searchString: "" + }, + // composition which is canceled shouldn't cause opening the popup. + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow); + synthesizeText( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow); + synthesizeText( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "empty compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow); + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "", searchString: "" + }, + { description: "canceled compositionend shouldn't open the popup if it was closed", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "" }, aWindow); + synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow); + }, popup: false, value: "", searchString: "" + }, + // Down key should open the popup even if the editor is empty. + { description: "DOWN key should open the popup even if the value is empty", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_DOWN", {}, aWindow); + }, popup: true, value: "", searchString: "" + }, + // If popup is open at starting composition, the popup should be reopened + // after composition anyway. + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow); + synthesizeText( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow); + synthesizeText( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "empty compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow); + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "", searchString: "" + }, + { description: "canceled compositionend should open the popup if it was opened", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "" }, aWindow); + synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow); + }, popup: true, value: "", searchString: "" + }, + // Type normally, and hit escape, the popup should be closed. + { description: "ESCAPE should close the popup after typing something", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("M", { shiftKey: true }, aWindow); + synthesizeKey("o", { shiftKey: true }, aWindow); + synthesizeKey("VK_ESCAPE", {}, aWindow); + }, popup: false, value: "Mo", searchString: "Mo" + }, + // Even if the popup is closed, composition which is canceled should open + // the popup if the value isn't empty. + // XXX This might not be good behavior, but anyway, this is minor issue... + { description: "compositionstart shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("z", { type: "keydown", shiftKey: true }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "z" }, aWindow); + synthesizeText( + { "composition": + { "string": "z", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "Moz", searchString: "Mo" + }, + { description: "compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "zi" }, aWindow); + synthesizeText( + { "composition": + { "string": "zi", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mozi", searchString: "Mo" + }, + { description: "empty compositionupdate shouldn't open the popup", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow); + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "Mo" + }, + { description: "canceled compositionend shouldn't open the popup if the popup was closed", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 0, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "" }, aWindow); + synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow); + }, popup: true, value: "Mo", searchString: "Mo" + }, + // House keeping... + { description: "house keeping for next tests", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + }, popup: false, value: "", searchString: "" + }, + // Testing for nsIAutoCompleteInput.completeDefaultIndex being true. + { description: "compositionstart shouldn't open the popup (completeDefaultIndex is true)", + completeDefaultIndex: true, + execute: function (aWindow) { + synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow); + synthesizeComposition({ type: "compositionstart" }, aWindow); + synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow); + synthesizeText( + { "composition": + { "string": "M", + "clauses": + [ + { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 1, "length": 0 } + }, aWindow); + }, popup: false, value: "M", searchString: "" + }, + { description: "compositionupdate shouldn't open the popup (completeDefaultIndex is true)", + completeDefaultIndex: true, + execute: function (aWindow) { + synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow); + synthesizeText( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + }, popup: false, value: "Mo", searchString: "" + }, + { description: "compositionend should open the popup (completeDefaultIndex is true)", + completeDefaultIndex: true, + execute: function (aWindow) { + synthesizeText( + { "composition": + { "string": "Mo", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 2, "length": 0 } + }, aWindow); + synthesizeComposition({ type: "compositionend", data: "Mo" }, aWindow); + synthesizeKey("VK_ENTER", { type: "keyup" }, aWindow); + }, popup: true, value: "Mozilla", searchString: "Mo" + }, + // House keeping... + { description: "house keeping for next tests", + completeDefaultIndex: false, + execute: function (aWindow) { + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + synthesizeKey("VK_BACK_SPACE", {}, aWindow); + }, popup: false, value: "", searchString: "" + } + ] +}; diff --git a/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html new file mode 100644 index 00000000000..471611aea39 --- /dev/null +++ b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html @@ -0,0 +1,65 @@ + + + + autocomplete with composition tests on HTML input element + + + + + + + +

+ +
+ +
+ +
+
+ +
+
+
+ + diff --git a/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_textbox.xul b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_textbox.xul new file mode 100644 index 00000000000..50f7f2e76b4 --- /dev/null +++ b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_textbox.xul @@ -0,0 +1,125 @@ + + + + + + + From 6ea043acbce2cbce30d87eeb80b5bb944bc827fb Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Tue, 27 Mar 2012 16:29:42 +0200 Subject: [PATCH 019/113] Bug 737846 - followup: fix typo in test. --HG-- extra : rebase_source : 14b5abf42bc25cb54eaf490988fb9814abe6dc66 --- .../components/places/tests/chrome/test_favicon_annotations.xul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/components/places/tests/chrome/test_favicon_annotations.xul b/toolkit/components/places/tests/chrome/test_favicon_annotations.xul index bad9a1f9d2c..01d352f8bb2 100644 --- a/toolkit/components/places/tests/chrome/test_favicon_annotations.xul +++ b/toolkit/components/places/tests/chrome/test_favicon_annotations.xul @@ -179,7 +179,7 @@ function test() loadNextTest(); } } - }); + ); } From 8d304ca1047d30da4fc1a33dc1a6221ce10d28fa Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 27 Mar 2012 10:59:38 -0400 Subject: [PATCH 020/113] Bug 729528 - Follow-up to fix incorrect calculation. r=Cwiiis --- mobile/android/chrome/content/browser.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 6550542b3aa..b2ad2635603 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1611,17 +1611,35 @@ Tab.prototype = { if (zoom <= 0 || resolution <= 0) return; + // "zoom" is the user-visible zoom of the "this" tab + // "resolution" is the zoom at which we wish gecko to render "this" tab at + // these two may be different if we are, for example, trying to render a + // large area of the page at low resolution because the user is panning real + // fast. + // The viewport values (aViewportX and aViewportY) correspond to the + // gecko scroll position, and are zoom-multiplied. The display port rect + // values (aDisplayPort), however, is in CSS pixels multiplied by the desired + // rendering resolution. Therefore care must be taken when doing math with + // these sets of values, to ensure that they are normalized to the same coordinate + // space first. + let element = this.browser.contentDocument.documentElement; if (!element) return; + // we should never be drawing background tabs at resolutions other than the user- + // visible zoom. for foreground tabs, however, if we are drawing at some other + // resolution, we need to set the resolution as specified. let cwu = window.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); if (BrowserApp.selectedTab == this) cwu.setResolution(resolution, resolution); else if (resolution != zoom) dump("Warning: setDisplayPort resolution did not match zoom for background tab!"); - cwu.setDisplayPortForElement((aDisplayPort.left - aViewportX) / resolution, - (aDisplayPort.top - aViewportY) / resolution, + + // finally, we set the display port, taking care to convert everything into the CSS-pixel + // coordinate space, because that is what the function accepts. + cwu.setDisplayPortForElement((aDisplayPort.left / resolution) - (aViewportX / zoom), + (aDisplayPort.top / resolution) - (aViewportY / zoom), (aDisplayPort.right - aDisplayPort.left) / resolution, (aDisplayPort.bottom - aDisplayPort.top) / resolution, element); From 16dbeaf8edca3539d26671083ba8dfc436c2bb0b Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Tue, 27 Mar 2012 12:00:34 -0400 Subject: [PATCH 021/113] Bug 738919. Add reftest for a canvas dash array with a single element. r=mwoodrow. --HG-- extra : rebase_source : 06afe9bc1401f53a6e6929a5063fd4af3da699cc --- layout/reftests/canvas/dash-1-ref.svg | 4 ++++ layout/reftests/canvas/dash-1.html | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/layout/reftests/canvas/dash-1-ref.svg b/layout/reftests/canvas/dash-1-ref.svg index b577edf5ae1..b1c3b967f92 100644 --- a/layout/reftests/canvas/dash-1-ref.svg +++ b/layout/reftests/canvas/dash-1-ref.svg @@ -11,4 +11,8 @@ + + + diff --git a/layout/reftests/canvas/dash-1.html b/layout/reftests/canvas/dash-1.html index e0921e1eac6..c7b032bc22f 100644 --- a/layout/reftests/canvas/dash-1.html +++ b/layout/reftests/canvas/dash-1.html @@ -17,6 +17,14 @@ window.onload = function() { ctx.lineTo(250, 100); ctx.stroke(); ctx.beginPath(); + + ctx.mozDashOffset = 5; + ctx.mozDash = [ 5 ]; // 5 on, 5 off + ctx.moveTo(50, 150); + ctx.lineTo(250, 150); + ctx.stroke(); + ctx.beginPath(); + } From f1875ed381f0fadc0019077ce1a379d657252e10 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 27 Mar 2012 08:49:03 -0700 Subject: [PATCH 022/113] bug 231162 - support custom casing behavior for Turkish and similar writing systems. r=smontagu --- gfx/thebes/Makefile.in | 2 ++ gfx/thebes/gfxAtomList.h | 6 ++++ layout/generic/nsTextRunTransformations.cpp | 35 ++++++++++++++++++--- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/gfx/thebes/Makefile.in b/gfx/thebes/Makefile.in index 8f431b37ce2..dbae87dbab4 100644 --- a/gfx/thebes/Makefile.in +++ b/gfx/thebes/Makefile.in @@ -50,6 +50,8 @@ EXPORTS = \ gfx3DMatrix.h \ gfxASurface.h \ gfxAlphaRecovery.h \ + gfxAtomList.h \ + gfxAtoms.h \ gfxBlur.h \ gfxCachedTempSurface.h \ gfxColor.h \ diff --git a/gfx/thebes/gfxAtomList.h b/gfx/thebes/gfxAtomList.h index a10e9e8a9d8..ed57d56a284 100644 --- a/gfx/thebes/gfxAtomList.h +++ b/gfx/thebes/gfxAtomList.h @@ -95,3 +95,9 @@ GFX_ATOM(x_symbol, "x-symbol") // referenced in all.js GFX_ATOM(x_user_def, "x-user-def") + +// additional languages that use Turkish-style case transformation +GFX_ATOM(az, "az") +GFX_ATOM(ba, "ba") +GFX_ATOM(crh, "crh") +GFX_ATOM(tt, "tt") diff --git a/layout/generic/nsTextRunTransformations.cpp b/layout/generic/nsTextRunTransformations.cpp index 07d89fa07b6..0213c6d5101 100644 --- a/layout/generic/nsTextRunTransformations.cpp +++ b/layout/generic/nsTextRunTransformations.cpp @@ -39,6 +39,7 @@ #include "nsTextFrameUtils.h" #include "gfxSkipChars.h" +#include "gfxAtoms.h" #include "nsStyleConsts.h" #include "nsStyleContext.h" @@ -48,6 +49,10 @@ #define SZLIG 0x00DF +// Unicode characters needing special casing treatment in tr/az languages +#define LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE 0x0130 +#define LATIN_SMALL_LETTER_DOTLESS_I 0x0131 + nsTransformedTextRun * nsTransformedTextRun::Create(const gfxTextRunFactory::Parameters* aParams, nsTransformingTextRunFactory* aFactory, @@ -357,31 +362,49 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, nsAutoTArray canBreakBeforeArray; PRUint32 extraCharsCount = 0; + const nsIAtom* lang = nsnull; + bool turkishCasing = false; PRUint32 i; for (i = 0; i < length; ++i) { PRUint32 ch = str[i]; + nsStyleContext* styleContext = styles[i]; charsToMergeArray.AppendElement(false); - styleArray.AppendElement(styles[i]); + styleArray.AppendElement(styleContext); canBreakBeforeArray.AppendElement(aTextRun->CanBreakLineBefore(i)); PRUint8 style = mAllUppercase ? NS_STYLE_TEXT_TRANSFORM_UPPERCASE - : styles[i]->GetStyleText()->mTextTransform; + : styleContext->GetStyleText()->mTextTransform; bool extraChar = false; if (NS_IS_HIGH_SURROGATE(ch) && i < length - 1 && NS_IS_LOW_SURROGATE(str[i + 1])) { ch = SURROGATE_TO_UCS4(ch, str[i + 1]); } + if (lang != styleContext->GetStyleFont()->mLanguage) { + lang = styleContext->GetStyleFont()->mLanguage; + turkishCasing = lang == gfxAtoms::tr || + lang == gfxAtoms::az || + lang == gfxAtoms::ba || + lang == gfxAtoms::crh || + lang == gfxAtoms::tt; + } + switch (style) { case NS_STYLE_TEXT_TRANSFORM_LOWERCASE: - ch = ToLowerCase(ch); + if (turkishCasing && ch == 'I') { + ch = LATIN_SMALL_LETTER_DOTLESS_I; + } else { + ch = ToLowerCase(ch); + } break; case NS_STYLE_TEXT_TRANSFORM_UPPERCASE: if (ch == SZLIG) { convertedString.Append('S'); extraChar = true; ch = 'S'; + } else if (turkishCasing && ch == 'i') { + ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE; } else { ch = ToUpperCase(ch); } @@ -392,6 +415,8 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, convertedString.Append('S'); extraChar = true; ch = 'S'; + } else if (turkishCasing && ch == 'i') { + ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE; } else { ch = ToTitleCase(ch); } @@ -408,14 +433,14 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun, convertedString.Append(L_SURROGATE(ch)); i++; charsToMergeArray.AppendElement(false); - styleArray.AppendElement(styles[i]); + styleArray.AppendElement(styleContext); canBreakBeforeArray.AppendElement(false); } if (extraChar) { ++extraCharsCount; charsToMergeArray.AppendElement(true); - styleArray.AppendElement(styles[i]); + styleArray.AppendElement(styleContext); canBreakBeforeArray.AppendElement(false); } } From e14cf120b1edc42f1ce84eb9159a885762ffac44 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 27 Mar 2012 08:49:50 -0700 Subject: [PATCH 023/113] bug 231162 - reftests for Turkish casing behavior. r=smontagu --- layout/reftests/text-transform/reftest.list | 2 ++ .../small-caps-turkish-1-notref.html | 24 +++++++++++++++++ .../text-transform/small-caps-turkish-1.html | 24 +++++++++++++++++ .../text-transform/turkish-casing-1-ref.html | 27 +++++++++++++++++++ .../text-transform/turkish-casing-1.html | 27 +++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 layout/reftests/text-transform/small-caps-turkish-1-notref.html create mode 100644 layout/reftests/text-transform/small-caps-turkish-1.html create mode 100644 layout/reftests/text-transform/turkish-casing-1-ref.html create mode 100644 layout/reftests/text-transform/turkish-casing-1.html diff --git a/layout/reftests/text-transform/reftest.list b/layout/reftests/text-transform/reftest.list index ad403e83c7f..ec0c6404f87 100644 --- a/layout/reftests/text-transform/reftest.list +++ b/layout/reftests/text-transform/reftest.list @@ -13,3 +13,5 @@ == smtp-upper.html smtp-upper-ref.html == smtp-lower.html smtp-lower-ref.html == smtp-title.html smtp-title-ref.html +== turkish-casing-1.html turkish-casing-1-ref.html +HTTP(..) != small-caps-turkish-1.html small-caps-turkish-1-notref.html diff --git a/layout/reftests/text-transform/small-caps-turkish-1-notref.html b/layout/reftests/text-transform/small-caps-turkish-1-notref.html new file mode 100644 index 00000000000..4e735277a1a --- /dev/null +++ b/layout/reftests/text-transform/small-caps-turkish-1-notref.html @@ -0,0 +1,24 @@ + + + + +Test for Turkish small-caps behavior + + + +
+Evrensel Kod her yazı karakteri için bir ve yalnız bir sayı şart koşar, +hangi altyapı, +hangi yazılım, +hangi dil olursa olsun. +
+ + diff --git a/layout/reftests/text-transform/small-caps-turkish-1.html b/layout/reftests/text-transform/small-caps-turkish-1.html new file mode 100644 index 00000000000..be848f4b27b --- /dev/null +++ b/layout/reftests/text-transform/small-caps-turkish-1.html @@ -0,0 +1,24 @@ + + + + +Test for Turkish small-caps behavior + + + +
+Evrensel Kod her yazı karakteri için bir ve yalnız bir sayı şart koşar, +hangi altyapı, +hangi yazılım, +hangi dil olursa olsun. +
+ + diff --git a/layout/reftests/text-transform/turkish-casing-1-ref.html b/layout/reftests/text-transform/turkish-casing-1-ref.html new file mode 100644 index 00000000000..77acf66cad0 --- /dev/null +++ b/layout/reftests/text-transform/turkish-casing-1-ref.html @@ -0,0 +1,27 @@ + + + + +Test for Turkish casing behavior + + +
+EVRENSEL KOD HER YAZI KARAKTERİ İÇİN BİR VE YALNIZ BİR SAYI ŞART KOŞAR, +HANGİ ALTYAPI, +HANGİ YAZILIM, +HANGİ DİL OLURSA OLSUN. +
+
+evrensel kod her yazı karakteri için bir ve yalnız bir sayı şart koşar, +hangi altyapı, +hangi yazılım, +hangi dil olursa olsun. +
+
+Evrensel Kod Her Yazı Karakteri İçin Bir Ve Yalnız Bir Sayı Şart Koşar, +Hangi Altyapı, +Hangi Yazılım, +Hangi Dil Olursa Olsun. +
+ + diff --git a/layout/reftests/text-transform/turkish-casing-1.html b/layout/reftests/text-transform/turkish-casing-1.html new file mode 100644 index 00000000000..976b9dd8cf1 --- /dev/null +++ b/layout/reftests/text-transform/turkish-casing-1.html @@ -0,0 +1,27 @@ + + + + +Test for Turkish casing behavior + + +
+Evrensel Kod her yazı karakteri için bir ve yalnız bir sayı şart koşar, +hangi altyapı, +hangi yazılım, +hangi dil olursa olsun. +
+
+EVRENSEL KOD HER YAZI KARAKTERİ İÇİN BİR VE YALNIZ BİR SAYI ŞART KOŞAR, +HANGİ ALTYAPI, +HANGİ YAZILIM, +HANGİ DİL OLURSA OLSUN. +
+
+Evrensel Kod her yazı karakteri için bir ve yalnız bir sayı şart koşar, +hangi altyapı, +hangi yazılım, +hangi dil olursa olsun. +
+ + From 2fe21688ad68f0b61c10b410e7dcdafee097fe7b Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Tue, 27 Mar 2012 11:46:40 -0400 Subject: [PATCH 024/113] Bug 739632 - fix -Wwrite-strings warnings in dom/workers/EventTarget.cpp; r=bent --- dom/workers/EventTarget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/workers/EventTarget.cpp b/dom/workers/EventTarget.cpp index 7644fd3c484..097469e1be1 100644 --- a/dom/workers/EventTarget.cpp +++ b/dom/workers/EventTarget.cpp @@ -69,7 +69,7 @@ DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget") inline bool -EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, char* aFunctionName) +EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, const char* aFunctionName) { JSClass* classPtr = JS_GetClass(aObj); if (ClassIsWorker(classPtr) || ClassIsWorkerGlobalScope(classPtr) || From 1bd52abc32f5b5338c20c1ade9d137e4f169ce12 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 27 Mar 2012 18:05:41 +0100 Subject: [PATCH 025/113] Bug 737867 - Apply ViewHolder pattern in AwesomeBar's All/Bookmarks tabs (r=mfinkle) --- mobile/android/base/AwesomeBarTabs.java | 200 +++++++++++++----------- 1 file changed, 105 insertions(+), 95 deletions(-) diff --git a/mobile/android/base/AwesomeBarTabs.java b/mobile/android/base/AwesomeBarTabs.java index 2607b4a9037..083630cd59e 100644 --- a/mobile/android/base/AwesomeBarTabs.java +++ b/mobile/android/base/AwesomeBarTabs.java @@ -117,6 +117,12 @@ public class AwesomeBarTabs extends TabHost { public void onSearch(String engine); } + private class ViewHolder { + public TextView titleView; + public TextView urlView; + public ImageView faviconView; + } + private class HistoryListAdapter extends SimpleExpandableListAdapter { public HistoryListAdapter(Context context, List> groupData, int groupLayout, String[] groupFrom, int[] groupTo, @@ -152,51 +158,6 @@ public class AwesomeBarTabs extends TabHost { } } - private class AwesomeCursorViewBinder implements SimpleCursorAdapter.ViewBinder { - private boolean updateFavicon(View view, Cursor cursor, int faviconIndex) { - byte[] b = cursor.getBlob(faviconIndex); - ImageView favicon = (ImageView) view; - - if (b == null) { - favicon.setImageDrawable(null); - } else { - Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); - favicon.setImageBitmap(bitmap); - } - - return true; - } - - private boolean updateTitle(View view, Cursor cursor, int titleIndex) { - String title = cursor.getString(titleIndex); - TextView titleView = (TextView)view; - // Use the URL instead of an empty title for consistency with the normal URL - // bar view - this is the equivalent of getDisplayTitle() in Tab.java - if (TextUtils.isEmpty(title)) { - int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL); - title = cursor.getString(urlIndex); - } - - titleView.setText(title); - return true; - } - - public boolean setViewValue(View view, Cursor cursor, int columnIndex) { - int faviconIndex = cursor.getColumnIndexOrThrow(URLColumns.FAVICON); - if (columnIndex == faviconIndex) { - return updateFavicon(view, cursor, faviconIndex); - } - - int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE); - if (columnIndex == titleIndex) { - return updateTitle(view, cursor, titleIndex); - } - - // Other columns are handled automatically - return false; - } - } - private class BookmarksListAdapter extends SimpleCursorAdapter { private static final int VIEW_TYPE_ITEM = 0; private static final int VIEW_TYPE_FOLDER = 1; @@ -207,8 +168,8 @@ public class AwesomeBarTabs extends TabHost { private LinkedList> mParentStack; private LinearLayout mBookmarksTitleView; - public BookmarksListAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { - super(context, layout, c, from, to); + public BookmarksListAdapter(Context context, Cursor c) { + super(context, -1, c, new String[] {}, new int[] {}); mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mResources = mContext.getResources(); @@ -294,15 +255,38 @@ public class AwesomeBarTabs extends TabHost { @Override public View getView(int position, View convertView, ViewGroup parent) { int viewType = getItemViewType(position); + ViewHolder viewHolder = null; - if (viewType == VIEW_TYPE_ITEM) - return super.getView(position, convertView, parent); + if (convertView == null) { + if (viewType == VIEW_TYPE_ITEM) + convertView = mInflater.inflate(R.layout.awesomebar_row, null); + else + convertView = mInflater.inflate(R.layout.awesomebar_folder_row, null); - if (convertView == null) - convertView = mInflater.inflate(R.layout.awesomebar_folder_row, null); + viewHolder = new ViewHolder(); + viewHolder.titleView = (TextView) convertView.findViewById(R.id.title); + viewHolder.faviconView = (ImageView) convertView.findViewById(R.id.favicon); - TextView titleView = (TextView) convertView.findViewById(R.id.title); - titleView.setText(getFolderTitle(position)); + if (viewType == VIEW_TYPE_ITEM) + viewHolder.urlView = (TextView) convertView.findViewById(R.id.url); + + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + + Cursor cursor = getCursor(); + if (!cursor.moveToPosition(position)) + throw new IllegalStateException("Couldn't move cursor to position " + position); + + if (viewType == VIEW_TYPE_ITEM) { + updateTitle(viewHolder.titleView, cursor); + updateUrl(viewHolder.urlView, cursor); + } else { + viewHolder.titleView.setText(getFolderTitle(position)); + } + + updateFavicon(viewHolder.faviconView, cursor); return convertView; } @@ -360,18 +344,7 @@ public class AwesomeBarTabs extends TabHost { list.setAdapter(null); if (mBookmarksAdapter == null) { - // Load the list using a custom adapter so we can create the bitmaps - mBookmarksAdapter = new BookmarksListAdapter( - mContext, - R.layout.awesomebar_row, - cursor, - new String[] { URLColumns.TITLE, - URLColumns.URL, - URLColumns.FAVICON }, - new int[] { R.id.title, R.id.url, R.id.favicon } - ); - - mBookmarksAdapter.setViewBinder(new AwesomeCursorViewBinder()); + mBookmarksAdapter = new BookmarksListAdapter(mContext, cursor); } else { mBookmarksAdapter.changeCursor(cursor); } @@ -595,11 +568,14 @@ public class AwesomeBarTabs extends TabHost { } private class AwesomeBarCursorAdapter extends SimpleCursorAdapter { + private LayoutInflater mInflater; private String mSearchTerm; - public AwesomeBarCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { - super(context, layout, c, from, to); + public AwesomeBarCursorAdapter(Context context) { + super(context, -1, null, new String[] {}, new int[] {}); mSearchTerm = ""; + + mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void filter(String searchTerm) { @@ -641,18 +617,35 @@ public class AwesomeBarTabs extends TabHost { @Override public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder = null; + + if (convertView == null) { + convertView = mInflater.inflate(R.layout.awesomebar_row, null); + + viewHolder = new ViewHolder(); + viewHolder.titleView = (TextView) convertView.findViewById(R.id.title); + viewHolder.urlView = (TextView) convertView.findViewById(R.id.url); + viewHolder.faviconView = (ImageView) convertView.findViewById(R.id.favicon); + + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + final int resultCount = super.getCount(); - if (position < resultCount) - return super.getView(position, convertView, parent); + if (position < resultCount) { + Cursor cursor = getCursor(); + if (!cursor.moveToPosition(position)) + throw new IllegalStateException("Couldn't move cursor to position " + position); - View v; - if (convertView == null) - v = newView(mContext, null, parent); - else - v = convertView; - bindSearchEngineView(position - resultCount, v); + updateTitle(viewHolder.titleView, cursor); + updateUrl(viewHolder.urlView, cursor); + updateFavicon(viewHolder.faviconView, cursor); + } else { + bindSearchEngineView(position - resultCount, viewHolder); + } - return v; + return convertView; } private Drawable getDrawableFromDataURI(String dataURI) { @@ -669,7 +662,7 @@ public class AwesomeBarTabs extends TabHost { return drawable; } - private void bindSearchEngineView(int position, View view) { + private void bindSearchEngineView(int position, ViewHolder viewHolder) { String name; String iconURI; String searchText = getResources().getString(R.string.awesomebar_search_engine, mSearchTerm); @@ -682,14 +675,10 @@ public class AwesomeBarTabs extends TabHost { return; } - TextView titleView = (TextView) view.findViewById(R.id.title); - TextView urlView = (TextView) view.findViewById(R.id.url); - ImageView faviconView = (ImageView) view.findViewById(R.id.favicon); - - titleView.setText(name); - urlView.setText(searchText); + viewHolder.titleView.setText(name); + viewHolder.urlView.setText(searchText); Drawable drawable = getDrawableFromDataURI(iconURI); - faviconView.setImageDrawable(drawable); + viewHolder.faviconView.setImageDrawable(drawable); } }; @@ -793,17 +782,7 @@ public class AwesomeBarTabs extends TabHost { R.id.all_pages_list); // Load the list using a custom adapter so we can create the bitmaps - mAllPagesCursorAdapter = new AwesomeBarCursorAdapter( - mContext, - R.layout.awesomebar_row, - null, - new String[] { URLColumns.TITLE, - URLColumns.URL, - URLColumns.FAVICON }, - new int[] { R.id.title, R.id.url, R.id.favicon } - ); - - mAllPagesCursorAdapter.setViewBinder(new AwesomeCursorViewBinder()); + mAllPagesCursorAdapter = new AwesomeBarCursorAdapter(mContext); mAllPagesCursorAdapter.setFilterQueryProvider(new FilterQueryProvider() { public Cursor runQuery(CharSequence constraint) { @@ -922,6 +901,37 @@ public class AwesomeBarTabs extends TabHost { } } + private void updateFavicon(ImageView faviconView, Cursor cursor) { + byte[] b = cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON)); + if (b == null) { + faviconView.setImageDrawable(null); + } else { + Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); + faviconView.setImageBitmap(bitmap); + } + } + + private void updateTitle(TextView titleView, Cursor cursor) { + int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE); + String title = cursor.getString(titleIndex); + + // Use the URL instead of an empty title for consistency with the normal URL + // bar view - this is the equivalent of getDisplayTitle() in Tab.java + if (TextUtils.isEmpty(title)) { + int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL); + title = cursor.getString(urlIndex); + } + + titleView.setText(title); + } + + private void updateUrl(TextView urlView, Cursor cursor) { + int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL); + String url = cursor.getString(urlIndex); + + urlView.setText(url); + } + public void setOnUrlOpenListener(OnUrlOpenListener listener) { mUrlOpenListener = listener; } From 0e65aabc5d70b5f8d22664709af226c0b4bf22cb Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 27 Mar 2012 18:05:41 +0100 Subject: [PATCH 026/113] Bug 737867 - Apply ViewHolder pattern on AwesomeBar's History tab (r=mfinkle) --- mobile/android/base/AwesomeBarTabs.java | 45 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/mobile/android/base/AwesomeBarTabs.java b/mobile/android/base/AwesomeBarTabs.java index 083630cd59e..da6058ea2c9 100644 --- a/mobile/android/base/AwesomeBarTabs.java +++ b/mobile/android/base/AwesomeBarTabs.java @@ -124,37 +124,59 @@ public class AwesomeBarTabs extends TabHost { } private class HistoryListAdapter extends SimpleExpandableListAdapter { + LayoutInflater mInflater; + public HistoryListAdapter(Context context, List> groupData, int groupLayout, String[] groupFrom, int[] groupTo, - List>> childData, - int childLayout, String[] childFrom, int[] childTo) { + List>> childData) { super(context, groupData, groupLayout, groupFrom, groupTo, - childData, childLayout, childFrom, childTo); + childData, -1, new String[] {}, new int[] {}); + + mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + ViewHolder viewHolder = null; - View childView = - super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent); + if (convertView == null) { + convertView = mInflater.inflate(R.layout.awesomebar_row, null); + + viewHolder = new ViewHolder(); + viewHolder.titleView = (TextView) convertView.findViewById(R.id.title); + viewHolder.urlView = (TextView) convertView.findViewById(R.id.url); + viewHolder.faviconView = (ImageView) convertView.findViewById(R.id.favicon); + + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } @SuppressWarnings("unchecked") Map historyItem = (Map) mHistoryAdapter.getChild(groupPosition, childPosition); + String title = (String) historyItem.get(URLColumns.TITLE); + String url = (String) historyItem.get(URLColumns.URL); + + if (TextUtils.isEmpty(title)) + title = url; + + viewHolder.titleView.setText(title); + viewHolder.urlView.setText(url); + byte[] b = (byte[]) historyItem.get(URLColumns.FAVICON); - ImageView favicon = (ImageView) childView.findViewById(R.id.favicon); if (b == null) { - favicon.setImageDrawable(null); + viewHolder.faviconView.setImageDrawable(null); } else { Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); - favicon.setImageBitmap(bitmap); + viewHolder.faviconView.setImageBitmap(bitmap); } - return childView; + return convertView; } } @@ -532,10 +554,7 @@ public class AwesomeBarTabs extends TabHost { R.layout.awesomebar_header_row, new String[] { URLColumns.TITLE }, new int[] { R.id.title }, - result.second, - R.layout.awesomebar_row, - new String[] { URLColumns.TITLE, URLColumns.URL }, - new int[] { R.id.title, R.id.url } + result.second ); final ExpandableListView historyList = From 5601a2edc18ab616c7cb955956a99bdac19e1e56 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 27 Mar 2012 18:05:41 +0100 Subject: [PATCH 027/113] Bug 737867 - Share same LayoutInflater instance in AwesomeBarTabs (r=mfinkle) --- mobile/android/base/AwesomeBarTabs.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/mobile/android/base/AwesomeBarTabs.java b/mobile/android/base/AwesomeBarTabs.java index da6058ea2c9..6f59afebedf 100644 --- a/mobile/android/base/AwesomeBarTabs.java +++ b/mobile/android/base/AwesomeBarTabs.java @@ -96,6 +96,7 @@ public class AwesomeBarTabs extends TabHost { private Context mContext; private boolean mInflated; + private LayoutInflater mInflater; private OnUrlOpenListener mUrlOpenListener; private View.OnTouchListener mListTouchListener; private JSONArray mSearchEngines; @@ -124,16 +125,12 @@ public class AwesomeBarTabs extends TabHost { } private class HistoryListAdapter extends SimpleExpandableListAdapter { - LayoutInflater mInflater; - public HistoryListAdapter(Context context, List> groupData, int groupLayout, String[] groupFrom, int[] groupTo, List>> childData) { super(context, groupData, groupLayout, groupFrom, groupTo, childData, -1, new String[] {}, new int[] {}); - - mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override @@ -185,7 +182,6 @@ public class AwesomeBarTabs extends TabHost { private static final int VIEW_TYPE_FOLDER = 1; private static final int VIEW_TYPE_COUNT = 2; - private LayoutInflater mInflater; private Resources mResources; private LinkedList> mParentStack; private LinearLayout mBookmarksTitleView; @@ -193,7 +189,6 @@ public class AwesomeBarTabs extends TabHost { public BookmarksListAdapter(Context context, Cursor c) { super(context, -1, c, new String[] {}, new int[] {}); - mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mResources = mContext.getResources(); // mParentStack holds folder id/title pairs that allow us to navigate @@ -373,7 +368,7 @@ public class AwesomeBarTabs extends TabHost { LinearLayout headerView = mBookmarksAdapter.getHeaderView(); if (headerView == null) { - headerView = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.awesomebar_header_row, null); + headerView = (LinearLayout) mInflater.inflate(R.layout.awesomebar_header_row, null); mBookmarksAdapter.setHeaderView(headerView); } @@ -587,14 +582,11 @@ public class AwesomeBarTabs extends TabHost { } private class AwesomeBarCursorAdapter extends SimpleCursorAdapter { - private LayoutInflater mInflater; private String mSearchTerm; public AwesomeBarCursorAdapter(Context context) { super(context, -1, null, new String[] {}, new int[] {}); mSearchTerm = ""; - - mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void filter(String searchTerm) { @@ -710,6 +702,7 @@ public class AwesomeBarTabs extends TabHost { mInflated = false; mSearchEngines = new JSONArray(); mContentResolver = context.getContentResolver(); + mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override @@ -772,10 +765,7 @@ public class AwesomeBarTabs extends TabHost { private TabSpec addAwesomeTab(String id, int titleId, int contentId) { TabSpec tab = newTabSpec(id); - LayoutInflater inflater = - (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - View indicatorView = inflater.inflate(R.layout.awesomebar_tab_indicator, null); + View indicatorView = mInflater.inflate(R.layout.awesomebar_tab_indicator, null); Drawable background = indicatorView.getBackground(); try { background.setColorFilter(new LightingColorFilter(Color.WHITE, GeckoApp.mBrowserToolbar.getHighlightColor())); From d5cfa390dcc43a014184c67573d65520cdc4808a Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Tue, 27 Mar 2012 09:32:32 -0700 Subject: [PATCH 028/113] Set all languages to true in language.properties. Bug 730625, r=jfkthame --- intl/locale/src/language.properties | 528 ++++++++++++++-------------- 1 file changed, 264 insertions(+), 264 deletions(-) diff --git a/intl/locale/src/language.properties b/intl/locale/src/language.properties index 35c4ed1cb03..cc0e912b1ec 100644 --- a/intl/locale/src/language.properties +++ b/intl/locale/src/language.properties @@ -1,265 +1,265 @@ -aa.accept = false -ab.accept = true -ae.accept = false -af.accept = true -ak.accept = false -am.accept = true -an.accept = true -ar.accept = true -ar-ae.accept = true -ar-bh.accept = true -ar-dz.accept = true -ar-eg.accept = true -ar-iq.accept = true -ar-jo.accept = true -ar-kw.accept = true -ar-lb.accept = true -ar-ly.accept = true -ar-ma.accept = true -ar-om.accept = true -ar-qa.accept = true -ar-sa.accept = true -ar-sy.accept = true -ar-tn.accept = true -ar-ye.accept = true -as.accept = true -ast.accept = true -av.accept = false -ay.accept = true -az.accept = true -ba.accept = false -be.accept = true -bg.accept = true -bh.accept = false -bi.accept = false -bm.accept = false -bn.accept = true -bo.accept = true -br.accept = true -bs.accept = true -ca.accept = true -ce.accept = true -ch.accept = true -co.accept = true -cr.accept = true -cs.accept = true -cu.accept = false -cv.accept = true -cy.accept = true -da.accept = true -de.accept = true -de-at.accept = true -de-ch.accept = true -de-de.accept = true -de-li.accept = true -de-lu.accept = true -dv.accept = false -dz.accept = true -ee.accept = false -el.accept = true -en.accept = true -en-au.accept = true -en-bz.accept = true -en-ca.accept = true -en-gb.accept = true -en-ie.accept = true -en-jm.accept = true -en-nz.accept = true -en-ph.accept = true -en-tt.accept = true -en-us.accept = true -en-za.accept = true -en-zw.accept = true -eo.accept = true -es.accept = true -es-ar.accept = true -es-bo.accept = true -es-cl.accept = true -es-co.accept = true -es-cr.accept = true -es-do.accept = true -es-ec.accept = true -es-es.accept = true -es-gt.accept = true -es-hn.accept = true -es-mx.accept = true -es-ni.accept = true -es-pa.accept = true -es-pe.accept = true -es-pr.accept = true -es-py.accept = true -es-sv.accept = true -es-uy.accept = true -es-ve.accept = true -et.accept = true -eu.accept = true -fa.accept = true -fa-ir.accept = true -ff.accept = false -fi.accept = true -fj.accept = true -fo.accept = true -fr.accept = true -fr-be.accept = true -fr-ca.accept = true -fr-ch.accept = true -fr-fr.accept = true -fr-lu.accept = true -fr-mc.accept = true -fur.accept = true -fy.accept = true -ga.accept = true -gd.accept = true -gl.accept = true -gn.accept = true -gu.accept = true -gv.accept = true -ha.accept = false -he.accept = true -hi.accept = true -ho.accept = false -hsb.accept = true -hr.accept = true -ht.accept = true -hu.accept = true -hy.accept = true -hz.accept = false -ia.accept = true -id.accept = true -ie.accept = true -ig.accept = false -ii.accept = false -ik.accept = false -io.accept = false -is.accept = true -it.accept = true -it-ch.accept = true -iu.accept = true -ja.accept = true -jv.accept = false -ka.accept = true -kg.accept = false -ki.accept = false -kk.accept = true -kl.accept = true -km.accept = true -kn.accept = true -ko.accept = true -ko-kp.accept = true -ko-kr.accept = true -kok.accept = true -kr.accept = false -ks.accept = true -ku.accept = true -kv.accept = false -kw.accept = false -ky.accept = true -la.accept = true -lb.accept = true -lg.accept = false -li.accept = false -ln.accept = true -lo.accept = false -lt.accept = true -lu.accept = false -lv.accept = true -mg.accept = true -mh.accept = true -mi.accept = true -mk.accept = false -mk-mk.accept = true -ml.accept = true -mn.accept = true -mr.accept = true -ms.accept = true -mt.accept = true -my.accept = true -na.accept = true -nb.accept = true -nd.accept = true -ne.accept = true -ng.accept = true -nl.accept = true -nl-be.accept = true -nn.accept = true -no.accept = true -nr.accept = true -nso.accept = true -nv.accept = true -ny.accept = true -oc.accept = true -oj.accept = false -om.accept = true -or.accept = true -os.accept = false -pa.accept = true -pa-in.accept = true -pa-pk.accept = true -pi.accept = false -pl.accept = true -ps.accept = true -pt.accept = true -pt-br.accept = true -qu.accept = true -rm.accept = true -rn.accept = true -ro.accept = true -ro-md.accept = true -ro-ro.accept = true -ru.accept = true -ru-md.accept = false -rw.accept = true -sa.accept = true -sc.accept = true -sd.accept = true -sg.accept = true -si.accept = true -sk.accept = true -sl.accept = true -sm.accept = true -so.accept = true +aa.accept = true +ab.accept = true +ae.accept = true +af.accept = true +ak.accept = true +am.accept = true +an.accept = true +ar.accept = true +ar-ae.accept = true +ar-bh.accept = true +ar-dz.accept = true +ar-eg.accept = true +ar-iq.accept = true +ar-jo.accept = true +ar-kw.accept = true +ar-lb.accept = true +ar-ly.accept = true +ar-ma.accept = true +ar-om.accept = true +ar-qa.accept = true +ar-sa.accept = true +ar-sy.accept = true +ar-tn.accept = true +ar-ye.accept = true +as.accept = true +ast.accept = true +av.accept = true +ay.accept = true +az.accept = true +ba.accept = true +be.accept = true +bg.accept = true +bh.accept = true +bi.accept = true +bm.accept = true +bn.accept = true +bo.accept = true +br.accept = true +bs.accept = true +ca.accept = true +ce.accept = true +ch.accept = true +co.accept = true +cr.accept = true +cs.accept = true +cu.accept = true +cv.accept = true +cy.accept = true +da.accept = true +de.accept = true +de-at.accept = true +de-ch.accept = true +de-de.accept = true +de-li.accept = true +de-lu.accept = true +dv.accept = true +dz.accept = true +ee.accept = true +el.accept = true +en.accept = true +en-au.accept = true +en-bz.accept = true +en-ca.accept = true +en-gb.accept = true +en-ie.accept = true +en-jm.accept = true +en-nz.accept = true +en-ph.accept = true +en-tt.accept = true +en-us.accept = true +en-za.accept = true +en-zw.accept = true +eo.accept = true +es.accept = true +es-ar.accept = true +es-bo.accept = true +es-cl.accept = true +es-co.accept = true +es-cr.accept = true +es-do.accept = true +es-ec.accept = true +es-es.accept = true +es-gt.accept = true +es-hn.accept = true +es-mx.accept = true +es-ni.accept = true +es-pa.accept = true +es-pe.accept = true +es-pr.accept = true +es-py.accept = true +es-sv.accept = true +es-uy.accept = true +es-ve.accept = true +et.accept = true +eu.accept = true +fa.accept = true +fa-ir.accept = true +ff.accept = true +fi.accept = true +fj.accept = true +fo.accept = true +fr.accept = true +fr-be.accept = true +fr-ca.accept = true +fr-ch.accept = true +fr-fr.accept = true +fr-lu.accept = true +fr-mc.accept = true +fur.accept = true +fy.accept = true +ga.accept = true +gd.accept = true +gl.accept = true +gn.accept = true +gu.accept = true +gv.accept = true +ha.accept = true +he.accept = true +hi.accept = true +ho.accept = true +hsb.accept = true +hr.accept = true +ht.accept = true +hu.accept = true +hy.accept = true +hz.accept = true +ia.accept = true +id.accept = true +ie.accept = true +ig.accept = true +ii.accept = true +ik.accept = true +io.accept = true +is.accept = true +it.accept = true +it-ch.accept = true +iu.accept = true +ja.accept = true +jv.accept = true +ka.accept = true +kg.accept = true +ki.accept = true +kk.accept = true +kl.accept = true +km.accept = true +kn.accept = true +ko.accept = true +ko-kp.accept = true +ko-kr.accept = true +kok.accept = true +kr.accept = true +ks.accept = true +ku.accept = true +kv.accept = true +kw.accept = true +ky.accept = true +la.accept = true +lb.accept = true +lg.accept = true +li.accept = true +ln.accept = true +lo.accept = true +lt.accept = true +lu.accept = true +lv.accept = true +mg.accept = true +mh.accept = true +mi.accept = true +mk.accept = true +mk-mk.accept = true +ml.accept = true +mn.accept = true +mr.accept = true +ms.accept = true +mt.accept = true +my.accept = true +na.accept = true +nb.accept = true +nd.accept = true +ne.accept = true +ng.accept = true +nl.accept = true +nl-be.accept = true +nn.accept = true +no.accept = true +nr.accept = true +nso.accept = true +nv.accept = true +ny.accept = true +oc.accept = true +oj.accept = true +om.accept = true +or.accept = true +os.accept = true +pa.accept = true +pa-in.accept = true +pa-pk.accept = true +pi.accept = true +pl.accept = true +ps.accept = true +pt.accept = true +pt-br.accept = true +qu.accept = true +rm.accept = true +rn.accept = true +ro.accept = true +ro-md.accept = true +ro-ro.accept = true +ru.accept = true +ru-md.accept = true +rw.accept = true +sa.accept = true +sc.accept = true +sd.accept = true +sg.accept = true +si.accept = true +sk.accept = true +sl.accept = true +sm.accept = true +so.accept = true son-ml.accept = true -sq.accept = true -sr.accept = true -ss.accept = true -st.accept = true -su.accept = false -sv.accept = true -sv-fi.accept = true -sv-se.accept = true -sw.accept = true -ta.accept = true -te.accept = true -tg.accept = false -th.accept = true -ti.accept = true -tig.accept = true -tk.accept = true -tl.accept = true -tlh.accept = true -tn.accept = true -to.accept = true -tr.accept = true -ts.accept = true -tt.accept = true -tw.accept = false -ty.accept = false -ug.accept = false -uk.accept = true -ur.accept = true -uz.accept = false -ve.accept = true -vi.accept = true -vo.accept = true -wa.accept = true -wo.accept = true -xh.accept = true -yi.accept = true -yo.accept = false -za.accept = false -zh.accept = true -zh-cn.accept = true -zh-hk.accept = true -zh-sg.accept = true -zh-tw.accept = true -zu.accept = true +sq.accept = true +sr.accept = true +ss.accept = true +st.accept = true +su.accept = true +sv.accept = true +sv-fi.accept = true +sv-se.accept = true +sw.accept = true +ta.accept = true +te.accept = true +tg.accept = true +th.accept = true +ti.accept = true +tig.accept = true +tk.accept = true +tl.accept = true +tlh.accept = true +tn.accept = true +to.accept = true +tr.accept = true +ts.accept = true +tt.accept = true +tw.accept = true +ty.accept = true +ug.accept = true +uk.accept = true +ur.accept = true +uz.accept = true +ve.accept = true +vi.accept = true +vo.accept = true +wa.accept = true +wo.accept = true +xh.accept = true +yi.accept = true +yo.accept = true +za.accept = true +zh.accept = true +zh-cn.accept = true +zh-hk.accept = true +zh-sg.accept = true +zh-tw.accept = true +zu.accept = true From fe13627f8a0f12f950272c9981d10b0addc57984 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 27 Mar 2012 10:47:26 -0700 Subject: [PATCH 029/113] Bug 739515 - Defensive coding for Fennec history entries. r=emtwo,nalexander --- .../AndroidBrowserHistoryDataExtender.java | 5 +++++ .../AndroidBrowserHistoryRepositorySession.java | 15 +++++++++++++++ .../AndroidBrowserRepositoryDataAccessor.java | 10 +++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java index 415bcd7a423..b84a248363f 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java @@ -138,6 +138,11 @@ public class AndroidBrowserHistoryDataExtender extends CachedSQLiteOpenHelper { } public JSONArray visitsForGUID(String guid) throws NullCursorException { + if (guid == null) { + Logger.warn(LOG_TAG, "Asked for visits for null GUID."); + return new JSONArray(); + } + Logger.debug(LOG_TAG, "Fetching visits for GUID " + guid); Cursor visits = fetch(guid); try { diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java index c7bf3faf26c..e5267bd469d 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryRepositorySession.java @@ -6,9 +6,12 @@ package org.mozilla.gecko.sync.repositories.android; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.sync.repositories.InactiveSessionException; +import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException; import org.mozilla.gecko.sync.repositories.NullCursorException; import org.mozilla.gecko.sync.repositories.Repository; +import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionBeginDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate; import org.mozilla.gecko.sync.repositories.domain.HistoryRecord; import org.mozilla.gecko.sync.repositories.domain.Record; @@ -28,6 +31,18 @@ public class AndroidBrowserHistoryRepositorySession extends AndroidBrowserReposi dbHelper = new AndroidBrowserHistoryDataAccessor(context); } + @Override + public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException { + // HACK: Fennec creates history records without a GUID. Mercilessly drop + // them on the floor. See Bug 739514. + try { + dbHelper.delete(BrowserContract.History.GUID + " IS NULL", null); + } catch (Exception e) { + // Ignore. + } + super.begin(delegate); + } + @Override protected Record retrieveDuringStore(Cursor cur) { return RepoUtils.historyFromMirrorCursor(cur); diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java index 798bed6c755..cbbfc9a4148 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java @@ -92,10 +92,14 @@ public abstract class AndroidBrowserRepositoryDataAccessor { return BrowserContract.SyncColumns.DATE_MODIFIED + " >= " + Long.toString(timestamp); } - public void wipe() { + public void delete(String where, String[] args) { Uri uri = getUri(); - Logger.debug(LOG_TAG, "Wiping: " + uri); - context.getContentResolver().delete(uri, null, null); + context.getContentResolver().delete(uri, where, args); + } + + public void wipe() { + Logger.debug(LOG_TAG, "Wiping."); + delete(null, null); } public void purgeDeleted() throws NullCursorException { From e9e87ba8ede59ab6e98e5a52509867784a2a5758 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 27 Mar 2012 10:47:26 -0700 Subject: [PATCH 030/113] Bug 731024 - Part 4: Handle additional types. Test for livemarks. r=nalexander --- mobile/android/base/sync/Utils.java | 37 ++++ .../AndroidBrowserBookmarksDataAccessor.java | 15 +- ...roidBrowserBookmarksRepositorySession.java | 47 +++-- .../AndroidBrowserRepositorySession.java | 27 ++- .../repositories/domain/BookmarkRecord.java | 199 ++++++++++++++---- 5 files changed, 259 insertions(+), 66 deletions(-) diff --git a/mobile/android/base/sync/Utils.java b/mobile/android/base/sync/Utils.java index d4d16b88bb2..c1fd3142d5b 100644 --- a/mobile/android/base/sync/Utils.java +++ b/mobile/android/base/sync/Utils.java @@ -41,11 +41,14 @@ package org.mozilla.gecko.sync; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.URLDecoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.TreeMap; import org.json.simple.JSONArray; @@ -267,4 +270,38 @@ public class Utils { } return true; } + + /** + * Takes a URI, extracting URI components. + * @param scheme the URI scheme on which to match. + */ + public static Map extractURIComponents(String scheme, String uri) { + if (uri.indexOf(scheme) != 0) { + throw new IllegalArgumentException("URI scheme does not match: " + scheme); + } + + // Do this the hard way to avoid taking a large dependency on + // HttpClient or getting all regex-tastic. + String components = uri.substring(scheme.length()); + HashMap out = new HashMap(); + String[] parts = components.split("&"); + for (int i = 0; i < parts.length; ++i) { + String part = parts[i]; + if (part.length() == 0) { + continue; + } + String[] pair = part.split("=", 2); + switch (pair.length) { + case 0: + continue; + case 1: + out.put(URLDecoder.decode(pair[0]), null); + break; + case 2: + out.put(URLDecoder.decode(pair[0]), URLDecoder.decode(pair[1])); + break; + } + } + return out; + } } diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java index 46e3093dabb..a62e07d9867 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java @@ -187,9 +187,16 @@ public class AndroidBrowserBookmarksDataAccessor extends AndroidBrowserRepositor @Override protected ContentValues getContentValues(Record record) { - ContentValues cv = new ContentValues(); BookmarkRecord rec = (BookmarkRecord) record; + + final int recordType = BrowserContractHelpers.typeCodeForString(rec.type); + if (recordType == -1) { + throw new IllegalStateException("Unexpected record type " + rec.type); + } + + ContentValues cv = new ContentValues(); cv.put(BrowserContract.SyncColumns.GUID, rec.guid); + cv.put(BrowserContract.Bookmarks.TYPE, recordType); cv.put(BrowserContract.Bookmarks.TITLE, rec.title); cv.put(BrowserContract.Bookmarks.URL, rec.bookmarkURI); cv.put(BrowserContract.Bookmarks.DESCRIPTION, rec.description); @@ -201,12 +208,6 @@ public class AndroidBrowserBookmarksDataAccessor extends AndroidBrowserRepositor cv.put(BrowserContract.Bookmarks.PARENT, rec.androidParentID); cv.put(BrowserContract.Bookmarks.POSITION, rec.androidPosition); - // Only bookmark and folder types should make it this far. - // Other types should be filtered out and dropped. - cv.put(BrowserContract.Bookmarks.TYPE, rec.type.equalsIgnoreCase(TYPE_FOLDER) ? - BrowserContract.Bookmarks.TYPE_FOLDER : - BrowserContract.Bookmarks.TYPE_BOOKMARK); - // Note that we don't set the modified timestamp: we allow the // content provider to do that for us. return cv; diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index 66dea741c8c..61b4ee12315 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -198,8 +198,8 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo dataAccessor = (AndroidBrowserBookmarksDataAccessor) dbHelper; } - private static long getTypeFromCursor(Cursor cur) { - return RepoUtils.getLongFromCursor(cur, BrowserContract.Bookmarks.TYPE); + private static int getTypeFromCursor(Cursor cur) { + return RepoUtils.getIntFromCursor(cur, BrowserContract.Bookmarks.TYPE); } private static boolean rowIsFolder(Cursor cur) { @@ -479,10 +479,10 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo return true; } - if (bmk.isBookmark() || - bmk.isFolder()) { + if (BrowserContractHelpers.isSupportedType(bmk.type)) { return false; } + Logger.debug(LOG_TAG, "Ignoring record with guid: " + bmk.guid + " and type: " + bmk.type); return true; } @@ -578,22 +578,22 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo Logger.pii(LOG_TAG, "Inserting folder " + bmk.guid + ", " + bmk.title + " with parent " + bmk.androidParentID + " (" + bmk.parentID + ", " + bmk.parentName + - ", " + bmk.pos + ")"); + ", " + bmk.androidPosition + ")"); } else { Logger.pii(LOG_TAG, "Inserting bookmark " + bmk.guid + ", " + bmk.title + ", " + bmk.bookmarkURI + " with parent " + bmk.androidParentID + " (" + bmk.parentID + ", " + bmk.parentName + - ", " + bmk.pos + ")"); + ", " + bmk.androidPosition + ")"); } } else { if (bmk.isFolder()) { Logger.debug(LOG_TAG, "Inserting folder " + bmk.guid + ", parent " + bmk.androidParentID + - " (" + bmk.parentID + ", " + bmk.pos + ")"); + " (" + bmk.parentID + ", " + bmk.androidPosition + ")"); } else { Logger.debug(LOG_TAG, "Inserting bookmark " + bmk.guid + " with parent " + bmk.androidParentID + - " (" + bmk.parentID + ", " + ", " + bmk.pos + ")"); + " (" + bmk.parentID + ", " + ", " + bmk.androidPosition + ")"); } } return bmk; @@ -685,7 +685,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo } final BookmarkRecord bookmarkRecord = (BookmarkRecord) record; if (bookmarkRecord.isFolder()) { - Logger.debug(LOG_TAG, "Deleting folder. Ensuring consistency of children."); + Logger.debug(LOG_TAG, "Deleting folder. Ensuring consistency of children. TODO: Bug 724470."); handleFolderDeletion(bookmarkRecord); return; } @@ -768,7 +768,20 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo @Override protected String buildRecordString(Record record) { BookmarkRecord bmk = (BookmarkRecord) record; - return bmk.title + bmk.bookmarkURI + bmk.type + bmk.parentName; + String parent = bmk.parentName + "/"; + if (bmk.isBookmark()) { + return "b" + parent + bmk.bookmarkURI + ":" + bmk.title; + } + if (bmk.isFolder()) { + return "f" + parent + bmk.title; + } + if (bmk.isSeparator()) { + return "s" + parent + bmk.androidPosition; + } + if (bmk.isQuery()) { + return "q" + parent + bmk.bookmarkURI; + } + return null; } public static BookmarkRecord computeParentFields(BookmarkRecord rec, String suggestedParentGUID, String suggestedParentName) { @@ -815,8 +828,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo Logger.pii(LOG_TAG, "> Title: " + rec.title); Logger.pii(LOG_TAG, "> Type: " + rec.type); Logger.pii(LOG_TAG, "> URI: " + rec.bookmarkURI); - Logger.pii(LOG_TAG, "> Android position: " + rec.androidPosition); - Logger.pii(LOG_TAG, "> Position: " + rec.pos); + Logger.pii(LOG_TAG, "> Position: " + rec.androidPosition); if (rec.isFolder()) { Logger.pii(LOG_TAG, "FOLDER: Children are " + (rec.children == null ? @@ -843,15 +855,20 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo return logBookmark(rec); } - boolean isFolder = rowIsFolder(cur); + int rowType = getTypeFromCursor(cur); + String typeString = BrowserContractHelpers.typeStringForCode(rowType); + if (typeString == null) { + Logger.warn(LOG_TAG, "Unsupported type code " + rowType); + return null; + } + + rec.type = typeString; rec.title = RepoUtils.getStringFromCursor(cur, BrowserContract.Bookmarks.TITLE); rec.bookmarkURI = RepoUtils.getStringFromCursor(cur, BrowserContract.Bookmarks.URL); rec.description = RepoUtils.getStringFromCursor(cur, BrowserContract.Bookmarks.DESCRIPTION); rec.tags = RepoUtils.getJSONArrayFromCursor(cur, BrowserContract.Bookmarks.TAGS); rec.keyword = RepoUtils.getStringFromCursor(cur, BrowserContract.Bookmarks.KEYWORD); - rec.type = isFolder ? AndroidBrowserBookmarksDataAccessor.TYPE_FOLDER : - AndroidBrowserBookmarksDataAccessor.TYPE_BOOKMARK; rec.androidID = RepoUtils.getLongFromCursor(cur, BrowserContract.Bookmarks._ID); rec.androidPosition = RepoUtils.getLongFromCursor(cur, BrowserContract.Bookmarks.POSITION); diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java index 37e1f66ff8e..08c90ca13eb 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java @@ -456,7 +456,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } // TODO: pass in timestamps? - Logger.debug(LOG_TAG, "Replacing " + existingRecord.guid + " with record " + toStore.guid); + Logger.debug(LOG_TAG, "Replacing existing " + existingRecord.guid + " with record " + toStore.guid); Record replaced = replace(toStore, existingRecord); // Note that we don't track records here; deciding that is the job @@ -570,14 +570,20 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos Logger.debug(LOG_TAG, "Finding existing record for incoming record with GUID " + record.guid); String recordString = buildRecordString(record); + if (recordString == null) { + Logger.debug(LOG_TAG, "No record string for incoming record " + record.guid); + return null; + } + Logger.debug(LOG_TAG, "Searching with record string " + recordString); String guid = getRecordToGuidMap().get(recordString); - if (guid != null) { - Logger.debug(LOG_TAG, "Found one. Returning computed record."); - return retrieveByGUIDDuringStore(guid); + if (guid == null) { + Logger.debug(LOG_TAG, "findExistingRecord failed to find one for " + record.guid); + return null; } - Logger.debug(LOG_TAG, "findExistingRecord failed to find one for " + record.guid); - return null; + + Logger.debug(LOG_TAG, "Found one. Returning computed record."); + return retrieveByGUIDDuringStore(guid); } public HashMap getRecordToGuidMap() throws NoGuidForIdException, NullCursorException, ParentNotFoundException { @@ -602,7 +608,10 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos while (!cur.isAfterLast()) { Record record = retrieveDuringStore(cur); if (record != null) { - recordToGuid.put(buildRecordString(record), record.guid); + final String recordString = buildRecordString(record); + if (recordString != null) { + recordToGuid.put(recordString, record.guid); + } } cur.moveToNext(); } @@ -613,6 +622,10 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } public void putRecordToGuidMap(String recordString, String guid) throws NoGuidForIdException, NullCursorException, ParentNotFoundException { + if (recordString == null) { + return; + } + if (recordToGuid == null) { createRecordToGuidMap(); } diff --git a/mobile/android/base/sync/repositories/domain/BookmarkRecord.java b/mobile/android/base/sync/repositories/domain/BookmarkRecord.java index 79ce5c1da06..2b226ee99d3 100644 --- a/mobile/android/base/sync/repositories/domain/BookmarkRecord.java +++ b/mobile/android/base/sync/repositories/domain/BookmarkRecord.java @@ -38,6 +38,10 @@ package org.mozilla.gecko.sync.repositories.domain; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Map; + import org.json.simple.JSONArray; import org.mozilla.gecko.sync.ExtendedJSONObject; import org.mozilla.gecko.sync.Logger; @@ -53,6 +57,8 @@ import android.util.Log; * */ public class BookmarkRecord extends Record { + public static final String PLACES_URI_PREFIX = "places:"; + private static final String LOG_TAG = "BookmarkRecord"; public static final String COLLECTION_NAME = "bookmarks"; @@ -83,7 +89,6 @@ public class BookmarkRecord extends Record { public String parentName; public long androidParentID; public String type; - public String pos; public long androidPosition; public JSONArray children; @@ -131,7 +136,6 @@ public class BookmarkRecord extends Record { out.parentName = this.parentName; out.androidParentID = this.androidParentID; out.type = this.type; - out.pos = this.pos; out.androidPosition = this.androidPosition; out.children = this.copyChildren(); @@ -197,30 +201,12 @@ public class BookmarkRecord extends Record { @Override protected void initFromPayload(ExtendedJSONObject payload) { - this.type = (String) payload.get("type"); - this.title = (String) payload.get("title"); - this.description = (String) payload.get("description"); - this.parentID = (String) payload.get("parentid"); - this.parentName = (String) payload.get("parentName"); + this.type = payload.getString("type"); + this.title = payload.getString("title"); + this.description = payload.getString("description"); + this.parentID = payload.getString("parentid"); + this.parentName = payload.getString("parentName"); - // bookmark, microsummary, query. - if (isBookmarkIsh()) { - this.keyword = (String) payload.get("keyword"); - try { - this.tags = payload.getArray("tags"); - } catch (NonArrayJSONException e) { - Logger.warn(LOG_TAG, "Got non-array tags in bookmark record " + this.guid, e); - this.tags = new JSONArray(); - } - } - - // bookmark. - if (isBookmark()) { - this.bookmarkURI = (String) payload.get("bmkUri"); - return; - } - - // folder. if (isFolder()) { try { this.children = payload.getArray("children"); @@ -232,20 +218,64 @@ public class BookmarkRecord extends Record { return; } + final String bmkUri = payload.getString("bmkUri"); + + // bookmark, microsummary, query. + if (isBookmarkIsh()) { + this.keyword = payload.getString("keyword"); + try { + this.tags = payload.getArray("tags"); + } catch (NonArrayJSONException e) { + Logger.warn(LOG_TAG, "Got non-array tags in bookmark record " + this.guid, e); + this.tags = new JSONArray(); + } + } + + if (isBookmark()) { + this.bookmarkURI = bmkUri; + return; + } + if (isLivemark()) { - // TODO: siteUri, feedUri. + String siteUri = payload.getString("siteUri"); + String feedUri = payload.getString("feedUri"); + this.bookmarkURI = encodeUnsupportedTypeURI(bmkUri, + "siteUri", siteUri, + "feedUri", feedUri); return; } if (isQuery()) { - // TODO: queryId (optional), folderName. + String queryId = payload.getString("queryId"); + String folderName = payload.getString("folderName"); + this.bookmarkURI = encodeUnsupportedTypeURI(bmkUri, + "queryId", queryId, + "folderName", folderName); return; } if (isMicrosummary()) { - // TODO: generatorUri, staticTitle. + String generatorUri = payload.getString("generatorUri"); + String staticTitle = payload.getString("staticTitle"); + this.bookmarkURI = encodeUnsupportedTypeURI(bmkUri, + "generatorUri", generatorUri, + "staticTitle", staticTitle); return; } if (isSeparator()) { - this.pos = payload.getString("pos"); + Object p = payload.get("pos"); + if (p instanceof Long) { + this.androidPosition = (Long) p; + } else if (p instanceof String) { + try { + this.androidPosition = Long.parseLong((String) p, 10); + } catch (NumberFormatException e) { + return; + } + } else { + Logger.warn(LOG_TAG, "Unsupported position value " + p); + return; + } + String pos = String.valueOf(this.androidPosition); + this.bookmarkURI = encodeUnsupportedTypeURI(null, "pos", pos, null, null); return; } } @@ -259,17 +289,57 @@ public class BookmarkRecord extends Record { putPayload(payload, "parentName", this.parentName); putPayload(payload, "keyword", this.keyword); - if (this.tags != null) { - payload.put("tags", this.tags); - } - - if (isBookmark()) { - payload.put("bmkUri", bookmarkURI); - } else if (isFolder()) { + if (isFolder()) { payload.put("children", this.children); + return; } - // TODO: fields for other types. + // bookmark, microsummary, query. + if (isBookmarkIsh()) { + if (isBookmark()) { + payload.put("bmkUri", bookmarkURI); + } + + if (isQuery()) { + Map parts = Utils.extractURIComponents(PLACES_URI_PREFIX, this.bookmarkURI); + putPayload(payload, "queryId", parts.get("queryId")); + putPayload(payload, "folderName", parts.get("folderName")); + return; + } + + if (this.tags != null) { + payload.put("tags", this.tags); + } + + putPayload(payload, "keyword", this.keyword); + return; + } + + if (isLivemark()) { + Map parts = Utils.extractURIComponents(PLACES_URI_PREFIX, this.bookmarkURI); + putPayload(payload, "siteUri", parts.get("siteUri")); + putPayload(payload, "feedUri", parts.get("feedUri")); + return; + } + if (isMicrosummary()) { + Map parts = Utils.extractURIComponents(PLACES_URI_PREFIX, this.bookmarkURI); + putPayload(payload, "generatorUri", parts.get("generatorUri")); + putPayload(payload, "staticTitle", parts.get("staticTitle")); + return; + } + if (isSeparator()) { + Map parts = Utils.extractURIComponents(PLACES_URI_PREFIX, this.bookmarkURI); + String pos = parts.get("pos"); + if (pos == null) { + return; + } + try { + payload.put("pos", Long.parseLong(pos, 10)); + } catch (NumberFormatException e) { + return; + } + return; + } } private void trace(String s) { @@ -348,6 +418,61 @@ public class BookmarkRecord extends Record { if (a != null && b == null) return false; return RepoUtils.stringsEqual(a.toJSONString(), b.toJSONString()); } + + /** + * URL-encode the provided string. If the input is null, + * the empty string is returned. + * + * @param in the string to encode. + * @return a URL-encoded version of the input. + */ + protected static String encode(String in) { + if (in == null) { + return ""; + } + try { + return URLEncoder.encode(in, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // Will never occur. + return null; + } + } + + /** + * Take the provided URI and two parameters, constructing a URI like + * + * places:uri=$uri&p1=$p1&p2=$p2 + * + * null values in either parameter or value result in the parameter being omitted. + */ + protected static String encodeUnsupportedTypeURI(String originalURI, String p1, String v1, String p2, String v2) { + StringBuilder b = new StringBuilder(PLACES_URI_PREFIX); + boolean previous = false; + if (originalURI != null) { + b.append("uri="); + b.append(encode(originalURI)); + previous = true; + } + if (p1 != null) { + if (previous) { + b.append("&"); + } + b.append(p1); + b.append("="); + b.append(encode(v1)); + previous = true; + } + if (p2 != null) { + if (previous) { + b.append("&"); + } + b.append(p2); + b.append("="); + b.append(encode(v2)); + previous = true; + } + return b.toString(); + } } From 647d01776d1c5dc989e148c3b597ccdbbcc54ed6 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 27 Mar 2012 10:47:26 -0700 Subject: [PATCH 031/113] Bug 731024 - Part 5: Safer handling of deleted items. r=nalexander --- .../android/AndroidBrowserBookmarksDataAccessor.java | 7 +++++++ .../AndroidBrowserBookmarksRepositorySession.java | 5 +++++ .../android/AndroidBrowserRepositorySession.java | 11 ++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java index a62e07d9867..caf8b5a658f 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java @@ -189,6 +189,13 @@ public class AndroidBrowserBookmarksDataAccessor extends AndroidBrowserRepositor protected ContentValues getContentValues(Record record) { BookmarkRecord rec = (BookmarkRecord) record; + if (rec.deleted) { + ContentValues cv = new ContentValues(); + cv.put(BrowserContract.SyncColumns.GUID, rec.guid); + cv.put(BrowserContract.Bookmarks.IS_DELETED, 1); + return cv; + } + final int recordType = BrowserContractHelpers.typeCodeForString(rec.type); if (recordType == -1) { throw new IllegalStateException("Unexpected record type " + rec.type); diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index 61b4ee12315..c1d654bc7c1 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -566,6 +566,11 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo @Override protected Record prepareRecord(Record record) { + if (record.deleted) { + Logger.debug(LOG_TAG, "No need to prepare deleted record " + record.guid); + return record; + } + BookmarkRecord bmk = (BookmarkRecord) record; if (!isSpecialRecord(record)) { diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java index 08c90ca13eb..5a3c1003314 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java @@ -456,7 +456,16 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } // TODO: pass in timestamps? - Logger.debug(LOG_TAG, "Replacing existing " + existingRecord.guid + " with record " + toStore.guid); + + // This section of code will only run if the incoming record is not + // marked as deleted, so we never want to just drop ours from the database: + // we need to upload it later. + // Allowing deleted items to propagate through `replace` allows normal + // logging and side-effects to occur, and is no more expensive than simply + // bumping the modified time. + Logger.debug(LOG_TAG, "Replacing existing " + existingRecord.guid + + (toStore.deleted ? " with deleted record " : " with record ") + + toStore.guid); Record replaced = replace(toStore, existingRecord); // Note that we don't track records here; deciding that is the job From adf7394c63a0531b9ef843aa1f8a0a6943cb3a24 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Tue, 27 Mar 2012 13:48:58 -0400 Subject: [PATCH 032/113] Bug 719427. Add a comment about malloc_logger. r=espindola --- xpcom/base/nsStackWalk.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xpcom/base/nsStackWalk.cpp b/xpcom/base/nsStackWalk.cpp index 85331447f3c..09a8e56feb6 100644 --- a/xpcom/base/nsStackWalk.cpp +++ b/xpcom/base/nsStackWalk.cpp @@ -151,6 +151,7 @@ StackWalkInitCriticalAddress() // we force a situation where new_sem_from_pool is on the stack and // use dladdr to check the addresses. + // malloc_logger can be set by external tools like 'Instruments' or 'leaks' malloc_logger_t *old_malloc_logger = malloc_logger; malloc_logger = my_malloc_logger; @@ -164,6 +165,8 @@ StackWalkInitCriticalAddress() MOZ_ASSERT(r == 0); struct timespec abstime = {0, 1}; r = pthread_cond_timedwait_relative_np(&cond, &mutex, &abstime); + + // restore the previous malloc logger malloc_logger = old_malloc_logger; // On Lion, malloc is no longer called from pthread_cond_*wait*. This prevents From d0f06adfaca2e7b63a4157359259250cc3fa5e0b Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Tue, 27 Mar 2012 10:54:04 -0700 Subject: [PATCH 033/113] Bug 738841 - Fix handling of 'this' in methodjit without TI (r=bhackett) --- js/src/jit-test/tests/basic/bug738841.js | 49 ++++++++++++++++++++++++ js/src/jit-test/tests/basic/bug738846.js | 49 ++++++++++++++++++++++++ js/src/methodjit/Compiler.cpp | 16 ++++---- 3 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug738841.js create mode 100644 js/src/jit-test/tests/basic/bug738846.js diff --git a/js/src/jit-test/tests/basic/bug738841.js b/js/src/jit-test/tests/basic/bug738841.js new file mode 100644 index 00000000000..71b7d1290f9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug738841.js @@ -0,0 +1,49 @@ +try { + for (let z = 0; z < 1; ++evalcx("[]", newGlobal("new-compartment"))) {} +} catch (e) {} +try { + for (y in [schedulegc(58)]) { + b + } +} catch (e) {} +try { + e +} catch (e) {} +try { + (function() { + h + }()) +} catch (e) {} +try { + (function() { + this.m.f = function() {} + }()) +} catch (e) {} +try { + t() +} catch (e) {} +try { + p +} catch (e) {} +try { + gc() + p +} catch (e) {} +try { + (function() { + for (var v of m) {} + }()) +} catch (e) {} +try { + m +} catch (e) {} +try { + var f = function() { + { + print(new function(q)("", s)) + let u + } + }; + dis(f); + f(); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug738846.js b/js/src/jit-test/tests/basic/bug738846.js new file mode 100644 index 00000000000..d99c5686035 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug738846.js @@ -0,0 +1,49 @@ +try { + (function() { + var m + ArrayBuffer() + var _ = t + var _2 = [] + }()) +} catch (e) {} +try { + for (y in [schedulegc(58)]) { + m + } +} catch (e) {} +try { + (function() { + n.(O) + }()) +} catch (e) {} +try { + (function() { + s + }()) +} catch (e) {} +try { + e +} catch (e) {} +try { + "" () +} catch (e) {} +try { + gc() + s +} catch (e) {} +try { + (function() { + for (v of m) {} + }()) +} catch (e) {} +try { + t +} catch (e) {} +try { + (function() { + "use strict"; + print(new function() { + r + }(this)) + }()) +} catch (e) {} diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 1c1a31c6ed4..2ae7f126e6a 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -4122,15 +4122,15 @@ mjit::Compiler::inlineCallHelper(uint32_t callImmArgc, bool callingNew, FrameSiz frame.discardFe(origThis); /* - * If inference is enabled, the 'this' value of the pushed frame always - * needs to be coherent. If a GC gets triggered before the callee can - * fill in the slot (i.e. the GC happens on constructing the 'new' - * object or the call object for a heavyweight callee), it needs to be - * able to read the 'this' value to tell whether newScript constraints - * will need to be regenerated afterwards. + * We store NULL here to ensure that the slot doesn't contain + * garbage. Additionally, we need to store a non-object value here for + * TI. If a GC gets triggered before the callee can fill in the slot + * (i.e. the GC happens on constructing the 'new' object or the call + * object for a heavyweight callee), it needs to be able to read the + * 'this' value to tell whether newScript constraints will need to be + * regenerated afterwards. */ - if (cx->typeInferenceEnabled()) - masm.storeValue(NullValue(), frame.addressOf(origThis)); + masm.storeValue(NullValue(), frame.addressOf(origThis)); } if (!cx->typeInferenceEnabled()) { From 00527c918a8628946cb47bf60b5af5fe8f4c879a Mon Sep 17 00:00:00 2001 From: Ian Melven Date: Tue, 27 Mar 2012 10:55:50 -0700 Subject: [PATCH 034/113] Bug 650386 - CSP should not follow redirects for report-uri r=jst --- content/base/src/contentSecurityPolicy.js | 57 +++++++++++++- content/base/test/Makefile.in | 6 ++ content/base/test/file_bug650386_content.sjs | 37 +++++++++ content/base/test/file_bug650386_report.sjs | 16 ++++ .../test/test_bug650386_redirect_301.html | 78 +++++++++++++++++++ .../test/test_bug650386_redirect_302.html | 78 +++++++++++++++++++ .../test/test_bug650386_redirect_303.html | 78 +++++++++++++++++++ .../test/test_bug650386_redirect_307.html | 78 +++++++++++++++++++ 8 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 content/base/test/file_bug650386_content.sjs create mode 100644 content/base/test/file_bug650386_report.sjs create mode 100644 content/base/test/test_bug650386_redirect_301.html create mode 100644 content/base/test/test_bug650386_redirect_302.html create mode 100644 content/base/test/test_bug650386_redirect_303.html create mode 100644 content/base/test/test_bug650386_redirect_307.html diff --git a/content/base/src/contentSecurityPolicy.js b/content/base/src/contentSecurityPolicy.js index b288837bd0a..91ef65dd1ce 100644 --- a/content/base/src/contentSecurityPolicy.js +++ b/content/base/src/contentSecurityPolicy.js @@ -19,6 +19,7 @@ * Contributor(s): * Sid Stamm * Brandon Sterne + * Ian Melven * * 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 @@ -301,7 +302,7 @@ ContentSecurityPolicy.prototype = { var failure = function(aEvt) { if (req.readyState == 4 && req.status != 200) { - CSPError("Failed to send report to " + reportURI); + CSPError("Failed to send report to " + uris[i]); } }; var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] @@ -313,6 +314,10 @@ ContentSecurityPolicy.prototype = { req.upload.addEventListener("error", failure, false); req.upload.addEventListener("abort", failure, false); + // we need to set an nsIChannelEventSink on the XHR object + // so we can tell it to not follow redirects when posting the reports + req.channel.notificationCallbacks = new CSPReportRedirectSink(); + req.send(JSON.stringify(report)); CSPdebug("Sent violation report to " + uris[i]); } catch(e) { @@ -494,4 +499,54 @@ ContentSecurityPolicy.prototype = { }, }; +// The POST of the violation report (if it happens) should not follow +// redirects, per the spec. hence, we implement an nsIChannelEventSink +// with an object so we can tell XHR to abort if a redirect happens. +function CSPReportRedirectSink() { +} + +CSPReportRedirectSink.prototype = { + QueryInterface: function requestor_qi(iid) { + if (iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIInterfaceRequestor) || + iid.equals(Ci.nsIChannelEventSink)) + return this; + throw Cr.NS_ERROR_NO_INTERFACE; + }, + + // nsIInterfaceRequestor + getInterface: function requestor_gi(iid) { + if (iid.equals(Ci.nsIChannelEventSink)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + + // nsIChannelEventSink + asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel, + flags, callback) { + CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec + + " failed, as a redirect occurred"); + + // cancel the old channel so XHR failure callback happens + oldChannel.cancel(Cr.NS_ERROR_ABORT); + + // notify an observer that we have blocked the report POST due to a redirect, + // used in testing, do this async since we're in an async call now to begin with + Services.tm.mainThread.dispatch( + function() { + observerSubject = Cc["@mozilla.org/supports-cstring;1"] + .createInstance(Ci.nsISupportsCString); + observerSubject.data = oldChannel.URI.asciiSpec; + + Services.obs.notifyObservers(observerSubject, + CSP_VIOLATION_TOPIC, + "denied redirect while sending violation report"); + }, Ci.nsIThread.DISPATCH_NORMAL); + + // throw to stop the redirect happening + throw Cr.NS_BINDING_REDIRECTED; + } +}; + var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentSecurityPolicy]); diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index d3c7da73e97..f641589f7e2 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -572,6 +572,12 @@ _TEST_FILES2 = \ test_bug737612.html \ test_bug738108.html \ test_bug366944.html \ + test_bug650386_redirect_301.html \ + test_bug650386_redirect_302.html \ + test_bug650386_redirect_303.html \ + test_bug650386_redirect_307.html \ + file_bug650386_content.sjs \ + file_bug650386_report.sjs \ $(NULL) _CHROME_FILES = \ diff --git a/content/base/test/file_bug650386_content.sjs b/content/base/test/file_bug650386_content.sjs new file mode 100644 index 00000000000..c4f20dc4ffc --- /dev/null +++ b/content/base/test/file_bug650386_content.sjs @@ -0,0 +1,37 @@ +// SJS file for tests for bug650386, serves file_bug650386_content.html +// with a CSP that will trigger a violation and that will report it +// to file_bug650386_report.sjs +// +// This handles 301, 302, 303 and 307 redirects. The HTTP status code +// returned/type of redirect to do comes from the query string +// parameter passed in from the test_bug650386_* files and then also +// uses that value in the report-uri parameter of the CSP +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + + // this gets used in the CSP as part of the report URI. + var redirect = request.queryString; + + if (redirect < 301 || (redirect > 303 && redirect <= 306) || redirect > 307) { + // if we somehow got some bogus redirect code here, + // do a 302 redirect to the same URL as the report URI + // redirects to - this will fail the test. + var loc = "http://example.com/some/fake/path"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", loc, false); + return; + } + + var csp = "default-src \'self\';report-uri http://mochi.test:8888/tests/content/base/test/file_bug650386_report.sjs?" + redirect; + + response.setHeader("X-Content-Security-Policy", csp, false); + + // the actual file content. + // this image load will (intentionally) fail due to the CSP policy of default-src: 'self' + // specified by the CSP string above. + var content = ""; + + response.write(content); + + return; +} diff --git a/content/base/test/file_bug650386_report.sjs b/content/base/test/file_bug650386_report.sjs new file mode 100644 index 00000000000..af777a9ef8b --- /dev/null +++ b/content/base/test/file_bug650386_report.sjs @@ -0,0 +1,16 @@ +// SJS file for tests for bug650386, this serves as CSP violation report target +// and issues a redirect, to make sure the browser does not post to the target +// of the redirect, per CSP spec. +// This handles 301, 302, 303 and 307 redirects. The HTTP status code +// returned/type of redirect to do comes from the query string +// parameter +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + + var redirect = request.queryString; + + var loc = "http://example.com/some/fake/path"; + response.setStatusLine("1.1", redirect, "Found"); + response.setHeader("Location", loc, false); + return; +} diff --git a/content/base/test/test_bug650386_redirect_301.html b/content/base/test/test_bug650386_redirect_301.html new file mode 100644 index 00000000000..d90c2c4c4b9 --- /dev/null +++ b/content/base/test/test_bug650386_redirect_301.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 650386 + + + + +Mozilla Bug 650386 +

+ +
+
+
+ + diff --git a/content/base/test/test_bug650386_redirect_302.html b/content/base/test/test_bug650386_redirect_302.html new file mode 100644 index 00000000000..b45fddb9b5c --- /dev/null +++ b/content/base/test/test_bug650386_redirect_302.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 650386 + + + + +Mozilla Bug 650386 +

+ +
+
+
+ + diff --git a/content/base/test/test_bug650386_redirect_303.html b/content/base/test/test_bug650386_redirect_303.html new file mode 100644 index 00000000000..ea0075f10c0 --- /dev/null +++ b/content/base/test/test_bug650386_redirect_303.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 650386 + + + + +Mozilla Bug 650386 +

+ +
+
+
+ + diff --git a/content/base/test/test_bug650386_redirect_307.html b/content/base/test/test_bug650386_redirect_307.html new file mode 100644 index 00000000000..d16670602a8 --- /dev/null +++ b/content/base/test/test_bug650386_redirect_307.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 650386 + + + + +Mozilla Bug 650386 +

+ +
+
+
+ + From 03dcccc25ef49f30b24200fe3efd9889d9e2d1f6 Mon Sep 17 00:00:00 2001 From: Malini Das Date: Tue, 27 Mar 2012 11:24:49 -0700 Subject: [PATCH 035/113] Bug 737930 - Enable marionette in confvars.sh instead of mozconfig, r=jgriffin --- b2g/confvars.sh | 1 + configure.in | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/b2g/confvars.sh b/b2g/confvars.sh index 8ac2ae546a0..d5924b125ac 100644 --- a/b2g/confvars.sh +++ b/b2g/confvars.sh @@ -69,3 +69,4 @@ fi MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61} MOZ_EXTENSION_MANAGER=1 +ENABLE_MARIONETTE=1 diff --git a/configure.in b/configure.in index 08cfa7af181..9f6075f40ff 100644 --- a/configure.in +++ b/configure.in @@ -6458,14 +6458,6 @@ MOZ_ARG_DISABLE_BOOL(tests, ENABLE_TESTS=, ENABLE_TESTS=1 ) -dnl ======================================================== -dnl Marionette -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(marionette, -[ --enable-marionette Enable Marionette for remote testing and control], - ENABLE_MARIONETTE=1, - ENABLE_MARIONETTE) - dnl ======================================================== dnl parental controls (for Windows Vista) dnl ======================================================== From b765de23753d06d442ab62f34f61f62602461883 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 27 Mar 2012 11:33:25 -0700 Subject: [PATCH 036/113] Bug 729589 - Fix js-ctypes tests for compartment-per-global. r=jorendorff --- .../ctypes/tests/unit/test_jsctypes.js.in | 91 ++++--------------- 1 file changed, 16 insertions(+), 75 deletions(-) diff --git a/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in b/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in index bd86cd561ab..3a9ae7f8e65 100644 --- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in +++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in @@ -48,18 +48,6 @@ try { CTYPES_TEST_LIB = ctypes.libraryName("jsctypes-test"); CTYPES_UNICODE_LIB = ctypes.libraryName("jsctyp\u00E8s-t\u00EB\u00DFt"); -function getParent(obj, fun) -{ - if (typeof parent === "function") - fun(parent(obj)); -} - -function checkParentIsCTypes(o) -{ - function parentIsCTypes(p) { do_check_true(p === ctypes); } - getParent(o, parentIsCTypes); -} - function do_check_throws(f, type, stack) { if (!stack) { @@ -73,7 +61,7 @@ function do_check_throws(f, type, stack) try { f(); } catch (exc) { - if (exc instanceof type) { + if (exc.constructor.name === type.name) { do_check_true(true); return; } @@ -269,20 +257,10 @@ function run_abstract_class_tests() do_check_class(ctypes.CType, "Function"); do_check_class(ctypes.CType.prototype, "CType"); - checkParentIsCTypes(ctypes.CType); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(ctypes.CType) === p.Function.prototype); - do_check_true(ctypes.CType instanceof p.Function); - }); - do_check_true(ctypes.CType.hasOwnProperty("prototype")); do_check_throws(function() { ctypes.CType.prototype(); }, Error); do_check_throws(function() { new ctypes.CType.prototype() }, Error); - checkParentIsCTypes(ctypes.CType.prototype); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(ctypes.CType.prototype) === p.Function.prototype); - do_check_true(ctypes.CType.prototype instanceof p.Function); - }); + do_check_true(ctypes.CType.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.CType.prototype.constructor === ctypes.CType); @@ -316,15 +294,10 @@ function run_abstract_class_tests() do_check_class(ctypes.CData, "Function"); do_check_class(ctypes.CData.prototype, "CData"); - checkParentIsCTypes(ctypes.CData); do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype); do_check_true(ctypes.CData instanceof ctypes.CType); do_check_true(ctypes.CData.hasOwnProperty("prototype")); - checkParentIsCTypes(ctypes.CData.prototype); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(ctypes.CData.prototype) === p.Object.prototype); - }); do_check_true(ctypes.CData.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.CData.prototype.constructor === ctypes.CData); @@ -355,14 +328,7 @@ function run_Int64_tests() { do_check_class(ctypes.Int64, "Function"); do_check_class(ctypes.Int64.prototype, "Int64"); - checkParentIsCTypes(ctypes.Int64); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(ctypes.Int64) === p.Function.prototype); - do_check_true(Object.getPrototypeOf(ctypes.Int64.prototype) === p.Object.prototype); - }); - do_check_true(ctypes.Int64.hasOwnProperty("prototype")); - checkParentIsCTypes(ctypes.Int64.prototype); do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64); @@ -380,7 +346,6 @@ function run_Int64_tests() { do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, Error); let i = ctypes.Int64(0); - checkParentIsCTypes(i); do_check_true(i.__proto__ === ctypes.Int64.prototype); do_check_true(i instanceof ctypes.Int64); @@ -534,16 +499,7 @@ function run_UInt64_tests() { do_check_class(ctypes.UInt64, "Function"); do_check_class(ctypes.UInt64.prototype, "UInt64"); - checkParentIsCTypes(ctypes.UInt64); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(ctypes.UInt64) === p.Function.prototype); - }); - do_check_true(ctypes.UInt64.hasOwnProperty("prototype")); - checkParentIsCTypes(ctypes.UInt64.prototype); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(ctypes.UInt64.prototype) === p.Object.prototype); - }); do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64); @@ -561,7 +517,6 @@ function run_UInt64_tests() { do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, Error); let i = ctypes.UInt64(0); - checkParentIsCTypes(i); do_check_true(i.__proto__ === ctypes.UInt64.prototype); do_check_true(i instanceof ctypes.UInt64); @@ -798,11 +753,9 @@ function run_basic_class_tests(t) do_check_class(t, "CType"); do_check_class(t.prototype, "CData"); - checkParentIsCTypes(t); do_check_true(t.__proto__ === ctypes.CType.prototype); do_check_true(t instanceof ctypes.CType); - checkParentIsCTypes(t.prototype); do_check_true(t.prototype.__proto__ === ctypes.CData.prototype); do_check_true(t.prototype instanceof ctypes.CData); do_check_true(t.prototype.constructor === t); @@ -821,7 +774,6 @@ function run_basic_class_tests(t) // Test that an instance 'd' of 't' is a CData. let d = t(); do_check_class(d, "CData"); - checkParentIsCTypes(d); do_check_true(d.__proto__ === t.prototype); do_check_true(d instanceof t); do_check_true(d.constructor === t); @@ -1346,13 +1298,6 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance do_check_class(c, "Function"); do_check_class(c.prototype, "CType"); - checkParentIsCTypes(c); - getParent(ctypes, function(p) { - do_check_true(Object.getPrototypeOf(c) === p.Function.prototype); - do_check_true(c instanceof p.Function); - }); - - checkParentIsCTypes(c.prototype); do_check_true(c.prototype.__proto__ === ctypes.CType.prototype); do_check_true(c.prototype instanceof ctypes.CType); do_check_true(c.prototype.constructor === c); @@ -1374,18 +1319,15 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance do_check_class(t, "CType"); do_check_class(t.prototype, "CData"); - checkParentIsCTypes(t); do_check_true(t.__proto__ === c.prototype); do_check_true(t instanceof c); - checkParentIsCTypes(t.prototype); do_check_class(t.prototype.__proto__, "CData"); // 't.prototype.__proto__' is the common ancestor of all types constructed // from 'c'; while not available from 'c' directly, it should be identically // equal to 't2.prototype.__proto__' where 't2' is a different CType // constructed from 'c'. do_check_true(t.prototype.__proto__ === t2.prototype.__proto__); - checkParentIsCTypes(Object.getPrototypeOf(t.prototype)); do_check_true(t.prototype.__proto__.__proto__ === ctypes.CData.prototype); do_check_true(t.prototype instanceof ctypes.CData); do_check_true(t.prototype.constructor === t); @@ -1423,7 +1365,6 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance if (t.__proto__ != ctypes.FunctionType.prototype) { let d = t(); do_check_class(d, "CData"); - checkParentIsCTypes(d); do_check_true(d.__proto__ === t.prototype); do_check_true(d instanceof t); do_check_true(d.constructor === t); @@ -1614,7 +1555,7 @@ function run_StructType_tests() { g = new g_t(1, 2); do_check_eq(g.a, 1); do_check_eq(g.b, 2); - do_check_throws(function() { g_t(1); }, Error); + do_check_throws(function() { g_t(1); }, TypeError); do_check_throws(function() { g_t(1, 2, 3); }, Error); for (let field in g) @@ -1656,11 +1597,11 @@ function run_StructType_tests() { s.value = s_init; do_check_eq(s.b.a, 9); do_check_eq(s.c, 13); - do_check_throws(function() { s.value = 5; }, Error); - do_check_throws(function() { s.value = ctypes.int32_t(); }, Error); + do_check_throws(function() { s.value = 5; }, TypeError); + do_check_throws(function() { s.value = ctypes.int32_t(); }, TypeError); do_check_throws(function() { s.value = {}; }, Error); do_check_throws(function() { s.value = { "a": 2 }; }, Error); - do_check_throws(function() { s.value = { "a": 2, "b": 5, "c": 10 }; }, Error); + do_check_throws(function() { s.value = { "a": 2, "b": 5, "c": 10 }; }, TypeError); do_check_throws(function() { s.value = { "5": 2, "b": { "a": 9, "b": 5 }, "c": 13 }; }, Error); @@ -1682,7 +1623,7 @@ function run_StructType_tests() { v = v_t(8); do_check_eq(v.x, 8); let w_t = ctypes.StructType("w_t", [{ "y": v_t }]); - do_check_throws(function() { w_t(9); }, Error); + do_check_throws(function() { w_t(9); }, TypeError); let w = w_t({ "x": 3 }); do_check_eq(w.y.x, 3); w = w_t({ "y": { "x": 19 } }); @@ -1758,7 +1699,7 @@ function run_PointerType_tests() { // Test ImplicitConvert. p.value = null; do_check_eq(ptrValue(p), 0); - do_check_throws(function() { p.value = 5; }, Error); + do_check_throws(function() { p.value = 5; }, TypeError); // Test opaque pointers. let f_t = ctypes.StructType("FILE").ptr; @@ -1771,9 +1712,9 @@ function run_PointerType_tests() { do_check_throws(function() { f.contents = 0; }, Error); do_check_eq(f.toSource(), 'FILE.ptr(ctypes.UInt64("0x5"))'); - do_check_throws(function() { f_t(p); }, Error); - do_check_throws(function() { f.value = p; }, Error); - do_check_throws(function() { p.value = f; }, Error); + do_check_throws(function() { f_t(p); }, TypeError); + do_check_throws(function() { f.value = p; }, TypeError); + do_check_throws(function() { p.value = f; }, TypeError); // Test void pointers. let v_t = ctypes.PointerType(ctypes.void_t); @@ -1884,15 +1825,15 @@ function run_FunctionType_tests() { // Test ImplicitConvert. f.value = null; do_check_eq(ptrValue(f), 0); - do_check_throws(function() { f.value = 5; }, Error); + do_check_throws(function() { f.value = 5; }, TypeError); do_check_eq(f.toSource(), 'ctypes.FunctionType(ctypes.default_abi, g_t).ptr(ctypes.UInt64("0x0"))'); // Test ImplicitConvert from a function pointer of different type. let f2_t = ctypes.FunctionType(ctypes.default_abi, g_t, [ ctypes.int32_t ]); let f2 = f2_t.ptr(); - do_check_throws(function() { f.value = f2; }, Error); - do_check_throws(function() { f2.value = f; }, Error); + do_check_throws(function() { f.value = f2; }, TypeError); + do_check_throws(function() { f2.value = f; }, TypeError); // Test that converting to a voidptr_t works. let v = ctypes.voidptr_t(f2); @@ -2060,7 +2001,7 @@ function run_ArrayType_tests() { do_check_throws(function() { c.value; }, Error); do_check_throws(function() { c.value = [1, 2, 3, 4, 5]; }, Error); do_check_throws(function() { c.value = [1, 2, 3, 4, 5, 6, 7]; }, Error); - do_check_throws(function() { c.value = [1, 2, 7.4, 4, 5, 6]; }, Error); + do_check_throws(function() { c.value = [1, 2, 7.4, 4, 5, 6]; }, TypeError); do_check_throws(function() { c.value = []; }, Error); } @@ -2535,7 +2476,7 @@ function run_variadic_tests(library) { [ctypes.uint8_t]).ptr; do_check_throws(function() { sum_va_type().value = sum_notva_type(); - }, Error); + }, TypeError); } function run_static_data_tests(library) From 89832a48128715b102dda1806f2248a3bf78e511 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 27 Mar 2012 11:43:11 -0700 Subject: [PATCH 037/113] Bug 738956 - Wrap values in nsStructuredCloneContainer::InitFromVariant before passing them to JS_WriteStructuredClone. r=khuey --- dom/base/nsStructuredCloneContainer.cpp | 1 + js/src/jsapi.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/dom/base/nsStructuredCloneContainer.cpp b/dom/base/nsStructuredCloneContainer.cpp index d82e0a3b0f3..0dd2ffb79c3 100644 --- a/dom/base/nsStructuredCloneContainer.cpp +++ b/dom/base/nsStructuredCloneContainer.cpp @@ -85,6 +85,7 @@ nsStructuredCloneContainer::InitFromVariant(nsIVariant *aData, JSContext *aCx) JSAutoRequest ar(aCx); JSAutoEnterCompartment ac; NS_ENSURE_STATE(ac.enter(aCx, JS_GetGlobalObject(aCx))); + JS_WrapValue(aCx, &jsData); nsCxPusher cxPusher; cxPusher.Push(aCx); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 4edd5c49585..2ab186b07d0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5909,6 +5909,7 @@ JS_WriteStructuredClone(JSContext *cx, jsval v, uint64_t **bufp, size_t *nbytesp { AssertNoGC(cx); CHECK_REQUEST(cx); + assertSameCompartment(cx, v); const JSStructuredCloneCallbacks *callbacks = optionalCallbacks ? @@ -5924,6 +5925,7 @@ JS_StructuredClone(JSContext *cx, jsval v, jsval *vp, { AssertNoGC(cx); CHECK_REQUEST(cx); + assertSameCompartment(cx, v); const JSStructuredCloneCallbacks *callbacks = optionalCallbacks ? From 1cd43ea140f46d4682c2b3dc9998baf5e5a8a706 Mon Sep 17 00:00:00 2001 From: Rail Aliiev Date: Tue, 27 Mar 2012 15:06:01 -0400 Subject: [PATCH 038/113] Bug 731795 - MOZ_SOURCESTAMP_FILE shouldn't depend on MOZ_PKG_PRETTYNAMES; r=khuey --- toolkit/mozapps/installer/package-name.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/toolkit/mozapps/installer/package-name.mk b/toolkit/mozapps/installer/package-name.mk index 728abe347f1..1526f2a7433 100644 --- a/toolkit/mozapps/installer/package-name.mk +++ b/toolkit/mozapps/installer/package-name.mk @@ -132,14 +132,15 @@ endif endif PKG_PATH = $(MOZ_PKG_PLATFORM)/$(AB_CD)/ CHECKSUMS_FILE_BASENAME = $(MOZ_PKG_APPNAME_LC)-$(MOZ_PKG_VERSION) +MOZ_SOURCESTAMP_FILE_BASENAME = $(MOZ_PKG_APPNAME_LC)-$(MOZ_PKG_VERSION) ifeq ($(MOZ_APP_NAME),xulrunner) PKG_PATH = runtimes/ PKG_BASENAME = $(MOZ_APP_NAME)-$(MOZ_PKG_VERSION).$(AB_CD).$(MOZ_PKG_PLATFORM) CHECKSUMS_FILE_BASENAME = $(PKG_BASENAME) +MOZ_SOURCESTAMP_FILE_BASENAME = $(PKG_BASENAME) endif PKG_INST_PATH = $(PKG_PATH) PKG_UPDATE_BASENAME = $(MOZ_PKG_APPNAME_LC)-$(MOZ_PKG_VERSION) -MOZ_SOURCESTAMP_FILE_BASENAME = $(MOZ_PKG_APPNAME_LC)-$(MOZ_PKG_VERSION) PKG_UPDATE_PATH = update/$(PKG_PATH) COMPLETE_MAR = $(PKG_UPDATE_PATH)$(PKG_UPDATE_BASENAME).complete.mar # PARTIAL_MAR needs to be processed by $(wildcard) before you use it. From a2f68f19c5deecacab1f8be206f3c3ebcff32996 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 27 Mar 2012 12:22:10 -0700 Subject: [PATCH 039/113] Bug 736563 - mark global objects held by live windows black during GC. r=smaug --- content/base/src/nsCCUncollectableMarker.cpp | 26 ++++++++++++++++++++ content/base/src/nsCCUncollectableMarker.h | 12 +++++++-- js/xpconnect/src/XPCJSRuntime.cpp | 3 +++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/content/base/src/nsCCUncollectableMarker.cpp b/content/base/src/nsCCUncollectableMarker.cpp index 7e13014fd43..87ed09284b7 100644 --- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -378,3 +378,29 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } +static PLDHashOperator +TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure) +{ + if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) { + if (JSObject* global = aWindow->FastGetGlobalJSObject()) { + JSTracer* trc = static_cast(aClosure); + JS_CALL_OBJECT_TRACER(trc, global, "active window global"); + } + } + return PL_DHASH_NEXT; +} + +void +mozilla::dom::TraceBlackJS(JSTracer* aTrc) +{ + if (!nsCCUncollectableMarker::sGeneration) { + return; + } + + // Mark globals of active windows black. + nsGlobalWindow::WindowByIdTable* windowsById = + nsGlobalWindow::GetWindowsTable(); + if (windowsById) { + windowsById->Enumerate(TraceActiveWindowGlobal, aTrc); + } +} diff --git a/content/base/src/nsCCUncollectableMarker.h b/content/base/src/nsCCUncollectableMarker.h index 2cdab8779cb..34c6a3032b6 100644 --- a/content/base/src/nsCCUncollectableMarker.h +++ b/content/base/src/nsCCUncollectableMarker.h @@ -38,6 +38,8 @@ #include "nsIObserver.h" #include "nsCycleCollectionParticipant.h" +struct JSTracer; + class nsCCUncollectableMarker : public nsIObserver { NS_DECL_ISUPPORTS @@ -56,10 +58,10 @@ class nsCCUncollectableMarker : public nsIObserver return aGeneration && aGeneration == sGeneration; } - static bool InGeneration(nsCycleCollectionTraversalCallback &cb, + static bool InGeneration(nsCycleCollectionTraversalCallback& aCb, PRUint32 aGeneration) { - return InGeneration(aGeneration) && !cb.WantAllTraces(); + return InGeneration(aGeneration) && !aCb.WantAllTraces(); } static PRUint32 sGeneration; @@ -68,3 +70,9 @@ private: nsCCUncollectableMarker() {} }; + +namespace mozilla { +namespace dom { +void TraceBlackJS(JSTracer* aTrc); +} +} diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 9a8d85296c7..eeb29d9b311 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -347,6 +347,9 @@ void XPCJSRuntime::TraceBlackJS(JSTracer* trc, void* data) for (e = self->mObjectHolderRoots; e; e = e->GetNextRoot()) static_cast(e)->TraceJS(trc); } + + dom::TraceBlackJS(trc); + } // static From 56ce0e0c933a1904113a4feef436a827142513f7 Mon Sep 17 00:00:00 2001 From: Brian Nicholson Date: Tue, 27 Mar 2012 12:25:26 -0700 Subject: [PATCH 040/113] Bug 738859 - Increment mActivityDepth for all activities launched from GeckoApp. r=blassey --HG-- extra : rebase_source : f336548259f18347e0592329c2e5e678abbc8c43 --- mobile/android/base/GeckoApp.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 4ae99aeece7..7c00ecefec3 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -151,7 +151,7 @@ abstract public class GeckoApp public String mLastSnapshotUri; public String mLastViewport; public byte[] mLastScreen; - public int mOwnActivityDepth = 0; + private int mOwnActivityDepth = 0; private boolean mRestoreSession = false; private boolean mInitialized = false; @@ -2560,7 +2560,6 @@ abstract public class GeckoApp } } } - mOwnActivityDepth++; startActivityForResult(intent, AWESOMEBAR_REQUEST); return true; } @@ -2851,6 +2850,18 @@ abstract public class GeckoApp } } } + + @Override + public void startActivity(Intent intent) { + mOwnActivityDepth++; + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int request) { + mOwnActivityDepth++; + super.startActivityForResult(intent, request); + } } class PluginLayoutParams extends AbsoluteLayout.LayoutParams From 46f7cfbdbdd065e65d7957785af8876677f72586 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 27 Mar 2012 16:16:13 -0400 Subject: [PATCH 041/113] Bug 739415 - Add ability to log exceptions to robocop log file. r=jmaher --- build/mobile/robocop/Assert.java.in | 1 + .../robocop/FennecMochitestAssert.java.in | 5 ++ .../mobile/robocop/FennecNativeDriver.java.in | 49 +++++++++++-------- .../mobile/robocop/FennecTalosAssert.java.in | 5 ++ 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/build/mobile/robocop/Assert.java.in b/build/mobile/robocop/Assert.java.in index 28a14dbdb5c..2dddfdded2b 100644 --- a/build/mobile/robocop/Assert.java.in +++ b/build/mobile/robocop/Assert.java.in @@ -41,6 +41,7 @@ package @ANDROID_PACKAGE_NAME@; public interface Assert { void dumpLog(String message); + void dumpLog(String message, Throwable t); void setLogFile(String filename); void setTestName(String testName); diff --git a/build/mobile/robocop/FennecMochitestAssert.java.in b/build/mobile/robocop/FennecMochitestAssert.java.in index 93d2ef11ba1..9576aabfe2e 100644 --- a/build/mobile/robocop/FennecMochitestAssert.java.in +++ b/build/mobile/robocop/FennecMochitestAssert.java.in @@ -66,6 +66,11 @@ public class FennecMochitestAssert implements Assert { FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message); } + /** Write information to a logfile and logcat */ + public void dumpLog(String message, Throwable t) { + FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t); + } + /** Set the filename used for dumpLog. */ public void setLogFile(String filename) { FennecNativeDriver.setLogFile(filename); diff --git a/build/mobile/robocop/FennecNativeDriver.java.in b/build/mobile/robocop/FennecNativeDriver.java.in index dea231f04d8..deda41919a7 100644 --- a/build/mobile/robocop/FennecNativeDriver.java.in +++ b/build/mobile/robocop/FennecNativeDriver.java.in @@ -41,7 +41,6 @@ package @ANDROID_PACKAGE_NAME@; import java.io.BufferedOutputStream; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.File; import java.io.FileReader; @@ -49,6 +48,7 @@ import java.io.FileWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.PrintWriter; import java.nio.IntBuffer; import java.util.HashMap; import java.util.List; @@ -459,41 +459,48 @@ public class FennecNativeDriver implements Driver { } public static void log(LogLevel level, String message) { + log(level, message, null); + } + + public static void log(LogLevel level, Throwable t) { + log(level, null, t); + } + + public static void log(LogLevel level, String message, Throwable t) { if (mLogFile == null) { assert(false); } if (level.isEnabled(mLogLevel)) { - File file = new File(mLogFile); - BufferedWriter bw = null; - + PrintWriter pw = null; try { - bw = new BufferedWriter(new FileWriter(mLogFile, true)); - bw.write(message); - bw.newLine(); - } catch(IOException e) { + pw = new PrintWriter(new FileWriter(mLogFile, true)); + if (message != null) { + pw.println(message); + } + if (t != null) { + t.printStackTrace(pw); + } + } catch (IOException ioe) { Log.e("Robocop", "exception with file writer on: " + mLogFile); } finally { - try { - if (bw != null) { - bw.flush(); - bw.close(); - } - } catch (IOException ex) { - ex.printStackTrace(); - } + pw.close(); + } + // PrintWriter doesn't throw IOE but sets an error flag instead, + // so check for that + if (pw.checkError()) { + Log.e("Robocop", "exception with file writer on: " + mLogFile); } } if (level == LogLevel.LOG_LEVEL_INFO) { - Log.i("Robocop", message); + Log.i("Robocop", message, t); } else if (level == LogLevel.LOG_LEVEL_DEBUG) { - Log.d("Robocop", message); + Log.d("Robocop", message, t); } else if (level == LogLevel.LOG_LEVEL_WARN) { - Log.w("Robocop", message); + Log.w("Robocop", message, t); } else if (level == LogLevel.LOG_LEVEL_ERROR) { - Log.e("Robocop", message); + Log.e("Robocop", message, t); } } - } diff --git a/build/mobile/robocop/FennecTalosAssert.java.in b/build/mobile/robocop/FennecTalosAssert.java.in index 9a9d75511d4..6726b039627 100644 --- a/build/mobile/robocop/FennecTalosAssert.java.in +++ b/build/mobile/robocop/FennecTalosAssert.java.in @@ -49,6 +49,11 @@ public class FennecTalosAssert implements Assert { FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message); } + /** Write information to a logfile and logcat */ + public void dumpLog(String message, Throwable t) { + FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t); + } + /** * Set the filename used for dumpLog. */ From d0da20efa2a450bba0788dc2ae9e319c4e9a87aa Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 27 Mar 2012 16:16:13 -0400 Subject: [PATCH 042/113] Bug 739415 - Add ability to have raw files as test assets. r=jmaher --- build/mobile/robocop/Makefile.in | 4 ++-- mobile/android/base/tests/BaseTest.java.in | 10 +++++++++- mobile/android/base/tests/assets/README | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 mobile/android/base/tests/assets/README diff --git a/build/mobile/robocop/Makefile.in b/build/mobile/robocop/Makefile.in index 6488befce41..8790a36f29d 100644 --- a/build/mobile/robocop/Makefile.in +++ b/build/mobile/robocop/Makefile.in @@ -127,8 +127,8 @@ classes.dex: $(_JAVA_TESTS) $(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS)) $(DX) --dex --output=$@ classes $(ROBOTIUM_PATH) -robocop.ap_: AndroidManifest.xml - $(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -F $@ -J ./ +robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/* + $(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./ robocop.apk: robocop.ap_ classes.dex cp $(TESTPATH)/robocop.ini robocop.ini diff --git a/mobile/android/base/tests/BaseTest.java.in b/mobile/android/base/tests/BaseTest.java.in index bfbc26f758e..9f471660ebc 100644 --- a/mobile/android/base/tests/BaseTest.java.in +++ b/mobile/android/base/tests/BaseTest.java.in @@ -6,12 +6,15 @@ import @ANDROID_PACKAGE_NAME@.*; import android.app.Activity; import android.app.Instrumentation; -import android.database.Cursor; import android.content.ContentValues; import android.content.Intent; +import android.content.res.AssetManager; +import android.database.Cursor; import android.os.SystemClock; import android.test.ActivityInstrumentationTestCase2; import java.io.File; +import java.io.InputStream; +import java.io.IOException; import java.util.HashMap; @@ -204,4 +207,9 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { } return true; } + + public InputStream getAsset(String filename) throws IOException { + AssetManager assets = getInstrumentation().getContext().getAssets(); + return assets.open(filename); + } } diff --git a/mobile/android/base/tests/assets/README b/mobile/android/base/tests/assets/README new file mode 100644 index 00000000000..565ca2a9f4e --- /dev/null +++ b/mobile/android/base/tests/assets/README @@ -0,0 +1,4 @@ +You can place test assets in this file. +They can be read as raw InputStreams with the getAsset() method in BaseTest. + +(This file is a placeholder to ensure that the assets/ directory exists, as it is referenced in the robocop Makefile.) From 697ab20157b9ff29998eac4184f883a2ed467d83 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 27 Mar 2012 16:16:14 -0400 Subject: [PATCH 043/113] Bug 739415 - Add a talos test that replays a sequence of captured MotionEvents to simulate user behaviour. r=jmaher --- .../base/tests/MotionEventReplayer.java.in | 162 ++++++ .../base/tests/assets/testcheck2-motionevents | 460 ++++++++++++++++++ mobile/android/base/tests/robocop.ini | 1 + mobile/android/base/tests/testCheck2.java.in | 51 ++ 4 files changed, 674 insertions(+) create mode 100644 mobile/android/base/tests/MotionEventReplayer.java.in create mode 100644 mobile/android/base/tests/assets/testcheck2-motionevents create mode 100644 mobile/android/base/tests/testCheck2.java.in diff --git a/mobile/android/base/tests/MotionEventReplayer.java.in b/mobile/android/base/tests/MotionEventReplayer.java.in new file mode 100644 index 00000000000..06ea024f7b1 --- /dev/null +++ b/mobile/android/base/tests/MotionEventReplayer.java.in @@ -0,0 +1,162 @@ +#filter substitution +package @ANDROID_PACKAGE_NAME@.tests; + +import @ANDROID_PACKAGE_NAME@.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import android.app.Instrumentation; +import android.os.SystemClock; +import android.util.Log; +import android.view.MotionEvent; + +class MotionEventReplayer { + private static final String LOGTAG = "RobocopMotionEventReplayer"; + + private final Instrumentation mInstrumentation; + private final int mSurfaceOffsetX; + private final int mSurfaceOffsetY; + private final Map mActionTypes; + + public MotionEventReplayer(Instrumentation inst, int surfaceOffsetX, int surfaceOffsetY) { + mInstrumentation = inst; + mSurfaceOffsetX = surfaceOffsetX; + mSurfaceOffsetY = surfaceOffsetY; + Log.i(LOGTAG, "Initialized using offset (" + mSurfaceOffsetX + "," + mSurfaceOffsetY + ")"); + + mActionTypes = new HashMap(); + mActionTypes.put("ACTION_CANCEL", MotionEvent.ACTION_CANCEL); + mActionTypes.put("ACTION_DOWN", MotionEvent.ACTION_DOWN); + mActionTypes.put("ACTION_MOVE", MotionEvent.ACTION_MOVE); + mActionTypes.put("ACTION_POINTER_DOWN", MotionEvent.ACTION_POINTER_DOWN); + mActionTypes.put("ACTION_POINTER_UP", MotionEvent.ACTION_POINTER_UP); + mActionTypes.put("ACTION_UP", MotionEvent.ACTION_UP); + } + + private int parseAction(String action) { + int index = 0; + + // ACTION_POINTER_DOWN and ACTION_POINTER_UP might be followed by + // pointer index in parentheses, like ACTION_POINTER_UP(1) + int beginParen = action.indexOf("("); + if (beginParen >= 0) { + int endParen = action.indexOf(")", beginParen + 1); + index = Integer.parseInt(action.substring(beginParen + 1, endParen)); + action = action.substring(0, beginParen); + } + + return mActionTypes.get(action) | (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT); + } + + private int parseInt(String value) { + if (value == null) { + return 0; + } + if (value.startsWith("0x")) { + return Integer.parseInt(value.substring(2), 16); + } + return Integer.parseInt(value); + } + + public void replayEvents(InputStream eventDescriptions) throws IOException { + // As an example, a line in the input stream might look like: + // + // MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=424.41055, y[0]=825.2412, + // toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, + // edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=21972329, + // downTime=21972329, deviceId=6, source=0x1002 } + // + // These can be generated by printing out event.toString() in LayerController's + // onTouchEvent function on a phone running Ice Cream Sandwich. Different + // Android versions have different serializations of the motion event, and this + // code could probably be modified to parse other serializations if needed. + Pattern p = Pattern.compile("MotionEvent \\{ (.*?) \\}"); + Map eventProperties = new HashMap(); + + boolean firstEvent = true; + long timeDelta = 0L; + long lastEventTime = 0L; + + BufferedReader br = new BufferedReader(new InputStreamReader(eventDescriptions)); + try { + for (String eventStr = br.readLine(); eventStr != null; eventStr = br.readLine()) { + Matcher m = p.matcher(eventStr); + if (! m.find()) { + // this line doesn't have any MotionEvent data, skip it + continue; + } + + // extract the key-value pairs from the description and store them + // in the eventProperties table + StringTokenizer keyValues = new StringTokenizer(m.group(1), ","); + while (keyValues.hasMoreTokens()) { + String keyValue = keyValues.nextToken(); + String key = keyValue.substring(0, keyValue.indexOf('=')).trim(); + String value = keyValue.substring(keyValue.indexOf('=') + 1).trim(); + eventProperties.put(key, value); + } + + // set up the values we need to build the MotionEvent + long downTime = Long.parseLong(eventProperties.get("downTime")); + long eventTime = Long.parseLong(eventProperties.get("eventTime")); + int action = parseAction(eventProperties.get("action")); + float pressure = 1.0f; + float size = 1.0f; + int metaState = parseInt(eventProperties.get("metaState")); + float xPrecision = 1.0f; + float yPrecision = 1.0f; + int deviceId = 0; + int edgeFlags = parseInt(eventProperties.get("edgeFlags")); + int source = parseInt(eventProperties.get("source")); + int flags = parseInt(eventProperties.get("flags")); + + int pointerCount = parseInt(eventProperties.get("pointerCount")); + int[] pointerIds = new int[pointerCount]; + MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount]; + for (int i = 0; i < pointerCount; i++) { + pointerIds[i] = Integer.parseInt(eventProperties.get("id[" + i + "]")); + pointerCoords[i] = new MotionEvent.PointerCoords(); + pointerCoords[i].x = mSurfaceOffsetX + Float.parseFloat(eventProperties.get("x[" + i + "]")); + pointerCoords[i].y = mSurfaceOffsetY + Float.parseFloat(eventProperties.get("y[" + i + "]")); + } + + // we want to adjust the timestamps on all the generated events so that they line up with + // the time that this function is executing on-device. + long now = SystemClock.uptimeMillis(); + if (firstEvent) { + timeDelta = now - eventTime; + firstEvent = false; + } + downTime += timeDelta; + eventTime += timeDelta; + + // we also generate the events in "real-time" (i.e. have delays between events that + // correspond to the delays in the event timestamps). + if (now < eventTime) { + try { + Thread.sleep(eventTime - now); + } catch (InterruptedException ie) { + } + } + + // and finally we dispatch the event + MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, pointerCount, + pointerIds, pointerCoords, metaState, xPrecision, yPrecision, deviceId, edgeFlags, + source, flags); + Log.v(LOGTAG, "Injecting " + event.toString()); + mInstrumentation.sendPointerSync(event); + + eventProperties.clear(); + } + } finally { + br.close(); + } + } +} diff --git a/mobile/android/base/tests/assets/testcheck2-motionevents b/mobile/android/base/tests/assets/testcheck2-motionevents new file mode 100644 index 00000000000..e4121dd4b3b --- /dev/null +++ b/mobile/android/base/tests/assets/testcheck2-motionevents @@ -0,0 +1,460 @@ +03-27 16:20:00.753 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=360.49933, y[0]=813.2506, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25254517, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.776 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=359.5007, y[0]=802.25916, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254531, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.792 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=358.50208, y[0]=763.2896, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254550, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.807 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=364.49377, y[0]=684.35126, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254569, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.823 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=385.46463, y[0]=578.434, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254588, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.847 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=410.42996, y[0]=475.51447, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254607, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.862 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=434.39667, y[0]=380.58862, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254626, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.886 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=455.36755, y[0]=302.6495, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25254645, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:00.886 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=455.36755, y[0]=302.6495, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25254653, downTime=25254517, deviceId=6, source=0x1002 } +03-27 16:20:01.589 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=420.4161, y[0]=783.274, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25255352, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.604 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=415.42303, y[0]=739.30835, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255371, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.628 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=420.4161, y[0]=654.3747, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255390, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.643 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=427.4064, y[0]=604.41376, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25255400, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.667 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=448.37726, y[0]=498.49646, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255419, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.682 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=475.3398, y[0]=403.57062, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255438, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.698 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=494.31348, y[0]=331.62686, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255456, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:01.706 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=494.31348, y[0]=331.62686, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25255465, downTime=25255352, deviceId=6, source=0x1002 } +03-27 16:20:02.057 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=446.38004, y[0]=718.32477, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25255820, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.073 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=444.3828, y[0]=699.3396, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255839, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.097 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=444.3828, y[0]=670.36224, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25255848, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.112 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=453.37033, y[0]=585.4286, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255867, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.128 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=468.34952, y[0]=485.50665, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255886, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.151 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=485.32596, y[0]=398.57452, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255907, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.167 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=500.30515, y[0]=333.6253, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25255924, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.167 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=500.30515, y[0]=333.6253, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25255933, downTime=25255820, deviceId=6, source=0x1002 } +03-27 16:20:02.440 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=423.41193, y[0]=681.35364, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256201, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.456 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=421.4147, y[0]=655.3739, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256211, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.472 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=425.40915, y[0]=556.45123, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256230, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=438.39114, y[0]=439.54254, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256249, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.511 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=454.36893, y[0]=338.6214, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256268, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.526 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=472.34396, y[0]=260.68228, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256287, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.550 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=482.3301, y[0]=233.70337, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256297, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.550 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=482.3301, y[0]=233.70337, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256305, downTime=25256201, deviceId=6, source=0x1002 } +03-27 16:20:02.768 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=403.43967, y[0]=640.3856, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256536, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:02.792 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=403.43967, y[0]=609.40985, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256545, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:02.807 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=412.4272, y[0]=516.4824, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256564, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:02.831 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=428.405, y[0]=425.55347, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256583, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:02.847 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=447.37866, y[0]=344.6167, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256602, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:02.862 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=451.3731, y[0]=312.6417, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256612, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:02.870 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=451.3731, y[0]=312.6417, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256620, downTime=25256536, deviceId=6, source=0x1002 } +03-27 16:20:03.097 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=396.44937, y[0]=738.30914, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256860, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:03.112 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=395.45078, y[0]=713.3287, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256870, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:03.136 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=400.44385, y[0]=623.3989, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256889, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:03.151 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=417.42026, y[0]=521.4785, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256908, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:03.167 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=439.38974, y[0]=432.54803, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25256927, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:03.190 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=450.37448, y[0]=393.57843, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256936, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:03.190 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=450.37448, y[0]=393.57843, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25256946, downTime=25256860, deviceId=6, source=0x1002 } +03-27 16:20:04.018 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=621.1373, y[0]=420.55737, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25257777, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.034 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=617.1429, y[0]=424.55426, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257796, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.050 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=607.15674, y[0]=433.54724, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257815, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.073 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=592.17755, y[0]=441.54095, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257834, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.089 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=574.2025, y[0]=447.53632, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257853, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.104 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=561.2205, y[0]=450.53394, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25257863, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.128 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=533.2594, y[0]=456.5293, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257882, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.143 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=501.30374, y[0]=461.5254, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257901, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.167 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=475.3398, y[0]=464.523, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257920, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.182 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=449.3759, y[0]=468.5199, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257940, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.198 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=429.40363, y[0]=470.51837, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257959, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.222 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=411.4286, y[0]=473.516, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257978, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.237 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=399.44522, y[0]=474.5152, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25257996, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.245 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=399.44522, y[0]=474.5152, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258005, downTime=25257777, deviceId=6, source=0x1002 } +03-27 16:20:04.612 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=458.3634, y[0]=256.6854, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258379, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.636 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=457.36478, y[0]=259.68304, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258388, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.651 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=452.3717, y[0]=280.66666, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258408, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.675 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=446.38004, y[0]=309.644, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258427, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.690 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=446.38004, y[0]=345.61594, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258446, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.706 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=451.3731, y[0]=387.58313, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258465, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.729 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=460.36063, y[0]=435.54565, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258484, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.745 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=474.34122, y[0]=481.50977, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258503, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.761 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=493.31485, y[0]=529.4723, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258522, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.784 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=512.2885, y[0]=570.4403, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258541, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:04.792 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=512.2885, y[0]=570.4403, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258550, downTime=25258379, deviceId=6, source=0x1002 } +03-27 16:20:05.112 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=478.33566, y[0]=306.64636, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258875, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.128 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=478.33566, y[0]=314.64014, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258885, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.151 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=474.34122, y[0]=344.6167, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258904, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.167 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=469.34814, y[0]=386.58392, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258923, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.182 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=463.35645, y[0]=440.54175, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258942, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.206 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=489.50354, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258961, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.222 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=464.35507, y[0]=534.4684, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25258980, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.222 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=464.35507, y[0]=534.4684, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25258989, downTime=25258875, deviceId=6, source=0x1002 } +03-27 16:20:05.472 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=290.5964, y[0]=628.395, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25259238, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=292.59363, y[0]=628.395, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25259248, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.511 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=313.5645, y[0]=627.3958, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25259276, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.534 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=340.52704, y[0]=627.3958, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25259295, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.550 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=360.49933, y[0]=626.39655, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25259305, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.565 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=624.39813, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25259324, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.589 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=444.3828, y[0]=620.40125, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25259343, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.604 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=485.32596, y[0]=616.40436, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25259362, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.628 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=520.2774, y[0]=613.40674, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25259381, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.643 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=533.2594, y[0]=613.40674, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25259390, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:05.643 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=533.2594, y[0]=613.40674, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25259400, downTime=25259238, deviceId=6, source=0x1002 } +03-27 16:20:06.737 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=628.1276, y[0]=482.50897, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25260498, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.753 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=625.1318, y[0]=484.5074, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25260517, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.768 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=621.1373, y[0]=487.50507, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25260527, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.792 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=604.1609, y[0]=494.49963, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260546, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.807 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=587.1845, y[0]=502.49335, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260565, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.823 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=573.2039, y[0]=508.4887, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260584, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.847 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=565.21497, y[0]=512.48553, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260604, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.862 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=556.2275, y[0]=517.4816, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260623, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.886 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=549.2372, y[0]=522.4777, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260642, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.901 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=543.2455, y[0]=528.4731, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260661, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.917 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=540.2497, y[0]=535.4676, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260681, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.940 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=536.2552, y[0]=549.45667, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260699, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.956 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=535.2566, y[0]=570.4403, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260718, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.979 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=537.25385, y[0]=604.41376, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260737, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:06.995 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=541.2483, y[0]=648.3794, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260757, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:07.018 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=548.2386, y[0]=702.3372, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260779, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:07.034 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=558.2247, y[0]=761.2912, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260795, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:07.050 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=565.21497, y[0]=806.25604, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25260814, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:07.057 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=565.21497, y[0]=806.25604, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25260822, downTime=25260498, deviceId=6, source=0x1002 } +03-27 16:20:07.440 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=530.26355, y[0]=227.70804, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25261205, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=527.2677, y[0]=236.70102, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25261215, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=520.2774, y[0]=281.6659, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25261234, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=510.29126, y[0]=356.60733, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25261253, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.518 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=502.30237, y[0]=439.54254, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25261272, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.534 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=498.30792, y[0]=525.4754, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25261291, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=505.29822, y[0]=605.41296, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25261310, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.573 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=667.36456, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25261329, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:07.573 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=521.276, y[0]=667.36456, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25261338, downTime=25261205, deviceId=6, source=0x1002 } +03-27 16:20:08.511 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=501.30374, y[0]=272.6729, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25262275, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.526 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=500.30515, y[0]=276.6698, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25262284, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.550 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=495.31207, y[0]=297.65338, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25262304, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.565 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=486.32455, y[0]=335.62372, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25262323, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.589 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=478.33566, y[0]=386.58392, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25262342, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.604 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=473.3426, y[0]=444.53864, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25262361, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.620 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=482.3301, y[0]=534.4684, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25262389, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:08.636 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=482.3301, y[0]=534.4684, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25262398, downTime=25262275, deviceId=6, source=0x1002 } +03-27 16:20:10.050 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=398.44662, y[0]=457.5285, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25263814, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.057 I/System.out(18958): MotionEvent { action=ACTION_POINTER_DOWN(1), id[0]=0, x[0]=398.44662, y[0]=457.5285, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=469.34814, y[1]=660.37, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25263824, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.081 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=397.448, y[0]=456.5293, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=469.34814, y[1]=660.37, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25263843, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.097 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=397.448, y[0]=454.53082, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=471.34537, y[1]=663.3677, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25263862, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.112 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=397.448, y[0]=452.5324, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=473.3426, y[1]=665.3661, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25263881, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.136 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=397.448, y[0]=452.5324, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=474.34122, y[1]=667.36456, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25263890, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.151 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=396.44937, y[0]=447.53632, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=476.33844, y[1]=670.36224, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25263910, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.175 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=395.45078, y[0]=440.54175, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=478.33566, y[1]=672.36066, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25263928, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.190 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=395.45078, y[0]=433.54724, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=480.3329, y[1]=674.3591, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25263948, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.206 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=395.45078, y[0]=427.55194, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=482.3301, y[1]=677.35675, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25263967, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.229 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=395.45078, y[0]=420.55737, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=485.32596, y[1]=682.35284, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25263986, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.245 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=396.44937, y[0]=413.56287, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=489.3204, y[1]=690.3466, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264005, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.268 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=397.448, y[0]=406.5683, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=492.31622, y[1]=696.3419, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264024, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.284 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=399.44522, y[0]=399.5738, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=494.31348, y[1]=701.338, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264044, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.307 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=399.44522, y[0]=393.57843, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=498.30792, y[1]=708.3326, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264063, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.323 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=400.44385, y[0]=384.58545, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=500.30515, y[1]=713.3287, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264082, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.339 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=400.44385, y[0]=377.59094, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=502.30237, y[1]=717.3255, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264101, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.362 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=372.59485, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=503.301, y[1]=721.3224, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264120, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.378 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=370.59644, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=503.301, y[1]=725.3193, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264139, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.401 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=367.59875, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=503.301, y[1]=727.31775, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264158, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.417 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=365.6003, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=504.2996, y[1]=731.3146, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264177, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.432 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=363.60187, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=734.31226, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264196, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.456 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=361.60342, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=736.31067, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264216, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.472 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=401.44244, y[0]=361.60342, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=738.30914, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264234, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.487 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=359.60498, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=740.30756, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264254, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.511 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=357.60657, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=742.306, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264273, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.526 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=355.60812, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=745.30365, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264292, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.550 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=355.60812, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=747.3021, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264311, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.565 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=353.60968, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=749.30054, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264330, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.581 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=351.61124, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=751.299, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25264349, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.604 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=349.6128, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=753.2974, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264369, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.620 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=349.6128, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=755.29584, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264387, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.643 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=349.6128, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=757.2943, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264406, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.659 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=349.6128, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=505.29822, y[1]=759.2927, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264426, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.682 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=347.61435, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=506.2968, y[1]=761.2912, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264445, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.698 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=347.61435, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=506.2968, y[1]=763.2896, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264464, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.722 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=345.61594, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=506.2968, y[1]=765.288, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264483, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.737 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=343.6175, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=506.2968, y[1]=767.2865, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264502, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.761 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=341.61905, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=506.2968, y[1]=767.2865, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264511, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.761 I/System.out(18958): MotionEvent { action=ACTION_POINTER_UP(0), id[0]=0, x[0]=402.44107, y[0]=341.61905, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=506.2968, y[1]=769.2849, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25264521, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.776 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=1, x[0]=506.2968, y[0]=769.2849, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25264521, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:10.776 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=1, x[0]=506.2968, y[0]=769.2849, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25264537, downTime=25263814, deviceId=6, source=0x1002 } +03-27 16:20:11.386 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=511.2899, y[0]=675.35834, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265150, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.409 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=509.29266, y[0]=658.3716, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265169, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.425 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=508.29404, y[0]=643.3833, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265178, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.440 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=509.29266, y[0]=593.4223, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25265207, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=511.2899, y[0]=555.45197, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265226, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=515.28436, y[0]=516.4824, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265245, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=517.28156, y[0]=497.49725, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265255, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.518 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=522.27466, y[0]=462.5246, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265274, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.534 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=526.2691, y[0]=430.54956, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265293, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=531.26215, y[0]=401.5722, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265312, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.573 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=535.2566, y[0]=374.59326, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265331, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.597 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=537.25385, y[0]=352.61047, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265350, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.612 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=542.2469, y[0]=330.62762, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265369, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:11.620 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=542.2469, y[0]=330.62762, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265378, downTime=25265150, deviceId=6, source=0x1002 } +03-27 16:20:12.112 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=523.27325, y[0]=641.3848, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265875, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.128 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=523.27325, y[0]=630.39343, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265894, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.151 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=523.27325, y[0]=620.40125, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265904, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.167 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=525.27045, y[0]=592.4231, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265923, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.190 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=532.26074, y[0]=542.46216, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25265952, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.206 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=533.2594, y[0]=526.4746, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25265961, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.222 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=536.2552, y[0]=491.50195, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265980, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.245 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=538.25244, y[0]=468.5199, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25265999, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.261 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=541.2483, y[0]=442.54022, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266018, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.284 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=544.24414, y[0]=422.5558, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266038, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.300 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=547.2399, y[0]=407.5675, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266057, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.323 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=550.2358, y[0]=395.5769, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266076, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.339 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=553.2316, y[0]=383.58624, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266095, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.347 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=553.2316, y[0]=383.58624, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25266104, downTime=25265875, deviceId=6, source=0x1002 } +03-27 16:20:12.807 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=482.3301, y[0]=673.35986, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25266573, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.831 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=482.3301, y[0]=665.3661, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266592, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.847 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=482.3301, y[0]=655.3739, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25266601, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.862 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=484.32733, y[0]=618.40283, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25266630, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.886 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=487.32318, y[0]=585.4286, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266649, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.901 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=490.319, y[0]=552.45435, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266668, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.925 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=492.31622, y[0]=536.4668, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25266678, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.940 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=500.30515, y[0]=489.50354, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25266706, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.956 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=502.30237, y[0]=477.51288, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25266715, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.979 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=504.2996, y[0]=459.52692, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266735, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:12.995 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=507.29544, y[0]=442.54022, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266754, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:13.018 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=509.29266, y[0]=433.54724, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266773, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:13.034 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=511.2899, y[0]=426.55267, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266792, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:13.057 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=514.2857, y[0]=418.55896, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266811, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:13.073 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=517.28156, y[0]=413.56287, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25266830, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:13.073 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=517.28156, y[0]=413.56287, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25266839, downTime=25266573, deviceId=6, source=0x1002 } +03-27 16:20:13.409 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=391.45633, y[0]=720.3232, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267175, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.432 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=397.448, y[0]=719.324, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267193, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.448 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=403.43967, y[0]=717.3255, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267203, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=433.39807, y[0]=708.3326, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25267231, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.487 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=444.3828, y[0]=705.3349, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267241, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.503 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=465.3537, y[0]=700.3388, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267260, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.526 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=484.32733, y[0]=697.3411, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267279, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.542 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=500.30515, y[0]=694.3435, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267298, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=514.2857, y[0]=693.34424, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267317, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.581 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=527.2677, y[0]=692.34503, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267337, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.604 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=536.2552, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267356, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.620 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=541.2483, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267375, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.643 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=545.24274, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25267394, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.659 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=547.2399, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267413, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.675 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=549.2372, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267432, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.698 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=551.23444, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267461, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:13.972 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=551.23444, y[0]=691.3458, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25267738, downTime=25267175, deviceId=6, source=0x1002 } +03-27 16:20:14.386 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=547.2399, y[0]=841.2287, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25268151, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.393 I/System.out(18958): MotionEvent { action=ACTION_POINTER_DOWN(1), id[0]=0, x[0]=547.2399, y[0]=841.2287, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=415.42303, y[1]=97.809525, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268151, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.425 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=546.24133, y[0]=838.2311, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=415.42303, y[1]=97.809525, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268189, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.440 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=545.24274, y[0]=836.2326, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=415.42303, y[1]=97.809525, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268199, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=545.24274, y[0]=832.2358, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=414.4244, y[1]=103.80484, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268218, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=544.24414, y[0]=827.2397, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=413.4258, y[1]=112.79782, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268237, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=542.2469, y[0]=820.2451, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=411.4286, y[1]=126.786896, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268256, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.518 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=540.2497, y[0]=810.2529, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=409.43137, y[1]=144.77283, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268275, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.534 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=538.25244, y[0]=802.25916, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=408.43274, y[1]=162.75879, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268294, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=537.25385, y[0]=793.2662, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=408.43274, y[1]=180.74472, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268313, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.573 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=537.25385, y[0]=784.2732, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=408.43274, y[1]=200.72913, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268333, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.597 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=535.2566, y[0]=769.2849, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=410.42996, y[1]=217.71585, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268352, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.612 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=533.2594, y[0]=755.29584, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=411.4286, y[1]=235.70178, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268371, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.628 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=532.26074, y[0]=746.30286, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=412.4272, y[1]=251.6893, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268390, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.651 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=532.26074, y[0]=737.30994, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=412.4272, y[1]=265.67838, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268409, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.667 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=531.26215, y[0]=728.31696, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=412.4272, y[1]=280.66666, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268428, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.690 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=530.26355, y[0]=717.3255, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=413.4258, y[1]=295.65497, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268447, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.706 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=529.2649, y[0]=709.3318, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=413.4258, y[1]=308.6448, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268466, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.729 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=527.2677, y[0]=701.338, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=413.4258, y[1]=318.637, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268485, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.745 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=525.27045, y[0]=694.3435, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=414.4244, y[1]=327.62997, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268504, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.761 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=524.27185, y[0]=688.34814, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=414.4244, y[1]=338.6214, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268523, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.784 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=523.27325, y[0]=684.35126, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=415.42303, y[1]=349.6128, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268542, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.800 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=522.27466, y[0]=678.35596, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=415.42303, y[1]=359.60498, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268561, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.823 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=522.27466, y[0]=672.36066, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=416.42163, y[1]=367.59875, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268580, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.839 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=665.3661, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=417.42026, y[1]=373.59406, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268600, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.854 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=658.3716, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=418.41888, y[1]=378.59015, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268619, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.878 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=654.3747, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=418.41888, y[1]=382.58704, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268638, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.893 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=650.3778, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=418.41888, y[1]=384.58545, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25268657, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.917 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=648.3794, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=418.41888, y[1]=386.58392, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268676, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.932 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=646.3809, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=418.41888, y[1]=388.58234, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268695, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.948 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=521.276, y[0]=644.3825, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=418.41888, y[1]=390.5808, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268714, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.979 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=523.27325, y[0]=642.3841, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=420.4161, y[1]=392.57922, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268743, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:14.995 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=525.27045, y[0]=642.3841, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=420.4161, y[1]=392.57922, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268752, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:15.003 I/System.out(18958): MotionEvent { action=ACTION_POINTER_UP(1), id[0]=0, x[0]=525.27045, y[0]=642.3841, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=420.4161, y[1]=392.57922, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25268761, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:15.011 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=525.27045, y[0]=642.3841, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25268769, downTime=25268151, deviceId=6, source=0x1002 } +03-27 16:20:15.714 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=476.33844, y[0]=826.2404, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25269477, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.729 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=474.34122, y[0]=822.2435, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269496, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.753 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=471.34537, y[0]=799.26154, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269515, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.768 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=473.3426, y[0]=755.29584, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269534, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.792 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=477.33704, y[0]=700.3388, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269553, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.807 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=480.3329, y[0]=649.3786, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269572, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.823 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=485.32596, y[0]=601.4161, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269591, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.847 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=490.319, y[0]=555.45197, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269610, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.862 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=493.31485, y[0]=535.4676, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25269620, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.886 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=498.30792, y[0]=492.50116, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269639, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.901 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=504.2996, y[0]=450.53394, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269658, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.925 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=514.2857, y[0]=396.5761, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=25269686, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.940 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=518.28015, y[0]=379.58936, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25269696, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.956 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=522.27466, y[0]=355.60812, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269715, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.979 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=528.2663, y[0]=326.63077, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269734, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:15.995 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=535.2566, y[0]=300.65106, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269753, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:16.011 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=544.24414, y[0]=276.6698, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269772, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:16.034 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=550.2358, y[0]=255.68619, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25269791, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:16.034 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=550.2358, y[0]=255.68619, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25269800, downTime=25269477, deviceId=6, source=0x1002 } +03-27 16:20:16.839 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=490.319, y[0]=243.69556, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25270604, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.854 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=489.3204, y[0]=248.69165, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25270613, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.878 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=483.32874, y[0]=277.669, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270632, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.893 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=478.33566, y[0]=324.63232, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270651, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.917 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=470.34674, y[0]=387.58313, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270670, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.932 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=466.3523, y[0]=453.53162, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270689, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.948 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=465.3537, y[0]=513.4848, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270708, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.972 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=466.3523, y[0]=567.4426, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270728, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:16.987 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=469.34814, y[0]=612.4075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270747, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.011 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=470.34674, y[0]=649.3786, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270766, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.026 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=469.34814, y[0]=680.35443, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270785, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.050 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=467.35092, y[0]=707.3333, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270804, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.065 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=466.3523, y[0]=731.3146, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270823, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.081 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=466.3523, y[0]=752.2982, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270842, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.104 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=466.3523, y[0]=770.2842, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270861, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.120 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=467.35092, y[0]=789.26935, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270880, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.143 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=465.3537, y[0]=806.25604, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270900, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.159 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=464.35507, y[0]=821.2443, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270919, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.182 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=464.35507, y[0]=835.2334, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270938, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.198 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=463.35645, y[0]=846.2248, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270957, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.214 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=853.21936, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270976, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.237 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=858.21545, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25270995, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.253 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=862.21234, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25271014, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.268 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=864.21075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271033, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.292 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=866.2092, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271052, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.300 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=462.35785, y[0]=866.2092, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271061, downTime=25270604, deviceId=6, source=0x1002 } +03-27 16:20:17.714 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=389.4591, y[0]=350.61203, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271478, downTime=25271478, deviceId=6, source=0x1002 } +03-27 16:20:17.753 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=389.4591, y[0]=350.61203, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271519, downTime=25271478, deviceId=6, source=0x1002 } +03-27 16:20:17.870 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=402.44107, y[0]=357.60657, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271635, downTime=25271635, deviceId=6, source=0x1002 } +03-27 16:20:17.909 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=405.4369, y[0]=354.6089, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271673, downTime=25271635, deviceId=6, source=0x1002 } +03-27 16:20:17.917 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=405.4369, y[0]=354.6089, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25271682, downTime=25271635, deviceId=6, source=0x1002 } +03-27 16:20:18.800 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=352.5104, y[0]=516.4824, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272562, downTime=25272562, deviceId=6, source=0x1002 } +03-27 16:20:18.847 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=352.5104, y[0]=516.4824, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272608, downTime=25272562, deviceId=6, source=0x1002 } +03-27 16:20:18.964 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=358.50208, y[0]=477.51288, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272724, downTime=25272724, deviceId=6, source=0x1002 } +03-27 16:20:19.011 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=360.49933, y[0]=476.51367, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272772, downTime=25272724, deviceId=6, source=0x1002 } +03-27 16:20:19.026 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=363.49515, y[0]=474.5152, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272781, downTime=25272724, deviceId=6, source=0x1002 } +03-27 16:20:19.042 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=366.491, y[0]=469.5191, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272790, downTime=25272724, deviceId=6, source=0x1002 } +03-27 16:20:19.050 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=366.491, y[0]=469.5191, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25272799, downTime=25272724, deviceId=6, source=0x1002 } +03-27 16:20:20.425 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=430.40222, y[0]=719.324, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25274186, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.440 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=425.40915, y[0]=694.3435, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274205, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.456 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=421.4147, y[0]=659.3708, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274224, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=420.4161, y[0]=641.3848, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25274233, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=420.4161, y[0]=606.4122, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274252, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.518 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=423.41193, y[0]=570.4403, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274271, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.534 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=426.40778, y[0]=532.47, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274290, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.550 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=430.40222, y[0]=489.50354, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274309, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.573 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=437.39252, y[0]=443.53943, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274329, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.589 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=443.3842, y[0]=397.57532, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274348, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.612 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=450.37448, y[0]=352.61047, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274367, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.628 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=461.35922, y[0]=300.65106, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274386, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.643 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=476.33844, y[0]=251.6893, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274405, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.667 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=490.319, y[0]=211.72052, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25274424, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:20.667 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=490.319, y[0]=211.72052, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25274433, downTime=25274186, deviceId=6, source=0x1002 } +03-27 16:20:21.268 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=464.35507, y[0]=677.35675, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275036, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.292 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=670.36224, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275055, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.307 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=461.35922, y[0]=656.37317, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275074, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.331 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=460.36063, y[0]=635.3895, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275093, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.347 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=460.36063, y[0]=624.39813, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275102, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.362 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=459.362, y[0]=600.4169, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275121, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.386 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=459.362, y[0]=578.434, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275141, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.401 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=459.362, y[0]=562.44653, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275160, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.417 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=459.362, y[0]=548.45746, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275179, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.440 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=458.3634, y[0]=538.4653, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275198, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.456 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=457.36478, y[0]=531.4707, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275217, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=456.36618, y[0]=525.4754, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275236, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.495 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=455.36755, y[0]=521.4785, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25275255, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.518 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=455.36755, y[0]=519.4801, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275265, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.534 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=453.37033, y[0]=517.4816, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275284, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=452.3717, y[0]=515.4832, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275303, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.573 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=451.3731, y[0]=513.4848, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275322, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.597 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=449.3759, y[0]=512.48553, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275360, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.612 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=447.37866, y[0]=510.48712, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275369, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.620 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=447.37866, y[0]=510.48712, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275379, downTime=25275036, deviceId=6, source=0x1002 } +03-27 16:20:21.909 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=146.79613, y[0]=479.5113, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275676, downTime=25275676, deviceId=6, source=0x1002 } +03-27 16:20:21.964 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=146.79613, y[0]=479.5113, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275732, downTime=25275676, deviceId=6, source=0x1002 } +03-27 16:20:22.097 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=163.77254, y[0]=488.50427, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275861, downTime=25275861, deviceId=6, source=0x1002 } +03-27 16:20:22.128 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=163.77254, y[0]=488.50427, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25275894, downTime=25275861, deviceId=6, source=0x1002 } +03-27 16:20:23.097 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=415.42303, y[0]=156.76346, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25276862, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.128 I/System.out(18958): MotionEvent { action=ACTION_POINTER_DOWN(1), id[0]=0, x[0]=415.42303, y[0]=156.76346, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=448.37726, y[1]=850.2217, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25276891, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.143 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=413.4258, y[0]=159.76111, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=448.37726, y[1]=850.2217, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25276900, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.167 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=411.4286, y[0]=163.758, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=448.37726, y[1]=850.2217, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25276920, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.182 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=409.43137, y[0]=167.75488, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=446.38004, y[1]=852.22015, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25276939, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.198 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=172.75098, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=446.38004, y[1]=852.22015, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25276958, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.222 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=180.74472, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=446.38004, y[1]=852.22015, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25276977, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.237 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=190.73694, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=446.38004, y[1]=852.22015, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25276996, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.261 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=203.72678, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=445.38144, y[1]=850.2217, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277015, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.276 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=218.71506, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=446.38004, y[1]=844.2264, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277035, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.300 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=237.70023, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=449.3759, y[1]=837.2319, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277054, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.315 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=259.68304, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=452.3717, y[1]=828.2389, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277073, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.331 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=280.66666, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=456.36618, y[1]=817.24744, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277092, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.354 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=299.65182, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=460.36063, y[1]=806.25604, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277111, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.370 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=314.64014, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=462.35785, y[1]=800.26074, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277130, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.393 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=406.43552, y[0]=328.62918, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=464.35507, y[1]=795.26465, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277149, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.409 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=340.61984, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=465.3537, y[1]=791.26776, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277168, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.425 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=351.61124, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=467.35092, y[1]=787.2709, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277187, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.448 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=359.60498, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=469.34814, y[1]=783.274, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277206, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=364.6011, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=472.34396, y[1]=778.2779, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277226, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.487 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=368.59796, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=474.34122, y[1]=773.2818, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277244, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.503 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=372.59485, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=475.3398, y[1]=770.2842, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277263, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.526 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=376.59174, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=477.33704, y[1]=764.2888, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277283, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.542 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=378.59015, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=478.33566, y[1]=759.2927, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277302, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=380.58862, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=480.3329, y[1]=754.29663, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277321, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.581 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=407.43414, y[0]=383.58624, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=481.33148, y[1]=750.29974, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277340, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.597 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=408.43274, y[0]=385.58472, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=482.3301, y[1]=745.30365, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=25277358, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.604 I/System.out(18958): MotionEvent { action=ACTION_POINTER_UP(0), id[0]=0, x[0]=408.43274, y[0]=385.58472, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=482.3301, y[1]=745.30365, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=25277366, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:23.604 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=1, x[0]=482.3301, y[0]=745.30365, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25277366, downTime=25276862, deviceId=6, source=0x1002 } +03-27 16:20:24.331 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=484.32733, y[0]=285.66275, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278094, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.347 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=479.33426, y[0]=311.64246, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278112, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.370 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=475.3398, y[0]=336.62296, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278121, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.386 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=470.34674, y[0]=391.58002, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278140, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.401 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=465.3537, y[0]=456.5293, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278159, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.425 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=525.4754, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278179, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.440 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=458.3634, y[0]=591.4239, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278198, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=458.3634, y[0]=640.3856, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278217, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=456.36618, y[0]=657.3724, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278226, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.479 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=456.36618, y[0]=657.3724, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278235, downTime=25278094, deviceId=6, source=0x1002 } +03-27 16:20:24.932 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=582.1914, y[0]=333.6253, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278694, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:24.948 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=580.1942, y[0]=336.62296, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278714, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:24.972 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=577.19836, y[0]=339.6206, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25278723, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:24.987 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=569.2095, y[0]=354.6089, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278742, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.003 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=559.2233, y[0]=372.59485, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278761, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.026 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=545.24274, y[0]=396.5761, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278780, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.042 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=529.2649, y[0]=422.5558, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278799, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.065 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=514.2857, y[0]=447.53632, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278819, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.081 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=498.30792, y[0]=472.51678, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278838, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.104 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=482.3301, y[0]=494.49963, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278857, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.120 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=469.34814, y[0]=514.484, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278876, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.136 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=456.36618, y[0]=534.4684, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278895, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.159 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=442.3856, y[0]=554.45276, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278914, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.175 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=429.40363, y[0]=573.4379, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278933, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.198 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=414.4244, y[0]=593.4223, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278952, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.214 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=402.44107, y[0]=612.4075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278972, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.229 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=391.45633, y[0]=630.39343, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25278991, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.253 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=381.47018, y[0]=648.3794, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279010, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.268 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=375.47852, y[0]=661.36926, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279029, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.292 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=370.48544, y[0]=672.36066, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279048, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.307 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=367.4896, y[0]=681.35364, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279067, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.323 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=365.49237, y[0]=690.3466, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279086, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.347 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=363.49515, y[0]=695.3427, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279105, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.362 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=362.49655, y[0]=697.3411, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279115, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.386 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=360.49933, y[0]=699.3396, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279134, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.417 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=360.49933, y[0]=701.338, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279182, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=362.49655, y[0]=703.3364, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279230, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.479 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=364.49377, y[0]=704.3357, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279239, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.503 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=370.48544, y[0]=706.3341, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279258, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.518 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=379.47296, y[0]=708.3326, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279277, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.542 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=394.45215, y[0]=712.3294, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279296, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.557 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=415.42303, y[0]=721.3224, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279315, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.573 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=436.39392, y[0]=731.3146, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279334, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.597 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=453.37033, y[0]=743.30524, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279353, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.612 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=470.34674, y[0]=755.29584, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279372, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.636 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=486.32455, y[0]=768.2857, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279392, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.651 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=500.30515, y[0]=782.2748, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279411, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.675 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=514.2857, y[0]=795.26465, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279430, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.690 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=530.26355, y[0]=807.25525, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279449, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.706 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=549.2372, y[0]=818.2467, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279468, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.729 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=566.2136, y[0]=826.2404, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279487, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.745 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=581.1928, y[0]=835.2334, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279506, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.768 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=590.1803, y[0]=842.22797, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279525, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.784 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=595.1734, y[0]=846.2248, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25279545, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.807 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=597.1706, y[0]=848.22327, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279554, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.823 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=599.16785, y[0]=850.2217, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279573, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.839 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=601.16504, y[0]=852.22015, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279592, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:25.909 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=601.16504, y[0]=852.22015, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25279677, downTime=25278694, deviceId=6, source=0x1002 } +03-27 16:20:26.276 I/System.out(18958): MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=471.34537, y[0]=252.68854, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25280041, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.292 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=470.34674, y[0]=254.68695, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25280051, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.315 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=467.35092, y[0]=271.6737, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280070, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.331 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=462.35785, y[0]=306.64636, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280089, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.354 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=455.36755, y[0]=357.60657, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280108, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.370 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=451.3731, y[0]=419.55817, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280127, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.393 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=449.3759, y[0]=488.50427, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280146, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.409 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=448.37726, y[0]=555.45197, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280166, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.425 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=452.3717, y[0]=614.40594, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280185, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.448 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=458.3634, y[0]=675.35834, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280204, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.464 I/System.out(18958): MotionEvent { action=ACTION_MOVE, id[0]=0, x[0]=470.34674, y[0]=730.31537, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=25280223, downTime=25280041, deviceId=6, source=0x1002 } +03-27 16:20:26.472 I/System.out(18958): MotionEvent { action=ACTION_UP, id[0]=0, x[0]=470.34674, y[0]=730.31537, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=25280231, downTime=25280041, deviceId=6, source=0x1002 } diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index fe313aca3f5..a44c980383f 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -19,4 +19,5 @@ # Used for Talos, please don't use in mochitest #[testPan] #[testCheck] +#[testCheck2] #[testBrowserProviderPerf] diff --git a/mobile/android/base/tests/testCheck2.java.in b/mobile/android/base/tests/testCheck2.java.in new file mode 100644 index 00000000000..af29896b1fd --- /dev/null +++ b/mobile/android/base/tests/testCheck2.java.in @@ -0,0 +1,51 @@ +#filter substitution +package @ANDROID_PACKAGE_NAME@.tests; + +import java.io.IOException; +import @ANDROID_PACKAGE_NAME@.*; + +public class testCheck2 extends PixelTest { + public void testCheck2() { + setTestType("talos"); + String url = getAbsoluteUrl("/startup_test/fennecmark/timecube.html"); + + mActions.expectGeckoEvent("Gecko:Ready").blockForEvent(); + loadAndPaint(url); + mDriver.setupScrollHandling(); + + /* + * for this test, we load the timecube page, and replay a recorded sequence of events + * that is a user panning/zooming around the page. specific things in the sequence + * include: + * - scroll on one axis followed by scroll on another axis + * - pinch zoom (in and out) + * - double-tap zoom (in and out) + * - multi-fling panning with different velocities on each fling + * + * this checkerboarding metric is going to be more of a "functional" style test than + * a "unit" style test; i.e. it covers a little bit of a lot of things to measure + * overall performance, but doesn't really allow identifying which part is slow. + */ + + MotionEventReplayer mer = new MotionEventReplayer(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); + + mDriver.startCheckerboardRecording(); + // replay the events + try { + mer.replayEvents(getAsset("testcheck2-motionevents")); + } catch (IOException ioe) { + mAsserter.dumpLog("IOException while replaying events", ioe); + } + // give it some time to draw any final frames + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + } + float completeness = mDriver.stopCheckerboardRecording(); + + mAsserter.dumpLog("__start_report" + completeness + "__end_report"); + System.out.println("Completeness score: " + completeness); + long msecs = System.currentTimeMillis(); + mAsserter.dumpLog("__startTimestamp" + msecs + "__endTimestamp"); + } +} From ac6701a55b21f3e7a5d3a600c320bf6d43a1e544 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Tue, 27 Mar 2012 13:48:46 -0700 Subject: [PATCH 044/113] Bug 738766 - Marionette's log() now also dump()'s, r=mdas --- testing/marionette/marionette-simpletest.js | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/marionette/marionette-simpletest.js b/testing/marionette/marionette-simpletest.js index 51609940c95..7a46898df25 100644 --- a/testing/marionette/marionette-simpletest.js +++ b/testing/marionette/marionette-simpletest.js @@ -36,6 +36,7 @@ Marionette.prototype = { }, log: function Marionette__log(msg, level) { + dump("MARIONETTE LOG: " + (level ? level : "INFO") + ": " + msg); if (this.logObj != null) { this.logObj.log(msg, level); } From 5c1c03e064708da077cc77b5ca9abada36a4d4f1 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Tue, 27 Mar 2012 13:50:50 -0700 Subject: [PATCH 045/113] Bug 730318 - Implement a way for chrome js to enumerate the plugin objects on a page for activation. r=khuey --- content/base/public/nsIDocument.h | 5 ++ .../base/public/nsIObjectLoadingContent.idl | 8 ++- content/base/src/nsDocument.cpp | 50 ++++++++++++++++++- content/base/src/nsDocument.h | 13 +++++ content/base/src/nsObjectLoadingContent.cpp | 47 ++++++++++++++++- content/base/src/nsObjectLoadingContent.h | 10 ++++ .../html/content/src/nsHTMLObjectElement.cpp | 6 +++ .../content/src/nsHTMLSharedObjectElement.cpp | 6 +++ dom/base/nsDOMWindowUtils.cpp | 25 ++++++++++ dom/interfaces/base/nsIDOMWindowUtils.idl | 13 ++++- js/src/jsapi.cpp | 2 +- js/xpconnect/public/Makefile.in | 1 + js/xpconnect/public/nsTArrayHelpers.h | 49 ++++++++++++++++++ 13 files changed, 229 insertions(+), 6 deletions(-) create mode 100644 js/xpconnect/public/nsTArrayHelpers.h diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 0c0892a2cad..a2e08e8be21 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -111,6 +111,7 @@ class imgIRequest; class nsISHEntry; class nsDOMNavigationTiming; class nsWindowSizes; +class nsIObjectLoadingContent; namespace mozilla { namespace css { @@ -1570,6 +1571,10 @@ public: // state is unlocked/false. virtual nsresult SetImageLockingState(bool aLocked) = 0; + virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) = 0; + virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) = 0; + virtual void GetPlugins(nsTArray& aPlugins) = 0; + virtual nsresult GetStateObject(nsIVariant** aResult) = 0; virtual nsDOMNavigationTiming* GetNavigationTiming() const = 0; diff --git a/content/base/public/nsIObjectLoadingContent.idl b/content/base/public/nsIObjectLoadingContent.idl index bf688caa76f..1b0a1a7f470 100644 --- a/content/base/public/nsIObjectLoadingContent.idl +++ b/content/base/public/nsIObjectLoadingContent.idl @@ -52,7 +52,7 @@ interface nsIURI; /** * This interface represents a content node that loads objects. */ -[scriptable, uuid(3FF07AB3-5BAC-4D98-9549-5BD15CCEBCD3)] +[scriptable, uuid(fd56fda8-d3c3-4368-8cf3-67dbc992aec9)] interface nsIObjectLoadingContent : nsISupports { const unsigned long TYPE_LOADING = 0; @@ -125,6 +125,12 @@ interface nsIObjectLoadingContent : nsISupports */ void playPlugin(); + /** + * This attribute will return true if the plugin has been activated + * and false if the plugin is still in the click-to-play state. + */ + readonly attribute boolean activated; + [noscript] void stopPluginInstance(); [noscript] void syncStartPluginInstance(); diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index a2573e0fb08..9e40cc8413c 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1674,6 +1674,8 @@ nsDocument::~nsDocument() // unlocked state, and then clear the table. SetImageLockingState(false); mImageTracker.Clear(); + + mPlugins.Clear(); } NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument) @@ -2024,7 +2026,8 @@ nsDocument::Init() mScriptLoader = new nsScriptLoader(this); NS_ENSURE_TRUE(mScriptLoader, NS_ERROR_OUT_OF_MEMORY); - if (!mImageTracker.Init()) { + if (!mImageTracker.Init() || + !mPlugins.Init()) { return NS_ERROR_OUT_OF_MEMORY; } @@ -8361,6 +8364,51 @@ nsDocument::RemoveImage(imgIRequest* aImage) return rv; } +nsresult +nsDocument::AddPlugin(nsIObjectLoadingContent* aPlugin) +{ + MOZ_ASSERT(aPlugin); + if (!mPlugins.PutEntry(aPlugin)) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +void +nsDocument::RemovePlugin(nsIObjectLoadingContent* aPlugin) +{ + MOZ_ASSERT(aPlugin); + mPlugins.RemoveEntry(aPlugin); +} + +static bool +AllSubDocumentPluginEnum(nsIDocument* aDocument, void* userArg) +{ + nsTArray* plugins = + reinterpret_cast< nsTArray* >(userArg); + MOZ_ASSERT(plugins); + aDocument->GetPlugins(*plugins); + return true; +} + +static PLDHashOperator +AllPluginEnum(nsPtrHashKey* aPlugin, void* userArg) +{ + nsTArray* allPlugins = + reinterpret_cast< nsTArray* >(userArg); + MOZ_ASSERT(allPlugins); + allPlugins->AppendElement(aPlugin->GetKey()); + return PL_DHASH_NEXT; +} + +void +nsDocument::GetPlugins(nsTArray& aPlugins) +{ + aPlugins.SetCapacity(aPlugins.Length() + mPlugins.Count()); + mPlugins.EnumerateEntries(AllPluginEnum, &aPlugins); + EnumerateSubDocuments(AllSubDocumentPluginEnum, &aPlugins); +} + PLDHashOperator LockEnumerator(imgIRequest* aKey, PRUint32 aData, void* userArg) diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 8bfbfc1802d..4674a7309bb 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -935,6 +935,16 @@ public: virtual NS_HIDDEN_(nsresult) RemoveImage(imgIRequest* aImage); virtual NS_HIDDEN_(nsresult) SetImageLockingState(bool aLocked); + // AddPlugin adds a plugin-related element to mPlugins when the element is + // added to the tree. + virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin); + // RemovePlugin removes a plugin-related element to mPlugins when the + // element is removed from the tree. + virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin); + // GetPlugins returns the plugin-related elements from + // the frame and any subframes. + virtual void GetPlugins(nsTArray& aPlugins); + virtual nsresult GetStateObject(nsIVariant** aResult); virtual nsDOMNavigationTiming* GetNavigationTiming() const; @@ -1300,6 +1310,9 @@ private: // Tracking for images in the document. nsDataHashtable< nsPtrHashKey, PRUint32> mImageTracker; + // Tracking for plugins in the document. + nsTHashtable< nsPtrHashKey > mPlugins; + VisibilityState mVisibilityState; #ifdef DEBUG diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index 87ef4be73e2..3d5a88a51cf 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -115,6 +115,18 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc"); #include "mozilla/Preferences.h" +static bool gClickToPlayPlugins = false; + +static void +InitPrefCache() +{ + static bool initializedPrefCache = false; + if (!initializedPrefCache) { + mozilla::Preferences::AddBoolVarCache(&gClickToPlayPlugins, "plugins.click_to_play"); + } + initializedPrefCache = true; +} + class nsAsyncInstantiateEvent : public nsRunnable { public: nsObjectLoadingContent *mContent; @@ -546,6 +558,26 @@ bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& return false; } +nsresult +nsObjectLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* /*aParent*/, + nsIContent* /*aBindingParent*/, + bool /*aCompileEventHandlers*/) +{ + if (aDocument) { + return aDocument->AddPlugin(this); + } + return NS_OK; +} + +void +nsObjectLoadingContent::UnbindFromTree(bool /*aDeep*/, bool /*aNullParent*/) +{ + nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); + MOZ_ASSERT(thisContent); + nsIDocument* ownerDoc = thisContent->OwnerDoc(); + ownerDoc->RemovePlugin(this); +} + nsObjectLoadingContent::nsObjectLoadingContent() : mPendingInstantiateEvent(nsnull) , mChannel(nsnull) @@ -554,11 +586,14 @@ nsObjectLoadingContent::nsObjectLoadingContent() , mUserDisabled(false) , mSuppressed(false) , mNetworkCreated(true) - // If plugins.click_to_play is false, plugins should always play - , mShouldPlay(!mozilla::Preferences::GetBool("plugins.click_to_play", false)) , mSrcStreamLoading(false) , mFallbackReason(ePluginOtherState) { + InitPrefCache(); + // If plugins.click_to_play is false, plugins should always play + mShouldPlay = !gClickToPlayPlugins; + // If plugins.click_to_play is true, track the activated state of plugins. + mActivated = !gClickToPlayPlugins; } nsObjectLoadingContent::~nsObjectLoadingContent() @@ -2206,5 +2241,13 @@ nsObjectLoadingContent::PlayPlugin() return NS_OK; mShouldPlay = true; + mActivated = true; return LoadObject(mURI, true, mContentType, true); } + +NS_IMETHODIMP +nsObjectLoadingContent::GetActivated(bool* aActivated) +{ + *aActivated = mActivated; + return NS_OK; +} diff --git a/content/base/src/nsObjectLoadingContent.h b/content/base/src/nsObjectLoadingContent.h index 720e9ca8bb9..8e24376f386 100644 --- a/content/base/src/nsObjectLoadingContent.h +++ b/content/base/src/nsObjectLoadingContent.h @@ -244,6 +244,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent static void DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop); + nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandler); + void UnbindFromTree(bool aDeep = true, + bool aNullParent = true); + private: void NotifyContentObjectWrapper(); @@ -399,6 +405,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent // This is used for click-to-play plugins. bool mShouldPlay : 1; + // Used to keep track of whether or not a plugin has been played. + // This is used for click-to-play plugins. + bool mActivated : 1; + // Used to track when we might try to instantiate a plugin instance based on // a src data stream being delivered to this object. When this is true we don't // want plugin instance instantiation code to attempt to load src data again or diff --git a/content/html/content/src/nsHTMLObjectElement.cpp b/content/html/content/src/nsHTMLObjectElement.cpp index a45e4de3035..b9d8a79bfba 100644 --- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -265,6 +265,11 @@ nsHTMLObjectElement::BindToTree(nsIDocument *aDocument, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); + rv = nsObjectLoadingContent::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + // If we already have all the children, start the load. if (mIsDoneAddingChildren) { void (nsHTMLObjectElement::*start)() = &nsHTMLObjectElement::StartObjectLoad; @@ -279,6 +284,7 @@ nsHTMLObjectElement::UnbindFromTree(bool aDeep, bool aNullParent) { RemovedFromDocument(); + nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent); } diff --git a/content/html/content/src/nsHTMLSharedObjectElement.cpp b/content/html/content/src/nsHTMLSharedObjectElement.cpp index 177518aef2b..975f78211aa 100644 --- a/content/html/content/src/nsHTMLSharedObjectElement.cpp +++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp @@ -283,6 +283,11 @@ nsHTMLSharedObjectElement::BindToTree(nsIDocument *aDocument, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); + rv = nsObjectLoadingContent::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + // If we already have all the children, start the load. if (mIsDoneAddingChildren) { void (nsHTMLSharedObjectElement::*start)() = @@ -298,6 +303,7 @@ nsHTMLSharedObjectElement::UnbindFromTree(bool aDeep, bool aNullParent) { RemovedFromDocument(); + nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); } diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 6d81c651354..93519679afd 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -51,6 +51,7 @@ #include "nsRefreshDriver.h" #include "nsDOMTouchEvent.h" #include "nsIDOMTouchEvent.h" +#include "nsObjectLoadingContent.h" #include "nsIScrollableFrame.h" @@ -76,6 +77,7 @@ #include "nsCSSProps.h" #include "nsDOMFile.h" #include "BasicLayers.h" +#include "nsTArrayHelpers.h" #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2) #include @@ -2230,3 +2232,26 @@ nsDOMWindowUtils::GetPaintingSuppressed(bool *aPaintingSuppressed) return NS_OK; } +NS_IMETHODIMP +nsDOMWindowUtils::GetPlugins(JSContext* cx, jsval* aPlugins) +{ + if (!IsUniversalXPConnectCapable()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsIDOMDocument* ddoc = mWindow->GetExtantDocument(); + + nsresult rv; + nsCOMPtr doc = do_QueryInterface(ddoc, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsTArray plugins; + doc->GetPlugins(plugins); + + JSObject* jsPlugins = nsnull; + rv = nsTArrayToJSArray(cx, plugins, &jsPlugins); + NS_ENSURE_SUCCESS(rv, rv); + + *aPlugins = OBJECT_TO_JSVAL(jsPlugins); + return NS_OK; +} diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index b90c2b57e8b..a86f14081ae 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -70,7 +70,7 @@ interface nsIDOMFile; interface nsIFile; interface nsIDOMTouch; -[scriptable, uuid(43feb172-30e1-4ff1-b021-004f973da516)] +[scriptable, uuid(c7f303a1-4f7b-4d38-a192-c3f0e25dadb1)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1099,4 +1099,15 @@ interface nsIDOMWindowUtils : nsISupports { * otherwise. */ readonly attribute boolean paintingSuppressed; + + /** + * Returns an array of plugins on the page for opt-in activation. + * + * Cannot be accessed from unprivileged context (not content-accessible). + * Will throw a DOM security error if called without UniversalXPConnect + * privileges. + * + */ + [implicit_jscontext] + readonly attribute jsval plugins; }; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 2ab186b07d0..26ff03b87bb 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4101,7 +4101,7 @@ JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp) { AssertNoGC(cx); CHECK_REQUEST(cx); - assertSameCompartment(cx, obj); + assertSameCompartment(cx, obj, *vp); JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING); return obj->setElement(cx, index, vp, false); } diff --git a/js/xpconnect/public/Makefile.in b/js/xpconnect/public/Makefile.in index ab1afea4b7b..ded8d99b62c 100644 --- a/js/xpconnect/public/Makefile.in +++ b/js/xpconnect/public/Makefile.in @@ -49,6 +49,7 @@ EXPORTS = \ nsAXPCNativeCallContext.h \ xpc_map_end.h \ nsAutoJSValHolder.h \ + nsTArrayHelpers.h \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/js/xpconnect/public/nsTArrayHelpers.h b/js/xpconnect/public/nsTArrayHelpers.h new file mode 100644 index 00000000000..1a5be9ece7e --- /dev/null +++ b/js/xpconnect/public/nsTArrayHelpers.h @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __NSTARRAYHELPERS_H__ +#define __NSTARRAYHELPERS_H__ + +template +inline nsresult +nsTArrayToJSArray(JSContext* aCx, const nsTArray& aSourceArray, + JSObject** aResultArray) +{ + MOZ_ASSERT(aCx); + JSAutoRequest ar(aCx); + + JSObject* arrayObj = JS_NewArrayObject(aCx, aSourceArray.Length(), nsnull); + if (!arrayObj) { + NS_WARNING("JS_NewArrayObject failed!"); + return NS_ERROR_OUT_OF_MEMORY; + } + + JSObject* global = JS_GetGlobalForScopeChain(aCx); + MOZ_ASSERT(global); + + for (PRUint32 index = 0; index < aSourceArray.Length(); index++) { + nsCOMPtr obj; + nsresult rv = CallQueryInterface(aSourceArray[index], getter_AddRefs(obj)); + NS_ENSURE_SUCCESS(rv, rv); + + jsval wrappedVal; + rv = nsContentUtils::WrapNative(aCx, global, obj, &wrappedVal, nsnull, true); + NS_ENSURE_SUCCESS(rv, rv); + + if (!JS_SetElement(aCx, arrayObj, index, &wrappedVal)) { + NS_WARNING("JS_SetElement failed!"); + return NS_ERROR_FAILURE; + } + } + + if (!JS_FreezeObject(aCx, arrayObj)) { + NS_WARNING("JS_FreezeObject failed!"); + return NS_ERROR_FAILURE; + } + + *aResultArray = arrayObj; + return NS_OK; +} + +#endif /* __NSTARRAYHELPERS_H__ */ From f32094b575838c46d13cf3804813293359ee4305 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Tue, 27 Mar 2012 13:50:52 -0700 Subject: [PATCH 046/113] Bug 730318 - Opt-in activated plugins should use internal APIs to keep track of plugin activation. r=margaret --- mobile/android/chrome/content/browser.js | 105 +++++++++-------------- 1 file changed, 39 insertions(+), 66 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index b2ad2635603..19d818a7781 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1464,8 +1464,6 @@ function Tab(aURL, aParams) { this.create(aURL, aParams); this._zoom = 1.0; this.userScrollPos = { x: 0, y: 0 }; - this._pluginCount = 0; - this._pluginOverlayShowing = false; this.contentDocumentIsDisplayed = true; } @@ -1519,6 +1517,7 @@ Tab.prototype = { this.browser.sessionHistory.addSHistoryListener(this); this.browser.addEventListener("DOMContentLoaded", this, true); + this.browser.addEventListener("load", this, true); this.browser.addEventListener("DOMLinkAdded", this, true); this.browser.addEventListener("DOMTitleChanged", this, true); this.browser.addEventListener("DOMWindowClose", this, true); @@ -1526,8 +1525,6 @@ Tab.prototype = { this.browser.addEventListener("scroll", this, true); this.browser.addEventListener("MozScrolledAreaChanged", this, true); this.browser.addEventListener("PluginClickToPlay", this, true); - this.browser.addEventListener("pagehide", this, true); - this.browser.addEventListener("pageshow", this, true); Services.obs.addObserver(this, "before-first-paint", false); @@ -1565,6 +1562,7 @@ Tab.prototype = { this.browser.removeProgressListener(this); this.browser.removeEventListener("DOMContentLoaded", this, true); + this.browser.removeEventListener("load", this, true); this.browser.removeEventListener("DOMLinkAdded", this, true); this.browser.removeEventListener("DOMTitleChanged", this, true); this.browser.removeEventListener("DOMWindowClose", this, true); @@ -1572,8 +1570,6 @@ Tab.prototype = { this.browser.removeEventListener("scroll", this, true); this.browser.removeEventListener("PluginClickToPlay", this, true); this.browser.removeEventListener("MozScrolledAreaChanged", this, true); - this.browser.removeEventListener("pagehide", this, true); - this.browser.removeEventListener("pageshow", this, true); Services.obs.removeObserver(this, "before-first-paint"); @@ -1793,13 +1789,24 @@ Tab.prototype = { this.browser.removeEventListener("pagehide", listener, true); }.bind(this), true); } + break; + } - // Show a plugin doorhanger if there are plugins on the page but no - // clickable overlays showing (this doesn't work on pages loaded after - // back/forward navigation - see bug 719875) - if (this._pluginCount && !this._pluginOverlayShowing) + case "load": { + // Show a plugin doorhanger if there are no clickable overlays showing + let contentWindow = this.browser.contentWindow; + let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + // XXX not sure if we should enable plugins for the parent documents... + let plugins = cwu.plugins; + let isAnyPluginVisible = false; + for (let plugin of plugins) { + let overlay = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox"); + if (overlay && !PluginHelper.isTooSmall(plugin, overlay)) + isAnyPluginVisible = true; + } + if (plugins && plugins.length && !isAnyPluginVisible) PluginHelper.showDoorHanger(this); - break; } @@ -1907,10 +1914,6 @@ Tab.prototype = { } case "PluginClickToPlay": { - // Keep track of the number of plugins to know whether or not to show - // the hidden plugins doorhanger - this._pluginCount++; - let plugin = aEvent.target; let overlay = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox"); if (!overlay) @@ -1924,22 +1927,14 @@ Tab.prototype = { } // Add click to play listener to the overlay - overlay.addEventListener("click", (function(event) { - // Play all the plugin objects when the user clicks on one - PluginHelper.playAllPlugins(this, event); - }).bind(this), true); - - this._pluginOverlayShowing = true; - break; - } - - case "pagehide": { - // Check to make sure it's top-level pagehide - if (aEvent.target.defaultView == this.browser.contentWindow) { - // Reset plugin state when we leave the page - this._pluginCount = 0; - this._pluginOverlayShowing = false; - } + overlay.addEventListener("click", function(e) { + if (e) { + if (!e.isTrusted) + return; + e.preventDefault(); + } + PluginHelper.playAllPlugins(e.target.ownerDocument.defaultView); + }, true); break; } } @@ -3912,7 +3907,7 @@ var PluginHelper = { { label: Strings.browser.GetStringFromName("clickToPlayPlugins.yes"), callback: function() { - PluginHelper.playAllPlugins(aTab); + PluginHelper.playAllPlugins(aTab.browser.contentWindow); } }, { @@ -3925,41 +3920,19 @@ var PluginHelper = { NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id); }, - playAllPlugins: function(aTab, aEvent) { - if (aEvent) { - if (!aEvent.isTrusted) - return; - aEvent.preventDefault(); + playAllPlugins: function(aContentWindow) { + let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + // XXX not sure if we should enable plugins for the parent documents... + let plugins = cwu.plugins; + if (!plugins || !plugins.length) + return; + + for (let plugin of plugins) { + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + if (!objLoadingContent.activated) + objLoadingContent.playPlugin(); } - - this._findAndPlayAllPlugins(aTab.browser.contentWindow); - }, - - // Helper function that recurses through sub-frames to find all plugin objects - _findAndPlayAllPlugins: function _findAndPlayAllPlugins(aWindow) { - let embeds = aWindow.document.getElementsByTagName("embed"); - for (let i = 0; i < embeds.length; i++) { - if (!embeds[i].hasAttribute("played")) - this._playPlugin(embeds[i]); - } - - let objects = aWindow.document.getElementsByTagName("object"); - for (let i = 0; i < objects.length; i++) { - if (!objects[i].hasAttribute("played")) - this._playPlugin(objects[i]); - } - - for (let i = 0; i < aWindow.frames.length; i++) { - this._findAndPlayAllPlugins(aWindow.frames[i]); - } - }, - - _playPlugin: function _playPlugin(aPlugin) { - let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - objLoadingContent.playPlugin(); - - // Set an attribute on the plugin object to avoid re-loading it - aPlugin.setAttribute("played", true); }, getPluginPreference: function getPluginPreference() { From 06ea7c030f5079f90f053291d97c218dd6e874b7 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Tue, 27 Mar 2012 13:50:54 -0700 Subject: [PATCH 047/113] Bug 734323 - Invisible plugins added to the DOM after the 'load' event will not prompt a doorhanger to appear. r=margaret --- mobile/android/chrome/content/browser.js | 41 ++++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 19d818a7781..9111a76ba7b 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1465,6 +1465,9 @@ function Tab(aURL, aParams) { this._zoom = 1.0; this.userScrollPos = { x: 0, y: 0 }; this.contentDocumentIsDisplayed = true; + this.clickToPlayPluginDoorhangerShown = false; + this.clickToPlayPluginsActivated = false; + this.loadEventProcessed = false; } Tab.prototype = { @@ -1793,6 +1796,7 @@ Tab.prototype = { } case "load": { + this.loadEventProcessed = true; // Show a plugin doorhanger if there are no clickable overlays showing let contentWindow = this.browser.contentWindow; let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) @@ -1915,14 +1919,20 @@ Tab.prototype = { case "PluginClickToPlay": { let plugin = aEvent.target; - let overlay = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox"); - if (!overlay) + + if (this.clickToPlayPluginsActivated) { + PluginHelper.playPlugin(plugin); return; + } // If the overlay is too small, hide the overlay and act like this // is a hidden plugin object - if (PluginHelper.isTooSmall(plugin, overlay)) { - overlay.style.visibility = "hidden"; + let overlay = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox"); + if (!overlay || PluginHelper.isTooSmall(plugin, overlay)) { + if (overlay) + overlay.style.visibility = "hidden"; + if (this.loadEventProcessed && !this.clickToPlayPluginDoorhangerShown) + PluginHelper.showDoorHanger(this); return; } @@ -1933,7 +1943,10 @@ Tab.prototype = { return; e.preventDefault(); } - PluginHelper.playAllPlugins(e.target.ownerDocument.defaultView); + let win = e.target.ownerDocument.defaultView.top; + let tab = BrowserApp.getTabForWindow(win); + tab.clickToPlayPluginsActivated = true; + PluginHelper.playAllPlugins(win); }, true); break; } @@ -1994,6 +2007,11 @@ Tab.prototype = { contentType = browser.contentDocument.contentType; } + // Reset state of click-to-play plugin notifications. + this.clickToPlayPluginDoorhangerShown = false; + this.clickToPlayPluginsActivated = false; + this.loadEventProcessed = false; + let message = { gecko: { type: "Content:LocationChange", @@ -3902,6 +3920,7 @@ var ClipboardHelper = { var PluginHelper = { showDoorHanger: function(aTab) { + aTab.clickToPlayPluginDoorhangerShown = true; let message = Strings.browser.GetStringFromName("clickToPlayPlugins.message"); let buttons = [ { @@ -3928,11 +3947,13 @@ var PluginHelper = { if (!plugins || !plugins.length) return; - for (let plugin of plugins) { - let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); - if (!objLoadingContent.activated) - objLoadingContent.playPlugin(); - } + plugins.forEach(this.playPlugin); + }, + + playPlugin: function(plugin) { + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + if (!objLoadingContent.activated) + objLoadingContent.playPlugin(); }, getPluginPreference: function getPluginPreference() { From 6f97f1db6e2dbef93900b005aef717d19e030191 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Mon, 2 Jan 2012 16:06:10 -0800 Subject: [PATCH 048/113] Bug 711552 - Click to play plugins for desktop Firefox. r=felipe --- browser/app/profile/firefox.js | 2 + browser/base/content/browser.js | 95 +++++++++++++++++-- .../en-US/chrome/browser/browser.properties | 3 + browser/themes/winstripe/browser.css | 3 +- .../en-US/chrome/mozapps/plugins/plugins.dtd | 4 +- .../mozapps/plugins/content/pluginProblem.xml | 5 +- .../plugins/content/pluginProblemContent.css | 1 + .../mozapps/plugins/pluginProblem.css | 9 ++ .../mozapps/plugins/pluginProblem.css | 17 ++++ 9 files changed, 125 insertions(+), 14 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index bc1f24a2125..0c40fc72d23 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -612,6 +612,8 @@ pref("plugins.hide_infobar_for_carbon_failure_plugin", false); pref("plugins.update.url", "https://www.mozilla.com/%LOCALE%/plugincheck/"); pref("plugins.update.notifyUser", false); +pref("plugins.click_to_play", false); + #ifdef XP_WIN pref("browser.preferences.instantApply", false); #else diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 43af50e5be3..5a0e887963b 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1428,6 +1428,7 @@ function prepareForStartup() { gBrowser.addEventListener("PluginBlocklisted", gPluginHandler, true); gBrowser.addEventListener("PluginOutdated", gPluginHandler, true); gBrowser.addEventListener("PluginDisabled", gPluginHandler, true); + gBrowser.addEventListener("PluginClickToPlay", gPluginHandler, true); gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true); #ifdef XP_MACOSX gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true); @@ -5175,24 +5176,34 @@ var TabsProgressListener = { // document URI is not yet the about:-uri of the error page. if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && - Components.isSuccessCode(aStatus) && - /^about:/.test(aWebProgress.DOMWindow.document.documentURI)) { - aBrowser.addEventListener("click", BrowserOnClick, false); - aBrowser.addEventListener("pagehide", function () { - aBrowser.removeEventListener("click", BrowserOnClick, false); - aBrowser.removeEventListener("pagehide", arguments.callee, true); - }, true); + Components.isSuccessCode(aStatus)) { + setTimeout(function() { + gPluginHandler.showPluginClickToPlayDoorhanger(aBrowser); + }, 0); - // We also want to make changes to page UI for unprivileged about pages. - BrowserOnAboutPageLoad(aWebProgress.DOMWindow.document); + if (/^about:/.test(aWebProgress.DOMWindow.document.documentURI)) { + aBrowser.addEventListener("click", BrowserOnClick, false); + aBrowser.addEventListener("pagehide", function () { + aBrowser.removeEventListener("click", BrowserOnClick, false); + aBrowser.removeEventListener("pagehide", arguments.callee, true); + }, true); + + // We also want to make changes to page UI for unprivileged about pages. + BrowserOnAboutPageLoad(aWebProgress.DOMWindow.document); + } } }, onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI, aFlags) { // Filter out any sub-frame loads - if (aBrowser.contentWindow == aWebProgress.DOMWindow) + if (aBrowser.contentWindow == aWebProgress.DOMWindow) { + // initialize the click-to-play state + aBrowser._loadEventHandled = false; + aBrowser._clickToPlayDoorhangerShown = false; + FullZoom.onLocationChange(aLocationURI, false, aBrowser); + } }, onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) { @@ -7145,6 +7156,10 @@ var gPluginHandler = { self.pluginUnavailable(plugin, event.type); break; + case "PluginClickToPlay": + self.handleClickToPlayEvent(plugin); + break; + case "PluginDisabled": let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink"); self.addLinkClickCallback(manageLink, "managePlugins"); @@ -7159,6 +7174,18 @@ var gPluginHandler = { } }, + activatePlugins: function(aContentWindow) { + let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + let plugins = cwu.plugins; + for (let plugin of plugins) { + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + if (!objLoadingContent.activated) + objLoadingContent.playPlugin(); + plugin.removeEventListener("click", plugin.clickHandler, true); + } + }, + newPluginInstalled : function(event) { // browser elements are anonymous so we can't just use target. var browser = event.originalTarget; @@ -7212,6 +7239,54 @@ var gPluginHandler = { openHelpLink("plugin-crashed", false); }, + // Event listener for click-to-play plugins. + handleClickToPlayEvent: function(aPlugin) { + let browser = gBrowser.getBrowserForDocument(aPlugin.ownerDocument.defaultView.top.document); + let notificationBox = gBrowser.getNotificationBox(browser); + + let doc = aPlugin.ownerDocument; + let overlay = doc.getAnonymousElementByAttribute(aPlugin, "class", "mainBox"); + let contentWindow = browser.contentWindow; + overlay.addEventListener("click", function(aEvent) { + if (aEvent.button == 0 && aEvent.isTrusted) + gPluginHandler.activatePlugins(aEvent.target.ownerDocument.defaultView.top); + }, true); + + if (browser._loadEventHandled && !browser._clickToPlayDoorhangerShown && + gPluginHandler.isTooSmall(aPlugin, overlay)) + gPluginHandler.showPluginClickToPlayDoorhanger(browser); + }, + + showPluginClickToPlayDoorhanger: function(aBrowser) { + aBrowser._loadEventHandled = true; + // Show a plugin doorhanger if there are no clickable overlays showing + let contentWindow = aBrowser.contentWindow; + let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + let plugins = cwu.plugins; + let isAnyPluginVisible = false; + for (let plugin of plugins) { + let overlay = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox"); + if (overlay && !gPluginHandler.isTooSmall(plugin, overlay)) { + isAnyPluginVisible = true; + break; + } + } + if (plugins && plugins.length && !isAnyPluginVisible) { + aBrowser._clickToPlayDoorhangerShown = true; + let messageString = gNavigatorBundle.getString("activatePluginsMessage.message"); + let action = { + label: gNavigatorBundle.getString("activatePluginsMessage.label"), + accessKey: gNavigatorBundle.getString("activatePluginsMessage.accesskey"), + callback: function() { gPluginHandler.activatePlugins(contentWindow); } + }; + let options = { timeout: Date.now() + 30000 }; + PopupNotifications.show(aBrowser, "click-to-play-plugins", + messageString, "addons-notification-icon", + action, null, options); + } + }, + // event listener for missing/blocklisted/outdated/carbonFailure plugins. pluginUnavailable: function (plugin, eventType) { let browser = gBrowser.getBrowserForDocument(plugin.ownerDocument diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties index df1537f2993..35ca7bfd3c7 100644 --- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -115,6 +115,9 @@ crashedpluginsMessage.learnMore=Learn More… carbonFailurePluginsMessage.message=This page asks to use a plugin that can only run in 32-bit mode carbonFailurePluginsMessage.restartButton.label=Restart in 32-bit mode carbonFailurePluginsMessage.restartButton.accesskey=R +activatePluginsMessage.message=Would you like to activate the plugins on this page? +activatePluginsMessage.label=Activate plugins +activatePluginsMessage.accesskey=A # Sanitize # LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to diff --git a/browser/themes/winstripe/browser.css b/browser/themes/winstripe/browser.css index 5f2d224f419..36ff406f5e5 100644 --- a/browser/themes/winstripe/browser.css +++ b/browser/themes/winstripe/browser.css @@ -2253,7 +2253,8 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { .popup-notification-icon[popupid="addon-install-cancelled"], .popup-notification-icon[popupid="addon-install-blocked"], .popup-notification-icon[popupid="addon-install-failed"], -.popup-notification-icon[popupid="addon-install-complete"] { +.popup-notification-icon[popupid="addon-install-complete"], +.popup-notification-icon[popupid="click-to-play-plugins"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); width: 32px; height: 32px; diff --git a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd index 8673940c5f2..a8fda4bb926 100644 --- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd +++ b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd @@ -21,7 +21,9 @@ - + + + diff --git a/toolkit/mozapps/plugins/content/pluginProblem.xml b/toolkit/mozapps/plugins/content/pluginProblem.xml index b1b04ec381c..6afe01530e4 100644 --- a/toolkit/mozapps/plugins/content/pluginProblem.xml +++ b/toolkit/mozapps/plugins/content/pluginProblem.xml @@ -49,8 +49,8 @@ xmlns:html="http://www.w3.org/1999/xhtml"> - + @@ -58,7 +58,8 @@ &missingPlugin; - &clickToPlayPlugin; + &tapToPlayPlugin; + &clickToPlayPlugins; &disabledPlugin; &blockedPlugin.label; diff --git a/toolkit/mozapps/plugins/content/pluginProblemContent.css b/toolkit/mozapps/plugins/content/pluginProblemContent.css index 3039718671e..59a3c053836 100644 --- a/toolkit/mozapps/plugins/content/pluginProblemContent.css +++ b/toolkit/mozapps/plugins/content/pluginProblemContent.css @@ -43,6 +43,7 @@ html|applet:not([height]), html|applet[height=""] { :-moz-type-unsupported .msgUnsupported, :-moz-handler-clicktoplay .msgClickToPlay, +:-moz-handler-clicktoplay .msgTapToPlay, :-moz-handler-disabled .msgDisabled, :-moz-handler-disabled .msgManagePlugins, :-moz-handler-blocked .msgBlocked, diff --git a/toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css b/toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css index 0924145e869..30d27c1870d 100644 --- a/toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css +++ b/toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css @@ -60,6 +60,15 @@ html|a { text-shadow: rgba(0,0,0,0.8) 0 0 3.5px; } +:-moz-handler-clicktoplay, +.msgClickToPlay { + cursor: pointer; +} + +:-moz-handler-clicktoplay .msgTapToPlay { + display: none; +} + .submitStatus div { min-height: 19px; /* height of biggest line (with throbber) */ } diff --git a/toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css b/toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css index 0924145e869..d577beb5024 100644 --- a/toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css +++ b/toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css @@ -60,6 +60,23 @@ html|a { text-shadow: rgba(0,0,0,0.8) 0 0 3.5px; } +:-moz-handler-clicktoplay, +.msgClickToPlay { + cursor: pointer; +} + +@media not all and (-moz-touch-enabled) { + :-moz-handler-clicktoplay .msgTapToPlay { + display: none; + } +} + +@media (-moz-touch-enabled) { + :-moz-handler-clicktoplay .msgClickToPlay { + display: none; + } +} + .submitStatus div { min-height: 19px; /* height of biggest line (with throbber) */ } From f320f33a7bd6a15ec5f1c8c700ab219d2ac3da09 Mon Sep 17 00:00:00 2001 From: Serge Gautherie Date: Tue, 27 Mar 2012 22:13:25 +0200 Subject: [PATCH 049/113] Bug 483992. (Av1) dom-level*-*/DOMTestCase.js: Remove sayrer's override of SimpleTest._logResult(). r=rcampbell. --- .../mochitest/dom-level1-core/DOMTestCase.js | 23 ------------------- .../mochitest/dom-level2-core/DOMTestCase.js | 23 ------------------- .../mochitest/dom-level2-html/DOMTestCase.js | 23 ------------------- 3 files changed, 69 deletions(-) diff --git a/dom/tests/mochitest/dom-level1-core/DOMTestCase.js b/dom/tests/mochitest/dom-level1-core/DOMTestCase.js index 45992250bfb..308e3cc5e3b 100644 --- a/dom/tests/mochitest/dom-level1-core/DOMTestCase.js +++ b/dom/tests/mochitest/dom-level1-core/DOMTestCase.js @@ -644,29 +644,6 @@ function getImplementation() { return builder.getImplementation(); } -//sayrer override the SimpleTest logger -SimpleTest._logResult = function(test, passString, failString) { - var msg = test.result ? passString : failString; - msg += " | " + test.name; - if (test.result) { - if (test.todo) - parentRunner.logger.error(msg) - else - parentRunner.logger.log(msg); - } else { - msg += " | " + test.diag; - if (test.todo) { - parentRunner.logger.log(msg) - } else { - if (todoTests[docName]) { - parentRunner.logger.log("expected error in todo testcase | " + test.name); - } else { - parentRunner.logger.error(msg); - } - } - } -} - function testFails (test) { if (!test.result) { test.todo = true; diff --git a/dom/tests/mochitest/dom-level2-core/DOMTestCase.js b/dom/tests/mochitest/dom-level2-core/DOMTestCase.js index 17179017e54..384dc8ef961 100644 --- a/dom/tests/mochitest/dom-level2-core/DOMTestCase.js +++ b/dom/tests/mochitest/dom-level2-core/DOMTestCase.js @@ -648,29 +648,6 @@ function getImplementation() { return builder.getImplementation(); } -//sayrer override the SimpleTest logger -SimpleTest._logResult = function(test, passString, failString) { - var msg = test.result ? passString : failString; - msg += " | " + test.name; - if (test.result) { - if (test.todo) - parentRunner.logger.error(msg) - else - parentRunner.logger.log(msg); - } else { - msg += " | " + test.diag; - if (test.todo) { - parentRunner.logger.log(msg) - } else { - if (todoTests[docName]) { - parentRunner.logger.log("expected error in todo testcase | " + test.name); - } else { - parentRunner.logger.error(msg); - } - } - } -} - window.doc = window; SimpleTest.waitForExplicitFinish(); addLoadEvent(function(){ setUpPage(); }); diff --git a/dom/tests/mochitest/dom-level2-html/DOMTestCase.js b/dom/tests/mochitest/dom-level2-html/DOMTestCase.js index e0287763ee7..80fece492ce 100644 --- a/dom/tests/mochitest/dom-level2-html/DOMTestCase.js +++ b/dom/tests/mochitest/dom-level2-html/DOMTestCase.js @@ -648,29 +648,6 @@ function getImplementation() { return builder.getImplementation(); } -//sayrer override the SimpleTest logger -SimpleTest._logResult = function(test, passString, failString) { - var msg = test.result ? passString : failString; - msg += " | " + test.name; - if (test.result) { - if (test.todo) - parentRunner.logger.error(msg) - else - parentRunner.logger.log(msg); - } else { - msg += " | " + test.diag; - if (test.todo) { - parentRunner.logger.log(msg) - } else { - // if (todoTests[docName]) { - // parentRunner.logger.log("expected error in todo testcase | " + test.name); - //} else { - parentRunner.logger.error(msg); - //} - } - } -} - window.doc = window; SimpleTest.waitForExplicitFinish(); addLoadEvent(function(){ setUpPage(); }); From dc48fa38466b155c9cec9437f4e5af1efc68c979 Mon Sep 17 00:00:00 2001 From: Armen Zambrano Gasparnian Date: Tue, 27 Mar 2012 10:11:30 -0400 Subject: [PATCH 050/113] Bug 739345 - update new talos.zip with fixed permissions for minidump_stackwalk. r=jmaher --HG-- extra : transplant_source : Or%2C%A8q-J%FB%D5%C4Tsw%AB%3EfO%1C%0E%7C --- testing/talos/talos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 22c370e45fb..814a3937e3b 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -1,6 +1,6 @@ { "talos.zip": { - "url": "http://build.mozilla.org/talos/zips/talos.bug738685.c08bb14e71cd.zip", + "url": "http://build.mozilla.org/talos/zips/talos.bug739345.c6013a2f09ce.zip", "path": "" } } From fc10fa7222e2061a7bb21f28ac02a6d186691a5e Mon Sep 17 00:00:00 2001 From: Armen Zambrano Gasparnian Date: Tue, 27 Mar 2012 17:16:48 -0400 Subject: [PATCH 051/113] Bug 739768. We fixed the talos.zip issue with a symlink but let's be cut and clear to which talos.zip is the good one. r=jhammel --- testing/talos/talos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 814a3937e3b..fcda8065feb 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -1,6 +1,6 @@ { "talos.zip": { - "url": "http://build.mozilla.org/talos/zips/talos.bug739345.c6013a2f09ce.zip", + "url": "http://build.mozilla.org/talos/zips/talos.bug739768.eb99eb78e42c.zip", "path": "" } } From f189b6f3455c600b75134ff637efb9474525b5b5 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Tue, 20 Mar 2012 16:18:41 -0700 Subject: [PATCH 052/113] Bug 728886 - Part 0: Use constants when initializing RIL state. r=qDot --- dom/system/gonk/RadioInterfaceLayer.js | 4 ++-- dom/system/gonk/ril_consts.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 7decb81ee87..d35f7739775 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -142,8 +142,8 @@ function RadioInterfaceLayer() { this.worker.onmessage = this.onmessage.bind(this); debug("Starting Worker\n"); this.radioState = { - radioState: null, - cardState: null, + radioState: RIL.GECKO_RADIOSTATE_UNAVAILABLE, + cardState: RIL.GECKO_CARDSTATE_UNAVAILABLE, connected: null, roaming: null, signalStrength: null, diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index 31a9ba3c438..520c10c5a01 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -1123,7 +1123,7 @@ const GECKO_NETWORK_STATE_DISCONNECTING = 3; const GECKO_NETWORK_STATE_DISCONNECTED = 4; // Other Gecko-specific constants -const GECKO_RADIOSTATE_UNAVAILABLE = "unavailable"; +const GECKO_RADIOSTATE_UNAVAILABLE = null; const GECKO_RADIOSTATE_OFF = "off"; const GECKO_RADIOSTATE_READY = "ready"; From e55de01d497fc13724cb94854c83b0589aabe731 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Mon, 19 Mar 2012 15:49:27 -0700 Subject: [PATCH 053/113] Bug 728886 - Part 1: Introduce constants from ril.h version 6. r=qDot --- dom/system/gonk/RadioInterfaceLayer.js | 10 +- dom/system/gonk/ril_consts.js | 163 +++++++++++++++++++++++-- dom/system/gonk/ril_worker.js | 60 ++++----- 3 files changed, 186 insertions(+), 47 deletions(-) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index d35f7739775..127225d42c8 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -194,15 +194,15 @@ RadioInterfaceLayer.prototype = { // This one will handle its own notifications. this.handleEnumerateCalls(message.calls); break; - case "registrationstatechange": - this.updateDataConnection(message.registrationState); + case "voiceregistrationstatechange": + this.updateDataConnection(message.voiceRegistrationState); break; - case "gprsregistrationstatechange": - let state = message.gprsRegistrationState; + case "dataregistrationstatechange": + let state = message.dataRegistrationState; this.updateDataConnection(state); //TODO for simplicity's sake, for now we only look at - // gprsRegistrationState for the radio registration state. + // dataRegistrationState for the radio registration state. if (!state || state.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { this.resetRadioState(); diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index 520c10c5a01..30c1f8be7f4 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -57,8 +57,8 @@ const REQUEST_CONFERENCE = 16; const REQUEST_UDUB = 17; const REQUEST_LAST_CALL_FAIL_CAUSE = 18; const REQUEST_SIGNAL_STRENGTH = 19; -const REQUEST_REGISTRATION_STATE = 20; -const REQUEST_GPRS_REGISTRATION_STATE = 21; +const REQUEST_VOICE_REGISTRATION_STATE = 20; +const REQUEST_DATA_REGISTRATION_STATE = 21; const REQUEST_OPERATOR = 22; const REQUEST_RADIO_POWER = 23; const REQUEST_DTMF = 24; @@ -114,7 +114,7 @@ const REQUEST_SET_PREFERRED_NETWORK_TYPE = 73; const REQUEST_GET_PREFERRED_NETWORK_TYPE = 74; const REQUEST_GET_NEIGHBORING_CELL_IDS = 75; const REQUEST_SET_LOCATION_UPDATES = 76; -const REQUEST_CDMA_SET_SUBSCRIPTION = 77; +const REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE = 77; const REQUEST_CDMA_SET_ROAMING_PREFERENCE = 78; const REQUEST_CDMA_QUERY_ROAMING_PREFERENCE = 79; const REQUEST_SET_TTY_MODE = 80; @@ -141,6 +141,28 @@ const REQUEST_GET_SMSC_ADDRESS = 100; const REQUEST_SET_SMSC_ADDRESS = 101; const REQUEST_REPORT_SMS_MEMORY_STATUS = 102; const REQUEST_REPORT_STK_SERVICE_IS_RUNNING = 103; +const REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE = 104; +const REQUEST_ISIM_AUTHENTICATION = 105; +const REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU = 106; +const REQUEST_STK_SEND_ENVELOPE_WITH_STATUS = 107; + +// Akami/Maguro specific parcel types. +const REQUEST_VOICE_RADIO_TECH = 105; +const REQUEST_IMS_REGISTRATION_STATE = 106; +const REQUEST_IMS_SEND_SMS = 107; +const REQUEST_GET_DATA_CALL_PROFILE = 108; +const REQUEST_SET_UICC_SUBSCRIPTION = 109; +const REQUEST_SET_DATA_SUBSCRIPTION = 110; +const REQUEST_GET_UICC_SUBSCRIPTION = 111; +const REQUEST_GET_DATA_SUBSCRIPTION = 112; +const REQUEST_SET_SUBSCRIPTION_MODE = 113; +const REQUEST_SET_TRANSMIT_POWER = 114; +const REQUEST_SETUP_QOS = 115; +const REQUEST_RELEASE_QOS = 116; +const REQUEST_GET_QOS_STATUS = 117; +const REQUEST_MODIFY_QOS = 118; +const REQUEST_SUSPEND_QOS = 119; +const REQUEST_RESUME_QOS = 120; const RESPONSE_TYPE_SOLICITED = 0; const RESPONSE_TYPE_UNSOLICITED = 1; @@ -148,7 +170,7 @@ const RESPONSE_TYPE_UNSOLICITED = 1; const UNSOLICITED_RESPONSE_BASE = 1000; const UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED = 1000; const UNSOLICITED_RESPONSE_CALL_STATE_CHANGED = 1001; -const UNSOLICITED_RESPONSE_NETWORK_STATE_CHANGED = 1002; +const UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED = 1002; const UNSOLICITED_RESPONSE_NEW_SMS = 1003; const UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT = 1004; const UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM = 1005; @@ -177,6 +199,20 @@ const UNSOLICITED_CDMA_INFO_REC = 1027; const UNSOLICITED_OEM_HOOK_RAW = 1028; const UNSOLICITED_RINGBACK_TONE = 1029; const UNSOLICITED_RESEND_INCALL_MUTE = 1030; +const UNSOLICITED_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1031; +const UNSOLICITED_CDMA_PRL_CHANGED = 1032; +const UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE = 1033; +const UNSOLICITED_RIL_CONNECTED = 1034; + +// Akami/Maguro specific parcels. +const UNSOLICITED_VOICE_RADIO_TECH_CHANGED = 1034; +const UNSOLICITED_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1035; +const UNSOLICITED_RESPONSE_TETHERED_MODE_STATE_CHANGED = 1036; +const UNSOLICITED_RESPONSE_DATA_NETWORK_STATE_CHANGED = 1037; +const UNSOLICITED_ON_SS = 1038; +const UNSOLICITED_STK_CC_ALPHA_NOTIFY = 1039; +const UNSOLICITED_UICC_SUBSCRIPTION_STATUS_CHANGED = 1040; +const UNSOLICITED_QOS_STATE_CHANGED_IND = 1041; const ERROR_SUCCESS = 0; const ERROR_RADIO_NOT_AVAILABLE = 1; @@ -194,9 +230,22 @@ const ERROR_SUBSCRIPTION_NOT_AVAILABLE = 12; const ERROR_MODE_NOT_SUPPORTED = 13; const ERROR_FDN_CHECK_FAILURE = 14; const ERROR_ILLEGAL_SIM_OR_ME = 15; +const ERROR_DIAL_MODIFIED_TO_USSD = 17; +const ERROR_DIAL_MODIFIED_TO_SS = 18; +const ERROR_DIAL_MODIFIED_TO_DIAL = 19; +const ERROR_USSD_MODIFIED_TO_DIAL = 20; +const ERROR_USSD_MODIFIED_TO_SS = 21; +const ERROR_USSD_MODIFIED_TO_USSD = 22; +const ERROR_SS_MODIFIED_TO_DIAL = 23; +const ERROR_SS_MODIFIED_TO_USSD = 24; +const ERROR_SS_MODIFIED_TO_SS = 25; +const ERROR_SUBSCRIPTION_NOT_SUPPORTED = 26; const RADIO_STATE_OFF = 0; const RADIO_STATE_UNAVAILABLE = 1; +const RADIO_STATE_ON = 2; + +// RIL v5 legacy constants: const RADIO_STATE_SIM_NOT_READY = 2; const RADIO_STATE_SIM_LOCKED_OR_ABSENT = 3; const RADIO_STATE_SIM_READY = 4; @@ -210,17 +259,74 @@ const CARD_STATE_ABSENT = 0; const CARD_STATE_PRESENT = 1; const CARD_STATE_ERROR = 2; -const CARD_APP_STATE_UNKNOWN = 0; -const CARD_APP_STATE_DETECTED = 1; -const CARD_APP_STATE_PIN = 2; // If PIN1 or UPin is required. -const CARD_APP_STATE_PUK = 3; // If PUK1 or Puk for UPin is required. -const CARD_APP_STATE_SUBSCRIPTION_PERSO = 4; // perso_substate should be looked - // at when app_state is assigned - // to this value. -const CARD_APP_STATE_READY = 5; +const CARD_PERSOSUBSTATE_UNKNOWN = 0; +const CARD_PERSOSUBSTATE_IN_PROGRESS = 1; +const CARD_PERSOSUBSTATE_READY = 2; +const CARD_PERSOSUBSTATE_SIM_NETWORK = 3; +const CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET = 4; +const CARD_PERSOSUBSTATE_SIM_CORPORATE = 5; +const CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER = 6; +const CARD_PERSOSUBSTATE_SIM_SIM = 7; +const CARD_PERSOSUBSTATE_SIM_NETWORK_PUK = 8; +const CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK = 9; +const CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK = 10; +const CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK = 11; +const CARD_PERSOSUBSTATE_SIM_SIM_PUK = 12; +const CARD_PERSOSUBSTATE_RUIM_NETWORK1 = 13; +const CARD_PERSOSUBSTATE_RUIM_NETWORK2 = 14; +const CARD_PERSOSUBSTATE_RUIM_HRPD = 15; +const CARD_PERSOSUBSTATE_RUIM_CORPORATE = 16; +const CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER = 17; +const CARD_PERSOSUBSTATE_RUIM_RUIM = 18; +const CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK = 19; +const CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK = 20; +const CARD_PERSOSUBSTATE_RUIM_HRPD_PUK = 21; +const CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK = 22; +const CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK = 23; +const CARD_PERSOSUBSTATE_RUIM_RUIM_PUK = 24; + +const CARD_APPSTATE_ILLEGAL = -1; +const CARD_APPSTATE_UNKNOWN = 0; +const CARD_APPSTATE_DETECTED = 1; +const CARD_APPSTATE_PIN = 2; // If PIN1 or UPin is required. +const CARD_APPSTATE_PUK = 3; // If PUK1 or Puk for UPin is required. +const CARD_APPSTATE_SUBSCRIPTION_PERSO = 4; // perso_substate should be looked + // at when app_state is assigned + // to this value. +const CARD_APPSTATE_READY = 5; + +const CARD_PINSTATE_UNKNOWN = 0; +const CARD_PINSTATE_ENABLED_NOT_VERIFIED = 1; +const CARD_PINSTATE_ENABLED_VERIFIED = 2; +const CARD_PINSTATE_DISABLED = 3; +const CARD_PINSTATE_ENABLED_BLOCKED = 4; +const CARD_PINSTATE_ENABLED_PERM_BLOCKED = 5; + +const CARD_APPTYPE_UNKNOWN = 0; +const CARD_APPTYPE_SIM = 1; +const CARD_APPTYPE_USIM = 2; +const CARD_APPTYPE_RUIM = 3; +const CARD_APPTYPE_CSIM = 4; +const CARD_APPTYPE_ISIM = 5; const CARD_MAX_APPS = 8; +const NETWORK_SELECTION_MODE_AUTOMATIC = 0; +const NETWORK_SELECTION_MODE_MANUAL = 1; + +const PREFERRED_NETWORK_TYPE_GSM_WCDMA = 0; +const PREFERRED_NETWORK_TYPE_GSM_ONLY = 1; +const PREFERRED_NETWORK_TYPE_WCDMA = 2; +const PREFERRED_NETWORK_TYPE_GSM_WCDMA_AUTO = 3; +const PREFERRED_NETWORK_TYPE_CDMA_EVDO_AUTO = 4; +const PREFERRED_NETWORK_TYPE_CDMA_ONLY = 5; +const PREFERRED_NETWORK_TYPE_EVDO_ONLY = 6; +const PREFERRED_NETWORK_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO = 7; +const PREFERRED_NETWORK_TYPE_LTE_CDMA_EVDO = 8; +const PREFERRED_NETWORK_TYPE_LTE_GSM_WCDMA = 9; +const PREFERRED_NETWORK_TYPE_LTE_CMDA_EVDO_GSM_WCDMA = 10; +const PREFERRED_NETWORK_TYPE_LTE_ONLY = 11; + // Network registration states. See TS 27.007 7.2 const NETWORK_CREG_STATE_NOT_SEARCHING = 0; const NETWORK_CREG_STATE_REGISTERED_HOME = 1; @@ -242,6 +348,9 @@ const NETWORK_CREG_TECH_HSDPA = 9; const NETWORK_CREG_TECH_HSUPA = 10; const NETWORK_CREG_TECH_HSPA = 11; const NETWORK_CREG_TECH_EVDOB = 12; +const NETWORK_CREG_TECH_EHRPD = 13; +const NETWORK_CREG_TECH_LTE = 14; +const NETWORK_CREG_TECH_HSPAP = 15; const CALL_STATE_ACTIVE = 0; const CALL_STATE_HOLDING = 1; @@ -1094,6 +1203,9 @@ const PDU_NL_SINGLE_SHIFT_TABLES = [ + " " ]; +const RADIOTECH_FAMILY_3GPP = 1; // GSM, WCDMA, LTE +const RADIOTECH_FAMILY_3GPP2 = 2; // CDMA, EVDO + const DATACALL_RADIOTECHNOLOGY_CDMA = 0; const DATACALL_RADIOTECHNOLOGY_GSM = 1; @@ -1114,6 +1226,30 @@ const DATACALL_INACTIVE = 0; const DATACALL_ACTIVE_DOWN = 1; const DATACALL_ACTIVE_UP = 2; +const DATACALL_FAIL_NONE = 0; +const DATACALL_FAIL_OPERATOR_BARRED = 0x08; +const DATACALL_FAIL_INSUFFICIENT_RESOURCES = 0x1A; +const DATACALL_FAIL_MISSING_UKNOWN_APN = 0x1B; +const DATACALL_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C; +const DATACALL_FAIL_USER_AUTHENTICATION = 0x1D; +const DATACALL_FAIL_ACTIVATION_REJECT_GGSN = 0x1E; +const DATACALL_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F; +const DATACALL_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20; +const DATACALL_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21; +const DATACALL_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22; +const DATACALL_FAIL_NSAPI_IN_USE = 0x23; +const DATACALL_FAIL_ONLY_IPV4_ALLOWED = 0x32; +const DATACALL_FAIL_ONLY_IPV6_ALLOWED = 0x33; +const DATACALL_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34; +const DATACALL_FAIL_PROTOCOL_ERRORS = 0x6F; +const DATACALL_FAIL_VOICE_REGISTRATION_FAIL = -1; +const DATACALL_FAIL_DATA_REGISTRATION_FAIL = -2; +const DATACALL_FAIL_SIGNAL_LOST = -3; +const DATACALL_FAIL_PREF_RADIO_TECH_CHANGED = -4; +const DATACALL_FAIL_RADIO_POWER_OFF = -5; +const DATACALL_FAIL_TETHERED_CALL_ACTIVE = -6; +const DATACALL_FAIL_ERROR_UNSPECIFIED = 0xffff; + // Keep consistent with nsINetworkManager.NETWORK_STATE_*. const GECKO_NETWORK_STATE_UNKNOWN = -1; const GECKO_NETWORK_STATE_CONNECTING = 0; @@ -1149,6 +1285,9 @@ const GECKO_RADIO_TECH = [ "hsupa", "hspa", "evdob", + "ehrpd", + "lte", + "hspa+", ]; // Allow this file to be imported via Components.utils.import(). diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 07a42edeea9..ce9f7d15b4e 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -576,8 +576,8 @@ let RIL = { SMSC: null, MSISDN: null, - registrationState: {}, - gprsRegistrationState: {}, + voiceRegistrationState: {}, + dataRegistrationState: {}, /** * List of strings identifying the network operator. @@ -820,12 +820,12 @@ let RIL = { Buf.sendParcel(); }, - getRegistrationState: function getRegistrationState() { - Buf.simpleRequest(REQUEST_REGISTRATION_STATE); + getVoiceRegistrationState: function getVoiceRegistrationState() { + Buf.simpleRequest(REQUEST_VOICE_REGISTRATION_STATE); }, - getGPRSRegistrationState: function getGPRSRegistrationState() { - Buf.simpleRequest(REQUEST_GPRS_REGISTRATION_STATE); + getDataRegistrationState: function getDataRegistrationState() { + Buf.simpleRequest(REQUEST_DATA_REGISTRATION_STATE); }, getOperator: function getOperator() { @@ -841,8 +841,8 @@ let RIL = { */ requestNetworkInfo: function requestNetworkInfo() { if (DEBUG) debug("Requesting phone state"); - this.getRegistrationState(); - this.getGPRSRegistrationState(); //TODO only GSM + this.getVoiceRegistrationState(); + this.getDataRegistrationState(); //TODO only GSM this.getOperator(); this.getNetworkSelectionMode(); }, @@ -1205,20 +1205,20 @@ let RIL = { let newCardState; switch (app.app_state) { - case CARD_APP_STATE_PIN: + case CARD_APPSTATE_PIN: newCardState = GECKO_CARDSTATE_PIN_REQUIRED; break; - case CARD_APP_STATE_PUK: + case CARD_APPSTATE_PUK: newCardState = GECKO_CARDSTATE_PUK_REQUIRED; break; - case CARD_APP_STATE_SUBSCRIPTION_PERSO: + case CARD_APPSTATE_SUBSCRIPTION_PERSO: newCardState = GECKO_CARDSTATE_NETWORK_LOCKED; break; - case CARD_APP_STATE_READY: + case CARD_APPSTATE_READY: newCardState = GECKO_CARDSTATE_READY; break; - case CARD_APP_STATE_UNKNOWN: - case CARD_APP_STATE_DETECTED: + case CARD_APPSTATE_UNKNOWN: + case CARD_APPSTATE_DETECTED: default: newCardState = GECKO_CARDSTATE_NOT_READY; } @@ -1274,8 +1274,8 @@ let RIL = { } }, - _processRegistrationState: function _processRegistrationState(state) { - let rs = this.registrationState; + _processVoiceRegistrationState: function _processVoiceRegistrationState(state) { + let rs = this.voiceRegistrationState; let stateChanged = false; let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN); @@ -1310,13 +1310,13 @@ let RIL = { } if (stateChanged) { - this.sendDOMMessage({type: "registrationstatechange", - registrationState: rs}); + this.sendDOMMessage({type: "voiceregistrationstatechange", + voiceRegistrationState: rs}); } }, - _processGPRSRegistrationState: function _processGPRSRegistrationState(state) { - let rs = this.gprsRegistrationState; + _processDataRegistrationState: function _processDataRegistrationState(state) { + let rs = this.dataRegistrationState; let stateChanged = false; let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN); @@ -1332,8 +1332,8 @@ let RIL = { } if (stateChanged) { - this.sendDOMMessage({type: "gprsregistrationstatechange", - gprsRegistrationState: rs}); + this.sendDOMMessage({type: "dataregistrationstatechange", + dataRegistrationState: rs}); } }, @@ -1584,9 +1584,9 @@ RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS() { for (let i = 0 ; i < apps_length ; i++) { iccStatus.apps.push({ - app_type: Buf.readUint32(), // APPTYPE_* - app_state: Buf.readUint32(), // CARD_APP_STATE_* - perso_substate: Buf.readUint32(), // PERSOSUBSTATE_* + app_type: Buf.readUint32(), // CARD_APPTYPE_* + app_state: Buf.readUint32(), // CARD_APPSTATE_* + perso_substate: Buf.readUint32(), // CARD_PERSOSUBSTATE_* aid: Buf.readString(), app_label: Buf.readString(), pin1_replaced: Buf.readUint32(), @@ -1700,13 +1700,13 @@ RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH() { this.sendDOMMessage({type: "signalstrengthchange", signalStrength: strength}); }; -RIL[REQUEST_REGISTRATION_STATE] = function REQUEST_REGISTRATION_STATE(length) { +RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length) { let state = Buf.readStringList(); - this._processRegistrationState(state); + this._processVoiceRegistrationState(state); }; -RIL[REQUEST_GPRS_REGISTRATION_STATE] = function REQUEST_GPRS_REGISTRATION_STATE(length) { +RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length) { let state = Buf.readStringList(); - this._processGPRSRegistrationState(state); + this._processDataRegistrationState(state); }; RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length) { let operator = Buf.readStringList(); @@ -1989,7 +1989,7 @@ RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RA RIL[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() { this.getCurrentCalls(); }; -RIL[UNSOLICITED_RESPONSE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_NETWORK_STATE_CHANGED() { +RIL[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() { if (DEBUG) debug("Network state changed, re-requesting phone state."); this.requestNetworkInfo(); }; From 962d8348616bfe90747b4f551376fb62ce9c65e9 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Tue, 20 Mar 2012 12:28:15 -0700 Subject: [PATCH 054/113] Bug 728886 - Part 2: Support ril.h v6 parcels. r=qDot DONTBUILD because NPOTB --- dom/system/gonk/RadioInterfaceLayer.js | 6 +- dom/system/gonk/ril_worker.js | 538 ++++++++++++++----------- 2 files changed, 314 insertions(+), 230 deletions(-) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 127225d42c8..261bfc05963 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -282,6 +282,9 @@ RadioInterfaceLayer.prototype = { case "siminfo": this.radioState.msisdn = message.msisdn; break; + case "error": + debug("Received error message: " + JSON.stringify(message)); + break; default: throw new Error("Don't know about this message type: " + message.type); } @@ -1083,7 +1086,8 @@ let RILNetworkInterface = { dataCallStateChanged: function dataCallStateChanged(cid, interfaceName, callState) { if (this.connecting && - callState == RIL.GECKO_NETWORK_STATE_CONNECTING) { + (callState == RIL.GECKO_NETWORK_STATE_CONNECTING || + callState == RIL.GECKO_NETWORK_STATE_CONNECTED)) { this.connecting = false; this.cid = cid; this.name = interfaceName; diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index ce9f7d15b4e..e399626244b 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -77,6 +77,9 @@ const PARCEL_SIZE_SIZE = UINT32_SIZE; let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false; let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false; +// This flag defaults to true since on RIL v6 and later, we get the +// version number via the UNSOLICITED_RIL_CONNECTED parcel. +let RILQUIRKS_V5_LEGACY = true; /** * This object contains helpers buffering incoming data & deconstructing it @@ -554,7 +557,7 @@ let RIL = { /** * One of the RADIO_STATE_* constants. */ - radioState: RADIO_STATE_UNAVAILABLE, + radioState: GECKO_RADIOSTATE_UNAVAILABLE, /** * ICC status. Keeps a reference of the data response to the @@ -651,6 +654,13 @@ let RIL = { RILQUIRKS_CALLSTATE_EXTRA_UINT32 = true; RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = true; } + if (model_id == "I9023" || model_id == "I9020") { + if (DEBUG) { + debug("Detected I9020/I9023, enabling " + + "RILQUIRKS_DATACALLSTATE_DOWN_IS_UP"); + } + RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = true; + } this.rilQuirksInitialized = true; }, @@ -836,6 +846,22 @@ let RIL = { Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE); }, + setNetworkSelectionAutomatic: function setNetworkSelectionAutomatic() { + Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC); + }, + + /** + * Set the preferred network type. + * + * @param network_type + * The network type. One of the PREFERRED_NETWORK_TYPE_* constants. + */ + setPreferredNetworkType: function setPreferredNetworkType(network_type) { + Buf.newParcel(REQUEST_SET_PREFERRED_NETWORK_TYPE); + Buf.writeUint32(network_type); + Buf.sendParcel(); + }, + /** * Request various states about the network. */ @@ -1168,68 +1194,50 @@ let RIL = { return; } - if ((this.radioState == RADIO_STATE_OFF) || - (this.radioState == RADIO_STATE_UNAVAILABLE) || - (this.radioState == RADIO_STATE_SIM_NOT_READY) || - (this.radioState == RADIO_STATE_RUIM_NOT_READY) || - (this.radioState == RADIO_STATE_NV_NOT_READY) || - (this.radioState == RADIO_STATE_NV_READY)) { - if (DEBUG) debug("ICC not ready"); - if (this.cardState == GECKO_CARDSTATE_NOT_READY) { + let app = iccStatus.apps[iccStatus.gsmUmtsSubscriptionAppIndex]; + if (!app) { + if (DEBUG) { + debug("Subscription application is not present in iccStatus."); + } + if (this.cardState == GECKO_CARDSTATE_ABSENT) { return; } - this.cardState = GECKO_CARDSTATE_NOT_READY; + this.cardState = GECKO_CARDSTATE_ABSENT; + this.operator = null; this.sendDOMMessage({type: "cardstatechange", cardState: this.cardState}); return; } - if ((this.radioState == RADIO_STATE_SIM_LOCKED_OR_ABSENT) || - (this.radioState == RADIO_STATE_SIM_READY) || - (this.radioState == RADIO_STATE_RUIM_LOCKED_OR_ABSENT) || - (this.radioState == RADIO_STATE_RUIM_READY)) { - let app = iccStatus.apps[iccStatus.gsmUmtsSubscriptionAppIndex]; - if (!app) { - if (DEBUG) { - debug("Subscription application is not present in iccStatus."); - } - if (this.cardState == GECKO_CARDSTATE_ABSENT) { - return; - } - this.cardState = GECKO_CARDSTATE_ABSENT; - this.operator = null; - this.sendDOMMessage({type: "cardstatechange", - cardState: this.cardState}); - return; - } - - let newCardState; - switch (app.app_state) { - case CARD_APPSTATE_PIN: - newCardState = GECKO_CARDSTATE_PIN_REQUIRED; - break; - case CARD_APPSTATE_PUK: - newCardState = GECKO_CARDSTATE_PUK_REQUIRED; - break; - case CARD_APPSTATE_SUBSCRIPTION_PERSO: - newCardState = GECKO_CARDSTATE_NETWORK_LOCKED; - break; - case CARD_APPSTATE_READY: - newCardState = GECKO_CARDSTATE_READY; - break; - case CARD_APPSTATE_UNKNOWN: - case CARD_APPSTATE_DETECTED: - default: - newCardState = GECKO_CARDSTATE_NOT_READY; - } - - if (this.cardState == newCardState) { - return; - } - this.cardState = newCardState; - this.sendDOMMessage({type: "cardstatechange", - cardState: this.cardState}); + let newCardState; + switch (app.app_state) { + case CARD_APPSTATE_PIN: + newCardState = GECKO_CARDSTATE_PIN_REQUIRED; + break; + case CARD_APPSTATE_PUK: + newCardState = GECKO_CARDSTATE_PUK_REQUIRED; + break; + case CARD_APPSTATE_SUBSCRIPTION_PERSO: + newCardState = GECKO_CARDSTATE_NETWORK_LOCKED; + break; + case CARD_APPSTATE_READY: + this.requestNetworkInfo(); + this.getSignalStrength(); + this.getMSISDN(); + newCardState = GECKO_CARDSTATE_READY; + break; + case CARD_APPSTATE_UNKNOWN: + case CARD_APPSTATE_DETECTED: + default: + newCardState = GECKO_CARDSTATE_NOT_READY; } + + if (this.cardState == newCardState) { + return; + } + this.cardState = newCardState; + this.sendDOMMessage({type: "cardstatechange", + cardState: this.cardState}); }, /** @@ -1282,6 +1290,10 @@ let RIL = { if (rs.regState != regState) { rs.regState = regState; stateChanged = true; + if (regState == NETWORK_CREG_STATE_REGISTERED_HOME || + regState == NETWORK_CREG_STATE_REGISTERED_ROAMING) { + RIL.getSMSCAddress(); + } } let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN); @@ -1386,6 +1398,72 @@ let RIL = { this.muted = Object.getOwnPropertyNames(this.currentCalls).length == 0; }, + _handleChangedCallState: function _handleChangedCallState(changedCall) { + let message = {type: "callStateChange", + call: {callIndex: changedCall.callIndex, + state: changedCall.state, + number: changedCall.number, + name: changedCall.name}}; + this.sendDOMMessage(message); + }, + + _handleDisconnectedCall: function _handleDisconnectedCall(disconnectedCall) { + let message = {type: "callDisconnected", + call: {callIndex: disconnectedCall.callIndex}}; + this.sendDOMMessage(message); + }, + + _processDataCallList: function _processDataCallList(datacalls) { + for each (let currentDataCall in this.currentDataCalls) { + let updatedDataCall; + if (datacalls) { + updatedDataCall = datacalls[currentDataCall.cid]; + delete datacalls[currentDataCall.cid]; + } + + if (!updatedDataCall) { + delete this.currentDataCalls[currentDataCall.callIndex]; + currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED; + this.sendDOMMessage({type: "datacallstatechange", + datacall: currentDataCall}); + continue; + } + + this._setDataCallGeckoState(updatedDataCall); + if (updatedDataCall.state != currentDataCall.state) { + currentDataCall.status = updatedDataCall.status; + currentDataCall.active = updatedDataCall.active; + currentDataCall.state = updatedDataCall.state; + this.sendDOMMessage({type: "datacallstatechange", + datacall: currentDataCall}); + } + } + + for each (let newDataCall in datacalls) { + this.currentDataCalls[newDataCall.cid] = newDataCall; + this._setDataCallGeckoState(newDataCall); + this.sendDOMMessage({type: "datacallstatechange", + datacall: newDataCall}); + } + }, + + _setDataCallGeckoState: function _setDataCallGeckoState(datacall) { + switch (datacall.active) { + case DATACALL_INACTIVE: + datacall.state = GECKO_NETWORK_STATE_DISCONNECTED; + break; + case DATACALL_ACTIVE_DOWN: + datacall.state = GECKO_NETWORK_STATE_SUSPENDED; + if (RILQUIRKS_DATACALLSTATE_DOWN_IS_UP) { + datacall.state = GECKO_NETWORK_STATE_CONNECTED; + } + break; + case DATACALL_ACTIVE_UP: + datacall.state = GECKO_NETWORK_STATE_CONNECTED; + break; + } + }, + /** * Helper for processing received multipart SMS. * @@ -1439,63 +1517,6 @@ let RIL = { return options; }, - _handleChangedCallState: function _handleChangedCallState(changedCall) { - let message = {type: "callStateChange", - call: {callIndex: changedCall.callIndex, - state: changedCall.state, - number: changedCall.number, - name: changedCall.name}}; - this.sendDOMMessage(message); - }, - - _handleDisconnectedCall: function _handleDisconnectedCall(disconnectedCall) { - let message = {type: "callDisconnected", - call: {callIndex: disconnectedCall.callIndex}}; - this.sendDOMMessage(message); - }, - - _processDataCallList: function _processDataCallList(datacalls) { - for each (let currentDataCall in this.currentDataCalls) { - let newDataCall; - if (datacalls) { - newDataCall = datacalls[currentDataCall.cid]; - delete datacalls[currentDataCall.cid]; - } - - if (newDataCall) { - switch (newDataCall.active) { - case DATACALL_INACTIVE: - newDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED; - break; - case DATACALL_ACTIVE_DOWN: - newDataCall.state = GECKO_NETWORK_STATE_SUSPENDED; - if (RILQUIRKS_DATACALLSTATE_DOWN_IS_UP) { - newDataCall.state = GECKO_NETWORK_STATE_CONNECTED; - } - break; - case DATACALL_ACTIVE_UP: - newDataCall.state = GECKO_NETWORK_STATE_CONNECTED; - break; - } - if (newDataCall.state != currentDataCall.state) { - currentDataCall.active = newDataCall.active; - currentDataCall.state = newDataCall.state; - this.sendDOMMessage({type: "datacallstatechange", - datacall: currentDataCall}); - } - } else { - delete this.currentDataCalls[currentDataCall.callIndex]; - currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED; - this.sendDOMMessage({type: "datacallstatechange", - datacall: currentDataCall}); - } - } - - for each (let datacall in datacalls) { - if (DEBUG) debug("Unexpected data call: " + JSON.stringify(datacall)); - } - }, - /** * Handle incoming messages from the main UI thread. * @@ -1569,19 +1590,21 @@ let RIL = { }; RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS() { - let iccStatus = { - cardState: Buf.readUint32(), // CARD_STATE_* - universalPINState: Buf.readUint32(), // PINSTATE_* - gsmUmtsSubscriptionAppIndex: Buf.readUint32(), - setCdmaSubscriptionAppIndex: Buf.readUint32(), - apps: [] - }; + let iccStatus = {}; + iccStatus.cardState = Buf.readUint32(); // CARD_STATE_* + iccStatus.universalPINState = Buf.readUint32(); // CARD_PINSTATE_* + iccStatus.gsmUmtsSubscriptionAppIndex = Buf.readUint32(); + iccStatus.cdmaSubscriptionAppIndex = Buf.readUint32(); + if (!RILQUIRKS_V5_LEGACY) { + iccStatus.imsSubscriptionAppIndex = Buf.readUint32(); + } let apps_length = Buf.readUint32(); if (apps_length > CARD_MAX_APPS) { apps_length = CARD_MAX_APPS; } + iccStatus.apps = []; for (let i = 0 ; i < apps_length ; i++) { iccStatus.apps.push({ app_type: Buf.readUint32(), // CARD_APPTYPE_* @@ -1673,35 +1696,56 @@ RIL[REQUEST_CONFERENCE] = null; RIL[REQUEST_UDUB] = null; RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = null; RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH() { - let signalStrength = Buf.readUint32(); + let obj = {}; + + // GSM + // Valid values are (0-31, 99) as defined in TS 27.007 8.5. + obj.gsmSignalStrength = Buf.readUint32(); // The SGS2 seems to compute the number of bars for us and expose those // instead of the actual signal strength. - let bars = signalStrength >> 8; - signalStrength = signalStrength & 0xff; - let strength = { + obj.bars = obj.gsmSignalStrength >> 8; //TODO remove this, see bug 729173 + obj.gsmSignalStrength = obj.gsmSignalStrength & 0xff; + // GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5. + obj.gsmBitErrorRate = Buf.readUint32(); + + // CDMA + // The CDMA RSSI value. + obj.cdmaDBM = Buf.readUint32(); + // The CDMA EC/IO. + obj.cdmaECIO = Buf.readUint32(); + // The EVDO RSSI value. + + // EVDO + obj.evdoDBM = Buf.readUint32(); + // The EVDO EC/IO. + obj.evdoECIO = Buf.readUint32(); + // Signal-to-noise ratio. Valid values are 0 to 8. + obj.evdoSNR = Buf.readUint32(); + + // LTE + if (!RILQUIRKS_V5_LEGACY) { // Valid values are (0-31, 99) as defined in TS 27.007 8.5. - gsmSignalStrength: signalStrength, - // Non-standard extension by the SGS2. - bars: bars, - // GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5. - gsmBitErrorRate: Buf.readUint32(), - // The CDMA RSSI value. - cdmaDBM: Buf.readUint32(), - // The CDMA EC/IO. - cdmaECIO: Buf.readUint32(), - // The EVDO RSSI value. - evdoDBM: Buf.readUint32(), - // The EVDO EC/IO. - evdoECIO: Buf.readUint32(), - // Valid values are 0-8. 8 is the highest signal to noise ratio - evdoSNR: Buf.readUint32() - }; - if (DEBUG) debug("Signal strength " + JSON.stringify(strength)); + obj.lteSignalStrength = Buf.readUint32(); + // Reference signal receive power in dBm, multiplied by -1. + // Valid values are 44 to 140. + obj.lteRSRP = Buf.readUint32(); + // Reference signal receive quality in dB, multiplied by -1. + // Valid values are 3 to 20. + obj.lteRSRQ = Buf.readUint32(); + // Signal-to-noise ratio for the reference signal. + // Valid values are -200 (20.0 dB) to +300 (30 dB). + obj.lteRSSNR = Buf.readUint32(); + // Channel Quality Indicator, valid values are 0 to 15. + obj.lteCQI = Buf.readUint32(); + } + + if (DEBUG) debug("Signal strength " + JSON.stringify(obj)); this.sendDOMMessage({type: "signalstrengthchange", - signalStrength: strength}); + signalStrength: obj}); }; RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length) { let state = Buf.readStringList(); +debug("voice registration state: " + state); this._processVoiceRegistrationState(state); }; RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length) { @@ -1710,6 +1754,7 @@ RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE( }; RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length) { let operator = Buf.readStringList(); + if (DEBUG) debug("Operator data: " + operator); if (operator.length < 3) { if (DEBUG) debug("Expected at least 3 strings for operator."); } @@ -1748,7 +1793,11 @@ RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) { this.sendDOMMessage(options); }; RIL[REQUEST_SEND_SMS_EXPECT_MORE] = null; -RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) { + +RIL.readSetupDataCall_v5 = function readSetupDataCall_v5(options) { + if (!options) { + options = {}; + } let [cid, ifname, ipaddr, dns, gw] = Buf.readStringList(); options.cid = cid; options.ifname = ifname; @@ -1757,13 +1806,21 @@ RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) options.gw = gw; options.active = DATACALL_ACTIVE_UNKNOWN; options.state = GECKO_NETWORK_STATE_CONNECTING; - this.currentDataCalls[options.cid] = options; - this.sendDOMMessage({type: "datacallstatechange", - datacall: options}); + return options; +}; - // Let's get the list of data calls to ensure we know whether it's active - // or not. - this.getDataCallList(); +RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) { + if (RILQUIRKS_V5_LEGACY) { + this.readSetupDataCall_v5(options); + this.currentDataCalls[options.cid] = options; + this.sendDOMMessage({type: "datacallstatechange", + datacall: options}); + // Let's get the list of data calls to ensure we know whether it's active + // or not. + this.getDataCallList(); + return; + } + this[REQUEST_DATA_CALL_LIST](length, options); }; RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) { switch (options.fileid) { @@ -1809,33 +1866,70 @@ RIL[REQUEST_DTMF_START] = null; RIL[REQUEST_DTMF_STOP] = null; RIL[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION() { this.basebandVersion = Buf.readString(); + if (DEBUG) debug("Baseband version: " + this.basebandVersion); }; RIL[REQUEST_SEPARATE_CONNECTION] = null; RIL[REQUEST_SET_MUTE] = null; RIL[REQUEST_GET_MUTE] = null; RIL[REQUEST_QUERY_CLIP] = null; RIL[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null; + +RIL.readDataCall_v5 = function readDataCall_v5() { + return { + cid: Buf.readUint32().toString(), + active: Buf.readUint32(), // DATACALL_ACTIVE_* + type: Buf.readString(), + apn: Buf.readString(), + address: Buf.readString() + }; +}; + +RIL.readDataCall_v6 = function readDataCall_v6(obj) { + if (!obj) { + obj = {}; + } + obj.status = Buf.readUint32(); // DATACALL_FAIL_* + obj.suggestedRetryTime = Buf.readUint32(); + obj.cid = Buf.readUint32().toString(); + obj.active = Buf.readUint32(); // DATACALL_ACTIVE_* + obj.type = Buf.readString(); + obj.ifname = Buf.readString(); + obj.ipaddr = Buf.readString(); + obj.dns = Buf.readString(); + obj.gw = Buf.readString(); + if (obj.dns) { + obj.dns = obj.dns.split(" "); + } + //TODO for now we only support one address and gateway + if (obj.ipaddr) { + obj.ipaddr = obj.ipaddr.split(" ")[0]; + } + if (obj.gw) { + obj.gw = obj.gw.split(" ")[0]; + } + return obj; +}; + RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length) { this.initRILQuirks(); - - let num = 0; - if (length) { - num = Buf.readUint32(); - } - if (!num) { + if (!length) { this._processDataCallList(null); return; } + let version = 0; + if (!RILQUIRKS_V5_LEGACY) { + version = Buf.readUint32(); + } + let num = num = Buf.readUint32(); let datacalls = {}; for (let i = 0; i < num; i++) { - let datacall = { - cid: Buf.readUint32().toString(), - active: Buf.readUint32(), - type: Buf.readString(), - apn: Buf.readString(), - address: Buf.readString() - }; + let datacall; + if (version < 6) { + datacall = this.readDataCall_v5(); + } else { + datacall = this.readDataCall_v6(); + } datacalls[datacall.cid] = datacall; } @@ -1860,7 +1954,7 @@ RIL[REQUEST_SET_PREFERRED_NETWORK_TYPE] = null; RIL[REQUEST_GET_PREFERRED_NETWORK_TYPE] = null; RIL[REQUEST_GET_NEIGHBORING_CELL_IDS] = null; RIL[REQUEST_SET_LOCATION_UPDATES] = null; -RIL[REQUEST_CDMA_SET_SUBSCRIPTION] = null; +RIL[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null; RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = null; RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = null; RIL[REQUEST_SET_TTY_MODE] = null; @@ -1899,92 +1993,66 @@ RIL[REQUEST_SET_SMSC_ADDRESS] = null; RIL[REQUEST_REPORT_SMS_MEMORY_STATUS] = null; RIL[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null; RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() { - let newState = Buf.readUint32(); + let radioState = Buf.readUint32(); + + let newState; + if (radioState == RADIO_STATE_UNAVAILABLE) { + newState = GECKO_RADIOSTATE_UNAVAILABLE; + } else if (radioState == RADIO_STATE_OFF) { + newState = GECKO_RADIOSTATE_OFF; + } else { + newState = GECKO_RADIOSTATE_READY; + } + if (DEBUG) { - debug("Radio state changed from " + this.radioState + " to " + newState); + debug("Radio state changed from '" + this.radioState + + "' to '" + newState + "'"); } if (this.radioState == newState) { - // No change in state, return. return; } - let gsm = newState == RADIO_STATE_SIM_NOT_READY || - newState == RADIO_STATE_SIM_LOCKED_OR_ABSENT || - newState == RADIO_STATE_SIM_READY; - let cdma = newState == RADIO_STATE_RUIM_NOT_READY || - newState == RADIO_STATE_RUIM_READY || - newState == RADIO_STATE_RUIM_LOCKED_OR_ABSENT || - newState == RADIO_STATE_NV_NOT_READY || - newState == RADIO_STATE_NV_READY; + // TODO hardcoded for now (see bug 726098) + let cdma = false; - // Figure out state transitions and send out more RIL requests as necessary - // as well as events to the main thread. - - if (this.radioState == RADIO_STATE_UNAVAILABLE && - newState != RADIO_STATE_UNAVAILABLE) { + if (this.radioState == GECKO_RADIOSTATE_UNAVAILABLE && + newState != GECKO_RADIOSTATE_UNAVAILABLE) { // The radio became available, let's get its info. - if (gsm) { + if (cdma) { + this.getDeviceIdentity(); + } else { this.getIMEI(); this.getIMEISV(); } - if (cdma) { - this.getDeviceIdentity(); - } this.getBasebandVersion(); - this.setScreenState(true); - this.sendDOMMessage({ - type: "radiostatechange", - radioState: (newState == RADIO_STATE_OFF) ? - GECKO_RADIOSTATE_OFF : GECKO_RADIOSTATE_READY - }); //XXX TODO For now, just turn the radio on if it's off. for the real // deal we probably want to do the opposite: start with a known state // when we boot up and let the UI layer control the radio power. - if (newState == RADIO_STATE_OFF) { + if (newState == GECKO_RADIOSTATE_OFF) { this.setRadioPower(true); } } - if (newState == RADIO_STATE_UNAVAILABLE) { - // The radio is no longer available, we need to deal with any - // remaining pending requests. - //TODO do that - this.sendDOMMessage({type: "radiostatechange", - radioState: GECKO_RADIOSTATE_UNAVAILABLE}); - } - - if (newState == RADIO_STATE_SIM_READY || - newState == RADIO_STATE_RUIM_READY || - newState == RADIO_STATE_NV_READY) { - // The ICC has become available. Get all the things. - this.getICCStatus(); - this.requestNetworkInfo(); - this.getSignalStrength(); - this.getSMSCAddress(); - this.getMSISDN(); - this.sendDOMMessage({type: "cardstatechange", - cardState: GECKO_CARDSTATE_READY}); - } - if (newState == RADIO_STATE_SIM_LOCKED_OR_ABSENT || - newState == RADIO_STATE_RUIM_LOCKED_OR_ABSENT) { - this.getICCStatus(); - this.sendDOMMessage({type: "cardstatechange", - cardState: GECKO_CARDSTATE_UNAVAILABLE}); - } - - let wasOn = this.radioState != RADIO_STATE_OFF && - this.radioState != RADIO_STATE_UNAVAILABLE; - let isOn = newState != RADIO_STATE_OFF && - newState != RADIO_STATE_UNAVAILABLE; - if (!wasOn && isOn) { - //TODO - } - if (wasOn && !isOn) { - //TODO - } - this.radioState = newState; + this.sendDOMMessage({ + type: "radiostatechange", + radioState: newState + }); + + // If the radio is up and on, so let's query the card state. + // On older RILs only if the card is actually ready, though. + if (radioState == RADIO_STATE_UNAVAILABLE || + radioState == RADIO_STATE_OFF) { + return; + } + if (RILQUIRKS_V5_LEGACY && + (radioState == RADIO_STATE_SIM_NOT_READY || + radioState == RADIO_STATE_RUIM_NOT_READY || + radioState == RADIO_STATE_NV_NOT_READY)) { + return; + } + this.getICCStatus(); }; RIL[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() { this.getCurrentCalls(); @@ -2086,8 +2154,12 @@ RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() RIL[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH() { this[REQUEST_SIGNAL_STRENGTH](); }; -RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) { - this.getDataCallList(); +RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length, options) { + if (RILQUIRKS_V5_LEGACY) { + this.getDataCallList(); + return; + } + this[REQUEST_GET_DATA_CALL_LIST](length, options); }; RIL[UNSOLICITED_SUPP_SVC_NOTIFICATION] = null; RIL[UNSOLICITED_STK_SESSION_END] = null; @@ -2124,6 +2196,14 @@ RIL[UNSOLICITED_CDMA_INFO_REC] = null; RIL[UNSOLICITED_OEM_HOOK_RAW] = null; RIL[UNSOLICITED_RINGBACK_TONE] = null; RIL[UNSOLICITED_RESEND_INCALL_MUTE] = null; +RIL[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length, options) { + let version = Buf.readUint32List()[0]; + RILQUIRKS_V5_LEGACY = (version < 5); + if (DEBUG) { + debug("Detected RIL version " + version); + debug("RILQUIRKS_V5_LEGACY is " + RILQUIRKS_V5_LEGACY); + } +}; /** From ed3aecfba274b9169e321ee74dde83bb57e03c1a Mon Sep 17 00:00:00 2001 From: Armen Zambrano Gasparnian Date: Tue, 27 Mar 2012 17:16:48 -0400 Subject: [PATCH 055/113] Bug 739768. We fixed the talos.zip issue with a symlink but let's be cut and clear to which talos.zip is the good one. DONTBUILD. r=jhammel --- testing/talos/talos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 814a3937e3b..fcda8065feb 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -1,6 +1,6 @@ { "talos.zip": { - "url": "http://build.mozilla.org/talos/zips/talos.bug739345.c6013a2f09ce.zip", + "url": "http://build.mozilla.org/talos/zips/talos.bug739768.eb99eb78e42c.zip", "path": "" } } From d705a99716ff3200bed1cc555f0040a374e9fd78 Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Mon, 26 Mar 2012 11:50:30 +0200 Subject: [PATCH 056/113] Bug 737758: part 1: Propagate mouse wheel event origin from ESM [r=roc] --- content/base/src/nsGkAtomList.h | 3 ++- content/events/src/nsEventStateManager.cpp | 9 +++++---- content/events/src/nsEventStateManager.h | 3 ++- layout/generic/nsGfxScrollFrame.cpp | 22 ++++++++++++++++------ layout/generic/nsGfxScrollFrame.h | 10 +++++----- layout/generic/nsIScrollableFrame.h | 2 +- modules/libpref/src/init/all.js | 7 +++++-- 7 files changed, 36 insertions(+), 20 deletions(-) diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 8731b840261..cc7576d706c 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1935,7 +1935,8 @@ GK_ATOM(VolumeUp, "VolumeUp") GK_ATOM(VolumeDown, "VolumeDown") GK_ATOM(Menu, "Menu") -// Smooth scroll profiles +// Smooth scroll events origins +GK_ATOM(mouseWheel, "mouseWheel") // For discrete wheel events (e.g. not OSX magic mouse) GK_ATOM(pixels, "pixels") GK_ATOM(lines, "lines") GK_ATOM(pages, "pages") diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 2143c8d266b..0a76b56f442 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2695,7 +2695,8 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame, nsMouseScrollEvent* aMouseEvent, nsIScrollableFrame::ScrollUnit aScrollQuantity, bool aAllowScrollSpeedOverride, - nsQueryContentEvent* aQueryEvent) + nsQueryContentEvent* aQueryEvent, + nsIAtom *aOrigin) { nsIScrollableFrame* frameToScroll = nsnull; nsIFrame* scrollFrame = aTargetFrame; @@ -2857,7 +2858,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame, nsIntPoint overflow; frameToScroll->ScrollBy(nsIntPoint(scrollX, scrollY), aScrollQuantity, - mode, &overflow); + mode, &overflow, aOrigin); aMouseEvent->scrollOverflow = isHorizontal ? overflow.x : overflow.y; return NS_OK; } @@ -2867,7 +2868,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame, aTargetFrame->PresContext()->FrameManager()->GetRootFrame()); if (newFrame) return DoScrollText(newFrame, aMouseEvent, aScrollQuantity, - aAllowScrollSpeedOverride, aQueryEvent); + aAllowScrollSpeedOverride, aQueryEvent, aOrigin); } aMouseEvent->scrollOverflow = numLines; @@ -3213,7 +3214,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, switch (action) { case MOUSE_SCROLL_N_LINES: DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::LINES, - useSysNumLines); + useSysNumLines, nsnull, nsGkAtoms::mouseWheel); break; case MOUSE_SCROLL_PAGE: diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index f831f587205..aec9036d0da 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -353,7 +353,8 @@ protected: nsMouseScrollEvent* aMouseEvent, nsIScrollableFrame::ScrollUnit aScrollQuantity, bool aAllowScrollSpeedOverride, - nsQueryContentEvent* aQueryEvent = nsnull); + nsQueryContentEvent* aQueryEvent = nsnull, + nsIAtom *aOrigin = nsnull); void DoScrollHistory(PRInt32 direction); void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment); nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index fc4a3555d6a..ba963825b81 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2322,26 +2322,36 @@ void nsGfxScrollFrameInner::ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit, nsIScrollableFrame::ScrollMode aMode, - nsIntPoint* aOverflow) + nsIntPoint* aOverflow, + nsIAtom *aOrigin) { nsSize deltaMultiplier; - nsCOMPtr aProfile = nsGkAtoms::other; + if (!aOrigin){ + aOrigin = nsGkAtoms::other; + } + bool isGenericOrigin = (aOrigin == nsGkAtoms::other); switch (aUnit) { case nsIScrollableFrame::DEVICE_PIXELS: { nscoord appUnitsPerDevPixel = mOuter->PresContext()->AppUnitsPerDevPixel(); deltaMultiplier = nsSize(appUnitsPerDevPixel, appUnitsPerDevPixel); - aProfile = nsGkAtoms::pixels; + if (isGenericOrigin){ + aOrigin = nsGkAtoms::pixels; + } break; } case nsIScrollableFrame::LINES: { deltaMultiplier = GetLineScrollAmount(); - aProfile = nsGkAtoms::lines; + if (isGenericOrigin){ + aOrigin = nsGkAtoms::lines; + } break; } case nsIScrollableFrame::PAGES: { deltaMultiplier = GetPageScrollAmount(); - aProfile = nsGkAtoms::pages; + if (isGenericOrigin){ + aOrigin = nsGkAtoms::pages; + } break; } case nsIScrollableFrame::WHOLE: { @@ -2361,7 +2371,7 @@ nsGfxScrollFrameInner::ScrollBy(nsIntPoint aDelta, nsPoint newPos = mDestination + nsPoint(aDelta.x*deltaMultiplier.width, aDelta.y*deltaMultiplier.height); - ScrollToWithSmoothnessProfile(newPos, aMode, aProfile); + ScrollToWithSmoothnessProfile(newPos, aMode, aOrigin); if (aOverflow) { nsPoint clampAmount = mDestination - newPos; diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 9f7520264de..08323f5c6e3 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -186,7 +186,7 @@ public: void ScrollToImpl(nsPoint aScrollPosition); void ScrollVisual(nsPoint aOldScrolledFramePosition); void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit, - nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow); + nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom *aOrigin = nsnull); void ScrollToRestoredPosition(); nsSize GetLineScrollAmount() const; nsSize GetPageScrollAmount() const; @@ -490,8 +490,8 @@ public: mInner.ScrollTo(aScrollPosition, aMode); } virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, - nsIntPoint* aOverflow) { - mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow); + nsIntPoint* aOverflow, nsIAtom *aOrigin = nsnull) { + mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin); } virtual void ScrollToRestoredPosition() { mInner.ScrollToRestoredPosition(); @@ -728,8 +728,8 @@ public: mInner.ScrollTo(aScrollPosition, aMode); } virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, - nsIntPoint* aOverflow) { - mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow); + nsIntPoint* aOverflow, nsIAtom *aOrigin = nsnull) { + mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin); } virtual void ScrollToRestoredPosition() { mInner.ScrollToRestoredPosition(); diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 8e33ff48f50..028e3739e44 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -165,7 +165,7 @@ public: * values are in device pixels. */ virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, - nsIntPoint* aOverflow = nsnull) = 0; + nsIntPoint* aOverflow = nsnull, nsIAtom *aOrigin = nsnull) = 0; /** * This tells the scroll frame to try scrolling to the scroll * position that was restored from the history. This must be called diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index d5cf699133a..2f7ad89a853 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -1362,8 +1362,10 @@ pref("mousewheel.horizscroll.withmetakey.sysnumlines",true); // Scrollbars: Clicking scrollbars arrows, clicking scrollbars tracks // Note: Currently OS X trackpad and magic mouse don't use our smooth scrolling // Note: These are relevant only when "general.smoothScroll" is enabled -pref("general.smoothScroll.pixels.durationMinMS", 200); -pref("general.smoothScroll.pixels.durationMaxMS", 400); +pref("general.smoothScroll.mouseWheel.durationMinMS", 200); +pref("general.smoothScroll.mouseWheel.durationMaxMS", 400); +pref("general.smoothScroll.pixels.durationMinMS", 150); +pref("general.smoothScroll.pixels.durationMaxMS", 150); pref("general.smoothScroll.lines.durationMinMS", 150); pref("general.smoothScroll.lines.durationMaxMS", 150); pref("general.smoothScroll.pages.durationMinMS", 150); @@ -1372,6 +1374,7 @@ pref("general.smoothScroll.scrollbars.durationMinMS", 150); pref("general.smoothScroll.scrollbars.durationMaxMS", 150); pref("general.smoothScroll.other.durationMinMS", 150); pref("general.smoothScroll.other.durationMaxMS", 150); +pref("general.smoothScroll.mouseWheel", true); pref("general.smoothScroll.pixels", true); pref("general.smoothScroll.lines", true); pref("general.smoothScroll.pages", true); From 3605c7f03f60cc444d12d9c7390aabbd8f11afe1 Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Mon, 26 Mar 2012 13:34:10 +0200 Subject: [PATCH 057/113] Bug 737758: Part 2: Address Windows abnormality (identify _faked_ pixel scrolls) [r=jmathies] --- content/events/src/nsEventStateManager.cpp | 7 +++++-- widget/nsGUIEvent.h | 11 ++++++++--- widget/windows/WinMouseScrollHandler.cpp | 3 +++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 0a76b56f442..e68fe2ec2da 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -3223,8 +3223,11 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, break; case MOUSE_SCROLL_PIXELS: - DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS, - false); + { + bool fromLines = msEvent->scrollFlags & nsMouseScrollEvent::kFromLines; + DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS, + false, nsnull, (fromLines ? nsGkAtoms::mouseWheel : nsnull)); + } break; case MOUSE_SCROLL_HISTORY: diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 6d0c93d277c..688c2cbad06 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1284,9 +1284,14 @@ public: kIsMomentum = 1 << 6, // Marks scroll events that aren't controlled by the // user but fire automatically as the result of a // "momentum" scroll. - kAllowSmoothScroll = 1 << 7 // Allow smooth scroll for the pixel scroll - // event. - }; + kAllowSmoothScroll = 1 << 7, // Allow smooth scroll for the pixel scroll + // event. + kFromLines = 1 << 8 // For a pixels scroll event, indicates that it + // originated from a lines scroll event. + // (Only used on windows which generates "faked" + // pixel scroll events even for simple mouse wheel + // scroll) +}; nsMouseScrollEvent(bool isTrusted, PRUint32 msg, nsIWidget *w) : nsMouseEvent_base(isTrusted, msg, w, NS_MOUSE_SCROLL_EVENT), diff --git a/widget/windows/WinMouseScrollHandler.cpp b/widget/windows/WinMouseScrollHandler.cpp index 93ffdb72704..b3123311b23 100644 --- a/widget/windows/WinMouseScrollHandler.cpp +++ b/widget/windows/WinMouseScrollHandler.cpp @@ -698,12 +698,14 @@ MouseScrollHandler::HandleMouseWheelMessage(nsWindow* aWindow, // Grab the widget, it might be destroyed by a DOM event handler. nsRefPtr kungFuDethGrip(aWindow); + bool fromLines = false; nsMouseScrollEvent scrollEvent(true, NS_MOUSE_SCROLL, aWindow); if (mLastEventInfo.InitMouseScrollEvent(aWindow, scrollEvent, scrollTargetInfo, modKeyState)) { PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, ("MouseScroll::HandleMouseWheelMessage: dispatching " "NS_MOUSE_SCROLL event")); + fromLines = true; DispatchEvent(aWindow, scrollEvent); if (aWindow->Destroyed()) { PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, @@ -727,6 +729,7 @@ MouseScrollHandler::HandleMouseWheelMessage(nsWindow* aWindow, PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, ("MouseScroll::HandleMouseWheelMessage: dispatching " "NS_MOUSE_PIXEL_SCROLL event")); + pixelEvent.scrollFlags |= fromLines ? nsMouseScrollEvent::kFromLines : 0; DispatchEvent(aWindow, pixelEvent); if (aWindow->Destroyed()) { PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, From 11eac7e423c6732634bb9acf1f3adcda2f3433c4 Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Mon, 26 Mar 2012 11:53:45 +0200 Subject: [PATCH 058/113] Bug 737758: part 3: Cleanups and semantic consistency [r=roc] --- layout/generic/nsGfxScrollFrame.cpp | 114 ++++++++++++++-------------- layout/generic/nsGfxScrollFrame.h | 9 +-- modules/libpref/src/init/all.js | 3 +- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index ba963825b81..57310d47512 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1330,7 +1330,7 @@ public: void InitSmoothScroll(TimeStamp aTime, nsPoint aCurrentPos, nsSize aCurrentVelocity, nsPoint aDestination, - nsIAtom *aProfile); + nsIAtom *aOrigin); bool IsFinished(TimeStamp aTime) { return aTime > mStartTime + mDuration; // XXX or if we've hit the wall @@ -1348,17 +1348,15 @@ public: bool mIsFirstIteration; // Cached Preferences values to avoid re-reading them when extending an existing - // animation for the same profile (can be as frequent as every 10(!)ms for a quick - // roll of the mouse wheel). - // These values are minimum and maximum animation duration per profile, is smoothness - // enabled for that profile, and a global ratio which defines how longer is the - // animation's duration compared to the average recent events intervals (such - // that for a relatively consistent events rate, the next event arrives before - // current animation ends) - nsIAtom* mProfile; - PRInt32 mProfileMinMS; - PRInt32 mProfileMaxMS; - bool mIsProfileSmoothnessEnabled; + // animation for the same event origin (can be as frequent as every 10(!)ms for + // a quick roll of the mouse wheel). + // These values are minimum and maximum animation duration per event origin, + // and a global ratio which defines how longer is the animation's duration + // compared to the average recent events intervals (such that for a relatively + // consistent events rate, the next event arrives before current animation ends) + nsCOMPtr mOrigin; + PRInt32 mOriginMinMS; + PRInt32 mOriginMaxMS; double mIntervalRatio; TimeDuration mDuration; @@ -1383,7 +1381,7 @@ protected: nscoord aCurrentPos, nscoord aCurrentVelocity, nscoord aDestination); - void InitDuration(nsIAtom *aProfile); + void InitDuration(nsIAtom *aOrigin); }; nsPoint @@ -1404,56 +1402,58 @@ nsGfxScrollFrameInner::AsyncScroll::VelocityAt(TimeStamp aTime) { } /* - * Calculate/update mDuration, possibly dynamically according to events rate and smoothness profile. + * Calculate/update mDuration, possibly dynamically according to events rate and event origin. * (also maintain previous timestamps - which are only used here). */ void -nsGfxScrollFrameInner::AsyncScroll::InitDuration(nsIAtom *aProfile) { - // Read preferences only on first iteration or for a different profile. - if (mIsFirstIteration || aProfile != mProfile) { - mProfile = aProfile; - mProfileMinMS = mProfileMaxMS = 0; - mIsProfileSmoothnessEnabled = false; +nsGfxScrollFrameInner::AsyncScroll::InitDuration(nsIAtom *aOrigin) { + if (!aOrigin){ + aOrigin = nsGkAtoms::other; + } + + // Read preferences only on first iteration or for a different event origin. + if (mIsFirstIteration || aOrigin != mOrigin) { + mOrigin = aOrigin; + mOriginMinMS = mOriginMaxMS = 0; + bool isOriginSmoothnessEnabled = false; mIntervalRatio = 1; // Default values for all preferences are defined in all.js - if (aProfile) { - static const PRInt32 kDefaultMinMS = 150, kDefaultMaxMS = 150; - static const bool kDefaultIsSmoothEnabled = true; + static const PRInt32 kDefaultMinMS = 150, kDefaultMaxMS = 150; + static const bool kDefaultIsSmoothEnabled = true; - nsCAutoString profileName; - aProfile->ToUTF8String(profileName); - nsCAutoString prefBase = NS_LITERAL_CSTRING("general.smoothScroll.") + profileName; + nsCAutoString originName; + aOrigin->ToUTF8String(originName); + nsCAutoString prefBase = NS_LITERAL_CSTRING("general.smoothScroll.") + originName; - mIsProfileSmoothnessEnabled = Preferences::GetBool(prefBase.get(), kDefaultIsSmoothEnabled); - if (mIsProfileSmoothnessEnabled) { - nsCAutoString prefMin = prefBase + NS_LITERAL_CSTRING(".durationMinMS"); - nsCAutoString prefMax = prefBase + NS_LITERAL_CSTRING(".durationMaxMS"); - mProfileMinMS = Preferences::GetInt(prefMin.get(), kDefaultMinMS); - mProfileMaxMS = Preferences::GetInt(prefMax.get(), kDefaultMaxMS); + isOriginSmoothnessEnabled = Preferences::GetBool(prefBase.get(), kDefaultIsSmoothEnabled); + if (isOriginSmoothnessEnabled) { + nsCAutoString prefMin = prefBase + NS_LITERAL_CSTRING(".durationMinMS"); + nsCAutoString prefMax = prefBase + NS_LITERAL_CSTRING(".durationMaxMS"); + mOriginMinMS = Preferences::GetInt(prefMin.get(), kDefaultMinMS); + mOriginMaxMS = Preferences::GetInt(prefMax.get(), kDefaultMaxMS); - static const PRInt32 kSmoothScrollMaxAllowedAnimationDurationMS = 10000; - mProfileMinMS = clamped(mProfileMinMS, 0, kSmoothScrollMaxAllowedAnimationDurationMS); - mProfileMaxMS = clamped(mProfileMaxMS, mProfileMinMS, kSmoothScrollMaxAllowedAnimationDurationMS); - } - - // Keep the animation duration longer than the average event intervals - // (to "connect" consecutive scroll animations before the scroll comes to a stop). - static const double kDefaultDurationToIntervalRatio = 2; // Duplicated at all.js - mIntervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio", - kDefaultDurationToIntervalRatio * 100) / 100.0; - - // Duration should be at least as long as the intervals -> ratio is at least 1 - mIntervalRatio = NS_MAX(1.0, mIntervalRatio); + static const PRInt32 kSmoothScrollMaxAllowedAnimationDurationMS = 10000; + mOriginMaxMS = clamped(mOriginMaxMS, 0, kSmoothScrollMaxAllowedAnimationDurationMS); + mOriginMinMS = clamped(mOriginMinMS, 0, mOriginMaxMS); } + // Keep the animation duration longer than the average event intervals + // (to "connect" consecutive scroll animations before the scroll comes to a stop). + static const double kDefaultDurationToIntervalRatio = 2; // Duplicated at all.js + mIntervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio", + kDefaultDurationToIntervalRatio * 100) / 100.0; + + // Duration should be at least as long as the intervals -> ratio is at least 1 + mIntervalRatio = NS_MAX(1.0, mIntervalRatio); + if (mIsFirstIteration) { // Starting a new scroll (i.e. not when extending an existing scroll animation), // create imaginary prev timestamps with maximum relevant intervals between them. mIsFirstIteration = false; // Longest relevant interval (which results in maximum duration) - TimeDuration maxDelta = TimeDuration::FromMilliseconds(mProfileMaxMS / mIntervalRatio); + TimeDuration maxDelta = TimeDuration::FromMilliseconds(mOriginMaxMS / mIntervalRatio); mPrevStartTime[0] = mStartTime - maxDelta; mPrevStartTime[1] = mPrevStartTime[0] - maxDelta; mPrevStartTime[2] = mPrevStartTime[1] - maxDelta; @@ -1471,7 +1471,7 @@ nsGfxScrollFrameInner::AsyncScroll::InitDuration(nsIAtom *aProfile) { // it's easier to follow, but reduce the duration to make it feel more snappy when // scrolling quickly. To reduce fluctuations of the duration, we average event // intervals using the recent 4 timestamps (now + three prev -> 3 intervals). - PRInt32 durationMS = clamped(eventsDeltaMs * mIntervalRatio, mProfileMinMS, mProfileMaxMS); + PRInt32 durationMS = clamped(eventsDeltaMs * mIntervalRatio, mOriginMinMS, mOriginMaxMS); mDuration = TimeDuration::FromMilliseconds(durationMS); } @@ -1481,11 +1481,11 @@ nsGfxScrollFrameInner::AsyncScroll::InitSmoothScroll(TimeStamp aTime, nsPoint aCurrentPos, nsSize aCurrentVelocity, nsPoint aDestination, - nsIAtom *aProfile) { + nsIAtom *aOrigin) { mStartTime = aTime; mStartPos = aCurrentPos; mDestination = aDestination; - InitDuration(aProfile); + InitDuration(aOrigin); InitTimingFunction(mTimingFunctionX, mStartPos.x, aCurrentVelocity.width, aDestination.x); InitTimingFunction(mTimingFunctionY, mStartPos.y, aCurrentVelocity.height, aDestination.y); } @@ -1653,9 +1653,9 @@ nsGfxScrollFrameInner::AsyncScrollCallback(nsITimer *aTimer, void* anInstance) * based on the setting of the smoothness scroll pref */ void -nsGfxScrollFrameInner::ScrollToWithSmoothnessProfile(nsPoint aScrollPosition, - nsIScrollableFrame::ScrollMode aMode, - nsIAtom *aProfile) +nsGfxScrollFrameInner::ScrollToWithOrigin(nsPoint aScrollPosition, + nsIScrollableFrame::ScrollMode aMode, + nsIAtom *aOrigin) { if (ShouldClampScrollPosition()) { mDestination = ClampScrollPosition(aScrollPosition); @@ -1707,7 +1707,7 @@ nsGfxScrollFrameInner::ScrollToWithSmoothnessProfile(nsPoint aScrollPosition, if (isSmoothScroll) { mAsyncScroll->InitSmoothScroll(now, currentPosition, currentVelocity, - mDestination, aProfile); + mDestination, aOrigin); } } @@ -2371,7 +2371,7 @@ nsGfxScrollFrameInner::ScrollBy(nsIntPoint aDelta, nsPoint newPos = mDestination + nsPoint(aDelta.x*deltaMultiplier.width, aDelta.y*deltaMultiplier.height); - ScrollToWithSmoothnessProfile(newPos, aMode, aOrigin); + ScrollToWithOrigin(newPos, aMode, aOrigin); if (aOverflow) { nsPoint clampAmount = mDestination - newPos; @@ -2787,9 +2787,9 @@ void nsGfxScrollFrameInner::CurPosAttributeChanged(nsIContent* aContent) // was. UpdateScrollbarPosition(); } - ScrollToWithSmoothnessProfile(dest, - isSmooth ? nsIScrollableFrame::SMOOTH : nsIScrollableFrame::INSTANT, - nsGkAtoms::scrollbars); + ScrollToWithOrigin(dest, + isSmooth ? nsIScrollableFrame::SMOOTH : nsIScrollableFrame::INSTANT, + nsGkAtoms::scrollbars); } /* ============= Scroll events ========== */ diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 08323f5c6e3..75a551f0c02 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -181,7 +181,7 @@ public: nsPoint ClampScrollPosition(const nsPoint& aPt) const; static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance); void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode) { - ScrollToWithSmoothnessProfile(aScrollPosition, aMode, nsGkAtoms::other); + ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other); }; void ScrollToImpl(nsPoint aScrollPosition); void ScrollVisual(nsPoint aOldScrolledFramePosition); @@ -344,10 +344,9 @@ public: bool mShouldBuildLayer:1; protected: - void ScrollToWithSmoothnessProfile(nsPoint aScrollPosition, - nsIScrollableFrame::ScrollMode aMode, - nsIAtom *aProfile); // nsnull indicates no smooth scroll - + void ScrollToWithOrigin(nsPoint aScrollPosition, + nsIScrollableFrame::ScrollMode aMode, + nsIAtom *aOrigin); // nsnull indicates "other" origin }; /** diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 2f7ad89a853..c92bc360ede 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -1356,7 +1356,7 @@ pref("mousewheel.horizscroll.withmetakey.sysnumlines",true); // These define the smooth scroll behavior (min ms, max ms) for different triggers // Some triggers: -// Pixels: Discrete mouse wheel events, Synaptics touchpads on windows (generate wheel events) +// mouseWheel: Discrete mouse wheel events, Synaptics touchpads on windows (generate wheel events) // Lines: Up/Down/Left/Right KB arrows // Pages: Page up/down, Space // Scrollbars: Clicking scrollbars arrows, clicking scrollbars tracks @@ -1374,6 +1374,7 @@ pref("general.smoothScroll.scrollbars.durationMinMS", 150); pref("general.smoothScroll.scrollbars.durationMaxMS", 150); pref("general.smoothScroll.other.durationMinMS", 150); pref("general.smoothScroll.other.durationMaxMS", 150); +// Enable disable smooth scrolling for different triggers (when "general.smoothScroll" is enabled) pref("general.smoothScroll.mouseWheel", true); pref("general.smoothScroll.pixels", true); pref("general.smoothScroll.lines", true); From 6657f6f4d3774b2aa0c4340fbc12164d16d59862 Mon Sep 17 00:00:00 2001 From: Sriram Ramasubramanian Date: Tue, 27 Mar 2012 14:31:29 -0700 Subject: [PATCH 059/113] Bug 736296: Avoid managed query while loading top sites. [r=mfinkle] --- mobile/android/base/AboutHomeContent.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/AboutHomeContent.java b/mobile/android/base/AboutHomeContent.java index f478b797c52..5dfc3e14506 100644 --- a/mobile/android/base/AboutHomeContent.java +++ b/mobile/android/base/AboutHomeContent.java @@ -250,6 +250,9 @@ public class AboutHomeContent extends ScrollView mAccountManager.removeOnAccountsUpdatedListener(mAccountListener); mAccountListener = null; } + + if (mCursor != null && !mCursor.isClosed()) + mCursor.close(); } void setLastTabsVisibility(boolean visible) { @@ -330,9 +333,6 @@ public class AboutHomeContent extends ScrollView } private void loadTopSites(final Activity activity) { - if (mCursor != null) - activity.stopManagingCursor(mCursor); - // Ensure we initialize GeckoApp's startup mode in // background thread before we use it when updating // the top sites section layout in main thread. @@ -344,7 +344,6 @@ public class AboutHomeContent extends ScrollView ContentResolver resolver = GeckoApp.mAppContext.getContentResolver(); mCursor = BrowserDB.getTopSites(resolver, NUMBER_OF_TOP_SITES_PORTRAIT); - activity.startManagingCursor(mCursor); GeckoApp.mAppContext.mMainHandler.post(new Runnable() { public void run() { From 4b37cde6fc5823bf306b47c05c901ba35c14a5e7 Mon Sep 17 00:00:00 2001 From: Margaret Leibovic Date: Tue, 27 Mar 2012 14:36:20 -0700 Subject: [PATCH 060/113] Bug 736278 - (1/2) Add support for checkbox in doorhanger message. r=mfinkle --- mobile/android/base/DoorHanger.java | 27 ++++++++++++++++++- .../base/resources/layout/doorhanger.xml | 6 +++++ mobile/android/chrome/content/browser.js | 9 +++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/mobile/android/base/DoorHanger.java b/mobile/android/base/DoorHanger.java index 372fba2f090..2f4864aa12b 100644 --- a/mobile/android/base/DoorHanger.java +++ b/mobile/android/base/DoorHanger.java @@ -43,9 +43,11 @@ import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.style.ForegroundColorSpan; import android.text.style.URLSpan; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; +import android.widget.CheckBox; import android.widget.LinearLayout; import android.widget.TextView; @@ -53,6 +55,8 @@ import org.json.JSONObject; import org.json.JSONException; public class DoorHanger extends LinearLayout implements Button.OnClickListener { + private static final String LOGTAG = "DoorHanger"; + private Context mContext; private LinearLayout mChoicesLayout; private TextView mTextView; @@ -61,6 +65,9 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener { // value used to identify the notification private String mValue; + // Optional checkbox added underneath message text + private CheckBox mCheckBox; + static private LayoutInflater mInflater; private int mPersistence = 0; @@ -99,7 +106,18 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener { } public void onClick(View v) { - GeckoEvent e = GeckoEvent.createBroadcastEvent("Doorhanger:Reply", v.getTag().toString()); + JSONObject response = new JSONObject(); + try { + response.put("callback", v.getTag().toString()); + + // If the checkbox is being used, pass its value + if (mCheckBox != null) + response.put("checked", mCheckBox.isChecked()); + } catch (JSONException ex) { + Log.e(LOGTAG, "Error creating onClick response: " + ex); + } + + GeckoEvent e = GeckoEvent.createBroadcastEvent("Doorhanger:Reply", response.toString()); GeckoAppShell.sendEventToGecko(e); mTab.removeDoorHanger(mValue); @@ -166,6 +184,13 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener { mTextView.setText(titleWithLink); mTextView.setMovementMethod(LinkMovementMethod.getInstance()); } catch (JSONException e) { } + + try { + String checkBoxText = options.getString("checkbox"); + mCheckBox = (CheckBox) findViewById(R.id.doorhanger_checkbox); + mCheckBox.setText(checkBoxText); + mCheckBox.setVisibility(VISIBLE); + } catch (JSONException e) { } } // This method checks with persistence and timeout options to see if diff --git a/mobile/android/base/resources/layout/doorhanger.xml b/mobile/android/base/resources/layout/doorhanger.xml index 9df165dcdf4..1f851610547 100644 --- a/mobile/android/base/resources/layout/doorhanger.xml +++ b/mobile/android/base/resources/layout/doorhanger.xml @@ -9,6 +9,12 @@ android:textColorLink="@color/doorhanger_link" android:padding="10dp"/> + + Date: Tue, 27 Mar 2012 14:36:25 -0700 Subject: [PATCH 061/113] Bug 736278 - Add always/never permissions for click-to-play plugins. r=mfinkle --- mobile/android/chrome/content/browser.js | 51 ++++++++++++++++--- .../locales/en-US/chrome/browser.properties | 8 ++- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 7794a9b36d2..24ab3909720 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -3925,23 +3925,53 @@ var ClipboardHelper = { var PluginHelper = { showDoorHanger: function(aTab) { + if (!aTab.browser) + return; + + // Even though we may not end up showing a doorhanger, this flag + // lets us know that we've tried to show a doorhanger. aTab.clickToPlayPluginDoorhangerShown = true; - let message = Strings.browser.GetStringFromName("clickToPlayPlugins.message"); + + let uri = aTab.browser.currentURI; + + // If the user has previously set a plugins permission for this website, + // either play or don't play the plugins instead of showing a doorhanger. + let permValue = Services.perms.testPermission(uri, "plugins"); + if (permValue != Services.perms.UNKNOWN_ACTION) { + if (permValue == Services.perms.ALLOW_ACTION) + PluginHelper.playAllPlugins(aTab.browser.contentWindow); + + return; + } + + let message = Strings.browser.formatStringFromName("clickToPlayPlugins.message1", + [uri.host], 1); let buttons = [ { label: Strings.browser.GetStringFromName("clickToPlayPlugins.yes"), - callback: function() { + callback: function(aChecked) { + // If the user checked "Don't ask again", make a permanent exception + if (aChecked) + Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION); + PluginHelper.playAllPlugins(aTab.browser.contentWindow); } }, { label: Strings.browser.GetStringFromName("clickToPlayPlugins.no"), - callback: function() { - // Do nothing - } + callback: function(aChecked) { + // If the user checked "Don't ask again", make a permanent exception + if (aChecked) + Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.DENY_ACTION); + + // Other than that, do nothing } - ] - NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id); + ]; + + // Add a checkbox with a "Don't ask again" message + let options = { checkbox: Strings.browser.GetStringFromName("clickToPlayPlugins.dontAskAgain") }; + + NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id, options); }, playAllPlugins: function(aContentWindow) { @@ -4003,7 +4033,7 @@ var PluginHelper = { var PermissionsHelper = { _permissonTypes: ["password", "geolocation", "popup", "indexedDB", - "offline-app", "desktop-notification"], + "offline-app", "desktop-notification", "plugins"], _permissionStrings: { "password": { label: "password.rememberPassword", @@ -4034,6 +4064,11 @@ var PermissionsHelper = { label: "desktopNotification.useNotifications", allowed: "desktopNotification.allow", denied: "desktopNotification.dontAllow" + }, + "plugins": { + label: "clickToPlayPlugins.playPlugins", + allowed: "clickToPlayPlugins.yes", + denied: "clickToPlayPlugins.no" } }, diff --git a/mobile/android/locales/en-US/chrome/browser.properties b/mobile/android/locales/en-US/chrome/browser.properties index db58a855be1..7c4b9e408c1 100644 --- a/mobile/android/locales/en-US/chrome/browser.properties +++ b/mobile/android/locales/en-US/chrome/browser.properties @@ -226,9 +226,15 @@ timer.start=%S: timer started timer.end=%1$S: %2$Sms # Click to play plugins -clickToPlayPlugins.message=This page contains plugin content. Would you like to play it? +clickToPlayPlugins.message1=%S contains plugin content. Would you like to play it? clickToPlayPlugins.yes=Yes clickToPlayPlugins.no=No +# LOCALIZATION NOTE (clickToPlayPlugins.dontAskAgain): This label appears next to a +# checkbox to indicate whether or not the user wants to make a permanent decision. +clickToPlayPlugins.dontAskAgain=Don't ask again for this site +# LOCALIZATION NOTE (clickToPlayPlugins.playPlugins): Label that +# will be used in site settings dialog. +clickToPlayPlugins.playPlugins=Play Plugins # Site settings dialog # LOCALIZATION NOTE (siteSettings.labelToValue): This string will be used to From caf83019b5a306089d1ab02703186c1f9b12688b Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 27 Mar 2012 14:38:39 -0700 Subject: [PATCH 062/113] bug 688125 - part 1 - add memory reporting for the platform font list. r=njn --- gfx/thebes/gfxDWriteFontList.cpp | 75 ++++++++++- gfx/thebes/gfxDWriteFontList.h | 17 ++- gfx/thebes/gfxFT2FontList.cpp | 17 +++ gfx/thebes/gfxFT2FontList.h | 5 + gfx/thebes/gfxFont.cpp | 73 +++++++++++ gfx/thebes/gfxFont.h | 19 +++ gfx/thebes/gfxFontUtils.h | 16 ++- gfx/thebes/gfxGDIFontList.cpp | 46 ++++++- gfx/thebes/gfxGDIFontList.h | 10 +- gfx/thebes/gfxMacPlatformFontList.h | 6 + gfx/thebes/gfxMacPlatformFontList.mm | 25 +++- gfx/thebes/gfxPlatformFontList.cpp | 188 +++++++++++++++++++++++++-- gfx/thebes/gfxPlatformFontList.h | 29 +++++ 13 files changed, 485 insertions(+), 41 deletions(-) diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 0cdf0b1bc0a..61077420fa2 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -249,6 +249,23 @@ gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName) aLocalizedName = nsDependentString(famName.Elements()); } +void +gfxDWriteFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + gfxFontFamily::SizeOfExcludingThis(aMallocSizeOf, aSizes); + // TODO: + // This doesn't currently account for |mDWFamily| +} + +void +gfxDWriteFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + //////////////////////////////////////////////////////////////////////////////// // gfxDWriteFontEntry @@ -377,7 +394,8 @@ gfxDWriteFontEntry::ReadCMAP() unicodeFont, symbolFont); #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", - NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize())); + NS_ConvertUTF16toUTF8(mName).get(), + mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", @@ -424,7 +442,8 @@ gfxDWriteFontEntry::ReadCMAP() #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", - NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize())); + NS_ConvertUTF16toUTF8(mName).get(), + mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", @@ -544,6 +563,23 @@ gfxDWriteFontEntry::IsCJKFont() return mIsCJK; } +void +gfxDWriteFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes); + // TODO: + // This doesn't currently account for the |mFont| and |mFontFile| members +} + +void +gfxDWriteFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + //////////////////////////////////////////////////////////////////////////////// // gfxDWriteFontList @@ -587,7 +623,6 @@ gfxFontEntry * gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, const nsAString& aFullname) { - bool found; gfxFontEntry *lookup; // initialize name lookup tables if needed @@ -596,8 +631,8 @@ gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, } // lookup in name lookup tables, return null if not found - if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) && - !(lookup = mFullnames.GetWeak(aFullname, &found))) + if (!(lookup = mPostscriptNames.GetWeak(aFullname)) && + !(lookup = mFullnames.GetWeak(aFullname))) { return nsnull; } @@ -1182,8 +1217,8 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName, nsAutoString keyName(aFontName); BuildKeyNameFromFontName(keyName); - nsRefPtr ff; - if (mFontSubstitutes.Get(keyName, &ff)) { + gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName); + if (ff) { aResolvedFontName = ff->Name(); return true; } @@ -1195,6 +1230,32 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName, return gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName); } +void +gfxDWriteFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes); + + aSizes->mFontListSize += + mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis, + aMallocSizeOf); + + aSizes->mFontListSize += + mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf); + for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) { + aSizes->mFontListSize += + mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf); + } +} + +void +gfxDWriteFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + static nsresult GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName) { HRESULT hr; diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index c1db3f0456f..5287402cd24 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -79,6 +79,11 @@ public: void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + protected: /** This font family's directwrite fontfamily object */ nsRefPtr mDWFamily; @@ -179,6 +184,11 @@ public: void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } bool GetForceGDIClassic() { return mForceGDIClassic; } + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + protected: friend class gfxDWriteFont; friend class gfxDWriteFontList; @@ -380,6 +390,11 @@ public: gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; } + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + private: friend class gfxDWriteFontFamily; @@ -401,7 +416,7 @@ private: */ nsTArray mNonExistingFonts; - typedef nsDataHashtable > FontTable; + typedef nsRefPtrHashtable FontTable; /** * Table of font substitutes, we grab this from the registry to get diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index 9165207a106..82c1819f57d 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -389,6 +389,23 @@ FT2FontEntry::GetFontTable(PRUint32 aTableTag, return NS_OK; } +void +FT2FontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes); + aSizes->mFontListSize += + mFilename.SizeOfExcludingThisIfUnshared(aMallocSizeOf); +} + +void +FT2FontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + /* * FT2FontFamily * A standard gfxFontFamily; just adds a method used to support sending diff --git a/gfx/thebes/gfxFT2FontList.h b/gfx/thebes/gfxFT2FontList.h index 9d430c452c9..9299b9418ee 100644 --- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -102,6 +102,11 @@ public: nsresult ReadCMAP(); nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray& aBuffer); + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + FT_Face mFTFace; cairo_font_face_t *mFontFace; diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 647f8043d73..911d58fadcc 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -272,6 +272,13 @@ public: mHashEntry = nsnull; } + size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const { + return mTableData.SizeOfExcludingThis(aMallocSizeOf); + } + size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + private: // The font table data block, owned (via adoption) FallibleTArray mTableData; @@ -401,6 +408,46 @@ gfxFontEntry::CheckForGraphiteTables() } #endif +/* static */ size_t +gfxFontEntry::FontTableHashEntry::SizeOfEntryExcludingThis + (FontTableHashEntry *aEntry, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + FontListSizes *sizes = static_cast(aUserArg); + if (aEntry->mBlob) { + sizes->mFontTableCacheSize += aMallocSizeOf(aEntry->mBlob); + } + if (aEntry->mSharedBlobData) { + sizes->mFontTableCacheSize += + aEntry->mSharedBlobData->SizeOfIncludingThis(aMallocSizeOf); + } + + // the size of the table is recorded in the FontListSizes record, + // so we return 0 here for the function result + return 0; +} + +void +gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); + aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf); + aSizes->mFontTableCacheSize += + mFontTableCache.SizeOfExcludingThis( + FontTableHashEntry::SizeOfEntryExcludingThis, + aMallocSizeOf, aSizes); +} + +void +gfxFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + ////////////////////////////////////////////////////////////////////////////// // // class gfxFontFamily @@ -975,6 +1022,32 @@ gfxFontFamily::FindFont(const nsAString& aPostscriptName) return nsnull; } +void +gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += + mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); + aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf); + + aSizes->mFontListSize += + mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf); + for (PRUint32 i = 0; i < mAvailableFonts.Length(); ++i) { + gfxFontEntry *fe = mAvailableFonts[i]; + if (fe) { + fe->SizeOfIncludingThis(aMallocSizeOf, aSizes); + } + } +} + +void +gfxFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + /* * gfxFontCache - global cache of gfxFont instances. * Expires unused fonts after a short interval; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 9fcf6a0cb47..dd44ddd91d9 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -91,6 +91,8 @@ struct THEBES_API gfxFontFeature { // to features that select among multiple alternatives }; +struct FontListSizes; + inline bool operator<(const gfxFontFeature& a, const gfxFontFeature& b) { @@ -314,6 +316,12 @@ public: hb_blob_t *ShareFontTableAndGetBlob(PRUint32 aTag, FallibleTArray* aTable); + // For memory reporting + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + nsString mName; bool mItalic : 1; @@ -468,6 +476,11 @@ private: void Clear(); + static size_t + SizeOfEntryExcludingThis(FontTableHashEntry *aEntry, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg); + private: static void DeleteFontTableBlobData(void *aBlobData); // not implemented @@ -634,6 +647,12 @@ public: // if so set the mIsSimpleFamily flag (defaults to False before we've checked) void CheckForSimpleFamily(); + // For memory reporter + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + protected: // fills in an array with weights of faces that match style, // returns whether any matching entries found diff --git a/gfx/thebes/gfxFontUtils.h b/gfx/thebes/gfxFontUtils.h index e7f853f4893..3d6ba81f7d9 100644 --- a/gfx/thebes/gfxFontUtils.h +++ b/gfx/thebes/gfxFontUtils.h @@ -264,14 +264,18 @@ public: } } - PRUint32 GetSize() { - PRUint32 size = 0; + size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const { + size_t total = mBlocks.SizeOfExcludingThis(aMallocSizeOf); for (PRUint32 i = 0; i < mBlocks.Length(); i++) { - if (mBlocks[i]) - size += sizeof(Block); - size += sizeof(nsAutoPtr); + if (mBlocks[i]) { + total += aMallocSizeOf(mBlocks[i]); + } } - return size; + return total; + } + + size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } // clear out all blocks in the array diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index 3230fa287fc..c40304bf73f 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -246,7 +246,8 @@ GDIFontEntry::ReadCMAP() #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", - NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize())); + NS_ConvertUTF16toUTF8(mName).get(), + mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", @@ -459,6 +460,14 @@ GDIFontEntry::CreateFontEntry(const nsAString& aName, return fe; } +void +GDIFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + /*************************************************************** * * GDIFontFamily @@ -658,7 +667,7 @@ gfxGDIFontList::GetFontSubstitutes() nsAutoString substituteName; substituteName.AssignLiteral("Courier"); BuildKeyNameFromFontName(substituteName); - if (!mFontSubstitutes.Get(substituteName)) { + if (!mFontSubstitutes.GetWeak(substituteName)) { gfxFontFamily *ff; nsAutoString actualFontName; actualFontName.AssignLiteral("Courier New"); @@ -743,7 +752,6 @@ gfxFontEntry* gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, const nsAString& aFullname) { - bool found; gfxFontEntry *lookup; // initialize name lookup tables if needed @@ -752,8 +760,8 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, } // lookup in name lookup tables, return null if not found - if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) && - !(lookup = mFullnames.GetWeak(aFullname, &found))) + if (!(lookup = mPostscriptNames.GetWeak(aFullname)) && + !(lookup = mFullnames.GetWeak(aFullname))) { return nsnull; } @@ -1038,8 +1046,8 @@ gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolved nsAutoString keyName(aFontName); BuildKeyNameFromFontName(keyName); - nsRefPtr ff; - if (mFontSubstitutes.Get(keyName, &ff)) { + gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName); + if (ff) { aResolvedFontName = ff->Name(); return true; } @@ -1052,3 +1060,27 @@ gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolved return false; } + +void +gfxGDIFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes); + aSizes->mFontListSize += + mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis, + aMallocSizeOf); + aSizes->mFontListSize += + mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf); + for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) { + aSizes->mFontListSize += + mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf); + } +} + +void +gfxGDIFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h index 320879b3d73..96834e023b5 100644 --- a/gfx/thebes/gfxGDIFontList.h +++ b/gfx/thebes/gfxGDIFontList.h @@ -274,6 +274,9 @@ public: virtual bool TestCharacterMap(PRUint32 aCh); + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + // create a font entry for a font with a given name static GDIFontEntry* CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, @@ -347,6 +350,11 @@ public: virtual bool ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName); + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + private: friend class gfxWindowsPlatform; @@ -361,7 +369,7 @@ private: DWORD fontType, LPARAM lParam); - typedef nsDataHashtable > FontTable; + typedef nsRefPtrHashtable FontTable; FontTable mFontSubstitutes; nsTArray mNonExistingFonts; diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h index 30d527b240e..91ec2c73080 100644 --- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -111,6 +111,9 @@ public: virtual nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray& aBuffer); + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + protected: virtual bool HasFontTable(PRUint32 aTableTag); @@ -134,6 +137,9 @@ public: virtual nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray& aBuffer); + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + protected: virtual bool HasFontTable(PRUint32 aTableTag); }; diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index 65e78092118..01a75ec7c0c 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -270,7 +270,7 @@ MacOSFontEntry::ReadCMAP() #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n", NS_ConvertUTF16toUTF8(mName).get(), - mCharacterMap.GetSize())); + mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of))); if (LOG_CMAPDATA_ENABLED()) { char prefix[256]; sprintf(prefix, "(cmapdata) name: %.220s", @@ -398,6 +398,14 @@ ATSFontEntry::HasFontTable(PRUint32 aTableTag) (::ATSFontGetTable(fontRef, aTableTag, 0, 0, 0, &size) == noErr); } +void +ATSFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + /* CGFontEntry - used on Mac OS X 10.6+ */ #pragma mark- @@ -486,6 +494,14 @@ CGFontEntry::HasFontTable(PRUint32 aTableTag) return true; } +void +CGFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} + /* gfxMacFontFamily */ #pragma mark- @@ -811,10 +827,9 @@ gfxMacPlatformFontList::InitSingleFaceList() #endif // add only if doesn't exist already - bool found; - gfxFontFamily *familyEntry; - if (!(familyEntry = mFontFamilies.GetWeak(key, &found))) { - familyEntry = new gfxSingleFaceMacFontFamily(familyName); + if (!mFontFamilies.GetWeak(key)) { + gfxFontFamily *familyEntry = + new gfxSingleFaceMacFontFamily(familyName); familyEntry->AddFontEntry(fontEntry); familyEntry->SetHasStyles(true); mFontFamilies.Put(key, familyEntry); diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index b65675f8ad9..ef8e2bbd4ad 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -130,6 +130,63 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject, return NS_OK; } +NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryMultiReporter) + +NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf, "font-list") + +NS_IMETHODIMP +gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName) +{ + aName.AssignLiteral("font-list"); + return NS_OK; +} + +NS_IMETHODIMP +gfxPlatformFontList::MemoryReporter::CollectReports + (nsIMemoryMultiReporterCallback* aCb, + nsISupports* aClosure) +{ + FontListSizes sizes; + sizes.mFontListSize = 0; + sizes.mFontTableCacheSize = 0; + sizes.mCharMapsSize = 0; + + gfxPlatformFontList::PlatformFontList()->SizeOfIncludingThis(&FontListMallocSizeOf, + &sizes); + + aCb->Callback(EmptyCString(), + NS_LITERAL_CSTRING("explicit/gfx/font-list"), + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + sizes.mFontListSize, + NS_LITERAL_CSTRING("Memory used to manage the list of font families and faces."), + aClosure); + + aCb->Callback(EmptyCString(), + NS_LITERAL_CSTRING("explicit/gfx/font-charmaps"), + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + sizes.mCharMapsSize, + NS_LITERAL_CSTRING("Memory used to record the character coverage of individual fonts."), + aClosure); + + if (sizes.mFontTableCacheSize) { + aCb->Callback(EmptyCString(), + NS_LITERAL_CSTRING("explicit/gfx/font-tables"), + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + sizes.mFontTableCacheSize, + NS_LITERAL_CSTRING("Memory used for cached font metrics and layout tables."), + aClosure); + } + + return NS_OK; +} + +NS_IMETHODIMP +gfxPlatformFontList::MemoryReporter::GetExplicitNonHeap(PRInt64* aAmount) +{ + // This reporter only measures heap memory. + *aAmount = 0; + return NS_OK; +} gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) : mNeedFullnamePostscriptNames(aNeedFullnamePostscriptNames), @@ -184,6 +241,8 @@ gfxPlatformFontList::InitFontList() mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls + NS_RegisterMemoryMultiReporter(new MemoryReporter); + sPlatformFontList = this; return NS_OK; @@ -244,12 +303,11 @@ gfxPlatformFontList::PreloadNamesList() PRUint32 numFonts = preloadFonts.Length(); for (PRUint32 i = 0; i < numFonts; i++) { - bool found; nsAutoString key; GenerateFontListKey(preloadFonts[i], key); // only search canonical names! - gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key, &found); + gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key); if (familyEntry) { familyEntry->ReadOtherFamilyNames(this); } @@ -549,18 +607,17 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily) { nsAutoString key; gfxFontFamily *familyEntry; - bool found; GenerateFontListKey(aFamily, key); NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly"); // lookup in canonical (i.e. English) family name list - if ((familyEntry = mFontFamilies.GetWeak(key, &found))) { + if ((familyEntry = mFontFamilies.GetWeak(key))) { return familyEntry; } // lookup in other family names list (mostly localized names) - if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) { + if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) { return familyEntry; } @@ -571,7 +628,7 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily) // in practice so avoid pulling in names at startup if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) { InitOtherFamilyNames(); - if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) { + if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) { return familyEntry; } } @@ -608,10 +665,9 @@ void gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName) { nsAutoString key; - bool found; GenerateFontListKey(aOtherFamilyName, key); - if (!mOtherFamilyNames.GetWeak(key, &found)) { + if (!mOtherFamilyNames.GetWeak(key)) { mOtherFamilyNames.Put(key, aFamilyEntry); #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, " @@ -627,9 +683,7 @@ gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& void gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname) { - bool found; - - if (!mFullnames.GetWeak(aFullname, &found)) { + if (!mFullnames.GetWeak(aFullname)) { mFullnames.Put(aFullname, aFontEntry); #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n", @@ -642,9 +696,7 @@ gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname) void gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName) { - bool found; - - if (!mPostscriptNames.GetWeak(aPostscriptName, &found)) { + if (!mPostscriptNames.GetWeak(aPostscriptName)) { mPostscriptNames.Put(aPostscriptName, aFontEntry); #ifdef PR_LOGGING LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n", @@ -714,3 +766,111 @@ gfxPlatformFontList::FinishLoader() mFontFamiliesToLoad.Clear(); mNumFamilies = 0; } + +// Support for memory reporting + +static size_t +SizeOfFamilyEntryExcludingThis(const nsAString& aKey, + const nsRefPtr& aFamily, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + FontListSizes *sizes = static_cast(aUserArg); + aFamily->SizeOfExcludingThis(aMallocSizeOf, sizes); + + sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); + + // we return zero here because the measurements have been added directly + // to the relevant fields of the FontListSizes record + return 0; +} + +// this is also used by subclasses that hold additional hashes of family names +/*static*/ size_t +gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis + (const nsAString& aKey, + const nsRefPtr& aFamily, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + // we don't count the size of the family here, because this is an *extra* + // reference to a family that will have already been counted in the main list + return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); +} + +static size_t +SizeOfFontNameEntryExcludingThis(const nsAString& aKey, + const nsRefPtr& aFont, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + // the font itself is counted by its owning family; here we only care about + // the name stored in the hashtable key + return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); +} + +static size_t +SizeOfPrefFontEntryExcludingThis + (const PRUint32& aKey, + const nsTArray >& aList, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + // again, we only care about the size of the array itself; we don't follow + // the refPtrs stored in it, because they point to entries already owned + // and accounted-for by the main font list + return aList.SizeOfExcludingThis(aMallocSizeOf); +} + +static size_t +SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf); +} + +void +gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += + mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis, + aMallocSizeOf, aSizes); + + aSizes->mFontListSize += + mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis, + aMallocSizeOf); + + if (mNeedFullnamePostscriptNames) { + aSizes->mFontListSize += + mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis, + aMallocSizeOf); + aSizes->mFontListSize += + mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis, + aMallocSizeOf); + } + + aSizes->mFontListSize += + mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf); + aSizes->mFontListSize += + mReplacementCharFallbackFamily.SizeOfExcludingThisIfUnshared(aMallocSizeOf); + aSizes->mFontListSize += + mFontFamiliesToLoad.SizeOfExcludingThis(aMallocSizeOf); + + aSizes->mFontListSize += + mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis, + aMallocSizeOf); + + aSizes->mFontListSize += + mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis, + aMallocSizeOf); +} + +void +gfxPlatformFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const +{ + aSizes->mFontListSize += aMallocSizeOf(this); + SizeOfExcludingThis(aMallocSizeOf, aSizes); +} diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 59509552660..b800d28c9d1 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -47,6 +47,7 @@ #include "gfxFont.h" #include "gfxPlatform.h" +#include "nsIMemoryReporter.h" #include "mozilla/FunctionTimer.h" // gfxPlatformFontList is an abstract class for the global font list on the system; @@ -57,6 +58,14 @@ // Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms. +struct FontListSizes { + PRUint32 mFontListSize; // size of the font list and dependent objects + // (font family and face names, etc), but NOT + // including the font table cache and the cmaps + PRUint32 mFontTableCacheSize; // memory used for the gfxFontEntry table caches + PRUint32 mCharMapsSize; // memory used for cmap coverage info +}; + class gfxPlatformFontList : protected gfxFontInfoLoader { public: @@ -141,7 +150,20 @@ public: // (platforms may override, eg Mac) virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); + virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + FontListSizes* aSizes) const; + protected: + class MemoryReporter + : public nsIMemoryMultiReporter + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIMEMORYMULTIREPORTER + }; + gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true); static gfxPlatformFontList *sPlatformFontList; @@ -200,6 +222,13 @@ protected: virtual bool RunLoader(); virtual void FinishLoader(); + // used by memory reporter to accumulate sizes of family names in the hash + static size_t + SizeOfFamilyNameEntryExcludingThis(const nsAString& aKey, + const nsRefPtr& aFamily, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg); + // canonical family name ==> family entry (unique, one name per family entry) nsRefPtrHashtable mFontFamilies; From 8158778c0f6e9bd360fe48f2fb5b6ddd9dac16d2 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Tue, 27 Mar 2012 17:44:25 -0400 Subject: [PATCH 063/113] Bug 697309 - Add support for the Open Web Apps API - part 1 : UI glue r=fabrice --- mobile/android/chrome/content/browser.js | 2 + mobile/android/chrome/content/browser.xul | 1 + mobile/android/chrome/content/webapps.js | 65 +++++++++++++++++++ mobile/android/chrome/jar.mn | 3 +- mobile/android/installer/package-manifest.in | 6 +- .../locales/en-US/chrome/browser.properties | 3 + .../android/locales/en-US/chrome/webapps.dtd | 7 -- mobile/android/locales/jar.mn | 1 - 8 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 mobile/android/chrome/content/webapps.js delete mode 100644 mobile/android/locales/en-US/chrome/webapps.dtd diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 24ab3909720..4642dea1d3c 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -236,6 +236,7 @@ var BrowserApp = { CharacterEncoding.init(); SearchEngines.init(); ActivityObserver.init(); + WebappsUI.init(); // Init LoginManager Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); @@ -415,6 +416,7 @@ var BrowserApp = { ConsoleAPI.uninit(); CharacterEncoding.uninit(); SearchEngines.uninit(); + WebappsUI.uninit(); }, // This function returns false during periods where the browser displayed document is diff --git a/mobile/android/chrome/content/browser.xul b/mobile/android/chrome/content/browser.xul index 30aa819f16e..f803a05bc79 100644 --- a/mobile/android/chrome/content/browser.xul +++ b/mobile/android/chrome/content/browser.xul @@ -9,6 +9,7 @@ + + + +
+
&aboutApps.title;
+ +
+
+
+
+
+
+ + diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 4642dea1d3c..d4a7089e8b0 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1288,7 +1288,9 @@ var NativeWindow = { let popupNode = aEvent.originalTarget; let title = ""; - if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || + if (popupNode.hasAttribute("title")) { + title = popupNode.getAttribute("title") + } else if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || (popupNode instanceof Ci.nsIDOMHTMLAreaElement && popupNode.href)) { title = this._getLinkURL(popupNode); } else if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) { diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn index 6161726a02d..710b1fe6269 100644 --- a/mobile/android/chrome/jar.mn +++ b/mobile/android/chrome/jar.mn @@ -10,6 +10,8 @@ chrome.jar: content/aboutCertError.xhtml (content/aboutCertError.xhtml) content/aboutHome.xhtml (content/aboutHome.xhtml) * content/aboutRights.xhtml (content/aboutRights.xhtml) +* content/aboutApps.xhtml (content/aboutApps.xhtml) + content/aboutApps.js (content/aboutApps.js) content/blockedSite.xhtml (content/blockedSite.xhtml) content/languages.properties (content/languages.properties) * content/browser.xul (content/browser.xul) diff --git a/mobile/android/components/AboutRedirector.js b/mobile/android/components/AboutRedirector.js index 1d1c7ecca18..cbf4f68c5e9 100644 --- a/mobile/android/components/AboutRedirector.js +++ b/mobile/android/components/AboutRedirector.js @@ -85,6 +85,10 @@ let modules = { home: { uri: "chrome://browser/content/aboutHome.xhtml", privileged: true + }, + apps: { + uri: "chrome://browser/content/aboutApps.xhtml", + privileged: true } } diff --git a/mobile/android/components/MobileComponents.manifest b/mobile/android/components/MobileComponents.manifest index 81173e7ddc7..d575b29d2d2 100644 --- a/mobile/android/components/MobileComponents.manifest +++ b/mobile/android/components/MobileComponents.manifest @@ -7,6 +7,7 @@ contract @mozilla.org/network/protocol/about;1?what=empty {322ba47e-7047-4f71-ae contract @mozilla.org/network/protocol/about;1?what=rights {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=certerror {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=home {322ba47e-7047-4f71-aebf-cb7d69325cd9} +contract @mozilla.org/network/protocol/about;1?what=apps {322ba47e-7047-4f71-aebf-cb7d69325cd9} #ifdef MOZ_SAFE_BROWSING contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9} #endif diff --git a/mobile/android/locales/en-US/chrome/aboutApps.dtd b/mobile/android/locales/en-US/chrome/aboutApps.dtd new file mode 100644 index 00000000000..c7ea6d37ce8 --- /dev/null +++ b/mobile/android/locales/en-US/chrome/aboutApps.dtd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/mobile/android/locales/en-US/chrome/aboutApps.properties b/mobile/android/locales/en-US/chrome/aboutApps.properties new file mode 100644 index 00000000000..86d5a7c049d --- /dev/null +++ b/mobile/android/locales/en-US/chrome/aboutApps.properties @@ -0,0 +1,2 @@ +appsContext.uninstall=Uninstall +appsContext.shortcut=Add to Home Screen diff --git a/mobile/android/locales/jar.mn b/mobile/android/locales/jar.mn index 7e1fb7a88eb..ff6eb31ef9c 100644 --- a/mobile/android/locales/jar.mn +++ b/mobile/android/locales/jar.mn @@ -5,6 +5,8 @@ locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd) locale/@AB_CD@/browser/aboutAddons.dtd (%chrome/aboutAddons.dtd) locale/@AB_CD@/browser/aboutAddons.properties (%chrome/aboutAddons.properties) + locale/@AB_CD@/browser/aboutApps.dtd (%chrome/aboutApps.dtd) + locale/@AB_CD@/browser/aboutApps.properties (%chrome/aboutApps.properties) locale/@AB_CD@/browser/aboutCertError.dtd (%chrome/aboutCertError.dtd) locale/@AB_CD@/browser/browser.properties (%chrome/browser.properties) locale/@AB_CD@/browser/config.dtd (%chrome/config.dtd) diff --git a/mobile/android/themes/core/aboutApps.css b/mobile/android/themes/core/aboutApps.css new file mode 100644 index 00000000000..f10b351d53f --- /dev/null +++ b/mobile/android/themes/core/aboutApps.css @@ -0,0 +1,43 @@ + +html { + font-family: "Droid Sans",helvetica,arial,clean,sans-serif; + font-size: 18px; + background-image: url("chrome://browser/skin/images/about-bg-lightblue.png"); + -moz-text-size-adjust: none; +} + +#main-container { + margin: 1em; + padding: 1em; + border-radius: 10px; + border: 1px solid grey; + background-color: white; +} + +.spacer { + clear: both; +} + +.app { + float: left; + cursor: pointer; + text-align: center; + margin: 1em; + width: 70px; + height: 85px; + font-size: 10px; +} + +.app img { + width: 64px; + height: 64px; +} + +#noapps { + padding: 1em; + text-align: center; +} + +.hidden { + display: none; +} diff --git a/mobile/android/themes/core/jar.mn b/mobile/android/themes/core/jar.mn index 4b308be2c87..9d912de5ceb 100644 --- a/mobile/android/themes/core/jar.mn +++ b/mobile/android/themes/core/jar.mn @@ -5,6 +5,7 @@ chrome.jar: skin/aboutPage.css (aboutPage.css) skin/about.css (about.css) skin/aboutAddons.css (aboutAddons.css) + skin/aboutApps.css (aboutApps.css) * skin/browser.css (browser.css) * skin/content.css (content.css) skin/config.css (config.css) From e792f2501f8c1220a7620c229e15a0636ba1f5ac Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Tue, 27 Mar 2012 14:41:50 -0700 Subject: [PATCH 065/113] Bug 739694 - Fix script filename saving in exception traces (r=luke) --- js/src/jit-test/tests/basic/bug739694-1.js | 12 ++++++++++++ js/src/jit-test/tests/basic/bug739694-2.js | 8 ++++++++ js/src/jsexn.cpp | 4 +++- js/src/jsscript.cpp | 7 ++----- js/src/jsscript.h | 3 +++ 5 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug739694-1.js create mode 100644 js/src/jit-test/tests/basic/bug739694-2.js diff --git a/js/src/jit-test/tests/basic/bug739694-1.js b/js/src/jit-test/tests/basic/bug739694-1.js new file mode 100644 index 00000000000..a05b2b4df04 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug739694-1.js @@ -0,0 +1,12 @@ +function newFunc(x) { new Function(x)(); }; try { newFunc("\ +var g = newGlobal('new-compartment');\ +g.h = function () {\ + names = foo.blaaaaaaaaaaaaah().environment.names();\ +};\ +g.eval('var obj = {a: 1};' + \"with ({a: 1, '0xcafe': 2, ' ': 3, '': 4, '0': 5}) h();\");\ +"); +} catch(exc1) {} +function newFunc(x) { new Function(x)(); }; newFunc("\ +gczeal(2);\ + a=b=c=d=0; this.__defineGetter__('g', gc); for each (y in this);\ +"); diff --git a/js/src/jit-test/tests/basic/bug739694-2.js b/js/src/jit-test/tests/basic/bug739694-2.js new file mode 100644 index 00000000000..057ba5e9194 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug739694-2.js @@ -0,0 +1,8 @@ +try { + ({ + f: evalcx("evalcx(\"e\",newGlobal('new-compartment'))", + newGlobal('new-compartment')) + }) +} catch (e) {} +gc() +gc() diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 3f4c16b954c..2018627bd4f 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -374,7 +374,9 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, frame.argc = 0; } if (fp->isScriptFrame()) { - frame.filename = fp->script()->filename; + frame.filename = SaveScriptFilename(cx, fp->script()->filename); + if (!frame.filename) + return false; frame.ulineno = PCToLineNumber(fp->script(), i.pc()); } else { frame.ulineno = 0; diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 02ef6a4fcb8..96141ea0882 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -389,9 +389,6 @@ XDRScriptConst(XDRState *xdr, HeapValue *vp) return true; } -static const char * -SaveScriptFilename(JSContext *cx, const char *filename); - template bool js::XDRScript(XDRState *xdr, JSScript **scriptp, JSScript *parentScript) @@ -836,8 +833,8 @@ JSScript::destroyCounts(JSContext *cx) * Shared script filename management. */ -static const char * -SaveScriptFilename(JSContext *cx, const char *filename) +const char * +js::SaveScriptFilename(JSContext *cx, const char *filename) { JSCompartment *comp = cx->compartment; diff --git a/js/src/jsscript.h b/js/src/jsscript.h index c9944db5d35..9a2d2804caf 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -801,6 +801,9 @@ js_CallDestroyScriptHook(JSContext *cx, JSScript *script); namespace js { +extern const char * +SaveScriptFilename(JSContext *cx, const char *filename); + extern void MarkScriptFilename(const char *filename); From 93de89e11c47269e48944f01350706cc592edb15 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Tue, 27 Mar 2012 15:20:20 -0700 Subject: [PATCH 066/113] Backed out changeset add087add91a (bug 697309) --- mobile/android/app/mobile.js | 1 - mobile/android/chrome/content/aboutApps.js | 160 ------------------ mobile/android/chrome/content/aboutApps.xhtml | 46 ----- mobile/android/chrome/content/browser.js | 4 +- mobile/android/chrome/jar.mn | 2 - mobile/android/components/AboutRedirector.js | 4 - .../components/MobileComponents.manifest | 1 - .../locales/en-US/chrome/aboutApps.dtd | 8 - .../locales/en-US/chrome/aboutApps.properties | 2 - mobile/android/locales/jar.mn | 2 - mobile/android/themes/core/aboutApps.css | 43 ----- mobile/android/themes/core/jar.mn | 1 - 12 files changed, 1 insertion(+), 273 deletions(-) delete mode 100644 mobile/android/chrome/content/aboutApps.js delete mode 100644 mobile/android/chrome/content/aboutApps.xhtml delete mode 100644 mobile/android/locales/en-US/chrome/aboutApps.dtd delete mode 100644 mobile/android/locales/en-US/chrome/aboutApps.properties delete mode 100644 mobile/android/themes/core/aboutApps.css diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 7895b035815..028e4a6a69a 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -485,7 +485,6 @@ pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/mobile/beta/faq/"); pref("app.featuresURL", "http://www.mozilla.com/%LOCALE%/mobile/features/"); pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/mobile/faq/"); #endif -pref("app.marketplaceURL", "https://marketplace.mozilla.org/"); // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror) pref("security.alternate_certificate_error_page", "certerror"); diff --git a/mobile/android/chrome/content/aboutApps.js b/mobile/android/chrome/content/aboutApps.js deleted file mode 100644 index 35884bfb792..00000000000 --- a/mobile/android/chrome/content/aboutApps.js +++ /dev/null @@ -1,160 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * ***** END LICENSE BLOCK ***** */ - -let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils; - -Cu.import("resource://gre/modules/Services.jsm") -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Webapps.jsm"); - -let gStrings = Services.strings.createBundle("chrome://browser/locale/aboutApps.properties"); - -XPCOMUtils.defineLazyGetter(window, "gChromeWin", function() - window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow) - .QueryInterface(Ci.nsIDOMChromeWindow)); - -var AppsUI = { - uninstall: null, - shortcut: null -}; - -function onLoad(aEvent) { - try { - let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); - let link = document.getElementById("marketplaceURL"); - let url = formatter.formatURLPref(link.getAttribute("pref")); - link.setAttribute("href", url); - } catch (e) {} - - navigator.mozApps.mgmt.oninstall = onInstall; - navigator.mozApps.mgmt.onuninstall = onUninstall; - updateList(); - - let contextmenus = gChromeWin.NativeWindow.contextmenus; - AppsUI.shortcut = contextmenus.add(gStrings.GetStringFromName("appsContext.shortcut"), contextmenus.SelectorContext("div[mozApp]"), - function(aTarget) { - let manifest = aTarget.manifest; - createShortcut(manifest.name, manifest.fullLaunchPath(), manifest.iconURLForSize("64"), "webapp"); - }); - AppsUI.uninstall = contextmenus.add(gStrings.GetStringFromName("appsContext.uninstall"), contextmenus.SelectorContext("div[mozApp]"), - function(aTarget) { - aTarget.app.uninstall(); - }); -} - -function onUnload(aEvent) { - let contextmenus = gChromeWin.NativeWindow.contextmenus; - if (AppsUI.shortcut) - contextmenus.remove(AppsUI.shortcut); - if (AppsUI.uninstall) - contextmenus.remove(AppsUI.uninstall); -} - -function updateList() { - let grid = document.getElementById("appgrid"); - while (grid.lastChild) { - grid.removeChild(grid.lastChild); - } - - let request = navigator.mozApps.mgmt.getAll(); - request.onsuccess = function() { - for (let i = 0; i < request.result.length; i++) - addApplication(request.result[i]); - if (!request.result.length) - document.getElementById("noapps").className = ""; - } -} - -function addApplication(aApp) { - let list = document.getElementById("appgrid"); - let manifest = new DOMApplicationManifest(aApp.manifest, aApp.origin); - - let container = document.createElement("div"); - container.className = "app"; - container.setAttribute("id", "app-" + aApp.origin); - container.setAttribute("mozApp", aApp.origin); - container.setAttribute("title", manifest.name); - - let img = document.createElement("img"); - img.src = manifest.iconURLForSize("64"); - img.setAttribute("title", manifest.name); - - let title = document.createElement("div"); - title.appendChild(document.createTextNode(manifest.name)); - - container.appendChild(img); - container.appendChild(title); - list.appendChild(container); - - container.addEventListener("click", function(aEvent) { - aApp.launch(); - }, false); - container.app = aApp; - container.manifest = manifest; -} - -function onInstall(aEvent) { - let node = document.getElementById("app-" + aEvent.application.origin); - if (node) - return; - - addApplication(aEvent.application); - document.getElementById("noapps").className = "hidden"; -} - -function onUninstall(aEvent) { - let node = document.getElementById("app-" + aEvent.application.origin); - if (node) { - let parent = node.parentNode; - parent.removeChild(node); - if (!parent.firstChild) - document.getElementById("noapps").className = ""; - } -} - -function createShortcut(aTitle, aURL, aIconURL, aType) { - // The background images are 72px, but Android will resize as needed. - // Bigger is better than too small. - const kIconSize = 72; - const kOverlaySize = 32; - const kOffset = 20; - - let canvas = document.createElement("canvas"); - - function _createShortcut() { - let icon = canvas.toDataURL("image/png", ""); - canvas = null; - try { - let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService); - shell.createShortcut(aTitle, aURL, icon, aType); - } catch(e) { - Cu.reportError(e); - } - } - - canvas.width = canvas.height = kIconSize; - let ctx = canvas.getContext("2d"); - - let favicon = new Image(); - favicon.onload = function() { - // Center the favicon and overlay it on the background - ctx.drawImage(favicon, kOffset, kOffset, kOverlaySize, kOverlaySize); - _createShortcut(); - } - - favicon.onerror = function() { - Cu.reportError("CreateShortcut: favicon image load error"); - } - - favicon.src = aIconURL; -} diff --git a/mobile/android/chrome/content/aboutApps.xhtml b/mobile/android/chrome/content/aboutApps.xhtml deleted file mode 100644 index 310d1ffdd99..00000000000 --- a/mobile/android/chrome/content/aboutApps.xhtml +++ /dev/null @@ -1,46 +0,0 @@ - - -# ***** BEGIN LICENSE BLOCK ***** -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. -# -# ***** END LICENSE BLOCK ***** - - - %htmlDTD; - - %globalDTD; - - %aboutAppsDTD; - - %browserDTD; -]> - - - - &aboutApps.title; - - - - - - - -
-
&aboutApps.title;
- -
-
-
-
-
-
- - diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index d4a7089e8b0..4642dea1d3c 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1288,9 +1288,7 @@ var NativeWindow = { let popupNode = aEvent.originalTarget; let title = ""; - if (popupNode.hasAttribute("title")) { - title = popupNode.getAttribute("title") - } else if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || + if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || (popupNode instanceof Ci.nsIDOMHTMLAreaElement && popupNode.href)) { title = this._getLinkURL(popupNode); } else if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) { diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn index 710b1fe6269..6161726a02d 100644 --- a/mobile/android/chrome/jar.mn +++ b/mobile/android/chrome/jar.mn @@ -10,8 +10,6 @@ chrome.jar: content/aboutCertError.xhtml (content/aboutCertError.xhtml) content/aboutHome.xhtml (content/aboutHome.xhtml) * content/aboutRights.xhtml (content/aboutRights.xhtml) -* content/aboutApps.xhtml (content/aboutApps.xhtml) - content/aboutApps.js (content/aboutApps.js) content/blockedSite.xhtml (content/blockedSite.xhtml) content/languages.properties (content/languages.properties) * content/browser.xul (content/browser.xul) diff --git a/mobile/android/components/AboutRedirector.js b/mobile/android/components/AboutRedirector.js index cbf4f68c5e9..1d1c7ecca18 100644 --- a/mobile/android/components/AboutRedirector.js +++ b/mobile/android/components/AboutRedirector.js @@ -85,10 +85,6 @@ let modules = { home: { uri: "chrome://browser/content/aboutHome.xhtml", privileged: true - }, - apps: { - uri: "chrome://browser/content/aboutApps.xhtml", - privileged: true } } diff --git a/mobile/android/components/MobileComponents.manifest b/mobile/android/components/MobileComponents.manifest index d575b29d2d2..81173e7ddc7 100644 --- a/mobile/android/components/MobileComponents.manifest +++ b/mobile/android/components/MobileComponents.manifest @@ -7,7 +7,6 @@ contract @mozilla.org/network/protocol/about;1?what=empty {322ba47e-7047-4f71-ae contract @mozilla.org/network/protocol/about;1?what=rights {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=certerror {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=home {322ba47e-7047-4f71-aebf-cb7d69325cd9} -contract @mozilla.org/network/protocol/about;1?what=apps {322ba47e-7047-4f71-aebf-cb7d69325cd9} #ifdef MOZ_SAFE_BROWSING contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9} #endif diff --git a/mobile/android/locales/en-US/chrome/aboutApps.dtd b/mobile/android/locales/en-US/chrome/aboutApps.dtd deleted file mode 100644 index c7ea6d37ce8..00000000000 --- a/mobile/android/locales/en-US/chrome/aboutApps.dtd +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/mobile/android/locales/en-US/chrome/aboutApps.properties b/mobile/android/locales/en-US/chrome/aboutApps.properties deleted file mode 100644 index 86d5a7c049d..00000000000 --- a/mobile/android/locales/en-US/chrome/aboutApps.properties +++ /dev/null @@ -1,2 +0,0 @@ -appsContext.uninstall=Uninstall -appsContext.shortcut=Add to Home Screen diff --git a/mobile/android/locales/jar.mn b/mobile/android/locales/jar.mn index ff6eb31ef9c..7e1fb7a88eb 100644 --- a/mobile/android/locales/jar.mn +++ b/mobile/android/locales/jar.mn @@ -5,8 +5,6 @@ locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd) locale/@AB_CD@/browser/aboutAddons.dtd (%chrome/aboutAddons.dtd) locale/@AB_CD@/browser/aboutAddons.properties (%chrome/aboutAddons.properties) - locale/@AB_CD@/browser/aboutApps.dtd (%chrome/aboutApps.dtd) - locale/@AB_CD@/browser/aboutApps.properties (%chrome/aboutApps.properties) locale/@AB_CD@/browser/aboutCertError.dtd (%chrome/aboutCertError.dtd) locale/@AB_CD@/browser/browser.properties (%chrome/browser.properties) locale/@AB_CD@/browser/config.dtd (%chrome/config.dtd) diff --git a/mobile/android/themes/core/aboutApps.css b/mobile/android/themes/core/aboutApps.css deleted file mode 100644 index f10b351d53f..00000000000 --- a/mobile/android/themes/core/aboutApps.css +++ /dev/null @@ -1,43 +0,0 @@ - -html { - font-family: "Droid Sans",helvetica,arial,clean,sans-serif; - font-size: 18px; - background-image: url("chrome://browser/skin/images/about-bg-lightblue.png"); - -moz-text-size-adjust: none; -} - -#main-container { - margin: 1em; - padding: 1em; - border-radius: 10px; - border: 1px solid grey; - background-color: white; -} - -.spacer { - clear: both; -} - -.app { - float: left; - cursor: pointer; - text-align: center; - margin: 1em; - width: 70px; - height: 85px; - font-size: 10px; -} - -.app img { - width: 64px; - height: 64px; -} - -#noapps { - padding: 1em; - text-align: center; -} - -.hidden { - display: none; -} diff --git a/mobile/android/themes/core/jar.mn b/mobile/android/themes/core/jar.mn index 9d912de5ceb..4b308be2c87 100644 --- a/mobile/android/themes/core/jar.mn +++ b/mobile/android/themes/core/jar.mn @@ -5,7 +5,6 @@ chrome.jar: skin/aboutPage.css (aboutPage.css) skin/about.css (about.css) skin/aboutAddons.css (aboutAddons.css) - skin/aboutApps.css (aboutApps.css) * skin/browser.css (browser.css) * skin/content.css (content.css) skin/config.css (config.css) From 8398dd7c18b5477412371bd14adc2aa79414221b Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Tue, 27 Mar 2012 15:20:27 -0700 Subject: [PATCH 067/113] Backed out changeset 5f20ab3487db (bug 697309) --- mobile/android/chrome/content/browser.js | 2 - mobile/android/chrome/content/browser.xul | 1 - mobile/android/chrome/content/webapps.js | 65 ------------------- mobile/android/chrome/jar.mn | 3 +- mobile/android/installer/package-manifest.in | 6 +- .../locales/en-US/chrome/browser.properties | 3 - .../android/locales/en-US/chrome/webapps.dtd | 7 ++ mobile/android/locales/jar.mn | 1 + 8 files changed, 12 insertions(+), 76 deletions(-) delete mode 100644 mobile/android/chrome/content/webapps.js create mode 100644 mobile/android/locales/en-US/chrome/webapps.dtd diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 4642dea1d3c..24ab3909720 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -236,7 +236,6 @@ var BrowserApp = { CharacterEncoding.init(); SearchEngines.init(); ActivityObserver.init(); - WebappsUI.init(); // Init LoginManager Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); @@ -416,7 +415,6 @@ var BrowserApp = { ConsoleAPI.uninit(); CharacterEncoding.uninit(); SearchEngines.uninit(); - WebappsUI.uninit(); }, // This function returns false during periods where the browser displayed document is diff --git a/mobile/android/chrome/content/browser.xul b/mobile/android/chrome/content/browser.xul index f803a05bc79..30aa819f16e 100644 --- a/mobile/android/chrome/content/browser.xul +++ b/mobile/android/chrome/content/browser.xul @@ -9,7 +9,6 @@ + + + +
+
&aboutApps.title;
+ +
+
+
+
+
+
+ + diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 67376240cde..204eba9fa26 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1288,7 +1288,9 @@ var NativeWindow = { let popupNode = aEvent.originalTarget; let title = ""; - if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || + if (popupNode.hasAttribute("title")) { + title = popupNode.getAttribute("title") + } else if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || (popupNode instanceof Ci.nsIDOMHTMLAreaElement && popupNode.href)) { title = this._getLinkURL(popupNode); } else if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) { diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn index 6161726a02d..710b1fe6269 100644 --- a/mobile/android/chrome/jar.mn +++ b/mobile/android/chrome/jar.mn @@ -10,6 +10,8 @@ chrome.jar: content/aboutCertError.xhtml (content/aboutCertError.xhtml) content/aboutHome.xhtml (content/aboutHome.xhtml) * content/aboutRights.xhtml (content/aboutRights.xhtml) +* content/aboutApps.xhtml (content/aboutApps.xhtml) + content/aboutApps.js (content/aboutApps.js) content/blockedSite.xhtml (content/blockedSite.xhtml) content/languages.properties (content/languages.properties) * content/browser.xul (content/browser.xul) diff --git a/mobile/android/components/AboutRedirector.js b/mobile/android/components/AboutRedirector.js index 1d1c7ecca18..cbf4f68c5e9 100644 --- a/mobile/android/components/AboutRedirector.js +++ b/mobile/android/components/AboutRedirector.js @@ -85,6 +85,10 @@ let modules = { home: { uri: "chrome://browser/content/aboutHome.xhtml", privileged: true + }, + apps: { + uri: "chrome://browser/content/aboutApps.xhtml", + privileged: true } } diff --git a/mobile/android/components/MobileComponents.manifest b/mobile/android/components/MobileComponents.manifest index 81173e7ddc7..d575b29d2d2 100644 --- a/mobile/android/components/MobileComponents.manifest +++ b/mobile/android/components/MobileComponents.manifest @@ -7,6 +7,7 @@ contract @mozilla.org/network/protocol/about;1?what=empty {322ba47e-7047-4f71-ae contract @mozilla.org/network/protocol/about;1?what=rights {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=certerror {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=home {322ba47e-7047-4f71-aebf-cb7d69325cd9} +contract @mozilla.org/network/protocol/about;1?what=apps {322ba47e-7047-4f71-aebf-cb7d69325cd9} #ifdef MOZ_SAFE_BROWSING contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9} #endif diff --git a/mobile/android/locales/en-US/chrome/aboutApps.dtd b/mobile/android/locales/en-US/chrome/aboutApps.dtd new file mode 100644 index 00000000000..c7ea6d37ce8 --- /dev/null +++ b/mobile/android/locales/en-US/chrome/aboutApps.dtd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/mobile/android/locales/en-US/chrome/aboutApps.properties b/mobile/android/locales/en-US/chrome/aboutApps.properties new file mode 100644 index 00000000000..86d5a7c049d --- /dev/null +++ b/mobile/android/locales/en-US/chrome/aboutApps.properties @@ -0,0 +1,2 @@ +appsContext.uninstall=Uninstall +appsContext.shortcut=Add to Home Screen diff --git a/mobile/android/locales/jar.mn b/mobile/android/locales/jar.mn index 7e1fb7a88eb..ff6eb31ef9c 100644 --- a/mobile/android/locales/jar.mn +++ b/mobile/android/locales/jar.mn @@ -5,6 +5,8 @@ locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd) locale/@AB_CD@/browser/aboutAddons.dtd (%chrome/aboutAddons.dtd) locale/@AB_CD@/browser/aboutAddons.properties (%chrome/aboutAddons.properties) + locale/@AB_CD@/browser/aboutApps.dtd (%chrome/aboutApps.dtd) + locale/@AB_CD@/browser/aboutApps.properties (%chrome/aboutApps.properties) locale/@AB_CD@/browser/aboutCertError.dtd (%chrome/aboutCertError.dtd) locale/@AB_CD@/browser/browser.properties (%chrome/browser.properties) locale/@AB_CD@/browser/config.dtd (%chrome/config.dtd) diff --git a/mobile/android/themes/core/aboutApps.css b/mobile/android/themes/core/aboutApps.css new file mode 100644 index 00000000000..f10b351d53f --- /dev/null +++ b/mobile/android/themes/core/aboutApps.css @@ -0,0 +1,43 @@ + +html { + font-family: "Droid Sans",helvetica,arial,clean,sans-serif; + font-size: 18px; + background-image: url("chrome://browser/skin/images/about-bg-lightblue.png"); + -moz-text-size-adjust: none; +} + +#main-container { + margin: 1em; + padding: 1em; + border-radius: 10px; + border: 1px solid grey; + background-color: white; +} + +.spacer { + clear: both; +} + +.app { + float: left; + cursor: pointer; + text-align: center; + margin: 1em; + width: 70px; + height: 85px; + font-size: 10px; +} + +.app img { + width: 64px; + height: 64px; +} + +#noapps { + padding: 1em; + text-align: center; +} + +.hidden { + display: none; +} diff --git a/mobile/android/themes/core/jar.mn b/mobile/android/themes/core/jar.mn index 4b308be2c87..9d912de5ceb 100644 --- a/mobile/android/themes/core/jar.mn +++ b/mobile/android/themes/core/jar.mn @@ -5,6 +5,7 @@ chrome.jar: skin/aboutPage.css (aboutPage.css) skin/about.css (about.css) skin/aboutAddons.css (aboutAddons.css) + skin/aboutApps.css (aboutApps.css) * skin/browser.css (browser.css) * skin/content.css (content.css) skin/config.css (config.css) From 728b59a9865aa0b43a9a1660d665097e6eb4b436 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Tue, 27 Mar 2012 12:13:13 -0700 Subject: [PATCH 079/113] Bug 736591 - Check for exceeding the operation limit when iteratively matching a global regexp against a string. r=luke --HG-- extra : rebase_source : 2a24b4a15909cfd2c04347b60131175fe77e83fe --- js/src/jsstr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 7d037911059..a19acda4c52 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1560,6 +1560,8 @@ DoMatch(JSContext *cx, RegExpStatics *res, JSString *str, RegExpShared &re, if (re.global()) { RegExpExecType type = (flags & TEST_GLOBAL_BIT) ? RegExpTest : RegExpExec; for (size_t count = 0, i = 0, length = str->length(); i <= length; ++count) { + if (!JS_CHECK_OPERATION_LIMIT(cx)) + return false; if (!ExecuteRegExp(cx, res, re, linearStr, chars, length, &i, type, rval)) return false; if (!Matched(type, *rval)) From 25c7f8484c210e8dd4585a085f1da3abc6c15459 Mon Sep 17 00:00:00 2001 From: Brian Nicholson Date: Tue, 27 Mar 2012 15:54:01 -0700 Subject: [PATCH 080/113] Bug 739698 - SearchEngines cleanup in browser.js. r=mfinkle --- mobile/android/chrome/content/browser.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 204eba9fa26..851f1a065f0 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -938,8 +938,6 @@ var BrowserApp = { } else if (aTopic == "Viewport:Change") { if (this.isBrowserContentDocumentDisplayed()) this.selectedTab.setViewport(JSON.parse(aData)); - } else if (aTopic == "SearchEngines:Get") { - this.getSearchEngines(); } else if (aTopic == "Passwords:Init") { // Force creation/upgrade of signons.sqlite let storage = Cc["@mozilla.org/login-manager/storage/mozStorage;1"].getService(Ci.nsILoginManagerStorage); From 4fda1ef56799a0b038b9f62d2608ea40f3aae7ba Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 27 Mar 2012 18:23:29 -0400 Subject: [PATCH 081/113] bug 648265 - non-xpcom accessible table interface and casting r=surkov sr=neil --- accessible/src/atk/Makefile.in | 2 + accessible/src/atk/nsMaiInterfaceTable.cpp | 26 ++- accessible/src/base/Makefile.in | 3 +- accessible/src/base/nsARIAGridAccessible.cpp | 30 +--- accessible/src/base/nsARIAGridAccessible.h | 14 +- accessible/src/base/nsAccessible.h | 7 + accessible/src/generic/TableAccessible.h | 170 ++++++++++++++++++ accessible/src/html/Makefile.in | 2 + accessible/src/html/nsHTMLTableAccessible.cpp | 49 ++--- accessible/src/html/nsHTMLTableAccessible.h | 25 ++- accessible/src/xpcom/Makefile.in | 2 + accessible/src/xpcom/xpcAccessibleTable.cpp | 34 ++++ accessible/src/xpcom/xpcAccessibleTable.h | 63 +++++++ accessible/src/xul/Makefile.in | 2 + accessible/src/xul/nsXULListboxAccessible.cpp | 30 ++-- accessible/src/xul/nsXULListboxAccessible.h | 17 +- .../src/xul/nsXULTreeGridAccessible.cpp | 24 +-- accessible/src/xul/nsXULTreeGridAccessible.h | 14 +- 18 files changed, 400 insertions(+), 114 deletions(-) create mode 100644 accessible/src/generic/TableAccessible.h create mode 100644 accessible/src/xpcom/xpcAccessibleTable.cpp create mode 100644 accessible/src/xpcom/xpcAccessibleTable.h diff --git a/accessible/src/atk/Makefile.in b/accessible/src/atk/Makefile.in index 9fe1f48b857..2bd347beae8 100644 --- a/accessible/src/atk/Makefile.in +++ b/accessible/src/atk/Makefile.in @@ -99,7 +99,9 @@ endif LOCAL_INCLUDES += \ -I$(srcdir) \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(topsrcdir)/other-licenses/atk-1.0 \ $(NULL) diff --git a/accessible/src/atk/nsMaiInterfaceTable.cpp b/accessible/src/atk/nsMaiInterfaceTable.cpp index 1c8971d4fbc..158e490dd7a 100644 --- a/accessible/src/atk/nsMaiInterfaceTable.cpp +++ b/accessible/src/atk/nsMaiInterfaceTable.cpp @@ -42,12 +42,14 @@ #include "nsAccessibleWrap.h" #include "nsAccUtils.h" #include "nsIAccessibleTable.h" +#include "TableAccessible.h" #include "nsMai.h" #include "nsArrayUtils.h" -extern "C" { +using namespace mozilla::a11y; +extern "C" { static AtkObject* refAtCB(AtkTable *aTable, gint aRow, gint aColumn) { @@ -208,23 +210,17 @@ getRowExtentAtCB(AtkTable *aTable, } static AtkObject* -getCaptionCB(AtkTable *aTable) +getCaptionCB(AtkTable* aTable) { - nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable)); - if (!accWrap) - return nsnull; + nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable)); + if (!accWrap) + return nsnull; - nsCOMPtr accTable; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable), - getter_AddRefs(accTable)); - NS_ENSURE_TRUE(accTable, nsnull); + TableAccessible* table = accWrap->AsTable(); + NS_ENSURE_TRUE(table, nsnull); - nsCOMPtr caption; - nsresult rv = accTable->GetCaption(getter_AddRefs(caption)); - if (NS_FAILED(rv) || !caption) - return nsnull; - - return nsAccessibleWrap::GetAtkObject(caption); + nsAccessible* caption = table->Caption(); + return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull; } static const gchar* diff --git a/accessible/src/base/Makefile.in b/accessible/src/base/Makefile.in index 7fd861756c4..b71efb0c1ba 100644 --- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -104,8 +104,9 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir) \ - -I$(srcdir)/../xpcom \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/style \ diff --git a/accessible/src/base/nsARIAGridAccessible.cpp b/accessible/src/base/nsARIAGridAccessible.cpp index ed7304d59aa..4a985b7a0fc 100644 --- a/accessible/src/base/nsARIAGridAccessible.cpp +++ b/accessible/src/base/nsARIAGridAccessible.cpp @@ -58,7 +58,7 @@ using namespace mozilla::a11y; nsARIAGridAccessible:: nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessibleWrap(aContent, aDoc) + nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) { } @@ -70,21 +70,18 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible, nsIAccessibleTable) //////////////////////////////////////////////////////////////////////////////// -// nsIAccessibleTable +//nsAccessNode -NS_IMETHODIMP -nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption) +void +nsARIAGridAccessible::Shutdown() { - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - // XXX: should be pointed by aria-labelledby on grid? - return NS_ERROR_NOT_IMPLEMENTED; + mTable = nsnull; + nsAccessibleWrap::Shutdown(); } +//////////////////////////////////////////////////////////////////////////////// +// nsIAccessibleTable + NS_IMETHODIMP nsARIAGridAccessible::GetSummary(nsAString &aSummary) { @@ -710,15 +707,6 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn) return NS_OK; } -NS_IMETHODIMP -nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) -{ - NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); - *aIsProbablyForLayout = false; - - return NS_OK; -} - //////////////////////////////////////////////////////////////////////////////// // Protected diff --git a/accessible/src/base/nsARIAGridAccessible.h b/accessible/src/base/nsARIAGridAccessible.h index 9a1806bc701..c17aaa99b4e 100644 --- a/accessible/src/base/nsARIAGridAccessible.h +++ b/accessible/src/base/nsARIAGridAccessible.h @@ -42,12 +42,16 @@ #include "nsIAccessibleTable.h" #include "nsHyperTextAccessibleWrap.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" /** * Accessible for ARIA grid and treegrid. */ class nsARIAGridAccessible : public nsAccessibleWrap, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc); @@ -56,7 +60,13 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable - NS_DECL_NSIACCESSIBLETABLE + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + + // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } + + // nsAccessNode + virtual void Shutdown(); protected: /** diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index e4203016756..daa0696bc33 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -66,6 +66,11 @@ class nsHTMLImageMapAccessible; class nsHTMLLIAccessible; struct nsRoleMapEntry; class Relation; +namespace mozilla { +namespace a11y { +class TableAccessible; +} +} class nsTextAccessible; struct nsRect; @@ -471,6 +476,8 @@ public: inline bool IsRoot() const { return mFlags & eRootAccessible; } nsRootAccessible* AsRoot(); + virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; } + inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; } nsTextAccessible* AsTextLeaf(); diff --git a/accessible/src/generic/TableAccessible.h b/accessible/src/generic/TableAccessible.h new file mode 100644 index 00000000000..694fb02ed15 --- /dev/null +++ b/accessible/src/generic/TableAccessible.h @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef TABLE_ACCESSIBLE_H +#define TABLE_ACCESSIBLE_H + +#include "nsString.h" +#include "nsTArray.h" +#include "prtypes.h" + +class nsAccessible; + +namespace mozilla { +namespace a11y { + +/** + * Accessible table interface. + */ +class TableAccessible +{ +public: + + /** + * Return the caption accessible if any for this table. + */ + virtual nsAccessible* Caption() { return nsnull; } + + /** + * Get the summary for this table. + */ + virtual void Summary(nsString& aSummary) { aSummary.Truncate(); } + + /** + * Return the number of columns in the table. + */ + virtual PRUint32 ColCount() { return 0; } + + /** + * Return the number of rows in the table. + */ + virtual PRUint32 RowCount() { return 0; } + + /** + * Return the accessible for the cell at the given row and column indices. + */ + virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; } + + /** + * Return the index of the cell at the given row and column. + */ + virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; } + + /** + * Return the column index of the cell with the given index. + */ + virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; } + + /** + * Return the row index of the cell with the given index. + */ + virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; } + + /** + * Get the row and column indices for the cell at the given index. + */ + virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx, + PRInt32* aColIdx) {} + + /** + * Return the number of columns occupied by the cell at the given row and + * column indices. + */ + virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; } + + /** + * Return the number of rows occupied by the cell at the given row and column + * indices. + */ + virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; } + + /** + * Get the description of the given column. + */ + virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription) + { aDescription.Truncate(); } + + /** + * Get the description for the given row. + */ + virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription) + { aDescription.Truncate(); } + + /** + * Return true if the given column is selected. + */ + virtual bool IsColSelected(PRUint32 aColIdx) { return false; } + + /** + * Return true if the given row is selected. + */ + virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; } + + /** + * Return true if the given cell is selected. + */ + virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; } + + /** + * Return the number of selected cells. + */ + virtual PRUint32 SelectedCellCount() { return 0; } + + /** + * Return the number of selected columns. + */ + virtual PRUint32 SelectedColCount() { return 0; } + + /** + * Return the number of selected rows. + */ + virtual PRUint32 SelectedRowCount() { return 0; } + + /** + * Get the set of selected cells. + */ + virtual void SelectedCells(nsTArray* aCells) {} + + /** + * Get the set of selected column indices. + */ + virtual void SelectedColIndices(nsTArray* aCols) {} + + /** + * Get the set of selected row indices. + */ + virtual void SelectedRowIndices(nsTArray* aRows) {} + + /** + * Select the given column unselecting any other selected columns. + */ + virtual void SelectCol(PRUint32 aColIdx) {} + + /** + * Select the given row unselecting all other previously selected rows. + */ + virtual void SelectRow(PRUint32 aRowIdx) {} + + /** + * Unselect the given column leaving other selected columns selected. + */ + virtual void UnselectCol(PRUint32 aColIdx) {} + + /** + * Unselect the given row leaving other selected rows selected. + */ + virtual void UnselectRow(PRUint32 aRowIdx) {} + + /** + * Return true if the table is probably for layout. + */ + virtual bool IsProbablyLayoutTable() { return false; } +}; + +} // namespace a11y +} // namespace mozilla + +#endif diff --git a/accessible/src/html/Makefile.in b/accessible/src/html/Makefile.in index 7820e4a8b1d..ebd86307696 100644 --- a/accessible/src/html/Makefile.in +++ b/accessible/src/html/Makefile.in @@ -73,6 +73,8 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ $(NULL) diff --git a/accessible/src/html/nsHTMLTableAccessible.cpp b/accessible/src/html/nsHTMLTableAccessible.cpp index a5547bb3d1c..a09c2740b68 100644 --- a/accessible/src/html/nsHTMLTableAccessible.cpp +++ b/accessible/src/html/nsHTMLTableAccessible.cpp @@ -436,7 +436,7 @@ nsHTMLTableHeaderCellAccessible::NativeRole() nsHTMLTableAccessible:: nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessibleWrap(aContent, aDoc) + nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) { } @@ -446,6 +446,16 @@ nsHTMLTableAccessible:: NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible, nsHTMLTableAccessible, nsIAccessibleTable) +//////////////////////////////////////////////////////////////////////////////// +//nsAccessNode + +void +nsHTMLTableAccessible::Shutdown() +{ + mTable = nsnull; + nsAccessibleWrap::Shutdown(); +} + //////////////////////////////////////////////////////////////////////////////// // nsHTMLTableAccessible: nsAccessible implementation @@ -511,9 +521,7 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes); NS_ENSURE_SUCCESS(rv, rv); - bool isProbablyForLayout; - IsProbablyForLayout(&isProbablyForLayout); - if (isProbablyForLayout) { + if (IsProbablyLayoutTable()) { nsAutoString oldValueUnused; aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"), NS_LITERAL_STRING("true"), oldValueUnused); @@ -538,13 +546,11 @@ nsHTMLTableAccessible::RelationByType(PRUint32 aType) //////////////////////////////////////////////////////////////////////////////// // nsHTMLTableAccessible: nsIAccessibleTable implementation -NS_IMETHODIMP -nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption) +nsAccessible* +nsHTMLTableAccessible::Caption() { - NS_ENSURE_ARG_POINTER(aCaption); - - NS_IF_ADDREF(*aCaption = Caption()); - return NS_OK; + nsAccessible* child = mChildren.SafeElementAt(0, nsnull); + return child && child->Role() == roles::CAPTION ? child : nsnull; } NS_IMETHODIMP @@ -1307,8 +1313,7 @@ nsHTMLTableAccessible::Description(nsString& aDescription) #ifdef SHOW_LAYOUT_HEURISTIC if (aDescription.IsEmpty()) { - bool isProbablyForLayout; - IsProbablyForLayout(&isProbablyForLayout); + bool isProbablyForLayout = IsProbablyLayoutTable(); aDescription = mLayoutHeuristic; } #ifdef DEBUG_A11Y @@ -1357,8 +1362,8 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName, return !!foundItem; } -NS_IMETHODIMP -nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) +bool +nsHTMLTableAccessible::IsProbablyLayoutTable() { // Implement a heuristic to determine if table is most likely used for layout // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells @@ -1370,18 +1375,16 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release #ifdef SHOW_LAYOUT_HEURISTIC #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \ - { *aIsProbablyForLayout = isLayout; \ - mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \ - mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; } + { \ + mLayoutHeuristic = isLayout ? \ + NS_LITERAL_STRING("layout table: " heuristic) : \ + NS_LITERAL_STRING("data table: " heuristic); \ + return isLayout; \ + } #else -#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; } +#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; } #endif - *aIsProbablyForLayout = false; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - nsDocAccessible* docAccessible = Document(); if (docAccessible) { PRUint64 docState = docAccessible->State(); diff --git a/accessible/src/html/nsHTMLTableAccessible.h b/accessible/src/html/nsHTMLTableAccessible.h index bf10061ba03..4691bd9fc6d 100644 --- a/accessible/src/html/nsHTMLTableAccessible.h +++ b/accessible/src/html/nsHTMLTableAccessible.h @@ -41,6 +41,8 @@ #include "nsHyperTextAccessibleWrap.h" #include "nsIAccessibleTable.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" class nsITableLayout; class nsITableCellLayout; @@ -121,16 +123,28 @@ public: } class nsHTMLTableAccessible : public nsAccessibleWrap, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLETABLE NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID) + // nsIAccessible Table + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + + // TableAccessible + virtual nsAccessible* Caption(); + virtual bool IsProbablyLayoutTable(); + + // nsAccessNode + virtual void Shutdown(); + // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual void Description(nsString& aDescription); virtual nsresult GetNameInternal(nsAString& aName); virtual mozilla::a11y::role NativeRole(); @@ -138,13 +152,6 @@ public: virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); virtual Relation RelationByType(PRUint32 aRelationType); - // TableAccessible - inline nsAccessible* Caption() const - { - nsAccessible* child = mChildren.SafeElementAt(0, nsnull); - return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull; - } - // nsHTMLTableAccessible /** diff --git a/accessible/src/xpcom/Makefile.in b/accessible/src/xpcom/Makefile.in index d270bd35ab3..31ffd6b24f1 100644 --- a/accessible/src/xpcom/Makefile.in +++ b/accessible/src/xpcom/Makefile.in @@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1 CPPSRCS = \ nsAccEvent.cpp \ nsAccessibleRelation.cpp \ + xpcAccessibleTable.cpp \ $(NULL) # we don't want the shared lib, but we want to force the creation of a static lib. @@ -59,4 +60,5 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ $(NULL) diff --git a/accessible/src/xpcom/xpcAccessibleTable.cpp b/accessible/src/xpcom/xpcAccessibleTable.cpp new file mode 100644 index 00000000000..9923490ecbe --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTable.cpp @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xpcAccessibleTable.h" + +#include "nsAccessible.h" +#include "TableAccessible.h" + +nsresult +xpcAccessibleTable::GetCaption(nsIAccessible** aCaption) +{ + NS_ENSURE_ARG_POINTER(aCaption); + *aCaption = nsnull; + if (!mTable) + return NS_ERROR_FAILURE; + + NS_IF_ADDREF(*aCaption = mTable->Caption()); + return NS_OK; +} + +nsresult +xpcAccessibleTable::IsProbablyForLayout(bool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = false; + if (!mTable) + return NS_ERROR_FAILURE; + + *aResult = mTable->IsProbablyLayoutTable(); + return NS_OK; +} diff --git a/accessible/src/xpcom/xpcAccessibleTable.h b/accessible/src/xpcom/xpcAccessibleTable.h new file mode 100644 index 00000000000..afec1960177 --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTable.h @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ +#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ + +#include "nscore.h" + +class nsIAccessible; +namespace mozilla { +namespace a11y { +class TableAccessible; +} +} + +class xpcAccessibleTable +{ +public: + xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { } + + nsresult GetCaption(nsIAccessible** aCaption); + nsresult IsProbablyForLayout(bool* aIsForLayout); + +protected: + mozilla::a11y::TableAccessible* mTable; +}; + +#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \ + NS_IMETHOD GetCaption(nsIAccessible** aCaption) \ + { return xpcAccessibleTable::GetCaption(aCaption); } \ + NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \ + NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \ + NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \ + NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \ + NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \ + NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \ + NS_IMETHOD IsProbablyForLayout(bool* aResult) \ + { return xpcAccessibleTable::IsProbablyForLayout(aResult); } \ + +#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ diff --git a/accessible/src/xul/Makefile.in b/accessible/src/xul/Makefile.in index 05a4bc7492e..e86dcd64420 100644 --- a/accessible/src/xul/Makefile.in +++ b/accessible/src/xul/Makefile.in @@ -72,7 +72,9 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir) \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ $(NULL) diff --git a/accessible/src/xul/nsXULListboxAccessible.cpp b/accessible/src/xul/nsXULListboxAccessible.cpp index 4adcc94d0e7..971620d3598 100644 --- a/accessible/src/xul/nsXULListboxAccessible.cpp +++ b/accessible/src/xul/nsXULListboxAccessible.cpp @@ -134,7 +134,7 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex) nsXULListboxAccessible:: nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - XULSelectControlAccessible(aContent, aDoc) + XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this) { nsIContent* parentContent = mContent->GetParent(); if (parentContent) { @@ -164,6 +164,16 @@ nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) return NS_ERROR_NO_INTERFACE; } +//////////////////////////////////////////////////////////////////////////////// +//nsAccessNode + +void +nsXULListboxAccessible::Shutdown() +{ + mTable = nsnull; + XULSelectControlAccessible::Shutdown(); +} + bool nsXULListboxAccessible::IsMulticolumn() { @@ -229,15 +239,6 @@ nsXULListboxAccessible::NativeRole() //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible. nsIAccessibleTable -NS_IMETHODIMP -nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption) -{ - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - - return NS_OK; -} - NS_IMETHODIMP nsXULListboxAccessible::GetSummary(nsAString &aSummary) { @@ -820,15 +821,6 @@ nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn) return NS_OK; } -NS_IMETHODIMP -nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) -{ - NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); - *aIsProbablyForLayout = false; - - return NS_OK; -} - //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible: Widgets diff --git a/accessible/src/xul/nsXULListboxAccessible.h b/accessible/src/xul/nsXULListboxAccessible.h index be49fadc6c3..06fdd3470c0 100644 --- a/accessible/src/xul/nsXULListboxAccessible.h +++ b/accessible/src/xul/nsXULListboxAccessible.h @@ -40,11 +40,12 @@ #ifndef __nsXULListboxAccessible_h__ #define __nsXULListboxAccessible_h__ -#include "nsIAccessibleTable.h" - #include "nsCOMPtr.h" #include "nsXULMenuAccessible.h" #include "nsBaseWidgetAccessible.h" +#include "nsIAccessibleTable.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" #include "XULSelectControlAccessible.h" class nsIWeakReference; @@ -90,19 +91,27 @@ public: * A class the represents the XUL Listbox widget. */ class nsXULListboxAccessible : public XULSelectControlAccessible, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc); virtual ~nsXULListboxAccessible() {} NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLETABLE + + // nsIAccessibleTable + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE // nsIAccessible NS_IMETHOD GetValue(nsAString& aValue); + // nsAccessNode + virtual void Shutdown(); + // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual mozilla::a11y::role NativeRole(); virtual PRUint64 NativeState(); diff --git a/accessible/src/xul/nsXULTreeGridAccessible.cpp b/accessible/src/xul/nsXULTreeGridAccessible.cpp index c3ca0269103..acd46c643ff 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -58,7 +58,7 @@ using namespace mozilla::a11y; nsXULTreeGridAccessible:: nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsXULTreeAccessible(aContent, aDoc) + nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this) { } @@ -72,15 +72,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible, //////////////////////////////////////////////////////////////////////////////// // nsXULTreeGridAccessible: nsIAccessibleTable implementation -NS_IMETHODIMP -nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption) -{ - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - - return IsDefunct() ? NS_ERROR_FAILURE : NS_OK; -} - NS_IMETHODIMP nsXULTreeGridAccessible::GetSummary(nsAString &aSummary) { @@ -570,13 +561,14 @@ nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex) return NS_OK; } -NS_IMETHODIMP -nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) -{ - NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); - *aIsProbablyForLayout = false; +//////////////////////////////////////////////////////////////////////////////// +// nsXULTreeGridAccessible: nsAccessNode implementation - return NS_OK; +void +nsXULTreeGridAccessible::Shutdown() +{ + mTable = nsnull; + nsXULTreeAccessible::Shutdown(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/xul/nsXULTreeGridAccessible.h b/accessible/src/xul/nsXULTreeGridAccessible.h index 0f3771373f8..bed9d95a157 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.h +++ b/accessible/src/xul/nsXULTreeGridAccessible.h @@ -39,15 +39,17 @@ #ifndef __nsXULTreeGridAccessible_h__ #define __nsXULTreeGridAccessible_h__ -#include "nsIAccessibleTable.h" - #include "nsXULTreeAccessible.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" /** * Represents accessible for XUL tree in the case when it has multiple columns. */ class nsXULTreeGridAccessible : public nsXULTreeAccessible, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc); @@ -56,9 +58,13 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable - NS_DECL_NSIACCESSIBLETABLE + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + + // nsAccessNode + virtual void Shutdown(); // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual mozilla::a11y::role NativeRole(); protected: From a85ca7ae683e50670f8869721e7b21ef3bf71b8b Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 27 Mar 2012 18:24:06 -0400 Subject: [PATCH 082/113] bug 648265 - reduce includes of nsXULTreeAccessible.h and nsHTMLTableAccessible.h r=surkov --- accessible/src/base/AccEvent.cpp | 3 --- accessible/src/base/nsAccUtils.cpp | 2 -- accessible/src/base/nsRootAccessible.h | 4 +--- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/accessible/src/base/AccEvent.cpp b/accessible/src/base/AccEvent.cpp index f3cf38eb626..3b34da027a5 100644 --- a/accessible/src/base/AccEvent.cpp +++ b/accessible/src/base/AccEvent.cpp @@ -44,9 +44,6 @@ #include "nsApplicationAccessibleWrap.h" #include "nsDocAccessible.h" #include "nsIAccessibleText.h" -#ifdef MOZ_XUL -#include "nsXULTreeAccessible.h" -#endif #include "nsAccEvent.h" #include "States.h" diff --git a/accessible/src/base/nsAccUtils.cpp b/accessible/src/base/nsAccUtils.cpp index 29f0a129daf..2c472d34992 100644 --- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -47,9 +47,7 @@ #include "nsARIAMap.h" #include "nsDocAccessible.h" #include "nsHyperTextAccessible.h" -#include "nsHTMLTableAccessible.h" #include "nsTextAccessible.h" -#include "nsXULTreeGridAccessible.h" #include "nsIDOMXULContainerElement.h" #include "nsIDOMXULSelectCntrlEl.h" diff --git a/accessible/src/base/nsRootAccessible.h b/accessible/src/base/nsRootAccessible.h index 884ef5d6500..1bef60b679c 100644 --- a/accessible/src/base/nsRootAccessible.h +++ b/accessible/src/base/nsRootAccessible.h @@ -41,15 +41,13 @@ #include "nsCaretAccessible.h" #include "nsDocAccessibleWrap.h" -#ifdef MOZ_XUL -#include "nsXULTreeAccessible.h" -#endif #include "nsHashtable.h" #include "nsCaretAccessible.h" #include "nsIDocument.h" #include "nsIDOMEventListener.h" +class nsXULTreeAccessible; class Relation; #define NS_ROOTACCESSIBLE_IMPL_CID \ From 2769592846f8c82ce6081173e4e418cfd1a55588 Mon Sep 17 00:00:00 2001 From: Eric Chou Date: Tue, 27 Mar 2012 19:17:35 -0400 Subject: [PATCH 083/113] Bug 731361 - Change bluetooth firmware loading to use a DOMRequest based API. r=bent --- dom/base/Navigator.cpp | 2 +- dom/bluetooth/BluetoothAdapter.cpp | 161 ++++++++++++----------- dom/bluetooth/BluetoothAdapter.h | 11 +- dom/bluetooth/nsIDOMBluetoothAdapter.idl | 7 +- 4 files changed, 97 insertions(+), 84 deletions(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 96ef78ba452..bf5d62e13f3 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1153,7 +1153,7 @@ Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth) nsCOMPtr window = do_QueryReferent(mWindow); NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); - mBluetooth = new bluetooth::BluetoothAdapter(); + mBluetooth = new bluetooth::BluetoothAdapter(window); bluetooth = mBluetooth; } diff --git a/dom/bluetooth/BluetoothAdapter.cpp b/dom/bluetooth/BluetoothAdapter.cpp index 0a1ec123a27..424d4a7b025 100644 --- a/dom/bluetooth/BluetoothAdapter.cpp +++ b/dom/bluetooth/BluetoothAdapter.cpp @@ -4,13 +4,33 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "BluetoothAdapter.h" + #include "nsDOMClassInfo.h" #include "nsDOMEvent.h" #include "nsThreadUtils.h" #include "nsXPCOMCIDInternal.h" #include "mozilla/LazyIdleThread.h" +#include "mozilla/Util.h" #include -#include "BluetoothAdapter.h" + +static void +FireEnabled(bool aResult, nsIDOMDOMRequest* aDomRequest) +{ + nsCOMPtr rs = do_GetService("@mozilla.org/dom/dom-request-service;1"); + + if (!rs) { + NS_WARNING("No DOMRequest Service!"); + return; + } + + mozilla::DebugOnly rv = aResult ? + rs->FireSuccess(aDomRequest, JSVAL_VOID) : + rs->FireError(aDomRequest, + NS_LITERAL_STRING("Bluetooth firmware loading failed")); + + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bluetooth firmware loading failed"); +} USING_BLUETOOTH_NAMESPACE @@ -67,11 +87,16 @@ static bool EnsureBluetoothInit() { class ToggleBtResultTask : public nsRunnable { public: - ToggleBtResultTask(nsRefPtr& adapterPtr, bool result) - : mResult(result) + ToggleBtResultTask(nsRefPtr& adapterPtr, + nsCOMPtr& req, + bool enabled, + bool result) + : mResult(result), + mEnabled(enabled) { MOZ_ASSERT(!NS_IsMainThread()); + mDOMRequest.swap(req); mAdapterPtr.swap(adapterPtr); } @@ -79,29 +104,35 @@ class ToggleBtResultTask : public nsRunnable { MOZ_ASSERT(NS_IsMainThread()); - if (!mResult) { - //TODO:Bug-731361 - NS_WARNING("BT firmware loading fails.\n"); + // Update bt power status to BluetoothAdapter only if loading bluetooth + // firmware succeeds. + if (mResult) { + mAdapterPtr->SetEnabledInternal(mEnabled); } - + + FireEnabled(mResult, mDOMRequest); + //mAdapterPtr must be null before returning to prevent the background //thread from racing to release it during the destruction of this runnable. - mAdapterPtr->FirePowered(); mAdapterPtr = nsnull; + mDOMRequest = nsnull; return NS_OK; } private: nsRefPtr mAdapterPtr; + nsCOMPtr mDOMRequest; + bool mEnabled; bool mResult; }; class ToggleBtTask : public nsRunnable { public: - ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr) - : mOnOff(onOff), + ToggleBtTask(bool enabled, nsIDOMDOMRequest* req, BluetoothAdapter* adapterPtr) + : mEnabled(enabled), + mDOMRequest(req), mAdapterPtr(adapterPtr) { MOZ_ASSERT(NS_IsMainThread()); @@ -111,23 +142,36 @@ class ToggleBtTask : public nsRunnable { MOZ_ASSERT(!NS_IsMainThread()); + bool result; + +#ifdef MOZ_WIDGET_GONK + // Platform specific check for gonk until object is divided in + // different implementations per platform. Linux doesn't require + // bluetooth firmware loading, but code should work otherwise. if(!EnsureBluetoothInit()) { NS_ERROR("Failed to load bluedroid library.\n"); return NS_ERROR_FAILURE; } - bool result; + // return 1 if it's enabled, 0 if it's disabled, and -1 on error + int isEnabled = sBluedroidFunctions.bt_is_enabled(); - //Toggle BT here - - if (mOnOff) { - result = sBluedroidFunctions.bt_enable(); + if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) { + result = true; + } else if (isEnabled < 0) { + result = false; + } else if (mEnabled) { + result = (sBluedroidFunctions.bt_enable() == 0) ? true : false; } else { - result = sBluedroidFunctions.bt_disable(); + result = (sBluedroidFunctions.bt_disable() == 0) ? true : false; } +#else + result = true; + NS_WARNING("No bluetooth support in this build configuration, faking a success event instead"); +#endif // Create a result thread and pass it to Main Thread, - nsCOMPtr resultRunnable = new ToggleBtResultTask(mAdapterPtr, result); + nsCOMPtr resultRunnable = new ToggleBtResultTask(mAdapterPtr, mDOMRequest, mEnabled, result); if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) { NS_WARNING("Failed to dispatch to main thread!"); @@ -137,8 +181,9 @@ class ToggleBtTask : public nsRunnable } private: - bool mOnOff; + bool mEnabled; nsRefPtr mAdapterPtr; + nsCOMPtr mDOMRequest; }; DOMCI_DATA(BluetoothAdapter, BluetoothAdapter) @@ -147,12 +192,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) - NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered) + NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) - NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered) + NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter) @@ -163,77 +208,43 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) -BluetoothAdapter::BluetoothAdapter() - : mPower(false) +BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow *aWindow) { + BindToOwner(aWindow); } NS_IMETHODIMP -BluetoothAdapter::GetPower(bool* aPower) +BluetoothAdapter::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest) { -#ifdef MOZ_WIDGET_GONK - if(!EnsureBluetoothInit()) { - NS_ERROR("Failed to load bluedroid library.\n"); + nsCOMPtr rs = do_GetService("@mozilla.org/dom/dom-request-service;1"); + + if (!rs) { + NS_ERROR("No DOMRequest Service!"); return NS_ERROR_FAILURE; } - *aPower = sBluedroidFunctions.bt_is_enabled(); -#else - *aPower = mPower; -#endif - return NS_OK; -} -NS_IMETHODIMP -BluetoothAdapter::SetPower(bool aPower) -{ - -#ifdef MOZ_WIDGET_GONK - // Platform specific check for gonk until object is divided in - // different implementations per platform. Linux doesn't require - // bluetooth firmware loading, but code should work otherwise. - if(!EnsureBluetoothInit()) { - NS_ERROR("Failed to load bluedroid library.\n"); - return NS_ERROR_FAILURE; - } -#endif - if (mPower != aPower) { - mPower = aPower; - -#ifdef MOZ_WIDGET_GONK - return ToggleBluetoothAsync(); -#endif - } - - return NS_OK; -} - -nsresult -BluetoothAdapter::ToggleBluetoothAsync() -{ + nsCOMPtr request; + nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request)); + NS_ENSURE_SUCCESS(rv, rv); + if (!mToggleBtThread) { mToggleBtThread = new LazyIdleThread(15000); } - nsCOMPtr r = new ToggleBtTask(mPower, this); + nsCOMPtr r = new ToggleBtTask(aEnabled, request, this); - return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL); -} - -nsresult -BluetoothAdapter::FirePowered() -{ - nsRefPtr event = new nsDOMEvent(nsnull, nsnull); - nsresult rv = event->InitEvent(NS_LITERAL_STRING("powered"), false, false); + rv = mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); - rv = event->SetTrusted(true); - NS_ENSURE_SUCCESS(rv, rv); - - bool dummy; - rv = DispatchEvent(event, &dummy); - NS_ENSURE_SUCCESS(rv, rv); + request.forget(aDomRequest); return NS_OK; } -NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered) +NS_IMETHODIMP +BluetoothAdapter::GetEnabled(bool* aEnabled) +{ + *aEnabled = mEnabled; + return NS_OK; +} + diff --git a/dom/bluetooth/BluetoothAdapter.h b/dom/bluetooth/BluetoothAdapter.h index c0559824672..b3a5ccb1f4b 100644 --- a/dom/bluetooth/BluetoothAdapter.h +++ b/dom/bluetooth/BluetoothAdapter.h @@ -10,6 +10,7 @@ #include "BluetoothCommon.h" #include "nsDOMEventTargetHelper.h" #include "nsIDOMBluetoothAdapter.h" +#include "nsIDOMDOMRequest.h" class nsIEventTarget; @@ -27,19 +28,19 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) - BluetoothAdapter(); + BluetoothAdapter(nsPIDOMWindow*); - nsresult FirePowered(); + inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;} protected: - bool mPower; + bool mEnabled; - NS_DECL_EVENT_HANDLER(powered) + NS_DECL_EVENT_HANDLER(enabled) private: nsCOMPtr mToggleBtThread; - nsresult ToggleBluetoothAsync(); }; END_BLUETOOTH_NAMESPACE + #endif diff --git a/dom/bluetooth/nsIDOMBluetoothAdapter.idl b/dom/bluetooth/nsIDOMBluetoothAdapter.idl index b7510691dd0..3bb0f0410f5 100644 --- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl +++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl @@ -6,12 +6,13 @@ #include "nsIDOMEventTarget.idl" +interface nsIDOMDOMRequest; interface nsIDOMEventListener; -[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)] +[scriptable, builtinclass, uuid(ac288eab-dcdb-4f6a-b94d-6c0e286d6a73)] interface nsIDOMBluetoothAdapter : nsIDOMEventTarget { - attribute boolean power; + readonly attribute bool enabled; - attribute nsIDOMEventListener onpowered; + nsIDOMDOMRequest setEnabled(in boolean enabled); }; From 4d7499d6b0b2654b072cca07c8fe08126eda1e16 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 27 Mar 2012 19:17:35 -0400 Subject: [PATCH 084/113] Bug 496653 - Command line option --class does not work, use MOZ_WM_CLASS workaround. r=karlt --- widget/gtk2/nsWindow.cpp | 95 ++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 63 deletions(-) diff --git a/widget/gtk2/nsWindow.cpp b/widget/gtk2/nsWindow.cpp index 9de734e8b12..9d8617276c7 100644 --- a/widget/gtk2/nsWindow.cpp +++ b/widget/gtk2/nsWindow.cpp @@ -3733,14 +3733,11 @@ nsWindow::Create(nsIWidget *aParent, // If we get explicitly moved, the position will also be set. mNeedsResize = true; - nsXPIDLString brandName; - GetBrandName(brandName); - NS_ConvertUTF16toUTF8 cBrand(brandName); - if (mWindowType == eWindowType_dialog) { mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL); SetDefaultIcon(); - gtk_window_set_wmclass(GTK_WINDOW(mShell), "Dialog", cBrand.get()); + gtk_window_set_wmclass(GTK_WINDOW(mShell), "Dialog", + gdk_get_program_class()); gtk_window_set_type_hint(GTK_WINDOW(mShell), GDK_WINDOW_TYPE_HINT_DIALOG); gtk_window_set_transient_for(GTK_WINDOW(mShell), @@ -3781,12 +3778,14 @@ nsWindow::Create(nsIWidget *aParent, // GTK_WINDOW_POPUP, which will use a Window with the // override-redirect attribute (for temporary windows). mShell = gtk_window_new(GTK_WINDOW_POPUP); - gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get()); + gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", + gdk_get_program_class()); } else { // For long-lived windows, their stacking order is managed by // the window manager, as indicated by GTK_WINDOW_TOPLEVEL ... mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get()); + gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", + gdk_get_program_class()); // ... but the window manager does not decorate this window, // nor provide a separate taskbar icon. if (mBorderStyle == eBorderStyle_default) { @@ -3848,7 +3847,8 @@ nsWindow::Create(nsIWidget *aParent, else { // must be eWindowType_toplevel mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL); SetDefaultIcon(); - gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel", cBrand.get()); + gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel", + gdk_get_program_class()); // each toplevel window gets its own window group mWindowGroup = gtk_window_group_new(); @@ -4076,62 +4076,14 @@ nsWindow::SetWindowClass(const nsAString &xulWinType) if (!mShell) return NS_ERROR_FAILURE; -#ifdef MOZ_X11 - nsXPIDLString brandName; - GetBrandName(brandName); - - XClassHint *class_hint = XAllocClassHint(); - if (!class_hint) - return NS_ERROR_OUT_OF_MEMORY; - const char *role = NULL; - class_hint->res_name = ToNewCString(xulWinType); - if (!class_hint->res_name) { - XFree(class_hint); - return NS_ERROR_OUT_OF_MEMORY; - } - class_hint->res_class = ToNewCString(brandName); - if (!class_hint->res_class) { - nsMemory::Free(class_hint->res_name); - XFree(class_hint); - return NS_ERROR_OUT_OF_MEMORY; - } - - // Parse res_name into a name and role. Characters other than - // [A-Za-z0-9_-] are converted to '_'. Anything after the first - // colon is assigned to role; if there's no colon, assign the - // whole thing to both role and res_name. - for (char *c = class_hint->res_name; *c; c++) { - if (':' == *c) { - *c = 0; - role = c + 1; - } - else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c))) - *c = '_'; - } - class_hint->res_name[0] = toupper(class_hint->res_name[0]); - if (!role) role = class_hint->res_name; - - GdkWindow *shellWindow = gtk_widget_get_window(GTK_WIDGET(mShell)); - gdk_window_set_role(shellWindow, role); - // Can't use gtk_window_set_wmclass() for this; it prints - // a warning & refuses to make the change. - XSetClassHint(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), - gdk_x11_window_get_xid(shellWindow), - class_hint); - nsMemory::Free(class_hint->res_class); - nsMemory::Free(class_hint->res_name); - XFree(class_hint); -#else /* MOZ_X11 */ - - char *res_name; - - res_name = ToNewCString(xulWinType); + const char *res_class = gdk_get_program_class(); + if (!res_class) + return NS_ERROR_FAILURE; + + char *res_name = ToNewCString(xulWinType); if (!res_name) return NS_ERROR_OUT_OF_MEMORY; - printf("WARN: res_name = '%s'\n", res_name); - - const char *role = NULL; // Parse res_name into a name and role. Characters other than @@ -4149,11 +4101,28 @@ nsWindow::SetWindowClass(const nsAString &xulWinType) res_name[0] = toupper(res_name[0]); if (!role) role = res_name; - gdk_window_set_role(gtk_widget_get_window(GTK_WIDGET(mShell)), role); + GdkWindow *shellWindow = gtk_widget_get_window(GTK_WIDGET(mShell)); + gdk_window_set_role(shellWindow, role); + +#ifdef MOZ_X11 + XClassHint *class_hint = XAllocClassHint(); + if (!class_hint) { + nsMemory::Free(res_name); + return NS_ERROR_OUT_OF_MEMORY; + } + class_hint->res_name = res_name; + class_hint->res_class = const_cast(res_class); + + // Can't use gtk_window_set_wmclass() for this; it prints + // a warning & refuses to make the change. + XSetClassHint(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), + gdk_x11_window_get_xid(shellWindow), + class_hint); + XFree(class_hint); +#endif /* MOZ_X11 */ nsMemory::Free(res_name); -#endif /* MOZ_X11 */ return NS_OK; } From 0d77c97b8a09f7f8be249c73307c26be48b02a41 Mon Sep 17 00:00:00 2001 From: aceman Date: Tue, 27 Mar 2012 19:17:35 -0400 Subject: [PATCH 085/113] Bug 738568 - Remove Services.prefs.getBranch(null) occurences in Toolkit. r=gavin --- .../alerts/resources/content/alert.js | 15 ++-- .../components/viewconfig/content/config.js | 2 +- .../viewsource/content/viewSource.js | 75 ++++++------------- 3 files changed, 31 insertions(+), 61 deletions(-) diff --git a/toolkit/components/alerts/resources/content/alert.js b/toolkit/components/alerts/resources/content/alert.js index 8e4dcf36906..610568c6d12 100644 --- a/toolkit/components/alerts/resources/content/alert.js +++ b/toolkit/components/alerts/resources/content/alert.js @@ -36,6 +36,8 @@ # # ***** END LICENSE BLOCK ***** +Components.utils.import("resource://gre/modules/Services.jsm"); + // Copied from nsILookAndFeel.h, see comments on eMetric_AlertNotificationOrigin const NS_ALERT_HORIZONTAL = 1; const NS_ALERT_LEFT = 2; @@ -93,14 +95,11 @@ function prefillAlertInfo() function onAlertLoad() { - var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(); - prefService = prefService.QueryInterface(Components.interfaces.nsIPrefService); - var prefBranch = prefService.getBranch(null); - gSlideIncrement = prefBranch.getIntPref("alerts.slideIncrement"); - gSlideTime = prefBranch.getIntPref("alerts.slideIncrementTime"); - gOpenTime = prefBranch.getIntPref("alerts.totalOpenTime"); - gDisableSlideEffect = prefBranch.getBoolPref("alerts.disableSlidingEffect"); - + gSlideIncrement = Services.prefs.getIntPref("alerts.slideIncrement"); + gSlideTime = Services.prefs.getIntPref("alerts.slideIncrementTime"); + gOpenTime = Services.prefs.getIntPref("alerts.totalOpenTime"); + gDisableSlideEffect = Services.prefs.getBoolPref("alerts.disableSlidingEffect"); + // Make sure that the contents are fixed at the window edge facing the // screen's center so that the window looks like "sliding in" and not // like "unfolding". The default packing of "start" only works for diff --git a/toolkit/components/viewconfig/content/config.js b/toolkit/components/viewconfig/content/config.js index d6c644fc1ed..04880ba7b30 100644 --- a/toolkit/components/viewconfig/content/config.js +++ b/toolkit/components/viewconfig/content/config.js @@ -52,7 +52,7 @@ const nsPrefService_CONTRACTID = "@mozilla.org/preferences-service;1"; const nsClipboardHelper_CONTRACTID = "@mozilla.org/widget/clipboardhelper;1"; const nsAtomService_CONTRACTID = "@mozilla.org/atom-service;1"; -const gPrefBranch = Services.prefs.getBranch(null); +const gPrefBranch = Services.prefs; const gClipboardHelper = Components.classes[nsClipboardHelper_CONTRACTID].getService(nsIClipboardHelper); const gAtomService = Components.classes[nsAtomService_CONTRACTID].getService(nsIAtomService); diff --git a/toolkit/components/viewsource/content/viewSource.js b/toolkit/components/viewsource/content/viewSource.js index 537cebc3125..82eefc5be9f 100644 --- a/toolkit/components/viewsource/content/viewSource.js +++ b/toolkit/components/viewsource/content/viewSource.js @@ -38,9 +38,10 @@ # # ***** END LICENSE BLOCK ***** +Components.utils.import("resource://gre/modules/Services.jsm"); + const Cc = Components.classes; const Ci = Components.interfaces; -var gPrefs = null; var gLastLineFound = ''; var gGoToLine = 0; @@ -72,13 +73,6 @@ __defineGetter__("gPageLoader", function () { return this.gPageLoader = webnav.QueryInterface(Ci.nsIWebPageDescriptor); }); -try { - var prefService = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - gPrefs = prefService.getBranch(null); -} catch (ex) { -} - var gSelectionListener = { timeout: 0, attached: false, @@ -219,22 +213,14 @@ function viewSource(url) // Check the view_source.wrap_long_lines pref and set the menuitem's checked // attribute accordingly. - if (gPrefs) { - try { - var wraplonglinesPrefValue = gPrefs.getBoolPref("view_source.wrap_long_lines"); + var wraplonglinesPrefValue = Services.prefs + .getBoolPref("view_source.wrap_long_lines"); - if (wraplonglinesPrefValue) - document.getElementById("menu_wrapLongLines").setAttribute("checked", "true"); - } catch (ex) { - } - try { - document.getElementById("menu_highlightSyntax").setAttribute("checked", - gPrefs.getBoolPref("view_source.syntax_highlight")); - } catch (ex) { - } - } else { - document.getElementById("menu_highlightSyntax").setAttribute("hidden", "true"); - } + if (wraplonglinesPrefValue) + document.getElementById("menu_wrapLongLines").setAttribute("checked", "true"); + + document.getElementById("menu_highlightSyntax").setAttribute("checked", + Services.prefs.getBoolPref("view_source.syntax_highlight")); window.addEventListener("AppCommand", HandleAppCommandEvent, true); window.addEventListener("MozSwipeGesture", HandleSwipeGesture, true); @@ -286,16 +272,13 @@ function onClickContent(event) { var target = event.originalTarget; var errorDoc = target.ownerDocument; - - var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"] - .getService(Ci.nsIURLFormatter); if (/^about:blocked/.test(errorDoc.documentURI)) { // The event came from a button on a malware/phishing block page // First check whether it's malware or phishing, so that we can // use the right strings/links var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI); - + if (target == errorDoc.getElementById('getMeOutButton')) { // Instead of loading some safe page, just close the window window.close(); @@ -308,7 +291,7 @@ function onClickContent(event) { // Get the stop badware "why is this blocked" report url, // append the current url, and go there. try { - let reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL", true); + let reportURL = Services.urlFormatter.formatURLPref("browser.safebrowsing.malware.reportURL", true); reportURL += errorDoc.location.href.slice(12); openURL(reportURL); } catch (e) { @@ -316,7 +299,7 @@ function onClickContent(event) { } } else { // It's a phishing site, not malware try { - var infoURL = formatter.formatURLPref("browser.safebrowsing.warning.infoURL", true); + var infoURL = Services.urlFormatter.formatURLPref("browser.safebrowsing.warning.infoURL", true); openURL(infoURL); } catch (e) { Components.utils.reportError("Couldn't get phishing info URL: " + e); @@ -422,12 +405,9 @@ function getWebNavigation() function ViewSourceGoToLine() { - var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Ci.nsIPromptService); - var input = {value:gLastLineFound}; for (;;) { - var ok = promptService.prompt( + var ok = Services.prompt.prompt( window, gViewSourceBundle.getString("goToLineTitle"), gViewSourceBundle.getString("goToLineText"), @@ -441,9 +421,9 @@ function ViewSourceGoToLine() var line = parseInt(input.value, 10); if (!(line > 0)) { - promptService.alert(window, - gViewSourceBundle.getString("invalidInputTitle"), - gViewSourceBundle.getString("invalidInputText")); + Services.prompt.alert(window, + gViewSourceBundle.getString("invalidInputTitle"), + gViewSourceBundle.getString("invalidInputText")); continue; } @@ -453,9 +433,9 @@ function ViewSourceGoToLine() if (found) break; - promptService.alert(window, - gViewSourceBundle.getString("outOfRangeTitle"), - gViewSourceBundle.getString("outOfRangeText")); + Services.prompt.alert(window, + gViewSourceBundle.getString("outOfRangeTitle"), + gViewSourceBundle.getString("outOfRangeText")); } } @@ -683,22 +663,13 @@ function wrapLongLines() if (myWrap.className == '') myWrap.className = 'wrap'; - else myWrap.className = ''; + else + myWrap.className = ''; // Since multiple viewsource windows are possible, another window could have // affected the pref, so instead of determining the new pref value via the current // pref value, we use myWrap.className. - if (gPrefs) { - try { - if (myWrap.className == '') { - gPrefs.setBoolPref("view_source.wrap_long_lines", false); - } - else { - gPrefs.setBoolPref("view_source.wrap_long_lines", true); - } - } catch (ex) { - } - } + Services.prefs.setBoolPref("view_source.wrap_long_lines", myWrap.className != ''); } // Toggles syntax highlighting and sets the view_source.syntax_highlight @@ -707,7 +678,7 @@ function highlightSyntax() { var highlightSyntaxMenu = document.getElementById("menu_highlightSyntax"); var highlightSyntax = (highlightSyntaxMenu.getAttribute("checked") == "true"); - gPrefs.setBoolPref("view_source.syntax_highlight", highlightSyntax); + Services.prefs.setBoolPref("view_source.syntax_highlight", highlightSyntax); gPageLoader.loadPage(gPageLoader.currentDescriptor, gPageLoader.DISPLAY_NORMAL); } From f955145443cbef90bd84372390a2b24a0aca872d Mon Sep 17 00:00:00 2001 From: Scott Downe Date: Tue, 27 Mar 2012 19:17:35 -0400 Subject: [PATCH 086/113] Bug 677122 - Update start/end times of mediafragment URL on hashchanges. r=bz --- content/html/document/src/MediaDocument.cpp | 23 +++++ content/html/document/src/MediaDocument.h | 1 + content/html/document/test/Makefile.in | 1 + .../html/document/test/test_bug677122.html | 85 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 content/html/document/test/test_bug677122.html diff --git a/content/html/document/src/MediaDocument.cpp b/content/html/document/src/MediaDocument.cpp index 5bdc7036ab9..0bd1e74b927 100644 --- a/content/html/document/src/MediaDocument.cpp +++ b/content/html/document/src/MediaDocument.cpp @@ -363,6 +363,25 @@ MediaDocument::LinkStylesheet(const nsAString& aStylesheet) return head->AppendChildTo(link, false); } +void +MediaDocument::InsertMediaFragmentScript() +{ + nsCOMPtr nodeInfo; + nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::script, nsnull, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + if (!nodeInfo) + { + return; + } + + nsRefPtr script = NS_NewHTMLScriptElement(nodeInfo.forget()); + script->SetTextContent(NS_LITERAL_STRING("window.addEventListener('hashchange',function(e){document.querySelector('audio,video').src=e.newURL;},false);")); + + Element* head = GetHeadElement(); + head->AppendChildTo(script, false); +} + void MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr, const char* const* aFormatNames, @@ -439,6 +458,10 @@ MediaDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) nsContentUtils::AddScriptRunner( new nsDocElementCreatedNotificationRunner(this)); } + + if (aGlobalObject) { + InsertMediaFragmentScript(); + } } } // namespace dom diff --git a/content/html/document/src/MediaDocument.h b/content/html/document/src/MediaDocument.h index 0a79a450abd..af5e7d59adb 100644 --- a/content/html/document/src/MediaDocument.h +++ b/content/html/document/src/MediaDocument.h @@ -75,6 +75,7 @@ protected: void GetFileName(nsAString& aResult); nsresult LinkStylesheet(const nsAString& aStylesheet); + void InsertMediaFragmentScript(); // |aFormatNames[]| needs to have four elements in the following order: // a format name with neither dimension nor file, a format name with diff --git a/content/html/document/test/Makefile.in b/content/html/document/test/Makefile.in index b5620427007..ae2774cbdd6 100644 --- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -106,6 +106,7 @@ _TEST_FILES = test_bug1682.html \ test_bug571981.html \ test_bug677495.html \ test_bug677495-1.html \ + test_bug677122.html \ $(NULL) ifneq (mobile,$(MOZ_BUILD_APP)) diff --git a/content/html/document/test/test_bug677122.html b/content/html/document/test/test_bug677122.html new file mode 100644 index 00000000000..b2a7d9979c9 --- /dev/null +++ b/content/html/document/test/test_bug677122.html @@ -0,0 +1,85 @@ + + + + Media test: MediaDocument hashchange mediafragment. + + + + + +
+
+
+ + From 53fd824a7f2ed310e6190e79b92d01704e09a389 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Wed, 28 Mar 2012 01:27:19 +0200 Subject: [PATCH 087/113] Bug 736589, r=jst --- dom/src/storage/nsDOMStorage.cpp | 44 ++++++++++---------------------- dom/src/storage/nsDOMStorage.h | 2 +- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index ef735daf603..a116ca20865 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -1318,8 +1318,6 @@ nsDOMStorage::nsDOMStorage() : mStorageType(nsPIDOMStorage::Unknown) , mEventBroadcaster(nsnull) { - mSecurityChecker = this; - if (XRE_GetProcessType() != GeckoProcessType_Default) mStorageImpl = new StorageChild(this); else @@ -1328,10 +1326,9 @@ nsDOMStorage::nsDOMStorage() nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat) : mStorageType(aThat.mStorageType) + , mPrincipal(aThat.mPrincipal) , mEventBroadcaster(nsnull) { - mSecurityChecker = this; - if (XRE_GetProcessType() != GeckoProcessType_Default) { StorageChild* other = static_cast(aThat.mStorageImpl.get()); mStorageImpl = new StorageChild(this, *other); @@ -1382,6 +1379,7 @@ nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring & NS_ENSURE_SUCCESS(rv, rv); mDocumentURI = aDocumentURI; + mPrincipal = aPrincipal; mStorageType = SessionStorage; @@ -1397,6 +1395,7 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aD NS_ENSURE_SUCCESS(rv, rv); mDocumentURI = aDocumentURI; + mPrincipal = aPrincipal; mStorageType = LocalStorage; @@ -1495,8 +1494,7 @@ nsDOMStorage::CacheStoragePermissions() nsresult rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)); NS_ENSURE_SUCCESS(rv, false); - NS_ASSERTION(mSecurityChecker, "Has non-null mSecurityChecker"); - return mSecurityChecker->CanAccess(subjectPrincipal); + return CanAccess(subjectPrincipal); } // static @@ -1729,17 +1727,17 @@ nsDOMStorage::CanAccessSystem(nsIPrincipal *aPrincipal) bool nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal) { - // Allow C++/system callers to access the storage - if (CanAccessSystem(aPrincipal)) + // Allow C++ callers to access the storage + if (!aPrincipal) return true; - nsCAutoString domain; - nsCOMPtr unused; - nsresult rv = GetPrincipalURIAndHost(aPrincipal, - getter_AddRefs(unused), domain); - NS_ENSURE_SUCCESS(rv, false); + // Allow more powerful principals (e.g. system) to access the storage + bool subsumes; + nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes); + if (NS_FAILED(rv)) + return false; - return domain.Equals(mStorageImpl->mDomain); + return subsumes; } nsPIDOMStorage::nsDOMStorageType @@ -1797,7 +1795,6 @@ nsDOMStorage2::nsDOMStorage2() nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat) { mStorage = new nsDOMStorage(*aThat.mStorage.get()); - mStorage->mSecurityChecker = mStorage; mPrincipal = aThat.mPrincipal; } @@ -1808,7 +1805,6 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring if (!mStorage) return NS_ERROR_OUT_OF_MEMORY; - mStorage->mSecurityChecker = this; mPrincipal = aPrincipal; mDocumentURI = aDocumentURI; @@ -1822,7 +1818,6 @@ nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &a if (!mStorage) return NS_ERROR_OUT_OF_MEMORY; - mStorage->mSecurityChecker = this; mPrincipal = aPrincipal; mDocumentURI = aDocumentURI; @@ -1892,20 +1887,7 @@ nsDOMStorage2::Principal() bool nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal) { - if (mStorage->mSecurityChecker != this) - return mStorage->mSecurityChecker->CanAccess(aPrincipal); - - // Allow C++ callers to access the storage - if (!aPrincipal) - return true; - - // Allow more powerful principals (e.g. system) to access the storage - bool subsumes; - nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes); - if (NS_FAILED(rv)) - return false; - - return subsumes; + return mStorage->CanAccess(aPrincipal); } nsPIDOMStorage::nsDOMStorageType diff --git a/dom/src/storage/nsDOMStorage.h b/dom/src/storage/nsDOMStorage.h index 1837bd87f43..dafb48bed51 100644 --- a/dom/src/storage/nsDOMStorage.h +++ b/dom/src/storage/nsDOMStorage.h @@ -419,7 +419,7 @@ public: nsDOMStorageType mStorageType; friend class nsIDOMStorage2; - nsPIDOMStorage* mSecurityChecker; + nsCOMPtr mPrincipal; nsPIDOMStorage* mEventBroadcaster; }; From e6c1f6da11b06b91cde37774e9fd57c22d045f69 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 27 Mar 2012 20:04:33 -0400 Subject: [PATCH 088/113] Backed out changeset 389eee1cce65 (bug 677122) due to bustage. --- content/html/document/src/MediaDocument.cpp | 23 ----- content/html/document/src/MediaDocument.h | 1 - content/html/document/test/Makefile.in | 1 - .../html/document/test/test_bug677122.html | 85 ------------------- 4 files changed, 110 deletions(-) delete mode 100644 content/html/document/test/test_bug677122.html diff --git a/content/html/document/src/MediaDocument.cpp b/content/html/document/src/MediaDocument.cpp index 0bd1e74b927..5bdc7036ab9 100644 --- a/content/html/document/src/MediaDocument.cpp +++ b/content/html/document/src/MediaDocument.cpp @@ -363,25 +363,6 @@ MediaDocument::LinkStylesheet(const nsAString& aStylesheet) return head->AppendChildTo(link, false); } -void -MediaDocument::InsertMediaFragmentScript() -{ - nsCOMPtr nodeInfo; - nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::script, nsnull, - kNameSpaceID_XHTML, - nsIDOMNode::ELEMENT_NODE); - if (!nodeInfo) - { - return; - } - - nsRefPtr script = NS_NewHTMLScriptElement(nodeInfo.forget()); - script->SetTextContent(NS_LITERAL_STRING("window.addEventListener('hashchange',function(e){document.querySelector('audio,video').src=e.newURL;},false);")); - - Element* head = GetHeadElement(); - head->AppendChildTo(script, false); -} - void MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr, const char* const* aFormatNames, @@ -458,10 +439,6 @@ MediaDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) nsContentUtils::AddScriptRunner( new nsDocElementCreatedNotificationRunner(this)); } - - if (aGlobalObject) { - InsertMediaFragmentScript(); - } } } // namespace dom diff --git a/content/html/document/src/MediaDocument.h b/content/html/document/src/MediaDocument.h index af5e7d59adb..0a79a450abd 100644 --- a/content/html/document/src/MediaDocument.h +++ b/content/html/document/src/MediaDocument.h @@ -75,7 +75,6 @@ protected: void GetFileName(nsAString& aResult); nsresult LinkStylesheet(const nsAString& aStylesheet); - void InsertMediaFragmentScript(); // |aFormatNames[]| needs to have four elements in the following order: // a format name with neither dimension nor file, a format name with diff --git a/content/html/document/test/Makefile.in b/content/html/document/test/Makefile.in index ae2774cbdd6..b5620427007 100644 --- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -106,7 +106,6 @@ _TEST_FILES = test_bug1682.html \ test_bug571981.html \ test_bug677495.html \ test_bug677495-1.html \ - test_bug677122.html \ $(NULL) ifneq (mobile,$(MOZ_BUILD_APP)) diff --git a/content/html/document/test/test_bug677122.html b/content/html/document/test/test_bug677122.html deleted file mode 100644 index b2a7d9979c9..00000000000 --- a/content/html/document/test/test_bug677122.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - Media test: MediaDocument hashchange mediafragment. - - - - - -
-
-
- - From 905c0f1adb46abe207e08205b2a5fc77a373d158 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 23 Mar 2012 17:59:56 -0700 Subject: [PATCH 089/113] Bug 739808: Remove method cloning optimization and method barrier, r=luke --HG-- extra : rebase_source : d383c3704c3efd08f9fbf1324433a94fc4a8dbb8 --- js/src/frontend/BytecodeEmitter.cpp | 81 +------ js/src/frontend/ParseNode.cpp | 9 - js/src/frontend/ParseNode.h | 2 - js/src/frontend/Parser.cpp | 4 +- js/src/frontend/SemanticAnalysis.cpp | 3 - .../tests/basic/testInitDictionary.js | 51 ----- js/src/jsanalyze.cpp | 3 - js/src/jsapi-tests/testLookup.cpp | 1 - js/src/jsapi.cpp | 31 +-- js/src/jsdbgapi.cpp | 11 - js/src/jsdbgapi.h | 29 --- js/src/jsfun.cpp | 114 +--------- js/src/jsfun.h | 37 --- js/src/jsfuninlines.h | 50 +---- js/src/jsinfer.cpp | 10 +- js/src/jsinterp.cpp | 82 +------ js/src/jsinterpinlines.h | 25 +-- js/src/jsiter.cpp | 4 +- js/src/jsobj.cpp | 210 ++---------------- js/src/jsobj.h | 58 +---- js/src/jsobjinlines.h | 66 +----- js/src/json.cpp | 2 +- js/src/jsopcode.cpp | 2 - js/src/jsopcode.h | 2 +- js/src/jsopcode.tbl | 13 +- js/src/jspropertytree.cpp | 1 - js/src/jsscope.cpp | 52 +---- js/src/jsscope.h | 32 +-- js/src/jsscopeinlines.h | 6 - js/src/jsstr.cpp | 2 +- js/src/jswatchpoint.cpp | 22 +- js/src/methodjit/Compiler.cpp | 45 +--- js/src/methodjit/Compiler.h | 2 +- js/src/methodjit/FastOps.cpp | 16 -- js/src/methodjit/LoopState.cpp | 3 +- js/src/methodjit/MonoIC.cpp | 5 +- js/src/methodjit/PolyIC.cpp | 81 ++----- js/src/methodjit/PolyIC.h | 3 +- js/src/methodjit/StubCalls.cpp | 74 +----- js/src/methodjit/StubCalls.h | 5 - js/src/shell/js.cpp | 9 +- js/src/vm/Debugger.cpp | 2 +- js/src/vm/Stack-inl.h | 7 - js/src/vm/Stack.h | 14 -- 44 files changed, 127 insertions(+), 1154 deletions(-) delete mode 100644 js/src/jit-test/tests/basic/testInitDictionary.js diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 23cd4ac5d05..c465c0e999d 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4565,43 +4565,6 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) return PopStatementBCE(cx, bce); } -static bool -SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom) -{ - RootedVarObject parent(cx); - parent = funbox->function()->getParent(); - - /* - * Replace a boxed function with a new one with a method atom. Methods - * require a function with the extended size finalize kind, which normal - * functions don't have. We don't eagerly allocate functions with the - * expanded size for boxed functions, as most functions are not methods. - */ - JSFunction *fun = js_NewFunction(cx, NULL, NULL, - funbox->function()->nargs, - funbox->function()->flags, - parent, - funbox->function()->atom, - JSFunction::ExtendedFinalizeKind); - if (!fun) - return false; - - JSScript *script = funbox->function()->script(); - if (script) { - fun->setScript(script); - if (!script->typeSetFunction(cx, fun)) - return false; - } - - JS_ASSERT(funbox->function()->joinable()); - fun->setJoinable(); - - fun->setMethodAtom(atom); - - funbox->object = fun; - return true; -} - static bool EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top) { @@ -5371,23 +5334,6 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) } #endif if (op != JSOP_NOP) { - /* - * Specialize JSOP_SETPROP to JSOP_SETMETHOD to defer or - * avoid null closure cloning. Do this only for assignment - * statements that are not completion values wanted by a - * script evaluator, to ensure that the joined function - * can't escape directly. - */ - if (!wantval && - pn2->isKind(PNK_ASSIGN) && - pn2->pn_left->isOp(JSOP_SETPROP) && - pn2->pn_right->isOp(JSOP_LAMBDA) && - pn2->pn_right->pn_funbox->joinable()) - { - if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom)) - return false; - pn2->pn_left->setOp(JSOP_SETMETHOD); - } if (!EmitTree(cx, bce, pn2)) return false; if (Emit1(cx, bce, op) < 0) @@ -5894,28 +5840,13 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) if (!bce->makeAtomIndex(pn3->pn_atom, &index)) return false; - /* Check whether we can optimize to JSOP_INITMETHOD. */ - ParseNode *init = pn2->pn_right; - bool lambda = init->isOp(JSOP_LAMBDA); - if (lambda) - ++methodInits; - if (op == JSOP_INITPROP && lambda && init->pn_funbox->joinable()) { + /* + * Disable NEWOBJECT on initializers that set __proto__, which has + * a non-standard setter on objects. + */ + if (pn3->pn_atom == cx->runtime->atomState.protoAtom) obj = NULL; - op = JSOP_INITMETHOD; - if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom)) - return JS_FALSE; - pn2->setOp(op); - } else { - /* - * Disable NEWOBJECT on initializers that set __proto__, which has - * a non-standard setter on objects. - */ - if (pn3->pn_atom == cx->runtime->atomState.protoAtom) - obj = NULL; - op = JSOP_INITPROP; - if (lambda) - ++slowMethodInits; - } + op = JSOP_INITPROP; if (obj) { JS_ASSERT(!obj->inDictionaryMode()); diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index c3534a21bee..1f0fa28f230 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -108,15 +108,6 @@ ParseNode::clear() pn_parens = false; } -bool -FunctionBox::joinable() const -{ - return function()->isNullClosure() && - (tcflags & (TCF_FUN_USES_ARGUMENTS | - TCF_FUN_USES_OWN_NAME | - TCF_COMPILE_N_GO)) == TCF_COMPILE_N_GO; -} - bool FunctionBox::inAnyDynamicScope() const { diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 17ed30807fe..b55bea34e1c 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -1554,8 +1554,6 @@ struct FunctionBox : public ObjectBox JSFunction *function() const { return (JSFunction *) object; } - bool joinable() const; - /* * True if this function is inside the scope of a with-statement, an E4X * filter-expression, or a function that uses direct eval. diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 48b0eee57ba..6b3673320e2 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1069,8 +1069,6 @@ LeaveFunction(ParseNode *fn, TreeContext *funtc, PropertyName *funName = NULL, dn->setOp(JSOP_CALLEE); dn->pn_cookie.set(funtc->staticLevel, UpvarCookie::CALLEE_SLOT); dn->pn_dflags |= PND_BOUND; - - funbox->tcflags |= TCF_FUN_USES_OWN_NAME; foundCallee = 1; continue; } @@ -2049,7 +2047,7 @@ DefineGlobal(ParseNode *pn, BytecodeEmitter *bce, PropertyName *name) globalObj != holder || shape->configurable() || !shape->hasSlot() || - !shape->hasDefaultGetterOrIsMethod() || + !shape->hasDefaultGetter() || !shape->hasDefaultSetter()) { return true; } diff --git a/js/src/frontend/SemanticAnalysis.cpp b/js/src/frontend/SemanticAnalysis.cpp index b30a661bf99..12cf7cbd08d 100644 --- a/js/src/frontend/SemanticAnalysis.cpp +++ b/js/src/frontend/SemanticAnalysis.cpp @@ -217,9 +217,6 @@ SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool isDirectEval) FlagHeavyweights(lexdep, funbox, tcflags); } } - - if (funbox->joinable()) - fun->setJoinable(); } } diff --git a/js/src/jit-test/tests/basic/testInitDictionary.js b/js/src/jit-test/tests/basic/testInitDictionary.js deleted file mode 100644 index 2baded26a36..00000000000 --- a/js/src/jit-test/tests/basic/testInitDictionary.js +++ /dev/null @@ -1,51 +0,0 @@ - -var shapes = {}; - -function stringify(a) { - assertEq(shapes[shapeOf(a)], undefined); - shapes[shapeOf(a)] = 1; - var b = ""; - for (var c in a) { - b += c + ":"; - if (typeof a[c] == "function") - b += "function,"; - else - b += a[c] + ","; - } - return b; -} - -function test1() { - return stringify({a: 0, b: 1, a: function() {} }); -} -for (var i = 0; i < 3; i++) - assertEq(test1(), "a:function,b:1,"); - -// This does not cause the object to go to dictionary mode, unlike the above. -function test2() { - return stringify({a: 0, b: 1, a: 2, b: 3}); -} -assertEq(test2(), "a:2,b:3,"); - -function test3() { - return stringify({ - aa:0,ab:1,ac:2,ad:3,ae:4,af:5,ag:6,ah:7,ai:8,aj:9, - ba:0,bb:1,bc:2,bd:3,be:4,bf:5,bg:6,bh:7,bi:8,bj:9, - ca:0,cb:1,cc:2,cd:3,ce:4,cf:5,cg:6,ch:7,ci:8,cj:9, - da:0,db:1,dc:2,dd:3,de:4,df:5,dg:6,dh:7,di:8,dj:9, - ea:0,eb:1,ec:2,ed:3,ee:4,ef:5,eg:6,eh:7,ei:8,ej:9, - fa:0,fb:1,fc:2,fd:3,fe:4,ff:5,fg:6,fh:7,fi:8,fj:9, - ga:0,gb:1,gc:2,gd:3,ge:4,gf:5,gg:6,gh:7,gi:8,gj:9, - ha:0,hb:1,hc:2,hd:3,he:4,hf:5,hg:6,hh:7,hi:8,hj:9, - ia:0,ib:1,ic:2,id:3,ie:4,if:5,ig:6,ih:7,ii:8,ij:9, - ja:0,jb:1,jc:2,jd:3,je:4,jf:5,jg:6,jh:7,ji:8,jj:9, - ka:0,kb:1,kc:2,kd:3,ke:4,kf:5,kg:6,kh:7,ki:8,kj:9, - la:0,lb:1,lc:2,ld:3,le:4,lf:5,lg:6,lh:7,li:8,lj:9, - ma:0,mb:1,mc:2,md:3,me:4,mf:5,mg:6,mh:7,mi:8,mj:9, - na:0,nb:1,nc:2,nd:3,ne:4,nf:5,ng:6,nh:7,ni:8,nj:9, - oa:0,ob:1,oc:2,od:3,oe:4,of:5,og:6,oh:7,oi:8,oj:9, - pa:0,pb:1,pc:2,pd:3,pe:4,pf:5,pg:6,ph:7,pi:8,pj:9, - }); -} -for (var i = 0; i < 10; i++) - assertEq(test3(), "aa:0,ab:1,ac:2,ad:3,ae:4,af:5,ag:6,ah:7,ai:8,aj:9,ba:0,bb:1,bc:2,bd:3,be:4,bf:5,bg:6,bh:7,bi:8,bj:9,ca:0,cb:1,cc:2,cd:3,ce:4,cf:5,cg:6,ch:7,ci:8,cj:9,da:0,db:1,dc:2,dd:3,de:4,df:5,dg:6,dh:7,di:8,dj:9,ea:0,eb:1,ec:2,ed:3,ee:4,ef:5,eg:6,eh:7,ei:8,ej:9,fa:0,fb:1,fc:2,fd:3,fe:4,ff:5,fg:6,fh:7,fi:8,fj:9,ga:0,gb:1,gc:2,gd:3,ge:4,gf:5,gg:6,gh:7,gi:8,gj:9,ha:0,hb:1,hc:2,hd:3,he:4,hf:5,hg:6,hh:7,hi:8,hj:9,ia:0,ib:1,ic:2,id:3,ie:4,if:5,ig:6,ih:7,ii:8,ij:9,ja:0,jb:1,jc:2,jd:3,je:4,jf:5,jg:6,jh:7,ji:8,jj:9,ka:0,kb:1,kc:2,kd:3,ke:4,kf:5,kg:6,kh:7,ki:8,kj:9,la:0,lb:1,lc:2,ld:3,le:4,lf:5,lg:6,lh:7,li:8,lj:9,ma:0,mb:1,mc:2,md:3,me:4,mf:5,mg:6,mh:7,mi:8,mj:9,na:0,nb:1,nc:2,nd:3,ne:4,nf:5,ng:6,nh:7,ni:8,nj:9,oa:0,ob:1,oc:2,od:3,oe:4,of:5,og:6,oh:7,oi:8,oj:9,pa:0,pb:1,pc:2,pd:3,pe:4,pf:5,pg:6,ph:7,pi:8,pj:9,"); diff --git a/js/src/jsanalyze.cpp b/js/src/jsanalyze.cpp index 6b10ab34ecf..1c48f38bdad 100644 --- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -617,11 +617,9 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx) case JSOP_NEWARRAY: case JSOP_NEWOBJECT: case JSOP_ENDINIT: - case JSOP_INITMETHOD: case JSOP_INITPROP: case JSOP_INITELEM: case JSOP_SETPROP: - case JSOP_SETMETHOD: case JSOP_IN: case JSOP_INSTANCEOF: case JSOP_LINENO: @@ -1522,7 +1520,6 @@ ScriptAnalysis::analyzeSSA(JSContext *cx) break; case JSOP_INITPROP: - case JSOP_INITMETHOD: stack[stackDepth - 1].v = code->poppedValues[1]; break; diff --git a/js/src/jsapi-tests/testLookup.cpp b/js/src/jsapi-tests/testLookup.cpp index 57f07316b23..1ecd5b1172f 100644 --- a/js/src/jsapi-tests/testLookup.cpp +++ b/js/src/jsapi-tests/testLookup.cpp @@ -28,7 +28,6 @@ BEGIN_TEST(testLookup_bug522590) JSObject *funobj = JSVAL_TO_OBJECT(r); CHECK(funobj->isFunction()); CHECK(!js::IsInternalFunctionObject(funobj)); - CHECK(funobj->toFunction()->isClonedMethod()); return true; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 2ab186b07d0..b7f09f38c48 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3455,11 +3455,6 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id, if (obj2->isNative()) { Shape *shape = (Shape *) prop; - if (shape->isMethod()) { - vp->setObject(*obj2->nativeGetMethod(shape)); - return !!obj2->methodReadBarrier(cx, *shape, vp); - } - /* Peek at the native property's slot value, without doing a Get. */ if (shape->hasSlot()) { *vp = obj2->nativeGetSlot(shape->slot()); @@ -3855,19 +3850,12 @@ GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags, if (obj2->isNative()) { Shape *shape = (Shape *) prop; desc->attrs = shape->attributes(); - - if (shape->isMethod()) { - desc->getter = JS_PropertyStub; - desc->setter = JS_StrictPropertyStub; - desc->value.setObject(*obj2->nativeGetMethod(shape)); - } else { - desc->getter = shape->getter(); - desc->setter = shape->setter(); - if (shape->hasSlot()) - desc->value = obj2->nativeGetSlot(shape->slot()); - else - desc->value.setUndefined(); - } + desc->getter = shape->getter(); + desc->setter = shape->setter(); + if (shape->hasSlot()) + desc->value = obj2->nativeGetSlot(shape->slot()); + else + desc->value.setUndefined(); } else { if (obj2->isProxy()) { JSAutoResolveFlags rf(cx, flags); @@ -3968,8 +3956,9 @@ SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, unsigned attrs, *foundp = false; return true; } + Shape *shape = (Shape *) prop; JSBool ok = obj->isNative() - ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs) + ? obj->changePropertyAttributes(cx, shape, attrs) : obj->setGenericAttributes(cx, id, &attrs); if (ok) *foundp = true; @@ -4072,7 +4061,7 @@ JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval * AssertNoGC(cx); CHECK_REQUEST(cx); assertSameCompartment(cx, obj, id); - if (!js_GetMethod(cx, obj, id, JSGET_METHOD_BARRIER, vp)) + if (!js_GetMethod(cx, obj, id, 0, vp)) return JS_FALSE; if (objp) *objp = obj; @@ -5366,7 +5355,7 @@ JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, unsigned arg Value v; JSAtom *atom = js_Atomize(cx, name, strlen(name)); return atom && - js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, &v) && + js_GetMethod(cx, obj, ATOM_TO_JSID(atom), 0, &v) && Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval); } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 921fb261be3..37a7c3a61c8 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -644,17 +644,6 @@ JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp) return Valueify(fp)->maybeCalleev().toObjectOrNull(); } -JS_PUBLIC_API(JSBool) -JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp) -{ - Value v; - - if (!Valueify(fp)->getValidCalleeObject(cx, &v)) - return false; - *vp = v.isObject() ? v : JSVAL_VOID; - return true; -} - JS_PUBLIC_API(JSBool) JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index da772b58054..d99692e1a8d 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -292,39 +292,10 @@ JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval); * Return fp's callee function object (fp->callee) if it has one. Note that * this API cannot fail. A null return means "no callee": fp is a global or * eval-from-global frame, not a call frame. - * - * This API began life as an infallible getter, but now it can return either: - * - * 1. An optimized closure that was compiled assuming the function could not - * escape and be called from sites the compiler could not see. - * - * 2. A "joined function object", an optimization whereby SpiderMonkey avoids - * creating fresh function objects for every evaluation of a function - * expression that is used only once by a consumer that either promises to - * clone later when asked for the value or that cannot leak the value. - * - * Because Mozilla's Gecko embedding of SpiderMonkey (and no doubt other - * embeddings) calls this API in potentially performance-sensitive ways (e.g. - * in nsContentUtils::GetDocumentFromCaller), we are leaving this API alone. It - * may now return an unwrapped non-escaping optimized closure, or a joined - * function object. Such optimized objects may work well if called from the - * correct context, never mutated or compared for identity, etc. - * - * However, if you really need to get the same callee object that JS code would - * see, which means undoing the optimizations, where an undo attempt can fail, - * then use JS_GetValidFrameCalleeObject. */ extern JS_PUBLIC_API(JSObject *) JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp); -/** - * Return fp's callee function object after running the deferred closure - * cloning "method read barrier". This API can fail! If the frame has no - * callee, this API returns true with JSVAL_IS_VOID(*vp). - */ -extern JS_PUBLIC_API(JSBool) -JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp); - /************************************************************************/ extern JS_PUBLIC_API(const char *) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index e0d94ce5b55..6f07032cc15 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -97,107 +97,6 @@ using namespace js; using namespace js::gc; using namespace js::types; -bool -StackFrame::getValidCalleeObject(JSContext *cx, Value *vp) -{ - if (!isFunctionFrame()) { - vp->setNull(); - return true; - } - - JSFunction *fun = this->callee().toFunction(); - vp->setObject(*fun); - - /* - * Check for an escape attempt by a joined function object, which must go - * through the frame's |this| object's method read barrier for the method - * atom by which it was uniquely associated with a property. - */ - const Value &thisv = functionThis(); - if (thisv.isObject() && fun->methodAtom() && !fun->isClonedMethod()) { - JSObject *thisp = &thisv.toObject(); - JSObject *first_barriered_thisp = NULL; - - do { - /* - * While a non-native object is responsible for handling its - * entire prototype chain, notable non-natives including dense - * and typed arrays have native prototypes, so keep going. - */ - if (!thisp->isNative()) - continue; - - const Shape *shape = thisp->nativeLookup(cx, ATOM_TO_JSID(fun->methodAtom())); - if (shape) { - /* - * Two cases follow: the method barrier was not crossed - * yet, so we cross it here; the method barrier *was* - * crossed but after the call, in which case we fetch - * and validate the cloned (unjoined) funobj from the - * method property's slot. - * - * In either case we must allow for the method property - * to have been replaced, or its value overwritten. - */ - if (shape->isMethod() && thisp->nativeGetMethod(shape) == fun) { - if (!thisp->methodReadBarrier(cx, *shape, vp)) - return false; - overwriteCallee(vp->toObject()); - return true; - } - - if (shape->hasSlot()) { - Value v = thisp->getSlot(shape->slot()); - JSFunction *clone; - - if (IsFunctionObject(v, &clone) && - clone->isInterpreted() && - clone->script() == fun->script() && - clone->methodObj() == thisp) { - /* - * N.B. If the method barrier was on a function - * with singleton type, then while crossing the - * method barrier CloneFunctionObject will have - * ignored the attempt to clone the function. - */ - JS_ASSERT_IF(!clone->hasSingletonType(), clone != fun); - *vp = v; - overwriteCallee(*clone); - return true; - } - } - } - - if (!first_barriered_thisp) - first_barriered_thisp = thisp; - } while ((thisp = thisp->getProto()) != NULL); - - if (!first_barriered_thisp) - return true; - - /* - * At this point, we couldn't find an already-existing clone (or - * force to exist a fresh clone) created via thisp's method read - * barrier, so we must clone fun and store it in fp's callee to - * avoid re-cloning upon repeated foo.caller access. - * - * This must mean the code in js_DeleteGeneric could not find this - * stack frame on the stack when the method was deleted. We've lost - * track of the method, so we associate it with the first barriered - * object found starting from thisp on the prototype chain. - */ - JSFunction *newfunobj = CloneFunctionObject(cx, fun); - if (!newfunobj) - return false; - newfunobj->setMethodObj(*first_barriered_thisp); - overwriteCallee(*newfunobj); - vp->setObject(*newfunobj); - return true; - } - - return true; -} - static JSBool fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { @@ -227,10 +126,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) for (; fp; fp = fp->prev()) { if (!fp->isFunctionFrame() || fp->isEvalFrame()) continue; - Value callee; - if (!fp->getValidCalleeObject(cx, &callee)) - return false; - if (&callee.toObject() == fun) + if (fp->callee().toFunction() == fun) break; } if (!fp) @@ -277,14 +173,13 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) while (frame && frame->isDummyFrame()) frame = frame->prev(); - if (frame && !frame->getValidCalleeObject(cx, vp)) - return false; - - if (!vp->isObject()) { + if (!frame || !frame->isFunctionFrame()) { JS_ASSERT(vp->isNull()); return true; } + vp->setObject(frame->callee()); + /* Censor the caller if it is from another compartment. */ JSObject &caller = vp->toObject(); if (caller.compartment() != cx->compartment) { @@ -1263,7 +1158,6 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj) JS_ASSERT(!shape->configurable()); JS_ASSERT(shape->isDataDescriptor()); JS_ASSERT(shape->hasSlot()); - JS_ASSERT(!shape->isMethod()); return shape; } diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 96ecedb5f99..464a182f9ea 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -67,10 +67,6 @@ * move to u.i.script->flags. For now we use function flag bits to minimize * pointer-chasing. */ -#define JSFUN_JOINABLE 0x0001 /* function is null closure that does not - appear to call itself via its own name - or arguments.callee */ - #define JSFUN_PROTOTYPE 0x0800 /* function is Function.prototype for some global object */ @@ -129,14 +125,6 @@ struct JSFunction : public JSObject #define JS_LOCAL_NAME_TO_ATOM(nameWord) ((JSAtom *) ((nameWord) & ~uintptr_t(1))) #define JS_LOCAL_NAME_IS_CONST(nameWord) ((((nameWord) & uintptr_t(1))) != 0) - bool mightEscape() const { - return isInterpreted() && isNullClosure(); - } - - bool joinable() const { - return flags & JSFUN_JOINABLE; - } - /* * For an interpreted function, accessors for the initial scope object of * activations (stack frames) of the function. @@ -147,8 +135,6 @@ struct JSFunction : public JSObject static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); } - inline void setJoinable(); - js::HeapPtrScript &script() const { JS_ASSERT(isInterpreted()); return *(js::HeapPtrScript *)&u.i.script_; @@ -218,33 +204,10 @@ struct JSFunction : public JSObject public: /* Accessors for data stored in extended functions. */ - inline void initializeExtended(); - inline void setExtendedSlot(size_t which, const js::Value &val); inline const js::Value &getExtendedSlot(size_t which) const; - /* Slot holding associated method property, needed for foo.caller handling. */ - static const uint32_t METHOD_PROPERTY_SLOT = 0; - - /* For cloned methods, slot holding the object this was cloned as a property from. */ - static const uint32_t METHOD_OBJECT_SLOT = 1; - - /* Whether this is a function cloned from a method. */ - inline bool isClonedMethod() const; - - /* For a cloned method, pointer to the object the method was cloned for. */ - inline JSObject *methodObj() const; - inline void setMethodObj(JSObject& obj); - - /* - * Method name imputed from property uniquely assigned to or initialized, - * where the function does not need to be cloned to carry a scope chain. - * This is set on both the original and cloned function. - */ - inline JSAtom *methodAtom() const; - inline void setMethodAtom(JSAtom *atom); - private: /* * These member functions are inherited from JSObject, but should never be applied to diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index 95e8a078f64..56d87e2805c 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -84,48 +84,6 @@ JSFunction::initializeExtended() toExtended()->extendedSlots[1].init(js::UndefinedValue()); } -inline void -JSFunction::setJoinable() -{ - JS_ASSERT(isInterpreted()); - flags |= JSFUN_JOINABLE; -} - -inline bool -JSFunction::isClonedMethod() const -{ - return joinable() && isExtended() && getExtendedSlot(METHOD_OBJECT_SLOT).isObject(); -} - -inline JSAtom * -JSFunction::methodAtom() const -{ - return (joinable() && isExtended() && getExtendedSlot(METHOD_PROPERTY_SLOT).isString()) - ? (JSAtom *) getExtendedSlot(METHOD_PROPERTY_SLOT).toString() - : NULL; -} - -inline void -JSFunction::setMethodAtom(JSAtom *atom) -{ - JS_ASSERT(joinable()); - setExtendedSlot(METHOD_PROPERTY_SLOT, js::StringValue(atom)); -} - -inline JSObject * -JSFunction::methodObj() const -{ - JS_ASSERT(joinable()); - return isClonedMethod() ? &getExtendedSlot(METHOD_OBJECT_SLOT).toObject() : NULL; -} - -inline void -JSFunction::setMethodObj(JSObject& obj) -{ - JS_ASSERT(joinable()); - setExtendedSlot(METHOD_OBJECT_SLOT, js::ObjectValue(obj)); -} - inline void JSFunction::setExtendedSlot(size_t which, const js::Value &val) { @@ -288,10 +246,10 @@ inline JSFunction * CloneFunctionObjectIfNotSingleton(JSContext *cx, JSFunction *fun, JSObject *parent) { /* - * For attempts to clone functions at a function definition opcode or from - * a method barrier, don't perform the clone if the function has singleton - * type. This was called pessimistically, and we need to preserve the - * type's property that if it is singleton there is only a single object + * For attempts to clone functions at a function definition opcode, + * don't perform the clone if the function has singleton type. This + * was called pessimistically, and we need to preserve the type's + * property that if it is singleton there is only a single object * with its type in existence. */ if (fun->hasSingletonType()) { diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 6481afa9806..b3394e891b4 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -800,7 +800,7 @@ static inline const Shape * GetSingletonShape(JSContext *cx, JSObject *obj, jsid id) { const Shape *shape = obj->nativeLookup(cx, id); - if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) + if (shape && shape->hasDefaultGetter() && shape->hasSlot()) return shape; return NULL; } @@ -2739,7 +2739,7 @@ UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, const Shape *sh if (shape->hasGetterValue() || shape->hasSetterValue()) { types->setOwnProperty(cx, true); types->addType(cx, Type::UnknownType()); - } else if (shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) { + } else if (shape->hasDefaultGetter() && shape->hasSlot()) { const Value &value = obj->nativeGetSlot(shape->slot()); /* @@ -3667,8 +3667,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, pushed[0].addType(cx, Type::LazyArgsType()); break; - case JSOP_SETPROP: - case JSOP_SETMETHOD: { + case JSOP_SETPROP: { jsid id = GetAtomId(cx, script, pc, 0); poppedTypes(pc, 1)->addSetProperty(cx, script, pc, poppedTypes(pc, 0), id); poppedTypes(pc, 0)->addSubset(cx, &pushed[0]); @@ -3875,8 +3874,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, state.hasHole = true; break; - case JSOP_INITPROP: - case JSOP_INITMETHOD: { + case JSOP_INITPROP: { const SSAValue &objv = poppedValue(pc, 1); jsbytecode *initpc = script->code + objv.pushedOffset(); TypeObject *initializer = GetInitializerType(cx, script, initpc); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 01725b82710..2523645f8a6 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -369,7 +369,7 @@ js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp) { jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom); AutoValueRooter tvr(cx); - if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, tvr.addr())) + if (!js_GetMethod(cx, obj, id, 0, tvr.addr())) return false; TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc); @@ -1215,11 +1215,9 @@ JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH); /* * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but - * remain distinct for the decompiler. Likewise for JSOP_INIT{PROP,METHOD}. + * remain distinct for the decompiler. */ JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH); -JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETMETHOD_LENGTH); -JS_STATIC_ASSERT(JSOP_INITPROP_LENGTH == JSOP_INITMETHOD_LENGTH); /* See TRY_BRANCH_AFTER_COND. */ JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH); @@ -1714,6 +1712,8 @@ ADD_EMPTY_CASE(JSOP_UNUSED25) ADD_EMPTY_CASE(JSOP_UNUSED26) ADD_EMPTY_CASE(JSOP_UNUSED27) ADD_EMPTY_CASE(JSOP_UNUSED28) +ADD_EMPTY_CASE(JSOP_UNUSED29) +ADD_EMPTY_CASE(JSOP_UNUSED30) ADD_EMPTY_CASE(JSOP_CONDSWITCH) ADD_EMPTY_CASE(JSOP_TRY) #if JS_HAS_XML_SUPPORT @@ -2585,7 +2585,6 @@ END_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_SETGNAME) BEGIN_CASE(JSOP_SETNAME) BEGIN_CASE(JSOP_SETPROP) -BEGIN_CASE(JSOP_SETMETHOD) { const Value &rval = regs.sp[-1]; const Value &lval = regs.sp[-2]; @@ -3159,73 +3158,6 @@ BEGIN_CASE(JSOP_LAMBDA) JSObject *parent; if (fun->isNullClosure()) { parent = ®s.fp()->scopeChain(); - - if (fun->joinable()) { - jsbytecode *pc2 = regs.pc + JSOP_LAMBDA_LENGTH; - JSOp op2 = JSOp(*pc2); - - /* - * Optimize var obj = {method: function () { ... }, ...}, - * this.method = function () { ... }; and other significant - * single-use-of-null-closure bytecode sequences. - */ - if (op2 == JSOP_INITMETHOD) { -#ifdef DEBUG - const Value &lref = regs.sp[-1]; - JS_ASSERT(lref.isObject()); - JSObject *obj2 = &lref.toObject(); - JS_ASSERT(obj2->isObject()); -#endif - JS_ASSERT(fun->methodAtom() == - script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH))); - break; - } - - if (op2 == JSOP_SETMETHOD) { -#ifdef DEBUG - op2 = JSOp(pc2[JSOP_SETMETHOD_LENGTH]); - JS_ASSERT(op2 == JSOP_POP || op2 == JSOP_POPV); -#endif - const Value &lref = regs.sp[-1]; - if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) { - JS_ASSERT(fun->methodAtom() == - script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH))); - break; - } - } else if (op2 == JSOP_CALL) { - /* - * Array.prototype.sort and String.prototype.replace are - * optimized as if they are special form. We know that they - * won't leak the joined function object in obj, therefore - * we don't need to clone that compiler-created function - * object for identity/mutation reasons. - */ - int iargc = GET_ARGC(pc2); - - /* - * Note that we have not yet pushed obj as the final argument, - * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)], - * is the callee for this JSOP_CALL. - */ - const Value &cref = regs.sp[1 - (iargc + 2)]; - JSFunction *fun; - - if (IsFunctionObject(cref, &fun)) { - if (Native native = fun->maybeNative()) { - if ((iargc == 1 && native == array_sort) || - (iargc == 2 && native == str_replace)) { - break; - } - } - } - } else if (op2 == JSOP_NULL) { - pc2 += JSOP_NULL_LENGTH; - op2 = JSOp(*pc2); - - if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0) - break; - } - } } else { parent = GetScopeChain(cx, regs.fp()); if (!parent) @@ -3405,7 +3337,6 @@ BEGIN_CASE(JSOP_ENDINIT) END_CASE(JSOP_ENDINIT) BEGIN_CASE(JSOP_INITPROP) -BEGIN_CASE(JSOP_INITMETHOD) { /* Load the property's initial value into rval. */ JS_ASSERT(regs.sp - regs.fp()->base() >= 2); @@ -3419,11 +3350,10 @@ BEGIN_CASE(JSOP_INITMETHOD) LOAD_ATOM(0, atom); jsid id = ATOM_TO_JSID(atom); - unsigned defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0; if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom) - ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode) + ? !js_SetPropertyHelper(cx, obj, id, 0, &rval, script->strictModeCode) : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL, - JSPROP_ENUMERATE, 0, 0, defineHow)) { + JSPROP_ENUMERATE, 0, 0, 0)) { goto error; } diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 55041f1ddef..e38b98ac868 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -244,17 +244,13 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp if (!obj) return false; - unsigned flags = (op == JSOP_CALLPROP) - ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER - : JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER; - PropertyCacheEntry *entry; JSObject *obj2; PropertyName *name; JS_PROPERTY_CACHE(cx).test(cx, pc, obj, obj2, entry, name); if (!name) { AssertValidPropertyCacheHit(cx, obj, obj2, entry); - if (!NativeGet(cx, obj, obj2, entry->prop, flags, vp)) + if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_CACHE_RESULT, vp)) return false; return true; } @@ -265,7 +261,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp)) return false; } else { - if (!GetPropertyHelper(cx, obj, id, flags, vp)) + if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, vp)) return false; } @@ -289,7 +285,6 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val if (!obj) return false; - JS_ASSERT_IF(*pc == JSOP_SETMETHOD, IsFunctionObject(rval)); JS_ASSERT_IF(*pc == JSOP_SETNAME || *pc == JSOP_SETGNAME, lval.isObject()); JS_ASSERT_IF(*pc == JSOP_SETGNAME, obj == &cx->fp()->scopeChain().global()); @@ -322,7 +317,7 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val } #endif - if (shape->hasDefaultSetter() && shape->hasSlot() && !shape->isMethod()) { + if (shape->hasDefaultSetter() && shape->hasSlot()) { /* Fast path for, e.g., plain Object instance properties. */ obj->nativeSetSlotWithType(cx, shape, rval); } else { @@ -344,13 +339,9 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val jsid id = ATOM_TO_JSID(name); if (JS_LIKELY(!obj->getOps()->setProperty)) { - unsigned defineHow; - if (op == JSOP_SETMETHOD) - defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD; - else if (op == JSOP_SETNAME) - defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED; - else - defineHow = DNP_CACHE_RESULT; + unsigned defineHow = (op == JSOP_SETNAME) + ? DNP_CACHE_RESULT | DNP_UNQUALIFIED + : DNP_CACHE_RESULT; if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rref, strict)) return false; } else { @@ -384,7 +375,7 @@ NameOperation(JSContext *cx, jsbytecode *pc, Value *vp) JS_PROPERTY_CACHE(cx).test(cx, pc, obj, obj2, entry, name); if (!name) { AssertValidPropertyCacheHit(cx, obj, obj2, entry); - if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, vp)) + if (!NativeGet(cx, obj, obj2, entry->prop, 0, vp)) return false; return true; } @@ -416,7 +407,7 @@ NameOperation(JSContext *cx, jsbytecode *pc, Value *vp) JSObject *normalized = obj; if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter()) normalized = &normalized->asWith().object(); - if (!NativeGet(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, vp)) + if (!NativeGet(cx, normalized, obj2, shape, 0, vp)) return false; } diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 5f99f7d5da7..e2b446a1f6a 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -459,7 +459,7 @@ GetCustomIterator(JSContext *cx, JSObject *obj, unsigned flags, Value *vp) /* Check whether we have a valid __iterator__ method. */ JSAtom *atom = cx->runtime->atomState.iteratorAtom; - if (!js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, vp)) + if (!js_GetMethod(cx, obj, ATOM_TO_JSID(atom), 0, vp)) return false; /* If there is no custom __iterator__ method, we are done here. */ @@ -1242,7 +1242,7 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval) } else { /* Call the iterator object's .next method. */ jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom); - if (!js_GetMethod(cx, iterobj, id, JSGET_METHOD_BARRIER, rval)) + if (!js_GetMethod(cx, iterobj, id, 0, rval)) return false; if (!Invoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) { /* Check for StopIteration. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 03c5434dfcf..fa14eb89e09 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1963,7 +1963,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropD return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval); } - if (!js_NativeGet(cx, obj, obj2, shape, JSGET_NO_METHOD_BARRIER, &v)) + if (!js_NativeGet(cx, obj, obj2, shape, 0, &v)) return JS_FALSE; } @@ -2092,14 +2092,8 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropD changed |= JSPROP_ENUMERATE; attrs = (shape->attributes() & ~changed) | (desc.attrs & changed); - if (shape->isMethod()) { - JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER))); - getter = JS_PropertyStub; - setter = JS_StrictPropertyStub; - } else { - getter = shape->getter(); - setter = shape->setter(); - } + getter = shape->getter(); + setter = shape->setter(); } else if (desc.isDataDescriptor()) { unsigned unchanged = 0; if (!desc.hasConfigurable) @@ -2126,8 +2120,6 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropD if (!CheckAccess(cx, obj2, id, JSACC_WATCH, &dummy, &attrs)) return JS_FALSE; - JS_ASSERT_IF(shape->isMethod(), !(attrs & (JSPROP_GETTER | JSPROP_SETTER))); - /* 8.12.9 step 12. */ unsigned changed = 0; if (desc.hasConfigurable) @@ -2143,7 +2135,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropD if (desc.hasGet) { getter = desc.getter(); } else { - getter = (shape->isMethod() || (shape->hasDefaultGetter() && !shape->hasGetterValue())) + getter = (shape->hasDefaultGetter() && !shape->hasGetterValue()) ? JS_PropertyStub : shape->getter(); } @@ -4399,8 +4391,6 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, PropertyOp getter, StrictPropertyOp setter, uint32_t slot, unsigned attrs, unsigned flags, int shortid) { - JS_ASSERT(!(flags & Shape::METHOD)); - /* Convert string indices to integers if appropriate. */ id = js_CheckForStringIndex(id); @@ -4415,26 +4405,6 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, return obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid); } -Shape * -js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, - Shape *shape, unsigned attrs, unsigned mask, - PropertyOp getter, StrictPropertyOp setter) -{ - /* - * Check for freezing an object with shape-memoized methods here, on a - * shape-by-shape basis. - */ - if ((attrs & JSPROP_READONLY) && shape->isMethod()) { - Value v = ObjectValue(*obj->nativeGetMethod(shape)); - - shape = obj->methodReadBarrier(cx, *shape, &v); - if (!shape) - return NULL; - } - - return obj->changeProperty(cx, shape, attrs, mask, getter, setter); -} - JSBool js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs) @@ -4482,15 +4452,12 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_, unsigned flags, int shortid, unsigned defineHow /* = 0 */) { JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_DONT_PURGE | - DNP_SET_METHOD | DNP_SKIP_TYPE)) == 0); + DNP_SKIP_TYPE)) == 0); RootObject objRoot(cx, &obj); RootId idRoot(cx, &id); - /* - * Make a local copy of value, in case a method barrier needs to update the - * value to define, and just so addProperty can mutate its inout parameter. - */ + /* Make a local copy of value so addProperty can mutate its inout parameter. */ RootedVarValue value(cx); value = value_; @@ -4549,15 +4516,12 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_, /* Use the object's class getter and setter by default. */ Class *clasp = obj->getClass(); - if (!(defineHow & DNP_SET_METHOD)) { - if (!getter && !(attrs & JSPROP_GETTER)) - getter = clasp->getProperty; - if (!setter && !(attrs & JSPROP_SETTER)) - setter = clasp->setProperty; - } + if (!getter && !(attrs & JSPROP_GETTER)) + getter = clasp->getProperty; + if (!setter && !(attrs & JSPROP_SETTER)) + setter = clasp->setProperty; - if (((defineHow & DNP_SET_METHOD) || getter == JS_PropertyStub) && - !(defineHow & DNP_SKIP_TYPE)) { + if ((getter == JS_PropertyStub) && !(defineHow & DNP_SKIP_TYPE)) { /* * Type information for normal native properties should reflect the * initial value of the property. @@ -4568,32 +4532,6 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_, } if (!shape) { - /* Add a new property, or replace an existing one of the same id. */ - if (defineHow & DNP_SET_METHOD) { - JS_ASSERT(clasp == &ObjectClass); - JS_ASSERT(IsFunctionObject(value)); - JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER))); - JS_ASSERT(!getter && !setter); - - JSObject *funobj = &value.raw().toObject(); - if (!funobj->toFunction()->isClonedMethod()) - flags |= Shape::METHOD; - } - - if (const Shape *existingShape = obj->nativeLookup(cx, id)) { - if (existingShape->isMethod() && - ObjectValue(*obj->nativeGetMethod(existingShape)) == value) - { - /* - * Redefining an existing shape-memoized method object without - * changing the property's value, perhaps to change attributes. - * Clone now via the method read barrier. - */ - if (!obj->methodReadBarrier(cx, *existingShape, value.address())) - return NULL; - } - } - shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT, attrs, flags, shortid); if (!shape) @@ -4970,7 +4908,7 @@ js_NativeGetInline(JSContext *cx, JSObject *receiver, JSObject *obj, JSObject *p if (shape->hasSlot()) { *vp = pobj->nativeGetSlot(shape->slot()); JS_ASSERT(!vp->isMagic()); - JS_ASSERT_IF(!pobj->hasSingletonType() && shape->hasDefaultGetterOrIsMethod(), + JS_ASSERT_IF(!pobj->hasSingletonType() && shape->hasDefaultGetter(), js::types::TypeHasProperty(cx, pobj->type(), shape->propid(), *vp)); } else { vp->setUndefined(); @@ -4978,9 +4916,6 @@ js_NativeGetInline(JSContext *cx, JSObject *receiver, JSObject *obj, JSObject *p if (shape->hasDefaultGetter()) return true; - if (JS_UNLIKELY(shape->isMethod()) && (getHow & JSGET_NO_METHOD_BARRIER)) - return true; - jsbytecode *pc; JSScript *script = cx->stack.currentScript(&pc); if (script && script->hasAnalysis()) { @@ -4993,11 +4928,8 @@ js_NativeGetInline(JSContext *cx, JSObject *receiver, JSObject *obj, JSObject *p return false; /* Update slotful shapes according to the value produced by the getter. */ - if (shape->hasSlot() && pobj->nativeContains(cx, *shape)) { - /* Method shapes were removed by methodReadBarrier under shape->get(). */ - JS_ASSERT(!shape->isMethod()); + if (shape->hasSlot() && pobj->nativeContains(cx, *shape)) pobj->nativeSetSlot(shape->slot(), *vp); - } return true; } @@ -5021,10 +4953,6 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, bool /* If shape has a stub setter, just store *vp. */ if (shape->hasDefaultSetter()) { - if (!added) { - if (shape->isMethod() && !obj->methodShapeChange(cx, *shape)) - return false; - } obj->nativeSetSlot(slot, *vp); return true; } @@ -5162,7 +5090,7 @@ JSBool js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */ - return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp); + return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp); } JSBool @@ -5173,7 +5101,7 @@ js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, return false; /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */ - return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp); + return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp); } JSBool @@ -5261,25 +5189,10 @@ bool JSObject::callMethod(JSContext *cx, jsid id, unsigned argc, Value *argv, Value *vp) { Value fval; - return js_GetMethod(cx, this, id, JSGET_NO_METHOD_BARRIER, &fval) && + return js_GetMethod(cx, this, id, 0, &fval) && Invoke(cx, ObjectValue(*this), fval, argc, argv, vp); } -static bool -CloneFunctionForSetMethod(JSContext *cx, Value *vp) -{ - JSFunction *fun = vp->toObject().toFunction(); - - /* Clone the fun unless it already has been. */ - if (!fun->isClonedMethod()) { - fun = CloneFunctionObject(cx, fun); - if (!fun) - return false; - vp->setObject(*fun); - } - return true; -} - JSBool js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, Value *vp, JSBool strict) @@ -5294,7 +5207,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, StrictPropertyOp setter; bool added; - JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_SET_METHOD | DNP_UNQUALIFIED)) == 0); + JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0); /* Convert string indices to integers if appropriate. */ id = js_CheckForStringIndex(id); @@ -5304,9 +5217,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, WatchpointMap *wpmap = cx->compartment->watchpointMap; if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp)) return false; - - /* A watchpoint handler may set *vp to a non-function value. */ - defineHow &= ~DNP_SET_METHOD; } if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop)) @@ -5381,12 +5291,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, * We found id in a prototype object: prepare to share or shadow. */ if (!shape->shadowable()) { - if (defineHow & DNP_SET_METHOD) { - JS_ASSERT(!shape->isMethod()); - if (!CloneFunctionForSetMethod(cx, vp)) - return false; - } - if (defineHow & DNP_CACHE_RESULT) JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, pobj, shape); @@ -5412,7 +5316,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, * about to create in obj. */ if (!shape->hasSlot()) { - defineHow &= ~DNP_SET_METHOD; if (shape->hasShortID()) { flags = Shape::HAS_SHORTID; shortid = shape->shortid(); @@ -5431,26 +5334,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, */ shape = NULL; } - - if (shape && (defineHow & DNP_SET_METHOD)) { - /* - * JSOP_SETMETHOD is assigning to an existing own property. If it - * is an identical method property, do nothing. Otherwise downgrade - * to ordinary assignment. Either way, do not fill the property - * cache, as the interpreter has no fast path for these unusual - * cases. - */ - if (shape->isMethod()) { - if (obj->nativeGetMethod(shape) == &vp->toObject()) - return true; - shape = obj->methodShapeChange(cx, *shape); - if (!shape) - return false; - } - if (!CloneFunctionForSetMethod(cx, vp)) - return false; - return js_NativeSet(cx, obj, shape, false, strict, vp); - } } added = false; @@ -5471,19 +5354,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow, if (!js_PurgeScopeChain(cx, obj, id)) return JS_FALSE; - /* - * Check for Object class here to avoid defining a method on a class - * with magic resolve, addProperty, getProperty, etc. hooks. - */ - if ((defineHow & DNP_SET_METHOD) && obj->canHaveMethodBarrier()) { - JS_ASSERT(IsFunctionObject(*vp)); - JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER))); - - JSObject *funobj = &vp->toObject(); - if (!funobj->toFunction()->isClonedMethod()) - flags |= Shape::METHOD; - } - shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT, attrs, flags, shortid); if (!shape) @@ -5557,14 +5427,6 @@ js_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned * return true; } -JSBool -js_SetNativeAttributes(JSContext *cx, JSObject *obj, Shape *shape, unsigned attrs) -{ - JS_ASSERT(obj->isNative()); - return !!js_ChangeNativePropertyAttrs(cx, obj, shape, attrs, 0, - shape->getter(), shape->setter()); -} - JSBool js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp) { @@ -5574,7 +5436,7 @@ js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp) if (!prop) return true; return obj->isNative() - ? js_SetNativeAttributes(cx, obj, (Shape *) prop, *attrsp) + ? obj->changePropertyAttributes(cx, (Shape *) prop, *attrsp) : obj->setGenericAttributes(cx, id, attrsp); } @@ -5587,7 +5449,7 @@ js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned * if (!prop) return true; return obj->isNative() - ? js_SetNativeAttributes(cx, obj, (Shape *) prop, *attrsp) + ? obj->changePropertyAttributes(cx, (Shape *) prop, *attrsp) : obj->setElementAttributes(cx, index, attrsp); } @@ -5624,35 +5486,6 @@ js_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool stri if (shape->hasSlot()) { const Value &v = obj->nativeGetSlot(shape->slot()); GCPoke(cx->runtime, v); - - /* - * Delete is rare enough that we can take the hit of checking for an - * active cloned method function object that must be homed to a callee - * slot on the active stack frame before this delete completes, in case - * someone saved the clone and checks it against foo.caller for a foo - * called from the active method. - * - * We do not check suspended frames. They can't be reached via caller, - * so the only way they could have the method's joined function object - * as callee is through an API abusage. We break any such edge case. - */ - JSFunction *fun; - if (IsFunctionObject(v, &fun) && fun->isClonedMethod()) { - for (StackFrame *fp = cx->maybefp(); fp; fp = fp->prev()) { - if (fp->isFunctionFrame() && - fp->fun()->script() == fun->script() && - fp->thisValue().isObject()) - { - JSObject *tmp = &fp->thisValue().toObject(); - do { - if (tmp == obj) { - fp->overwriteCallee(*fun); - break; - } - } while ((tmp = tmp->getProto()) != NULL); - } - } - } } if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, shape->getUserId(), rval)) @@ -5691,7 +5524,7 @@ HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { JS_ASSERT(id == js_CheckForStringIndex(id)); if (const Shape *shape = obj->nativeLookup(cx, id)) { - if (shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) { + if (shape->hasDefaultGetter() && shape->hasSlot()) { *vp = obj->nativeGetSlot(shape->slot()); return true; } @@ -5711,7 +5544,7 @@ HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) static bool MaybeCallMethod(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, vp)) + if (!js_GetMethod(cx, obj, id, 0, vp)) return false; if (!js_IsCallable(*vp)) { *vp = ObjectValue(*obj); @@ -6221,7 +6054,6 @@ DumpProperty(JSObject *obj, const Shape &shape) if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly "); if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent "); if (attrs & JSPROP_SHARED) fprintf(stderr, "shared "); - if (shape.isMethod()) fprintf(stderr, "method "); if (shape.hasGetterValue()) fprintf(stderr, "getterValue=%p ", (void *) shape.getterObject()); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index b5c55d14166..7d0fb977d8e 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -509,19 +509,8 @@ struct JSObject : public js::ObjectImpl public: inline bool nativeEmpty() const; - js::Shape *methodShapeChange(JSContext *cx, const js::Shape &shape); bool shadowingShapeChange(JSContext *cx, const js::Shape &shape); - /* - * Read barrier to clone a joined function object stored as a method. - * Defined in jsobjinlines.h, but not declared inline per standard style in - * order to avoid gcc warnings. - */ - js::Shape *methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp); - - /* Whether method shapes can be added to this object. */ - inline bool canHaveMethodBarrier() const; - /* Whether there may be indexed properties on this object. */ inline bool isIndexed() const; @@ -573,8 +562,6 @@ struct JSObject : public js::ObjectImpl void rollbackProperties(JSContext *cx, uint32_t slotSpan); - inline JSFunction *nativeGetMethod(const js::Shape *shape) const; - inline void nativeSetSlot(unsigned slot, const js::Value &value); inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value); @@ -940,6 +927,8 @@ struct JSObject : public js::ObjectImpl js::Shape *changeProperty(JSContext *cx, js::Shape *shape, unsigned attrs, unsigned mask, JSPropertyOp getter, JSStrictPropertyOp setter); + inline bool changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs); + /* Remove the property named by id from this object. */ bool removeProperty(JSContext *cx, jsid id); @@ -1351,16 +1340,6 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, JSPropertyOp getter, JSStrictPropertyOp setter, uint32_t slot, unsigned attrs, unsigned flags, int shortid); -/* - * Change shape to have the given attrs, getter, and setter in scope, morphing - * it into a potentially new js::Shape. Return a pointer to the changed - * or identical property. - */ -extern js::Shape * -js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, - js::Shape *shape, unsigned attrs, unsigned mask, - JSPropertyOp getter, JSStrictPropertyOp setter); - extern JSBool js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &descriptor, JSBool *bp); @@ -1372,13 +1351,10 @@ namespace js { */ const unsigned DNP_CACHE_RESULT = 1; /* an interpreter call from JSOP_INITPROP */ const unsigned DNP_DONT_PURGE = 2; /* suppress js_PurgeScopeChain */ -const unsigned DNP_SET_METHOD = 4; /* DefineNativeProperty,js_SetPropertyHelper - must pass the js::Shape::METHOD - flag on to JSObject::{add,put}Property */ -const unsigned DNP_UNQUALIFIED = 8; /* Unqualified property set. Only used in +const unsigned DNP_UNQUALIFIED = 4; /* Unqualified property set. Only used in the defineHow argument of js_SetPropertyHelper. */ -const unsigned DNP_SKIP_TYPE = 0x10; /* Don't update type information */ +const unsigned DNP_SKIP_TYPE = 8; /* Don't update type information */ /* * Return successfully added or changed shape or NULL on error. @@ -1460,22 +1436,8 @@ FindIdentifierBase(JSContext *cx, JSObject *scopeChain, PropertyName *name); extern JSObject * js_FindVariableScope(JSContext *cx, JSFunction **funp); -/* - * JSGET_CACHE_RESULT is the analogue of JSDNP_CACHE_RESULT for js_GetMethod. - * - * JSGET_METHOD_BARRIER (the default, hence 0 but provided for documentation) - * enables a read barrier that preserves standard function object semantics (by - * default we assume our caller won't leak a joined callee to script, where it - * would create hazardous mutable object sharing as well as observable identity - * according to == and ===. - * - * JSGET_NO_METHOD_BARRIER avoids the performance overhead of the method read - * barrier, which is not needed when invoking a lambda that otherwise does not - * leak its callee reference (via arguments.callee or its name). - */ -const unsigned JSGET_METHOD_BARRIER = 0; // get can leak joined function object -const unsigned JSGET_NO_METHOD_BARRIER = 1; // call to joined function can't leak -const unsigned JSGET_CACHE_RESULT = 2; // from a caching interpreter opcode +/* JSGET_CACHE_RESULT is the analogue of DNP_CACHE_RESULT for js_GetMethod. */ +const unsigned JSGET_CACHE_RESULT = 1; // from a caching interpreter opcode /* * NB: js_NativeGet and js_NativeSet are called with the scope containing shape @@ -1526,14 +1488,6 @@ GetMethod(JSContext *cx, JSObject *obj, PropertyName *name, unsigned getHow, Val } /* namespace js */ -/* - * Change attributes for the given native property. The caller must ensure - * that obj is locked and this function always unlocks obj on return. - */ -extern JSBool -js_SetNativeAttributes(JSContext *cx, JSObject *obj, js::Shape *shape, - unsigned attrs); - namespace js { /* diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 8d86f155c22..19df3268a56 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -170,6 +170,12 @@ JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrs return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp); } +inline bool +JSObject::changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs) +{ + return !!changeProperty(cx, shape, attrs, 0, shape->getter(), shape->setter()); +} + inline JSBool JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp) { @@ -265,50 +271,6 @@ JSObject::enclosingScope() return isScope() ? &asScope().enclosingScope() : getParent(); } -/* - * Property read barrier for deferred cloning of compiler-created function - * objects optimized as typically non-escaping, ad-hoc methods in obj. - */ -inline js::Shape * -JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp) -{ - JS_ASSERT(nativeContains(cx, shape)); - JS_ASSERT(shape.isMethod()); - JS_ASSERT(shape.hasSlot()); - JS_ASSERT(shape.hasDefaultSetter()); - JS_ASSERT(!isGlobal()); /* i.e. we are not changing the global shape */ - - JSFunction *fun = vp->toObject().toFunction(); - JS_ASSERT(!fun->isClonedMethod()); - JS_ASSERT(fun->isNullClosure()); - - fun = js::CloneFunctionObject(cx, fun); - if (!fun) - return NULL; - fun->setMethodObj(*this); - - /* - * Replace the method property with an ordinary data property. This is - * equivalent to this->setProperty(cx, shape.id, vp) except that any - * watchpoint on the property is not triggered. - */ - uint32_t slot = shape.slot(); - js::Shape *newshape = methodShapeChange(cx, shape); - if (!newshape) - return NULL; - JS_ASSERT(!newshape->isMethod()); - JS_ASSERT(newshape->slot() == slot); - vp->setObject(*fun); - nativeSetSlot(slot, *vp); - return newshape; -} - -inline bool -JSObject::canHaveMethodBarrier() const -{ - return isObject() || isFunction() || isPrimitive() || isDate(); -} - inline bool JSObject::isFixedSlot(size_t slot) { @@ -964,22 +926,6 @@ JSObject::principals(JSContext *cx) return cx->compartment ? cx->compartment->principals : NULL; } -inline JSFunction * -JSObject::nativeGetMethod(const js::Shape *shape) const -{ - /* - * For method shapes, this object must have an uncloned function object in - * the shape's slot. - */ - JS_ASSERT(shape->isMethod()); -#ifdef DEBUG - JSObject *obj = &nativeGetSlot(shape->slot()).toObject(); - JS_ASSERT(obj->isFunction() && !obj->toFunction()->isClonedMethod()); -#endif - - return static_cast(&nativeGetSlot(shape->slot()).toObject()); -} - inline void JSObject::nativeSetSlot(unsigned slot, const js::Value &value) { diff --git a/js/src/json.cpp b/js/src/json.cpp index 5843aad6314..359ffaf6fb6 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -312,7 +312,7 @@ PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, Value *vp, Stringi if (vp->isObject()) { Value toJSON; jsid id = ATOM_TO_JSID(cx->runtime->atomState.toJSONAtom); - if (!js_GetMethod(cx, &vp->toObject(), id, JSGET_NO_METHOD_BARRIER, &toJSON)) + if (!js_GetMethod(cx, &vp->toObject(), id, 0, &toJSON)) return false; if (js_IsCallable(toJSON)) { diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index fdc914be3a5..9b5b0c65af6 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -4515,7 +4515,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) break; case JSOP_SETPROP: - case JSOP_SETMETHOD: { LOAD_ATOM(0); GET_QUOTE_AND_FMT("[%s] %s= ", ".%s %s= ", xval); @@ -5120,7 +5119,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) break; case JSOP_INITPROP: - case JSOP_INITMETHOD: LOAD_ATOM(0); xval = QuoteString(&ss->sprinter, atom, jschar(IsIdentifier(atom) ? 0 : '\'')); if (!xval) diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 526d8d395b3..02a063bd2d8 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -569,7 +569,7 @@ class OpcodeCounts * Access ops include all name, element and property reads, as well as * SETELEM and SETPROP (for ElementCounts/PropertyCounts alignment). */ - if (op == JSOP_SETELEM || op == JSOP_SETPROP || op == JSOP_SETMETHOD) + if (op == JSOP_SETELEM || op == JSOP_SETPROP) return true; int format = js_CodeSpec[op].format; return !!(format & (JOF_NAME | JOF_GNAME | JOF_ELEM | JOF_PROP)) diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 4ab727d38f3..a47142adbd3 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -532,15 +532,10 @@ OPDEF(JSOP_LENGTH, 217, "length", NULL, 5, 1, 1, 18, JOF_ATOM|J OPDEF(JSOP_HOLE, 218, "hole", NULL, 1, 0, 1, 0, JOF_BYTE) OPDEF(JSOP_UNUSED17, 219,"unused17", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_UNUSED24, 220,"unused18", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_UNUSED25, 221,"unused19", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* - * Joined function object as method optimization support. - */ -OPDEF(JSOP_SETMETHOD, 222,"setmethod", NULL, 5, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) -OPDEF(JSOP_INITMETHOD, 223,"initmethod", NULL, 5, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) - +OPDEF(JSOP_UNUSED24, 220,"unused24", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED25, 221,"unused25", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED29, 222,"unused29", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED30, 223,"unused30", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_UNUSED16, 224,"unused16", NULL, 1, 0, 0, 0, JOF_BYTE) /* Pop the stack, convert to a jsid (int or string), and push back. */ diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index 3aeb248735c..f5fbf6c57fd 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -297,7 +297,6 @@ Shape::dump(JSContext *cx, FILE *fp) const fputs("(", fp); #define DUMP_FLAG(name, display) if (flags & name) fputs(&(" " #display)[first], fp), first = 0 DUMP_FLAG(HAS_SHORTID, has_shortid); - DUMP_FLAG(METHOD, method); DUMP_FLAG(IN_DICTIONARY, in_dictionary); #undef DUMP_FLAG fputs(") ", fp); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 72baeb5c156..1db72f3e39f 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -498,16 +498,9 @@ NormalizeGetterAndSetter(JSContext *cx, JSObject *obj, JS_ASSERT(!(attrs & JSPROP_SETTER)); setter = NULL; } - if (flags & Shape::METHOD) { - JS_ASSERT_IF(getter, getter == JS_PropertyStub); - JS_ASSERT(!setter); - JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER))); + if (getter == JS_PropertyStub) { + JS_ASSERT(!(attrs & JSPROP_GETTER)); getter = NULL; - } else { - if (getter == JS_PropertyStub) { - JS_ASSERT(!(attrs & JSPROP_GETTER)); - getter = NULL; - } } return true; @@ -808,9 +801,6 @@ JSObject::changeProperty(JSContext *cx, Shape *shape, unsigned attrs, unsigned m JS_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) || !(attrs & JSPROP_SHARED)); - /* Don't allow method properties to be changed to have a getter or setter. */ - JS_ASSERT_IF(shape->isMethod(), !getter && !setter); - types::MarkTypePropertyConfigured(cx, this, shape->propid()); if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) types::AddTypePropertyId(cx, this, shape->propid(), types::Type::UnknownType()); @@ -1041,44 +1031,6 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n return newShape; } -Shape * -JSObject::methodShapeChange(JSContext *cx, const Shape &shape) -{ - JS_ASSERT(shape.isMethod()); - - if (!inDictionaryMode() && !toDictionaryMode(cx)) - return NULL; - - Shape *spare = js_NewGCShape(cx); - if (!spare) - return NULL; - new (spare) Shape(shape.base()->unowned(), 0); - -#ifdef DEBUG - JS_ASSERT(canHaveMethodBarrier()); - JS_ASSERT(!shape.setter()); - JS_ASSERT(!shape.hasShortID()); -#endif - - /* - * Clear Shape::METHOD from flags as we are despecializing from a - * method memoized in the property tree to a plain old function-valued - * property. - */ - Shape *result = - putProperty(cx, shape.propid(), NULL, NULL, shape.slot(), - shape.attrs, - shape.getFlags() & ~Shape::METHOD, - 0); - if (!result) - return NULL; - - if (result != lastProperty()) - JS_ALWAYS_TRUE(generateOwnShape(cx, spare)); - - return result; -} - bool JSObject::shadowingShapeChange(JSContext *cx, const Shape &shape) { diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 35b5c0cb84d..4cedeea2cb5 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -649,43 +649,15 @@ struct Shape : public js::gc::Cell /* Public bits stored in shape->flags. */ enum { HAS_SHORTID = 0x40, - METHOD = 0x80, - PUBLIC_FLAGS = HAS_SHORTID | METHOD + PUBLIC_FLAGS = HAS_SHORTID }; bool inDictionary() const { return (flags & IN_DICTIONARY) != 0; } unsigned getFlags() const { return flags & PUBLIC_FLAGS; } bool hasShortID() const { return (flags & HAS_SHORTID) != 0; } - /* - * A shape has a method barrier when some compiler-created "null closure" - * function objects (functions that do not use lexical bindings above their - * scope, only free variable names) that have a correct JSSLOT_PARENT value - * thanks to the COMPILE_N_GO optimization are stored in objects without - * cloning. - * - * The de-facto standard JS language requires each evaluation of such a - * closure to result in a unique (according to === and observable effects) - * function object. When storing a function to a property, we use method - * shapes to speculate that these effects will never be observed: the - * property will only be used in calls, and f.callee will not be used - * to get a handle on the object. - * - * If either a non-call use or callee access occurs, then the function is - * cloned and the object is reshaped with a non-method property. - * - * Note that method shapes do not imply the object has a particular - * uncloned function, just that the object has *some* uncloned function - * in the shape's slot. - */ - bool isMethod() const { - JS_ASSERT_IF(flags & METHOD, !base()->rawGetter); - return (flags & METHOD) != 0; - } - PropertyOp getter() const { return base()->rawGetter; } - bool hasDefaultGetterOrIsMethod() const { return !base()->rawGetter; } - bool hasDefaultGetter() const { return !base()->rawGetter && !isMethod(); } + bool hasDefaultGetter() const { return !base()->rawGetter; } PropertyOp getterOp() const { JS_ASSERT(!hasGetterValue()); return base()->rawGetter; } JSObject *getterObject() const { JS_ASSERT(hasGetterValue()); return base()->getterObj; } diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index b6006c6f97f..3210568d8ed 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -282,16 +282,10 @@ Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js: JS_ASSERT(!hasDefaultGetter()); if (hasGetterValue()) { - JS_ASSERT(!isMethod()); js::Value fval = getterValue(); return js::InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp); } - if (isMethod()) { - vp->setObject(*pobj->nativeGetMethod(this)); - return pobj->methodReadBarrier(cx, *this, vp); - } - /* * |with (it) color;| ends up here, as do XML filter-expressions. * Avoid exposing the With object to native getters. diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index a19acda4c52..6eb50b76472 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3312,7 +3312,7 @@ js_ValueToSource(JSContext *cx, const Value &v) Value rval = NullValue(); Value fval; jsid id = ATOM_TO_JSID(cx->runtime->atomState.toSourceAtom); - if (!js_GetMethod(cx, &v.toObject(), id, JSGET_NO_METHOD_BARRIER, &fval)) + if (!js_GetMethod(cx, &v.toObject(), id, 0, &fval)) return NULL; if (js_IsCallable(fval)) { if (!Invoke(cx, v, fval, 0, NULL, &rval)) diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp index a37a2eb8344..c9b93df1269 100644 --- a/js/src/jswatchpoint.cpp +++ b/js/src/jswatchpoint.cpp @@ -149,26 +149,8 @@ WatchpointMap::triggerWatchpoint(JSContext *cx, JSObject *obj, jsid id, Value *v old.setUndefined(); if (obj->isNative()) { if (const Shape *shape = obj->nativeLookup(cx, id)) { - if (shape->hasSlot()) { - if (shape->isMethod()) { - /* - * The existing watched property is a method. Trip - * the method read barrier in order to avoid - * passing an uncloned function object to the - * handler. - */ - old = UndefinedValue(); - Value method = ObjectValue(*obj->nativeGetMethod(shape)); - if (!obj->methodReadBarrier(cx, *shape, &method)) - return false; - shape = obj->nativeLookup(cx, id); - JS_ASSERT(shape->isDataDescriptor()); - JS_ASSERT(!shape->isMethod()); - old = method; - } else { - old = obj->nativeGetSlot(shape->slot()); - } - } + if (shape->hasSlot()) + old = obj->nativeGetSlot(shape->slot()); } } diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 2ae7f126e6a..79e6f0e07b2 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1715,8 +1715,7 @@ mjit::Compiler::finishThisUp() jitPics[i].shapeRegHasBaseShape = true; jitPics[i].pc = pics[i].pc; - if (pics[i].kind == ic::PICInfo::SET || - pics[i].kind == ic::PICInfo::SETMETHOD) { + if (pics[i].kind == ic::PICInfo::SET) { jitPics[i].u.vr = pics[i].vr; } else if (pics[i].kind != ic::PICInfo::NAME) { if (pics[i].hasTypeCheck) { @@ -2900,11 +2899,6 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_ENDINIT) END_CASE(JSOP_ENDINIT) - BEGIN_CASE(JSOP_INITMETHOD) - jsop_initmethod(); - frame.pop(); - END_CASE(JSOP_INITMETHOD) - BEGIN_CASE(JSOP_INITPROP) jsop_initprop(); frame.pop(); @@ -2971,7 +2965,6 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_SETPROP) BEGIN_CASE(JSOP_SETNAME) - BEGIN_CASE(JSOP_SETMETHOD) { jsbytecode *next = &PC[JSOP_SETNAME_LENGTH]; bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next); @@ -3078,29 +3071,6 @@ mjit::Compiler::generateMethod() JSObjStubFun stub = stubs::Lambda; uint32_t uses = 0; - jsbytecode *pc2 = NULL; - if (fun->joinable()) { - pc2 = PC + JSOP_LAMBDA_LENGTH; - JSOp next = JSOp(*pc2); - - if (next == JSOP_INITMETHOD) { - stub = stubs::LambdaJoinableForInit; - } else if (next == JSOP_SETMETHOD) { - stub = stubs::LambdaJoinableForSet; - uses = 1; - } else if (next == JSOP_CALL) { - int iargc = GET_ARGC(pc2); - if (iargc == 1 || iargc == 2) { - stub = stubs::LambdaJoinableForCall; - uses = frame.frameSlots(); - } - } else if (next == JSOP_NULL) { - pc2 += JSOP_NULL_LENGTH; - if (JSOp(*pc2) == JSOP_CALL && GET_ARGC(pc2) == 0) - stub = stubs::LambdaJoinableForNull; - } - } - prepareStubCall(Uses(uses)); masm.move(ImmPtr(fun), Registers::ArgReg1); @@ -3249,7 +3219,7 @@ mjit::Compiler::generateMethod() /* Update information about the result type of access operations. */ if (OpcodeCounts::accessOp(op) && - op != JSOP_SETPROP && op != JSOP_SETMETHOD && op != JSOP_SETELEM) { + op != JSOP_SETPROP && op != JSOP_SETELEM) { FrameEntry *fe = (GetDefCount(script, lastPC - script->code) == 1) ? frame.peek(-1) : frame.peek(-2); @@ -5267,7 +5237,7 @@ mjit::Compiler::testSingletonProperty(JSObject *obj, jsid id) return false; if (holder->getSlot(shape->slot()).isUndefined()) return false; - } else if (!shape->isMethod()) { + } else { return false; } @@ -5600,10 +5570,7 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed) } #endif - ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD) - ? ic::PICInfo::SETMETHOD - : ic::PICInfo::SET; - PICGenInfo pic(kind, op); + PICGenInfo pic(ic::PICInfo::SET, op); pic.name = name; if (monitored(PC)) { @@ -6374,7 +6341,7 @@ mjit::Compiler::jsop_getgname(uint32_t index) * reallocation of the global object's slots. */ const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(name)); - if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) { + if (shape && shape->hasDefaultGetter() && shape->hasSlot()) { HeapSlot *value = &globalObj->getSlotRef(shape->slot()); if (!value->isUndefined() && !propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) { @@ -6497,7 +6464,7 @@ mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed) if (!types) return; const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(name)); - if (shape && !shape->isMethod() && shape->hasDefaultSetter() && + if (shape && shape->hasDefaultSetter() && shape->writable() && shape->hasSlot() && !types->isOwnProperty(cx, globalObj->getType(cx), true)) { watchGlobalReallocation(); diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 4c0218f850f..0ee93bb1c5e 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -262,7 +262,7 @@ class Compiler : public BaseCompiler return getPropLabels_; } ic::SetPropLabels &setPropLabels() { - JS_ASSERT(kind == ic::PICInfo::SET || kind == ic::PICInfo::SETMETHOD); + JS_ASSERT(kind == ic::PICInfo::SET); return setPropLabels_; } ic::BindNameLabels &bindNameLabels() { diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index c182d8884a8..32486e06b21 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -2658,22 +2658,6 @@ mjit::Compiler::jsop_pos() stubcc.rejoin(Changes(1)); } -void -mjit::Compiler::jsop_initmethod() -{ -#ifdef DEBUG - FrameEntry *obj = frame.peek(-2); -#endif - JSAtom *atom = script->getAtom(GET_UINT32_INDEX(PC)); - - /* Initializers with INITMETHOD are not fast yet. */ - JS_ASSERT(!frame.extra(obj).initObject); - - prepareStubCall(Uses(2)); - masm.move(ImmPtr(atom), Registers::ArgReg1); - INLINE_STUBCALL(stubs::InitMethod, REJOIN_FALLTHROUGH); -} - void mjit::Compiler::jsop_initprop() { diff --git a/js/src/methodjit/LoopState.cpp b/js/src/methodjit/LoopState.cpp index abd36d586fd..36aba92e42e 100644 --- a/js/src/methodjit/LoopState.cpp +++ b/js/src/methodjit/LoopState.cpp @@ -1869,8 +1869,7 @@ LoopState::analyzeLoopBody(unsigned frame) break; } - case JSOP_SETPROP: - case JSOP_SETMETHOD: { + case JSOP_SETPROP: { JSAtom *atom = script->getAtom(GET_UINT32_INDEX(pc)); jsid id = MakeTypeId(cx, ATOM_TO_JSID(atom)); diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index 297669b7de0..1a4527e4706 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -99,7 +99,7 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic) } if (!shape || - !shape->hasDefaultGetterOrIsMethod() || + !shape->hasDefaultGetter() || !shape->hasSlot()) { if (shape) @@ -165,8 +165,7 @@ UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Sh if (!shape) return Lookup_Uncacheable; - if (shape->isMethod() || - !shape->hasDefaultSetter() || + if (!shape->hasDefaultSetter() || !shape->writable() || !shape->hasSlot() || obj->watched()) diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 3c233c768b8..8b976045e91 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -350,23 +350,6 @@ class SetPropCompiler : public PICStubCompiler lastReg = pic.shapeReg; } - if (pic.kind == ic::PICInfo::SETMETHOD) { - /* - * Guard that the value is equal to the shape's method. - * We already know it is a function, so test the payload. - */ - JS_ASSERT(shape->isMethod()); - JSObject *funobj = obj->nativeGetMethod(shape); - if (pic.u.vr.isConstant()) { - JS_ASSERT(funobj == &pic.u.vr.value().toObject()); - } else { - Jump mismatchedFunction = - masm.branchPtr(Assembler::NotEqual, pic.u.vr.dataReg(), ImmPtr(funobj)); - if (!slowExits.append(mismatchedFunction)) - return error(); - } - } - if (obj->isFixedSlot(shape->slot())) { Address address(pic.objReg, JSObject::getFixedSlotOffset(shape->slot())); @@ -389,7 +372,6 @@ class SetPropCompiler : public PICStubCompiler /* Write the object's new shape. */ masm.storePtr(ImmPtr(shape), Address(pic.objReg, JSObject::offsetOfShape())); } else if (shape->hasDefaultSetter()) { - JS_ASSERT(!shape->isMethod()); Address address = masm.objPropAddress(obj, pic.objReg, shape->slot()); masm.storeValue(pic.u.vr, address); } else { @@ -585,17 +567,6 @@ class SetPropCompiler : public PICStubCompiler unsigned flags = 0; PropertyOp getter = clasp->getProperty; - if (pic.kind == ic::PICInfo::SETMETHOD) { - if (!obj->canHaveMethodBarrier()) - return disable("can't have method barrier"); - - JSObject *funobj = &f.regs.sp[-1].toObject(); - if (funobj->toFunction()->isClonedMethod()) - return disable("mismatched function"); - - flags |= Shape::METHOD; - } - /* * Define the property but do not set it yet. For setmethod, * populate the slot to satisfy the method invariant (in case we @@ -606,8 +577,6 @@ class SetPropCompiler : public PICStubCompiler SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0); if (!shape) return error(); - if (flags & Shape::METHOD) - obj->nativeSetSlot(shape->slot(), f.regs.sp[-1]); if (monitor.recompiled()) return Lookup_Uncacheable; @@ -647,13 +616,8 @@ class SetPropCompiler : public PICStubCompiler } const Shape *shape = (const Shape *) prop; - if (pic.kind == ic::PICInfo::SETMETHOD && !shape->isMethod()) - return disable("set method on non-method shape"); if (!shape->writable()) return disable("readonly"); - if (shape->isMethod()) - return disable("method"); - if (shape->hasDefaultSetter()) { if (!shape->hasSlot()) return disable("invalid slot"); @@ -789,27 +753,22 @@ struct GetPropHelper { LookupStatus testForGet() { if (!shape->hasDefaultGetter()) { - if (shape->isMethod()) { - if (JSOp(*f.pc()) != JSOP_CALLPROP) - return ic.disable(f, "method valued shape"); - } else { - if (shape->hasGetterValue()) - return ic.disable(f, "getter value shape"); - if (shape->hasSlot() && holder != obj) - return ic.disable(f, "slotful getter hook through prototype"); - if (!ic.canCallHook) - return ic.disable(f, "can't call getter hook"); - if (f.regs.inlined()) { - /* - * As with native stubs, getter hook stubs can't be - * generated for inline frames. Mark the inner function - * as uninlineable and recompile. - */ - f.script()->uninlineable = true; - MarkTypeObjectFlags(cx, f.script()->function(), - types::OBJECT_FLAG_UNINLINEABLE); - return Lookup_Uncacheable; - } + if (shape->hasGetterValue()) + return ic.disable(f, "getter value shape"); + if (shape->hasSlot() && holder != obj) + return ic.disable(f, "slotful getter hook through prototype"); + if (!ic.canCallHook) + return ic.disable(f, "can't call getter hook"); + if (f.regs.inlined()) { + /* + * As with native stubs, getter hook stubs can't be + * generated for inline frames. Mark the inner function + * as uninlineable and recompile. + */ + f.script()->uninlineable = true; + MarkTypeObjectFlags(cx, f.script()->function(), + types::OBJECT_FLAG_UNINLINEABLE); + return Lookup_Uncacheable; } } else if (!shape->hasSlot()) { return ic.disable(f, "no slot"); @@ -962,7 +921,7 @@ class GetPropCompiler : public PICStubCompiler return status; if (getprop.obj != getprop.holder) return disable("proto walk on String.prototype"); - if (!getprop.shape->hasDefaultGetterOrIsMethod()) + if (!getprop.shape->hasDefaultGetter()) return disable("getter hook on String.prototype"); if (hadGC()) return Lookup_Uncacheable; @@ -1239,7 +1198,7 @@ class GetPropCompiler : public PICStubCompiler pic.secondShapeGuard = 0; } - if (!shape->hasDefaultGetterOrIsMethod()) { + if (!shape->hasDefaultGetter()) { generateGetterStub(masm, shape, start, shapeMismatches); if (setStubShapeOffset) pic.getPropLabels().setStubShapeJump(masm, start, stubShapeJumpLabel); @@ -1327,7 +1286,7 @@ class GetPropCompiler : public PICStubCompiler return Lookup_Uncacheable; if (obj == getprop.holder && - getprop.shape->hasDefaultGetterOrIsMethod() && + getprop.shape->hasDefaultGetter() && !pic.inlinePathPatched) { return patchInline(getprop.holder, getprop.shape); } @@ -1675,7 +1634,7 @@ class ScopeNameCompiler : public PICStubCompiler JSObject *normalized = obj; if (obj->isWith() && !shape->hasDefaultGetter()) normalized = &obj->asWith().object(); - NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false); + NATIVE_GET(cx, normalized, holder, shape, 0, vp, return false); return true; } }; diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 23f217e85a8..f12e3b2c2b9 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -384,7 +384,6 @@ struct PICInfo : public BasePolyIC { { GET, // JSOP_GETPROP SET, // JSOP_SETPROP, JSOP_SETNAME - SETMETHOD, // JSOP_SETMETHOD NAME, // JSOP_NAME BIND, // JSOP_BINDNAME XNAME // JSOP_GETXPROP @@ -461,7 +460,7 @@ struct PICInfo : public BasePolyIC { types::TypeSet *rhsTypes; inline bool isSet() const { - return kind == SET || kind == SETMETHOD; + return kind == SET; } inline bool isGet() const { return kind == GET; diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index d04589fb39b..ca681d15c8e 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -998,69 +998,6 @@ stubs::RegExp(VMFrame &f, JSObject *regex) f.regs.sp[0].setObject(*obj); } -JSObject * JS_FASTCALL -stubs::LambdaJoinableForInit(VMFrame &f, JSFunction *fun) -{ - JS_ASSERT(fun->joinable()); - DebugOnly nextpc = f.regs.pc + JSOP_LAMBDA_LENGTH; - JS_ASSERT(fun->methodAtom() == f.script()->getAtom(GET_UINT32_INDEX(nextpc))); - return fun; -} - -JSObject * JS_FASTCALL -stubs::LambdaJoinableForSet(VMFrame &f, JSFunction *fun) -{ - JS_ASSERT(fun->joinable()); - const Value &lref = f.regs.sp[-1]; - if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) { - DebugOnly nextpc = f.regs.pc + JSOP_LAMBDA_LENGTH; - JS_ASSERT(fun->methodAtom() == f.script()->getAtom(GET_UINT32_INDEX(nextpc))); - return fun; - } - return Lambda(f, fun); -} - -JSObject * JS_FASTCALL -stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun) -{ - JS_ASSERT(fun->joinable()); - - /* - * Array.prototype.sort and String.prototype.replace are optimized as if - * they are special form. We know that they won't leak the joined function - * object fun, therefore we don't need to clone that compiler-created - * function object for identity/mutation reasons. - */ - int iargc = GET_ARGC(f.regs.pc + JSOP_LAMBDA_LENGTH); - - /* - * Note that we have not yet pushed fun as the final argument, so - * regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)], is the callee - * for this JSOP_CALL. - */ - const Value &cref = f.regs.sp[1 - (iargc + 2)]; - JSFunction *callee; - - if (IsFunctionObject(cref, &callee)) { - Native native = callee->maybeNative(); - - if (native) { - if (iargc == 1 && native == array_sort) - return fun; - if (iargc == 2 && native == str_replace) - return fun; - } - } - return Lambda(f, fun); -} - -JSObject * JS_FASTCALL -stubs::LambdaJoinableForNull(VMFrame &f, JSFunction *fun) -{ - JS_ASSERT(fun->joinable()); - return fun; -} - JSObject * JS_FASTCALL stubs::Lambda(VMFrame &f, JSFunction *fun) { @@ -1141,11 +1078,10 @@ InitPropOrMethod(VMFrame &f, PropertyName *name, JSOp op) /* Get the immediate property name into id. */ jsid id = ATOM_TO_JSID(name); - unsigned defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0; if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom) - ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, false) + ? !js_SetPropertyHelper(cx, obj, id, 0, &rval, false) : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL, - JSPROP_ENUMERATE, 0, 0, defineHow)) { + JSPROP_ENUMERATE, 0, 0, 0)) { THROW(); } } @@ -1156,12 +1092,6 @@ stubs::InitProp(VMFrame &f, PropertyName *name) InitPropOrMethod(f, name, JSOP_INITPROP); } -void JS_FASTCALL -stubs::InitMethod(VMFrame &f, PropertyName *name) -{ - InitPropOrMethod(f, name, JSOP_INITMETHOD); -} - void JS_FASTCALL stubs::IterNext(VMFrame &f, int32_t offset) { diff --git a/js/src/methodjit/StubCalls.h b/js/src/methodjit/StubCalls.h index 7ce9b5d629a..5d4b4616aa9 100644 --- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -62,7 +62,6 @@ void JS_FASTCALL Interrupt(VMFrame &f, jsbytecode *pc); void JS_FASTCALL RecompileForInline(VMFrame &f); void JS_FASTCALL InitElem(VMFrame &f, uint32_t last); void JS_FASTCALL InitProp(VMFrame &f, PropertyName *name); -void JS_FASTCALL InitMethod(VMFrame &f, PropertyName *name); void JS_FASTCALL HitStackQuota(VMFrame &f); void * JS_FASTCALL FixupArity(VMFrame &f, uint32_t argc); @@ -137,10 +136,6 @@ void JS_FASTCALL SetConst(VMFrame &f, PropertyName *name); template void JS_FASTCALL DefFun(VMFrame &f, JSFunction *fun); void JS_FASTCALL RegExp(VMFrame &f, JSObject *regex); JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun); -JSObject * JS_FASTCALL LambdaJoinableForInit(VMFrame &f, JSFunction *fun); -JSObject * JS_FASTCALL LambdaJoinableForSet(VMFrame &f, JSFunction *fun); -JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun); -JSObject * JS_FASTCALL LambdaJoinableForNull(VMFrame &f, JSFunction *fun); JSObject * JS_FASTCALL FlatLambda(VMFrame &f, JSFunction *fun); void JS_FASTCALL Arguments(VMFrame &f); void JS_FASTCALL EnterBlock(VMFrame &f, JSObject *obj); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 9a5fe79bceb..acde4a54972 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2170,8 +2170,7 @@ DumpStack(JSContext *cx, unsigned argc, Value *vp) Value v; if (iter.isScript()) { if (iter.fp()->isNonEvalFunctionFrame()) { - if (!iter.fp()->getValidCalleeObject(cx, &v)) - return false; + v = ObjectValue(iter.fp()->callee()); } else if (iter.fp()->isEvalFrame()) { v = StringValue(evalStr); } else { @@ -2782,11 +2781,7 @@ CopyProperty(JSContext *cx, JSObject *obj, JSObject *referent, jsid id, return true; const Shape *shape = (Shape *) prop; - if (shape->isMethod()) { - shape = referent->methodReadBarrier(cx, *shape, &desc.value); - if (!shape) - return false; - } else if (shape->hasSlot()) { + if (shape->hasSlot()) { desc.value = referent->nativeGetSlot(shape->slot()); } else { desc.value.setUndefined(); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 680da9941ee..f27da934ec2 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -925,7 +925,7 @@ CallMethodIfPresent(JSContext *cx, JSObject *obj, const char *name, int argc, Va JSAtom *atom = js_Atomize(cx, name, strlen(name)); Value fval; return atom && - js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, &fval) && + js_GetMethod(cx, obj, ATOM_TO_JSID(atom), 0, &fval) && (!js_IsCallable(fval) || Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval)); } diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index dc0ef91a88a..31bae3e0a90 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -189,13 +189,6 @@ StackFrame::initFixupFrame(StackFrame *prev, StackFrame::Flags flags, void *ncod u.nactual = nactual; } -inline void -StackFrame::overwriteCallee(JSObject &newCallee) -{ - JS_ASSERT(callee().toFunction()->script() == newCallee.toFunction()->script()); - mutableCalleev().setObject(newCallee); -} - inline Value & StackFrame::canonicalActualArg(unsigned i) const { diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index e154d2dea12..af0370872ba 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -818,13 +818,6 @@ class StackFrame return calleev; } - /* - * Beware! Ad hoc changes can corrupt the stack layout; the callee should - * only be changed to something that is equivalent to the current callee in - * terms of numFormalArgs etc. Prefer overwriteCallee since it checks. - */ - inline void overwriteCallee(JSObject &newCallee); - Value &mutableCalleev() const { JS_ASSERT(isFunctionFrame()); if (isEvalFrame()) @@ -832,13 +825,6 @@ class StackFrame return formalArgs()[-2]; } - /* - * Compute the callee function for this stack frame, cloning if needed to - * implement the method read barrier. If this is not a function frame, - * set *vp to null. - */ - bool getValidCalleeObject(JSContext *cx, Value *vp); - CallReceiver callReceiver() const { return CallReceiverFromArgv(formalArgs()); } From ec6279523d7ebf15f46163d4ef3842938543d574 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Mon, 26 Mar 2012 12:45:29 -0700 Subject: [PATCH 090/113] Bug 491947 - Disable DDE shell integration. r=jmathies --- browser/components/nsBrowserContentHandler.js | 23 +- .../shell/src/nsWindowsShellService.cpp | 252 ++++++++++++++---- browser/installer/windows/nsis/installer.nsi | 18 +- browser/installer/windows/nsis/shared.nsh | 62 ++--- .../installer/windows/nsis/uninstaller.nsi | 2 +- js/src/tests/e4x/Regress/regress-308111.js | 1 - modules/libpref/src/init/all.js | 7 - .../mozapps/installer/windows/nsis/common.nsh | 163 ++++++++++- 8 files changed, 393 insertions(+), 135 deletions(-) diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index f90234c10d0..b6e7927bae9 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -747,10 +747,6 @@ nsDefaultCommandLineHandler.prototype = { return this; }, - // List of uri's that were passed via the command line without the app - // running and have already been handled. This is compared against uri's - // opened using DDE on Win32 so we only open one of the requests. - _handledURIs: [ ], #ifdef XP_WIN _haveProfile: false, #endif @@ -784,25 +780,8 @@ nsDefaultCommandLineHandler.prototype = { try { var ar; while ((ar = cmdLine.handleFlagWithParam("url", false))) { - var found = false; var uri = resolveURIInternal(cmdLine, ar); - // count will never be greater than zero except on Win32. - var count = this._handledURIs.length; - for (var i = 0; i < count; ++i) { - if (this._handledURIs[i].spec == uri.spec) { - this._handledURIs.splice(i, 1); - found = true; - cmdLine.preventDefault = true; - break; - } - } - if (!found) { - urilist.push(uri); - // The requestpending command line flag is only used on Win32. - if (cmdLine.handleFlag("requestpending", false) && - cmdLine.state == nsICommandLine.STATE_INITIAL_LAUNCH) - this._handledURIs.push(uri) - } + urilist.push(uri); } } catch (e) { diff --git a/browser/components/shell/src/nsWindowsShellService.cpp b/browser/components/shell/src/nsWindowsShellService.cpp index 0cfc1653184..05f4984416f 100644 --- a/browser/components/shell/src/nsWindowsShellService.cpp +++ b/browser/components/shell/src/nsWindowsShellService.cpp @@ -77,7 +77,10 @@ #define INITGUID #include +#pragma comment(lib, "shlwapi.lib") // for SHDeleteKeyW + #include +#include #ifndef MAX_BUF #define MAX_BUF 4096 @@ -129,23 +132,17 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey) // // HKCU\SOFTWARE\Classes\FirefoxHTML\ // DefaultIcon (default) REG_SZ ,1 -// shell\open\command (default) REG_SZ -requestPending -osint -url "%1" -// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, -// shell\open\ddeexec NoActivateHandler REG_SZ -// \Application (default) REG_SZ Firefox -// \Topic (default) REG_SZ WWW_OpenURL +// shell\open\command (default) REG_SZ -osint -url "%1" +// shell\open\ddeexec (default) REG_SZ // -// - Windows Vista Protocol Handler +// - Windows Vista and above Protocol Handler // // HKCU\SOFTWARE\Classes\FirefoxURL\ (default) REG_SZ URL // EditFlags REG_DWORD 2 // FriendlyTypeName REG_SZ URL // DefaultIcon (default) REG_SZ ,1 -// shell\open\command (default) REG_SZ -requestPending -osint -url "%1" -// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, -// shell\open\ddeexec NoActivateHandler REG_SZ -// \Application (default) REG_SZ Firefox -// \Topic (default) REG_SZ WWW_OpenURL +// shell\open\command (default) REG_SZ -osint -url "%1" +// shell\open\ddeexec (default) REG_SZ // // - Protocol Mappings // ----------------- @@ -155,13 +152,10 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey) // // HKCU\SOFTWARE\Classes\\ // DefaultIcon (default) REG_SZ ,1 -// shell\open\command (default) REG_SZ -requestPending -osint -url "%1" -// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, -// shell\open\ddeexec NoActivateHandler REG_SZ -// \Application (default) REG_SZ Firefox -// \Topic (default) REG_SZ WWW_OpenURL +// shell\open\command (default) REG_SZ -osint -url "%1" +// shell\open\ddeexec (default) REG_SZ // -// - Windows Start Menu (Win2K SP2, XP SP1, and newer) +// - Windows Start Menu (XP SP1 and newer) // ------------------------------------------------- // The following keys are set to make Firefox appear in the Start Menu as the // browser: @@ -180,19 +174,22 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey) // shell\safemode\command (default) REG_SZ -safe-mode // +// The values checked are all default values so the value name is not needed. typedef struct { char* keyName; - char* valueName; char* valueData; + char* oldValueData; } SETTING; #define APP_REG_NAME L"Firefox" -#define CLS_HTML "FirefoxHTML" -#define CLS_URL "FirefoxURL" -#define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\"" #define VAL_FILE_ICON "%APPPATH%,1" +#define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\"" +#define OLD_VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\"" #define DI "\\DefaultIcon" -#define SOP "\\shell\\open\\command" +#define SOC "\\shell\\open\\command" +#define SOD "\\shell\\open\\ddeexec" +// Used for updating the FTP protocol handler's shell open command under HKCU. +#define FTP_SOC L"Software\\Classes\\ftp\\shell\\open\\command" #define MAKE_KEY_NAME1(PREFIX, MID) \ PREFIX MID @@ -201,19 +198,37 @@ typedef struct { // Firefox is the default browser for file handlers since other applications // (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon // Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for -// more info. +// more info. The FTP protocol is not checked so advanced users can set the FTP +// handler to another application and still have Firefox check if it is the +// default HTTP and HTTPS handler. static SETTING gSettings[] = { // File Handler Class - { MAKE_KEY_NAME1(CLS_HTML, SOP), "", VAL_OPEN }, + { MAKE_KEY_NAME1("FirefoxHTML", SOC), VAL_OPEN, OLD_VAL_OPEN }, // Protocol Handler Class - for Vista and above - { MAKE_KEY_NAME1(CLS_URL, SOP), "", VAL_OPEN }, + { MAKE_KEY_NAME1("FirefoxURL", SOC), VAL_OPEN, OLD_VAL_OPEN }, // Protocol Handlers - { MAKE_KEY_NAME1("HTTP", DI), "", VAL_FILE_ICON }, - { MAKE_KEY_NAME1("HTTP", SOP), "", VAL_OPEN }, - { MAKE_KEY_NAME1("HTTPS", DI), "", VAL_FILE_ICON }, - { MAKE_KEY_NAME1("HTTPS", SOP), "", VAL_OPEN } + { MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON }, + { MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN }, + { MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON }, + { MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN } +}; + +// The settings to disable DDE are separate from the default browser settings +// since they are only checked when Firefox is the default browser and if they +// are incorrect they are fixed without notifying the user. +static SETTING gDDESettings[] = { + // File Handler Class + { MAKE_KEY_NAME1("Software\\Classes\\FirefoxHTML", SOD) }, + + // Protocol Handler Class - for Vista and above + { MAKE_KEY_NAME1("Software\\Classes\\FirefoxURL", SOD) }, + + // Protocol Handlers + { MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) }, + { MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) }, + { MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) } }; nsresult @@ -245,11 +260,10 @@ LaunchHelper(nsAutoString& aPath) STARTUPINFOW si = {sizeof(si), 0}; PROCESS_INFORMATION pi = {0}; - BOOL ok = CreateProcessW(NULL, (LPWSTR)aPath.get(), NULL, NULL, - FALSE, 0, NULL, NULL, &si, &pi); - - if (!ok) + if (!CreateProcessW(NULL, (LPWSTR)aPath.get(), NULL, NULL, FALSE, 0, NULL, + NULL, &si, &pi)) { return NS_ERROR_FAILURE; + } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); @@ -367,9 +381,6 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck, if (aStartupCheck) mCheckedThisSession = true; - SETTING* settings; - SETTING* end = gSettings + sizeof(gSettings)/sizeof(SETTING); - *aIsDefaultBrowser = true; PRUnichar exePath[MAX_BUF]; @@ -383,40 +394,171 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck, nsAutoString appLongPath(exePath); + HKEY theKey; + DWORD res; nsresult rv; PRUnichar currValue[MAX_BUF]; - for (settings = gSettings; settings < end; ++settings) { - NS_ConvertUTF8toUTF16 dataLongPath(settings->valueData); - NS_ConvertUTF8toUTF16 key(settings->keyName); - NS_ConvertUTF8toUTF16 value(settings->valueName); - PRInt32 offset = dataLongPath.Find("%APPPATH%"); - dataLongPath.Replace(offset, 9, appLongPath); - ::ZeroMemory(currValue, sizeof(currValue)); - HKEY theKey; - rv = OpenKeyForReading(HKEY_CLASSES_ROOT, key, &theKey); + SETTING* settings; + SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING); + + for (settings = gSettings; settings < end; ++settings) { + NS_ConvertUTF8toUTF16 keyName(settings->keyName); + NS_ConvertUTF8toUTF16 valueData(settings->valueData); + PRInt32 offset = valueData.Find("%APPPATH%"); + valueData.Replace(offset, 9, appLongPath); + + rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey); if (NS_FAILED(rv)) { *aIsDefaultBrowser = false; return NS_OK; } + ::ZeroMemory(currValue, sizeof(currValue)); DWORD len = sizeof currValue; - DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(value).get(), - NULL, NULL, (LPBYTE)currValue, &len); - // Close the key we opened. + res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue, &len); + // Close the key that was opened. ::RegCloseKey(theKey); if (REG_FAILED(res) || - !dataLongPath.Equals(currValue, CaseInsensitiveCompare)) { - // Key wasn't set, or was set to something other than our registry entry - *aIsDefaultBrowser = false; - return NS_OK; + !valueData.Equals(currValue, CaseInsensitiveCompare)) { + // Key wasn't set or was set to something other than our registry entry. + NS_ConvertUTF8toUTF16 oldValueData(settings->oldValueData); + offset = oldValueData.Find("%APPPATH%"); + oldValueData.Replace(offset, 9, appLongPath); + // The current registry value doesn't match the current or the old format. + if (!oldValueData.Equals(currValue, CaseInsensitiveCompare)) { + *aIsDefaultBrowser = false; + return NS_OK; + } + + res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(), + 0, KEY_SET_VALUE, &theKey); + if (REG_FAILED(res)) { + // If updating the open command fails try to update it using the helper + // application when setting Firefox as the default browser. + *aIsDefaultBrowser = false; + return NS_OK; + } + + const nsString &flatValue = PromiseFlatString(valueData); + res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, + (const BYTE *) flatValue.get(), + (flatValue.Length() + 1) * sizeof(PRUnichar)); + // Close the key that was created. + ::RegCloseKey(theKey); + if (REG_FAILED(res)) { + // If updating the open command fails try to update it using the helper + // application when setting Firefox as the default browser. + *aIsDefaultBrowser = false; + return NS_OK; + } } } - // Only check if Firefox is the default browser on Vista if the previous - // checks show that Firefox is the default browser. - if (*aIsDefaultBrowser) + // Only check if Firefox is the default browser on Vista and above if the + // previous checks show that Firefox is the default browser. + if (*aIsDefaultBrowser) { IsDefaultBrowserVista(aIsDefaultBrowser); + } + + // To handle the case where DDE isn't disabled due for a user because there + // account didn't perform a Firefox update this will check if Firefox is the + // default browser and if dde is disabled for each handler + // and if it isn't disable it. When Firefox is not the default browser the + // helper application will disable dde for each handler. + if (*aIsDefaultBrowser) { + // Check ftp settings + + end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING); + + for (settings = gDDESettings; settings < end; ++settings) { + NS_ConvertUTF8toUTF16 keyName(settings->keyName); + + rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey); + if (NS_FAILED(rv)) { + ::RegCloseKey(theKey); + // If disabling DDE fails try to disable it using the helper + // application when setting Firefox as the default browser. + *aIsDefaultBrowser = false; + return NS_OK; + } + + ::ZeroMemory(currValue, sizeof(currValue)); + DWORD len = sizeof currValue; + res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue, + &len); + // Close the key that was opened. + ::RegCloseKey(theKey); + if (REG_FAILED(res) || PRUnichar('\0') != *currValue) { + // Key wasn't set or was set to something other than our registry entry. + // Delete the key along with all of its childrean and then recreate it. + const nsString &flatName = PromiseFlatString(keyName); + ::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get()); + res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, + &theKey, NULL); + if (REG_FAILED(res)) { + // If disabling DDE fails try to disable it using the helper + // application when setting Firefox as the default browser. + *aIsDefaultBrowser = false; + return NS_OK; + } + + res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, (const BYTE *) L"", + sizeof(PRUnichar)); + // Close the key that was created. + ::RegCloseKey(theKey); + if (REG_FAILED(res)) { + // If disabling DDE fails try to disable it using the helper + // application when setting Firefox as the default browser. + *aIsDefaultBrowser = false; + return NS_OK; + } + } + } + + // Update the FTP protocol handler's shell open command if it is the old + // format. + res = ::RegOpenKeyExW(HKEY_CURRENT_USER, FTP_SOC, 0, KEY_ALL_ACCESS, + &theKey); + // Don't update the FTP protocol handler's shell open command when opening + // its registry key fails under HKCU since it most likely doesn't exist. + if (NS_FAILED(rv)) { + return NS_OK; + } + + NS_ConvertUTF8toUTF16 oldValueOpen(OLD_VAL_OPEN); + PRInt32 offset = oldValueOpen.Find("%APPPATH%"); + oldValueOpen.Replace(offset, 9, appLongPath); + + ::ZeroMemory(currValue, sizeof(currValue)); + DWORD len = sizeof currValue; + res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue, + &len); + + // Don't update the FTP protocol handler's shell open command when the + // current registry value doesn't exist or matches the old format. + if (REG_FAILED(res) || + !oldValueOpen.Equals(currValue, CaseInsensitiveCompare)) { + ::RegCloseKey(theKey); + return NS_OK; + } + + NS_ConvertUTF8toUTF16 valueData(VAL_OPEN); + valueData.Replace(offset, 9, appLongPath); + const nsString &flatValue = PromiseFlatString(valueData); + res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, + (const BYTE *) flatValue.get(), + (flatValue.Length() + 1) * sizeof(PRUnichar)); + // Close the key that was created. + ::RegCloseKey(theKey); + // If updating the FTP protocol handlers shell open command fails try to + // update it using the helper application when setting Firefox as the + // default browser. + if (REG_FAILED(res)) { + *aIsDefaultBrowser = false; + } + } return NS_OK; } diff --git a/browser/installer/windows/nsis/installer.nsi b/browser/installer/windows/nsis/installer.nsi index d73ad1a7014..d9b5004ad90 100755 --- a/browser/installer/windows/nsis/installer.nsi +++ b/browser/installer/windows/nsis/installer.nsi @@ -103,7 +103,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe" ; Must be inserted before other macros that use logging !insertmacro _LoggingCommon -!insertmacro AddDDEHandlerValues +!insertmacro AddDisabledDDEHandlerValues !insertmacro ChangeMUIHeaderImage !insertmacro CheckForFilesInUse !insertmacro CleanUpdatesDir @@ -352,17 +352,15 @@ Section "-Application" APP_IDX ${SetUninstallKeys} ; On install always add the FirefoxHTML and FirefoxURL keys. - ; An empty string is used for the 5th param because FirefoxHTML and FirefoxURL - ; are not protocol handlers. + ; An empty string is used for the 5th param because FirefoxHTML is not a + ; protocol handler. ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8 - StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\"" - StrCpy $3 "$\"%1$\",,0,0,,,," + StrCpy $2 "$\"$8$\" -osint -url $\"%1$\"" - ${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} Document" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" - - ${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \ + "${AppRegName} Document" "" + ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \ + "true" ; The following keys should only be set if we can write to HKLM ${If} $TmpVal == "HKLM" diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh index 2d5fb05d037..20717b15f9e 100755 --- a/browser/installer/windows/nsis/shared.nsh +++ b/browser/installer/windows/nsis/shared.nsh @@ -79,7 +79,7 @@ ${GetLongPath} "$0" $0 ${EndIf} ${If} "$0" == "$INSTDIR" - ${SetStartMenuInternet} + ${SetStartMenuInternet} ; Does not use SHCTX ${EndIf} ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion" @@ -152,12 +152,12 @@ !define PostUpdate "!insertmacro PostUpdate" !macro SetAsDefaultAppGlobal - ${RemoveDeprecatedKeys} + ${RemoveDeprecatedKeys} ; Does not use SHCTX SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM) - ${SetHandlers} - ${SetStartMenuInternet} - ${FixShellIconHandler} + ${SetHandlers} ; Uses SHCTX + ${SetStartMenuInternet} ; Does not use SHCTX + ${FixShellIconHandler} ; Does not use SHCTX ${ShowShortcuts} ${StrFilter} "${FileMainEXE}" "+" "" "" $R9 WriteRegStr HKLM "Software\Clients\StartMenuInternet" "" "$R9" @@ -302,7 +302,7 @@ ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8 StrCpy $0 "SOFTWARE\Classes" - StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\"" + StrCpy $2 "$\"$8$\" -osint -url $\"%1$\"" ; Associate the file handlers with FirefoxHTML ReadRegStr $6 SHCTX "$0\.htm" "" @@ -336,25 +336,20 @@ WriteRegStr SHCTX "$0\.webm" "" "FirefoxHTML" ${EndIf} - StrCpy $3 "$\"%1$\",,0,0,,,," - ; An empty string is used for the 5th param because FirefoxHTML is not a ; protocol handler - ${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} HTML Document" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \ + "${AppRegName} HTML Document" "" - ${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \ + "true" ; An empty string is used for the 4th & 5th params because the following ; protocol handlers already have a display name and the additional keys ; required for a protocol handler. - ${AddDDEHandlerValues} "ftp" "$2" "$8,1" "" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" - ${AddDDEHandlerValues} "http" "$2" "$8,1" "" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" - ${AddDDEHandlerValues} "https" "$2" "$8,1" "" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "ftp" "$2" "$8,1" "" "" + ${AddDisabledDDEHandlerValues} "http" "$2" "$8,1" "" "" + ${AddDisabledDDEHandlerValues} "https" "$2" "$8,1" "" "" !macroend !define SetHandlers "!insertmacro SetHandlers" @@ -563,8 +558,7 @@ !macro UpdateProtocolHandlers ; Store the command to open the app with an url in a register for easy access. ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8 - StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\"" - StrCpy $3 "$\"%1$\",,0,0,,,," + StrCpy $2 "$\"$8$\" -osint -url $\"%1$\"" ; Only set the file and protocol handlers if the existing one under HKCR is ; for this install location. @@ -573,32 +567,32 @@ ${If} "$R9" == "true" ; An empty string is used for the 5th param because FirefoxHTML is not a ; protocol handler. - ${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} HTML Document" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \ + "${AppRegName} HTML Document" "" ${EndIf} ${IsHandlerForInstallDir} "FirefoxURL" $R9 ${If} "$R9" == "true" - ${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" \ + "${AppRegName} URL" "true" ${EndIf} + ; An empty string is used for the 4th & 5th params because the following + ; protocol handlers already have a display name and the additional keys + ; required for a protocol handler. ${IsHandlerForInstallDir} "ftp" $R9 ${If} "$R9" == "true" - ${AddDDEHandlerValues} "ftp" "$2" "$8,1" "" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "ftp" "$2" "$8,1" "" "" ${EndIf} ${IsHandlerForInstallDir} "http" $R9 ${If} "$R9" == "true" - ${AddDDEHandlerValues} "http" "$2" "$8,1" "" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "http" "$2" "$8,1" "" "" ${EndIf} ${IsHandlerForInstallDir} "https" $R9 ${If} "$R9" == "true" - ${AddDDEHandlerValues} "https" "$2" "$8,1" "" "" \ - "${DDEApplication}" "$3" "WWW_OpenURL" + ${AddDisabledDDEHandlerValues} "https" "$2" "$8,1" "" "" ${EndIf} !macroend !define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers" @@ -1157,11 +1151,13 @@ Function SetAsDefaultAppUser ; b) is not a member of the administrators group and chooses to elevate ${ElevateUAC} - ${SetStartMenuInternet} + ${SetStartMenuInternet} ; Does not use SHCTX SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM) - ${FixShellIconHandler} - ${RemoveDeprecatedKeys} + + ${FixClassKeys} ; Does not use SHCTX + ${FixShellIconHandler} ; Does not use SHCTX + ${RemoveDeprecatedKeys} ; Does not use SHCTX ClearErrors ${GetParameters} $0 diff --git a/browser/installer/windows/nsis/uninstaller.nsi b/browser/installer/windows/nsis/uninstaller.nsi index 2237ce732d6..8632b1541d7 100755 --- a/browser/installer/windows/nsis/uninstaller.nsi +++ b/browser/installer/windows/nsis/uninstaller.nsi @@ -92,7 +92,7 @@ Var MaintCertKey VIAddVersionKey "FileDescription" "${BrandShortName} Helper" VIAddVersionKey "OriginalFilename" "helper.exe" -!insertmacro AddDDEHandlerValues +!insertmacro AddDisabledDDEHandlerValues !insertmacro CleanVirtualStore !insertmacro ElevateUAC !insertmacro GetLongPath diff --git a/js/src/tests/e4x/Regress/regress-308111.js b/js/src/tests/e4x/Regress/regress-308111.js index d1c01d3bcda..a0f791f99d4 100644 --- a/js/src/tests/e4x/Regress/regress-308111.js +++ b/js/src/tests/e4x/Regress/regress-308111.js @@ -630,7 +630,6 @@ var xml = font.size.variable.x-guru font.size.variable.x-gujr network.protocol-handler.external.vnd.ms.radio -advanced.system.supportDDEExec browser.tabs.opentabfor.urlbar font.name.sans-serif.x-khmr mousewheel.horizscroll.withshiftkey.sysnumlines diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index ffc3392a1f1..957caf62e25 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -2085,13 +2085,6 @@ pref("plugin.allow.asyncdrawing", false); // when a network address is unreachable. pref("network.autodial-helper.enabled", true); -// Pref to control whether we set ddeexec subkeys for the http -// Internet shortcut protocol if we are handling it. These -// subkeys will be set only while we are running (to avoid the -// problem of Windows showing an alert when it tries to use DDE -// and we're not already running). -pref("advanced.system.supportDDEExec", true); - // Switch the keyboard layout per window pref("intl.keyboard.per_window_layout", false); diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh index 8db20ac0c25..31be50377c1 100755 --- a/toolkit/mozapps/installer/windows/nsis/common.nsh +++ b/toolkit/mozapps/installer/windows/nsis/common.nsh @@ -1193,7 +1193,9 @@ * @param _VALOPEN * The path and args to launch the application. * @param _VALICON - * The path to an exe that contains an icon and the icon resource id. + * The path to the binary that contains the icon group for the default icon + * followed by a comma and either the icon group's resource index or the icon + * group's resource id prefixed with a minus sign * @param _DISPNAME * The display name for the handler. If emtpy no value will be set. * @param _ISPROTOCOL @@ -1237,10 +1239,9 @@ WriteRegStr SHCTX "$R4" "" "$R7" WriteRegStr SHCTX "$R4" "FriendlyTypeName" "$R7" - StrCmp "$R8" "true" +1 +8 + StrCmp "$R8" "true" +1 +2 WriteRegStr SHCTX "$R4" "URL Protocol" "" StrCpy $R3 "" - ClearErrors ReadRegDWord $R3 SHCTX "$R4" "EditFlags" StrCmp $R3 "" +1 +3 ; Only add EditFlags if a value doesn't exist DeleteRegValue SHCTX "$R4" "EditFlags" @@ -1336,7 +1337,9 @@ * @param _VALOPEN * The path and args to launch the application. * @param _VALICON - * The path to an exe that contains an icon and the icon resource id. + * The path to the binary that contains the icon group for the default icon + * followed by a comma and either the icon group's resource index or the icon + * group's resource id prefixed with a minus sign * @param _DISPNAME * The display name for the handler. If emtpy no value will be set. * @param _ISPROTOCOL @@ -1389,10 +1392,9 @@ WriteRegStr SHCTX "$R0\$R2" "" "$R5" WriteRegStr SHCTX "$R0\$R2" "FriendlyTypeName" "$R5" - StrCmp "$R6" "true" +1 +8 + StrCmp "$R6" "true" +1 +2 WriteRegStr SHCTX "$R0\$R2" "URL Protocol" "" StrCpy $R1 "" - ClearErrors ReadRegDWord $R1 SHCTX "$R0\$R2" "EditFlags" StrCmp $R1 "" +1 +3 ; Only add EditFlags if a value doesn't exist DeleteRegValue SHCTX "$R0\$R2" "EditFlags" @@ -1485,6 +1487,154 @@ !endif !macroend +/** + * Writes common registry values for a handler that DOES NOT use DDE using SHCTX. + * + * @param _KEY + * The key name in relation to the HKCR root. SOFTWARE\Classes is + * prefixed to this value when using SHCTX. + * @param _VALOPEN + * The path and args to launch the application. + * @param _VALICON + * The path to the binary that contains the icon group for the default icon + * followed by a comma and either the icon group's resource index or the icon + * group's resource id prefixed with a minus sign + * @param _DISPNAME + * The display name for the handler. If emtpy no value will be set. + * @param _ISPROTOCOL + * Sets protocol handler specific registry values when "true". + * + * $R3 = storage for SOFTWARE\Classes + * $R4 = string value of the current registry key path. + * $R5 = _KEY + * $R6 = _VALOPEN + * $R7 = _VALICON + * $R8 = _DISPNAME + * $R9 = _ISPROTOCOL + */ +!macro AddDisabledDDEHandlerValues + + !ifndef ${_MOZFUNC_UN}AddDisabledDDEHandlerValues + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !define ${_MOZFUNC_UN}AddDisabledDDEHandlerValues "!insertmacro ${_MOZFUNC_UN}AddDisabledDDEHandlerValuesCall" + + Function ${_MOZFUNC_UN}AddDisabledDDEHandlerValues + Exch $R9 ; true if a protocol handler + Exch 1 + Exch $R8 ; FriendlyTypeName + Exch 2 + Exch $R7 ; icon index + Exch 3 + Exch $R6 ; shell\open\command + Exch 4 + Exch $R5 ; reg key + Push $R4 ; + Push $R3 ; base reg class + + StrCpy $R3 "SOFTWARE\Classes" + StrCmp "$R8" "" +6 +1 + ReadRegStr $R4 SHCTX "$R5" "FriendlyTypeName" + + StrCmp "$R4" "" +1 +3 + WriteRegStr SHCTX "$R3\$R5" "" "$R8" + WriteRegStr SHCTX "$R3\$R5" "FriendlyTypeName" "$R8" + + StrCmp "$R9" "true" +1 +2 + WriteRegStr SHCTX "$R3\$R5" "URL Protocol" "" + StrCpy $R4 "" + ReadRegDWord $R4 SHCTX "$R3\$R5" "EditFlags" + StrCmp $R4 "" +1 +3 ; Only add EditFlags if a value doesn't exist + DeleteRegValue SHCTX "$R3\$R5" "EditFlags" + WriteRegDWord SHCTX "$R3\$R5" "EditFlags" 0x00000002 + + StrCmp "$R7" "" +2 +1 + WriteRegStr SHCTX "$R3\$R5\DefaultIcon" "" "$R7" + + ; Main command handler for the app + WriteRegStr SHCTX "$R3\$R5\shell\open\command" "" "$R6" + + ; Drop support for DDE (bug 491947), and remove old dde entries if + ; they exist. + ; + ; Note, changes in SHCTX should propegate to hkey classes root when + ; current user or local machine entries are written. Windows will also + ; attempt to propegate entries when a handler is used. CR entries are a + ; combination of LM and CU, with CU taking priority. + ; + ; To disable dde, an empty shell/ddeexec key must be created in current + ; user or local machine. Unfortunately, settings have various different + ; behaviors depending on the windows version. The following code attempts + ; to address these differences. + ; + ; On XP (no SP, SP1, SP2), Vista: An empty default string + ; must be set under ddeexec. Empty strings propagate to CR. + ; + ; Win7: IE does not configure ddeexec, so issues with left over ddeexec keys + ; in LM are reduced. We configure an empty ddeexec key with an empty default + ; string in CU to be sure. + ; + DeleteRegKey SHCTX "SOFTWARE\Classes\$R5\shell\open\ddeexec" + WriteRegStr SHCTX "SOFTWARE\Classes\$R5\shell\open\ddeexec" "" "" + + ClearErrors + + Pop $R3 + Pop $R4 + Exch $R5 + Exch 4 + Exch $R6 + Exch 3 + Exch $R7 + Exch 2 + Exch $R8 + Exch 1 + Exch $R9 + FunctionEnd + + !verbose pop + !endif +!macroend + +!macro AddDisabledDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_KEY}" + Push "${_VALOPEN}" + Push "${_VALICON}" + Push "${_DISPNAME}" + Push "${_ISPROTOCOL}" + Call AddDisabledDDEHandlerValues + !verbose pop +!macroend + +!macro un.AddDisabledDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_KEY}" + Push "${_VALOPEN}" + Push "${_VALICON}" + Push "${_DISPNAME}" + Push "${_ISPROTOCOL}" + Call un.AddDisabledDDEHandlerValues + !verbose pop +!macroend + +!macro un.AddDisabledDDEHandlerValues + !ifndef un.AddDisabledDDEHandlerValues + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !undef _MOZFUNC_UN + !define _MOZFUNC_UN "un." + + !insertmacro AddDisabledDDEHandlerValues + + !undef _MOZFUNC_UN + !define _MOZFUNC_UN + !verbose pop + !endif +!macroend + ################################################################################ # Macros for handling DLL registration @@ -2804,6 +2954,7 @@ StrCmp "$R7" "$R8" +1 end DeleteRegValue HKLM "Software\Classes\$R9\DefaultIcon" "" DeleteRegValue HKLM "Software\Classes\$R9\shell\open" "" + DeleteRegValue HKLM "Software\Classes\$R9\shell\open\command" "" DeleteRegValue HKLM "Software\Classes\$R9\shell\ddeexec" "" DeleteRegValue HKLM "Software\Classes\$R9\shell\ddeexec\Application" "" DeleteRegValue HKLM "Software\Classes\$R9\shell\ddeexec\Topic" "" From 02941cac890225d9f6e581b1422a6bac2a3ef7fa Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Mon, 26 Mar 2012 17:10:07 -0700 Subject: [PATCH 091/113] Back out changesets 6a2c57fa8edf, 34526f45d863 (bug 737307) due to web-facing regressions (e.g. bug 739478). r=bz --HG-- extra : rebase_source : 4b595ee4ef7ab60a1d831bf50f1c973161e3187c --- docshell/base/nsDocShell.cpp | 48 ---------------------- docshell/base/nsDocShell.h | 5 --- dom/tests/mochitest/ajax/lib/AJAX_setup.js | 2 +- 3 files changed, 1 insertion(+), 54 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ed3cc52b7d6..ffa902687bf 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -8348,13 +8348,6 @@ nsDocShell::InternalLoad(nsIURI * aURI, sameExceptHashes && !newHash.IsEmpty()); if (doShortCircuitedLoad) { - // If our load group contains a LOAD_DOCUMENT_URI request with a - // channel which doesn't match our document's channel, cancel it. - // - // That is, a short-circuited load will cancel a non-short-circuited - // load of a different document. - StopOutstandingOtherDocumentLoad(); - // Save the current URI; we need it if we fire a hashchange later. nsCOMPtr oldURI = mCurrentURI; @@ -8654,47 +8647,6 @@ nsDocShell::InternalLoad(nsIURI * aURI, return rv; } -// If our load group contains a LOAD_DOCUMENT_URI channel that's not our -// document's channel, cancel it. -void -nsDocShell::StopOutstandingOtherDocumentLoad() -{ - nsCOMPtr docChannel = GetCurrentDocChannel(); - if (!docChannel || !mLoadGroup) { - return; - } - - nsCOMPtr requests; - mLoadGroup->GetRequests(getter_AddRefs(requests)); - if (!requests) { - return; - } - - while (true) { - bool hasMoreElements = false; - requests->HasMoreElements(&hasMoreElements); - if (!hasMoreElements) { - break; - } - - nsCOMPtr next; - requests->GetNext(getter_AddRefs(next)); - - nsCOMPtr channel = do_QueryInterface(next); - if (!channel) { - continue; - } - - nsLoadFlags flags; - channel->GetLoadFlags(&flags); - - // As promised, cancel the channel if it's loading a different document. - if ((flags & nsIChannel::LOAD_DOCUMENT_URI) && channel != docChannel) { - channel->Cancel(NS_BINDING_ABORTED); - } - } -} - nsIPrincipal* nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument) { diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 9b9b2b81077..29fa6d0d416 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -672,11 +672,6 @@ protected: nsresult EnsureCommandHandler(); nsIChannel* GetCurrentDocChannel(); - - // If our load group contains a LOAD_DOCUMENT_URI channel that's not our - // document's channel, cancel it. - void StopOutstandingOtherDocumentLoad(); - protected: // Override the parent setter from nsDocLoader virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader); diff --git a/dom/tests/mochitest/ajax/lib/AJAX_setup.js b/dom/tests/mochitest/ajax/lib/AJAX_setup.js index d56c5ad99d5..d90e14227b8 100644 --- a/dom/tests/mochitest/ajax/lib/AJAX_setup.js +++ b/dom/tests/mochitest/ajax/lib/AJAX_setup.js @@ -8,7 +8,7 @@ function runAJAXTest() { var test = AJAXtests.shift(); var testframe = document.getElementById("testframe"); - setTimeout(function() { testframe.src = test; }, 0); + testframe.src = test; } function onManifestLoad(manifest) { From ca248d70d7dbcefe23aa963911939b198d6fd369 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Tue, 27 Mar 2012 12:02:55 +0200 Subject: [PATCH 092/113] Bug 734280 - [New Tab Page] clean up newtab test suite; r=dietrich --- browser/base/content/newtab/drop.js | 5 +- browser/base/content/newtab/sites.js | 10 +- .../test/newtab/browser_newtab_block.js | 12 +- .../test/newtab/browser_newtab_bug722273.js | 15 +- .../test/newtab/browser_newtab_bug723102.js | 2 +- .../test/newtab/browser_newtab_bug723121.js | 32 +-- .../test/newtab/browser_newtab_bug725996.js | 35 +-- .../test/newtab/browser_newtab_bug734043.js | 3 +- .../test/newtab/browser_newtab_bug735987.js | 8 +- .../test/newtab/browser_newtab_disable.js | 6 +- .../test/newtab/browser_newtab_drag_drop.js | 20 +- .../newtab/browser_newtab_drop_preview.js | 5 +- .../newtab/browser_newtab_private_browsing.js | 6 +- .../test/newtab/browser_newtab_reset.js | 6 +- .../test/newtab/browser_newtab_tabsync.js | 26 +-- .../test/newtab/browser_newtab_unpin.js | 10 +- browser/base/content/test/newtab/head.js | 213 ++++++++++-------- 17 files changed, 190 insertions(+), 224 deletions(-) diff --git a/browser/base/content/newtab/drop.js b/browser/base/content/newtab/drop.js index f3d45db465f..6b46672ccd4 100644 --- a/browser/base/content/newtab/drop.js +++ b/browser/base/content/newtab/drop.js @@ -44,9 +44,8 @@ let gDrop = { * Handles the 'drop' event. * @param aCell The drop target cell. * @param aEvent The 'dragexit' event. - * @param aCallback The callback to call when the drop is finished. */ - drop: function Drop_drop(aCell, aEvent, aCallback) { + drop: function Drop_drop(aCell, aEvent) { // The cell that is the drop target could contain a pinned site. We need // to find out where that site has gone and re-pin it there. if (aCell.containsPinnedSite()) @@ -58,7 +57,7 @@ let gDrop = { this._cancelDelayedArrange(); // Update the grid and move all sites to their new places. - gUpdater.updateGrid(aCallback); + gUpdater.updateGrid(); }, /** diff --git a/browser/base/content/newtab/sites.js b/browser/base/content/newtab/sites.js index 1a368184ad5..899dc709259 100644 --- a/browser/base/content/newtab/sites.js +++ b/browser/base/content/newtab/sites.js @@ -61,13 +61,12 @@ Site.prototype = { /** * Unpins the site and calls the given callback when done. - * @param aCallback The callback to be called when finished. */ - unpin: function Site_unpin(aCallback) { + unpin: function Site_unpin() { if (this.isPinned()) { this._updateAttributes(false); gPinnedLinks.unpin(this._link); - gUpdater.updateGrid(aCallback); + gUpdater.updateGrid(); } }, @@ -82,15 +81,14 @@ Site.prototype = { /** * Blocks the site (removes it from the grid) and calls the given callback * when done. - * @param aCallback The function to be called when finished. */ - block: function Site_block(aCallback) { + block: function Site_block() { if (gBlockedLinks.isBlocked(this._link)) { if (aCallback) aCallback(); } else { gBlockedLinks.block(this._link); - gUpdater.updateGrid(aCallback); + gUpdater.updateGrid(); } }, diff --git a/browser/base/content/test/newtab/browser_newtab_block.js b/browser/base/content/test/newtab/browser_newtab_block.js index 97a83b4e186..c6cd3c91f63 100644 --- a/browser/base/content/test/newtab/browser_newtab_block.js +++ b/browser/base/content/test/newtab/browser_newtab_block.js @@ -15,13 +15,13 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8"); - yield blockCell(cells[4]); + yield blockCell(4); checkGrid("0,1,2,3,5,6,7,8,9"); - yield blockCell(cells[4]); + yield blockCell(4); checkGrid("0,1,2,3,6,7,8,9,"); - yield blockCell(cells[4]); + yield blockCell(4); checkGrid("0,1,2,3,7,8,9,,"); // we removed a pinned site @@ -32,7 +32,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1p,2,3,4,5,6,7,8"); - yield blockCell(cells[1]); + yield blockCell(1); checkGrid("0,2,3,4,5,6,7,8,"); // we remove the last site on the grid (which is pinned) and expect the gap @@ -44,7 +44,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8p"); - yield blockCell(cells[8]); + yield blockCell(8); checkGrid("0,1,2,3,4,5,6,7,9"); // we remove the first site on the grid with the last one pinned. all cells @@ -56,6 +56,6 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8p"); - yield blockCell(cells[0]); + yield blockCell(0); checkGrid("1,2,3,4,5,6,7,9,8p"); } diff --git a/browser/base/content/test/newtab/browser_newtab_bug722273.js b/browser/base/content/test/newtab/browser_newtab_bug722273.js index a929aa8db90..acc06bfddf5 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug722273.js +++ b/browser/base/content/test/newtab/browser_newtab_bug722273.js @@ -20,21 +20,12 @@ function runTests() { fillHistory(); yield addNewTabPageTab(); - is(cells[0].site.url, URL, "first site is our fake site"); + is(getCell(0).site.url, URL, "first site is our fake site"); - let page = { - update: function () { - executeSoon(TestRunner.next); - }, - - observe: function () {} - }; - - NewTabUtils.allPages.register(page); + whenPagesUpdated(); yield clearHistory(); - NewTabUtils.allPages.unregister(page); - ok(!cells[0].site, "the fake site is gone"); + ok(!getCell(0).site, "the fake site is gone"); } function fillHistory() { diff --git a/browser/base/content/test/newtab/browser_newtab_bug723102.js b/browser/base/content/test/newtab/browser_newtab_bug723102.js index b6ac4d2b36c..c0f6564149c 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug723102.js +++ b/browser/base/content/test/newtab/browser_newtab_bug723102.js @@ -14,5 +14,5 @@ function runTests() { ok(NewTabUtils.allPages.enabled, true, "page is enabled"); NewTabUtils.allPages.enabled = false; - ok(cw.gGrid.node.hasAttribute("page-disabled"), "page is disabled"); + ok(getGrid().node.hasAttribute("page-disabled"), "page is disabled"); } diff --git a/browser/base/content/test/newtab/browser_newtab_bug723121.js b/browser/base/content/test/newtab/browser_newtab_bug723121.js index e82f0ec5e0b..192903c0d06 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug723121.js +++ b/browser/base/content/test/newtab/browser_newtab_bug723121.js @@ -8,41 +8,23 @@ function runTests() { yield addNewTabPageTab(); checkGridLocked(false, "grid is unlocked"); - let cell = cells[0].node; - let site = cells[0].site.node; + let cell = getCell(0).node; + let site = getCell(0).site.node; let link = site.querySelector(".newtab-link"); - sendDragEvent(link, "dragstart"); + sendDragEvent("dragstart", link); checkGridLocked(true, "grid is now locked"); - sendDragEvent(link, "dragend"); + sendDragEvent("dragend", link); checkGridLocked(false, "grid isn't locked anymore"); - sendDragEvent(cell, "dragstart"); + sendDragEvent("dragstart", cell); checkGridLocked(false, "grid isn't locked - dragstart was ignored"); - sendDragEvent(site, "dragstart"); + sendDragEvent("dragstart", site); checkGridLocked(false, "grid isn't locked - dragstart was ignored"); } function checkGridLocked(aLocked, aMessage) { - is(cw.gGrid.node.hasAttribute("locked"), aLocked, aMessage); -} - -function sendDragEvent(aNode, aType) { - let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor); - let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils); - - let dataTransfer = { - mozUserCancelled: false, - setData: function () null, - setDragImage: function () null, - getData: function () "about:blank" - }; - - let event = cw.document.createEvent("DragEvents"); - event.initDragEvent(aType, true, true, cw, 0, 0, 0, 0, 0, - false, false, false, false, 0, null, dataTransfer); - - windowUtils.dispatchDOMEventViaPresShell(aNode, event, true); + is(getGrid().node.hasAttribute("locked"), aLocked, aMessage); } diff --git a/browser/base/content/test/newtab/browser_newtab_bug725996.js b/browser/base/content/test/newtab/browser_newtab_bug725996.js index c3c947a1de7..7e3a51fff1a 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug725996.js +++ b/browser/base/content/test/newtab/browser_newtab_bug725996.js @@ -8,45 +8,16 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8"); - let cell = cells[0].node; + let cell = getCell(0).node; - sendDropEvent(cell, "about:blank#99\nblank"); + sendDragEvent("drop", cell, "about:blank#99\nblank"); is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99", "first cell is pinned and contains the dropped site"); yield whenPagesUpdated(); checkGrid("99p,0,1,2,3,4,5,6,7"); - sendDropEvent(cell, ""); + sendDragEvent("drop", cell, ""); is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99", "first cell is still pinned with the site we dropped before"); } - -function sendDropEvent(aNode, aData) { - let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor); - let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils); - - let dataTransfer = { - mozUserCancelled: false, - setData: function () null, - setDragImage: function () null, - getData: function () aData, - - types: { - contains: function (aType) aType == "text/x-moz-url" - }, - - mozGetDataAt: function (aType, aIndex) { - if (aIndex || aType != "text/x-moz-url") - return null; - - return aData; - }, - }; - - let event = cw.document.createEvent("DragEvents"); - event.initDragEvent("drop", true, true, cw, 0, 0, 0, 0, 0, - false, false, false, false, 0, null, dataTransfer); - - windowUtils.dispatchDOMEventViaPresShell(aNode, event, true); -} diff --git a/browser/base/content/test/newtab/browser_newtab_bug734043.js b/browser/base/content/test/newtab/browser_newtab_bug734043.js index 2207f6a4344..5b01b39e549 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug734043.js +++ b/browser/base/content/test/newtab/browser_newtab_bug734043.js @@ -9,12 +9,13 @@ function runTests() { checkGrid("0,1,2,3,4,5,6,7,8"); let receivedError = false; - let block = cw.document.querySelector(".newtab-control-block"); + let block = getContentDocument().querySelector(".newtab-control-block"); function onError() { receivedError = true; } + let cw = getContentWindow(); cw.addEventListener("error", onError); for (let i = 0; i < 3; i++) diff --git a/browser/base/content/test/newtab/browser_newtab_bug735987.js b/browser/base/content/test/newtab/browser_newtab_bug735987.js index 4154d1da8fe..02d2f1df30e 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug735987.js +++ b/browser/base/content/test/newtab/browser_newtab_bug735987.js @@ -8,15 +8,15 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8"); - yield simulateDrop(cells[1]); + yield simulateDrop(1); checkGrid("0,99p,1,2,3,4,5,6,7"); - yield blockCell(cells[1]); + yield blockCell(1); checkGrid("0,1,2,3,4,5,6,7,8"); - yield simulateDrop(cells[1]); + yield simulateDrop(1); checkGrid("0,99p,1,2,3,4,5,6,7"); - yield blockCell(cells[1]); + yield blockCell(1); checkGrid("0,1,2,3,4,5,6,7,8"); } diff --git a/browser/base/content/test/newtab/browser_newtab_disable.js b/browser/base/content/test/newtab/browser_newtab_disable.js index 90c3ea805d0..2aa448d191c 100644 --- a/browser/base/content/test/newtab/browser_newtab_disable.js +++ b/browser/base/content/test/newtab/browser_newtab_disable.js @@ -11,14 +11,14 @@ function runTests() { setPinnedLinks(""); yield addNewTabPageTab(); - let gridNode = cw.gGrid.node; + let gridNode = getGrid().node; ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled"); NewTabUtils.allPages.enabled = false; ok(gridNode.hasAttribute("page-disabled"), "page is disabled"); - let oldGridNode = cw.gGrid.node; + let oldGridNode = gridNode; // create a second new tage page and make sure it's disabled. enable it // again and check if the former page gets enabled as well. @@ -26,7 +26,7 @@ function runTests() { ok(gridNode.hasAttribute("page-disabled"), "page is disabled"); // check that no sites have been rendered - is(0, cw.document.querySelectorAll(".site").length, "no sites have been rendered"); + is(0, getContentDocument().querySelectorAll(".site").length, "no sites have been rendered"); NewTabUtils.allPages.enabled = true; ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled"); diff --git a/browser/base/content/test/newtab/browser_newtab_drag_drop.js b/browser/base/content/test/newtab/browser_newtab_drag_drop.js index 022f6af1f24..9ad6b95ed33 100644 --- a/browser/base/content/test/newtab/browser_newtab_drag_drop.js +++ b/browser/base/content/test/newtab/browser_newtab_drag_drop.js @@ -15,7 +15,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8"); - yield simulateDrop(cells[1], cells[0]); + yield simulateDrop(1, 0); checkGrid("1,0p,2,3,4,5,6,7,8"); // drag a cell to its current cell and make sure it's not pinned afterwards @@ -25,7 +25,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8"); - yield simulateDrop(cells[0], cells[0]); + yield simulateDrop(0, 0); checkGrid("0,1,2,3,4,5,6,7,8"); // ensure that pinned pages aren't moved if that's not necessary @@ -35,7 +35,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1p,2p,3,4,5,6,7,8"); - yield simulateDrop(cells[3], cells[0]); + yield simulateDrop(3, 0); checkGrid("3,1p,2p,0p,4,5,6,7,8"); // pinned sites should always be moved around as blocks. if a pinned site is @@ -46,7 +46,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0p,1p,2,3,4,5,6,7,8"); - yield simulateDrop(cells[0], cells[2]); + yield simulateDrop(0, 2); checkGrid("2p,0p,1p,3,4,5,6,7,8"); // pinned sites should not be pushed out of the grid (unless there are only @@ -57,7 +57,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7p,8p"); - yield simulateDrop(cells[8], cells[2]); + yield simulateDrop(8, 2); checkGrid("0,1,3,4,5,6,7p,8p,2p"); // make sure that pinned sites are re-positioned correctly @@ -67,7 +67,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0p,1p,2p,3,4,5p,6,7,8"); - yield simulateDrop(cells[4], cells[0]); + yield simulateDrop(4, 0); checkGrid("3,1p,2p,4,0p,5p,6,7,8"); // drag a new site onto the very first cell @@ -77,7 +77,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7p,8p"); - yield simulateDrop(cells[0]); + yield simulateDrop(0); checkGrid("99p,0,1,2,3,4,5,7p,8p"); // drag a new site onto the grid and make sure that pinned cells don't get @@ -88,7 +88,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7p,8p"); - yield simulateDrop(cells[7]); + yield simulateDrop(7); checkGrid("0,1,2,3,4,5,7p,99p,8p"); // drag a new site beneath a pinned cell and make sure the pinned cell is @@ -99,7 +99,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7,8p"); - yield simulateDrop(cells[7]); + yield simulateDrop(7); checkGrid("0,1,2,3,4,5,6,99p,8p"); // drag a new site onto a block of pinned sites and make sure they're shifted @@ -110,6 +110,6 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0p,1p,2p"); - yield simulateDrop(cells[1]); + yield simulateDrop(1); checkGrid("0p,99p,1p,2p,3,4,5,6,7"); } diff --git a/browser/base/content/test/newtab/browser_newtab_drop_preview.js b/browser/base/content/test/newtab/browser_newtab_drop_preview.js index 1a90e1a7fc1..1b37e5ac0cb 100644 --- a/browser/base/content/test/newtab/browser_newtab_drop_preview.js +++ b/browser/base/content/test/newtab/browser_newtab_drop_preview.js @@ -13,8 +13,9 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0p,1p,2p,3,4,5p,6,7,8"); - cw.gDrag._draggedSite = cells[0].site; - let sites = cw.gDropPreview.rearrange(cells[4]); + let cw = getContentWindow(); + cw.gDrag._draggedSite = getCell(0).site; + let sites = cw.gDropPreview.rearrange(getCell(4)); cw.gDrag._draggedSite = null; checkGrid("3,1p,2p,4,0p,5p,6,7,8", sites); diff --git a/browser/base/content/test/newtab/browser_newtab_private_browsing.js b/browser/base/content/test/newtab/browser_newtab_private_browsing.js index c2e031a73f9..1b2aa5853fb 100644 --- a/browser/base/content/test/newtab/browser_newtab_private_browsing.js +++ b/browser/base/content/test/newtab/browser_newtab_private_browsing.js @@ -16,7 +16,7 @@ function runTests() { ok(!pb.privateBrowsingEnabled, "private browsing is disabled"); yield addNewTabPageTab(); - pinCell(cells[0]); + pinCell(0); checkGrid("0p,1,2,3,4,5,6,7,8"); // enter private browsing mode @@ -27,10 +27,10 @@ function runTests() { checkGrid("0p,1,2,3,4,5,6,7,8"); // modify the grid while we're in pb mode - yield blockCell(cells[1]); + yield blockCell(1); checkGrid("0p,2,3,4,5,6,7,8"); - yield unpinCell(cells[0]); + yield unpinCell(0); checkGrid("0,2,3,4,5,6,7,8"); // exit private browsing mode diff --git a/browser/base/content/test/newtab/browser_newtab_reset.js b/browser/base/content/test/newtab/browser_newtab_reset.js index 884207ac9a9..67fa1fa6aac 100644 --- a/browser/base/content/test/newtab/browser_newtab_reset.js +++ b/browser/base/content/test/newtab/browser_newtab_reset.js @@ -13,16 +13,16 @@ function runTests() { setPinnedLinks(""); yield addNewTabPageTab(); - let resetButton = cw.document.getElementById("toolbar-button-reset"); + let resetButton = getContentDocument().getElementById("toolbar-button-reset"); checkGrid("0,1,2,3,4,5,6,7,8"); ok(!resetButton.hasAttribute("modified"), "page is not modified"); - yield blockCell(cells[4]); + yield blockCell(4); checkGrid("0,1,2,3,5,6,7,8,"); ok(resetButton.hasAttribute("modified"), "page is modified"); - yield cw.gToolbar.reset(TestRunner.next); + yield getContentWindow().gToolbar.reset(TestRunner.next); checkGrid("0,1,2,3,4,5,6,7,8"); ok(!resetButton.hasAttribute("modified"), "page is not modified"); } diff --git a/browser/base/content/test/newtab/browser_newtab_tabsync.js b/browser/base/content/test/newtab/browser_newtab_tabsync.js index 8682ebb977f..9e4e411c303 100644 --- a/browser/base/content/test/newtab/browser_newtab_tabsync.js +++ b/browser/base/content/test/newtab/browser_newtab_tabsync.js @@ -17,45 +17,45 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1p,2,3,4,5,6,7,8"); - let resetButton = cw.document.getElementById("toolbar-button-reset"); + let resetButton = getContentDocument().getElementById("toolbar-button-reset"); ok(!resetButton.hasAttribute("modified"), "page is not modified"); - let oldCw = cw; + let oldSites = getGrid().sites; let oldResetButton = resetButton; // create the new tab page yield addNewTabPageTab(); checkGrid("0,1p,2,3,4,5,6,7,8"); - resetButton = cw.document.getElementById("toolbar-button-reset"); + resetButton = getContentDocument().getElementById("toolbar-button-reset"); ok(!resetButton.hasAttribute("modified"), "page is not modified"); // unpin a cell - yield unpinCell(cells[1]); + yield unpinCell(1); checkGrid("0,1,2,3,4,5,6,7,8"); - checkGrid("0,1,2,3,4,5,6,7,8", oldCw.gGrid.sites); + checkGrid("0,1,2,3,4,5,6,7,8", oldSites); // remove a cell - yield blockCell(cells[1]); + yield blockCell(1); checkGrid("0,2,3,4,5,6,7,8,9"); - checkGrid("0,2,3,4,5,6,7,8,9", oldCw.gGrid.sites); + checkGrid("0,2,3,4,5,6,7,8,9", oldSites); ok(resetButton.hasAttribute("modified"), "page is modified"); ok(oldResetButton.hasAttribute("modified"), "page is modified"); // insert a new cell by dragging - yield simulateDrop(cells[1]); + yield simulateDrop(1); checkGrid("0,99p,2,3,4,5,6,7,8"); - checkGrid("0,99p,2,3,4,5,6,7,8", oldCw.gGrid.sites); + checkGrid("0,99p,2,3,4,5,6,7,8", oldSites); // drag a cell around - yield simulateDrop(cells[1], cells[2]); + yield simulateDrop(1, 2); checkGrid("0,2p,99p,3,4,5,6,7,8"); - checkGrid("0,2p,99p,3,4,5,6,7,8", oldCw.gGrid.sites); + checkGrid("0,2p,99p,3,4,5,6,7,8", oldSites); // reset the new tab page - yield cw.gToolbar.reset(TestRunner.next); + yield getContentWindow().gToolbar.reset(TestRunner.next); checkGrid("0,1,2,3,4,5,6,7,8"); - checkGrid("0,1,2,3,4,5,6,7,8", oldCw.gGrid.sites); + checkGrid("0,1,2,3,4,5,6,7,8", oldSites); ok(!resetButton.hasAttribute("modified"), "page is not modified"); ok(!oldResetButton.hasAttribute("modified"), "page is not modified"); } diff --git a/browser/base/content/test/newtab/browser_newtab_unpin.js b/browser/base/content/test/newtab/browser_newtab_unpin.js index 90abe1dc4bb..c4032d1f5c1 100644 --- a/browser/base/content/test/newtab/browser_newtab_unpin.js +++ b/browser/base/content/test/newtab/browser_newtab_unpin.js @@ -14,7 +14,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1p,2,3,4,5,6,7,8"); - yield unpinCell(cells[1]); + yield unpinCell(1); checkGrid("0,1,2,3,4,5,6,7,8"); // we have a pinned link that is not anymore in the list of the most-visited @@ -26,7 +26,7 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,99p,1,2,3,4,5,6,7"); - yield unpinCell(cells[1]); + yield unpinCell(1); checkGrid("0,1,2,3,4,5,6,7,8"); // we have a pinned link that changed its position since it was pinned. it @@ -37,10 +37,10 @@ function runTests() { yield addNewTabPageTab(); checkGrid("2,1p,3,4,5,6,7,,0p"); - yield unpinCell(cells[1]); + yield unpinCell(1); checkGrid("1,2,3,4,5,6,7,,0p"); - yield unpinCell(cells[8]); + yield unpinCell(8); checkGrid("0,1,2,3,4,5,6,7,"); // we have pinned link that changed its position since it was pinned. the @@ -51,6 +51,6 @@ function runTests() { yield addNewTabPageTab(); checkGrid("9p,0,1,2,3,4,5,6,7"); - yield unpinCell(cells[0]); + yield unpinCell(0); checkGrid("0,1,2,3,4,5,6,7,8"); } diff --git a/browser/base/content/test/newtab/head.js b/browser/base/content/test/newtab/head.js index 2c8bddf39b1..c56c4d0b859 100644 --- a/browser/base/content/test/newtab/head.js +++ b/browser/base/content/test/newtab/head.js @@ -16,12 +16,6 @@ registerCleanupFunction(function () { Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED); }); -/** - * Global variables that are accessed by tests. - */ -let cw; -let cells; - /** * We'll want to restore the original links provider later. */ @@ -81,6 +75,39 @@ let TestRunner = { } }; +/** + * Returns the selected tab's content window. + * @return The content window. + */ +function getContentWindow() { + return gBrowser.selectedBrowser.contentWindow; +} + +/** + * Returns the selected tab's content document. + * @return The content document. + */ +function getContentDocument() { + return gBrowser.selectedBrowser.contentDocument; +} + +/** + * Returns the newtab grid of the selected tab. + * @return The newtab grid. + */ +function getGrid() { + return getContentWindow().gGrid; +} + +/** + * Returns the cell at the given index of the selected tab's newtab grid. + * @param aIndex The cell index. + * @return The newtab cell. + */ +function getCell(aIndex) { + return getGrid().cells[aIndex]; +} + /** * Allows to provide a list of links that is used to construct the grid. * @param aLinksPattern the pattern (see below) @@ -143,18 +170,14 @@ function addNewTabPageTab() { browser.addEventListener("load", function onLoad() { browser.removeEventListener("load", onLoad, true); - cw = browser.contentWindow; - if (NewTabUtils.allPages.enabled) { // Continue when the link cache has been populated. NewTabUtils.links.populateCache(function () { - cells = cw.gGrid.cells; executeSoon(TestRunner.next); }); } else { TestRunner.next(); } - }, true); } @@ -169,118 +192,118 @@ function addNewTabPageTab() { * The fourth cell contains the pinned site 'about:blank#4'. */ function checkGrid(aSitesPattern, aSites) { - let valid = true; + let length = aSitesPattern.split(",").length; + let sites = (aSites || getGrid().sites).slice(0, length); + let expected = sites.map(function (aSite) { + if (!aSite) + return ""; - aSites = aSites || cw.gGrid.sites; + let pinned = aSite.isPinned(); + let pinButton = aSite.node.querySelector(".newtab-control-pin"); + let hasPinnedAttr = pinButton.hasAttribute("pinned"); - aSitesPattern.split(/\s*,\s*/).forEach(function (id, index) { - let site = aSites[index]; - let match = id.match(/^\d+/); + if (pinned != hasPinnedAttr) + ok(false, "invalid state (site.isPinned() != site[pinned])"); - // We expect the cell to be empty. - if (!match) { - if (site) { - valid = false; - ok(false, "expected cell#" + index + " to be empty"); - } - - return; - } - - // We expect the cell to contain a site. - if (!site) { - valid = false; - ok(false, "didn't expect cell#" + index + " to be empty"); - - return; - } - - let num = match[0]; - - // Check the site's url. - if (site.url != "about:blank#" + num) { - valid = false; - is(site.url, "about:blank#" + num, "cell#" + index + " has the wrong url"); - } - - let shouldBePinned = /p$/.test(id); - let cellContainsPinned = site.isPinned(); - let cssClassPinned = site.node && site.node.querySelector(".newtab-control-pin").hasAttribute("pinned"); - - // Check if the site should be and is pinned. - if (shouldBePinned) { - if (!cellContainsPinned) { - valid = false; - ok(false, "expected cell#" + index + " to be pinned"); - } else if (!cssClassPinned) { - valid = false; - ok(false, "expected cell#" + index + " to have css class 'pinned'"); - } - } else { - if (cellContainsPinned) { - valid = false; - ok(false, "didn't expect cell#" + index + " to be pinned"); - } else if (cssClassPinned) { - valid = false; - ok(false, "didn't expect cell#" + index + " to have css class 'pinned'"); - } - } + return aSite.url.replace(/^about:blank#(\d+)$/, "$1") + (pinned ? "p" : ""); }); - // If every test passed, say so. - if (valid) - ok(true, "grid status = " + aSitesPattern); + is(aSitesPattern, expected, "grid status = " + aSitesPattern); } /** - * Blocks the given cell's site from the grid. - * @param aCell the cell that contains the site to block + * Blocks a site from the grid. + * @param aIndex The cell index. */ -function blockCell(aCell) { - aCell.site.block(function () executeSoon(TestRunner.next)); +function blockCell(aIndex) { + whenPagesUpdated(); + getCell(aIndex).site.block(); } /** - * Pins a given cell's site on a given position. - * @param aCell the cell that contains the site to pin - * @param aIndex the index the defines where the site should be pinned + * Pins a site on a given position. + * @param aIndex The cell index. + * @param aPinIndex The index the defines where the site should be pinned. */ -function pinCell(aCell, aIndex) { - aCell.site.pin(aIndex); +function pinCell(aIndex, aPinIndex) { + getCell(aIndex).site.pin(aPinIndex); } /** * Unpins the given cell's site. - * @param aCell the cell that contains the site to unpin + * @param aIndex The cell index. */ -function unpinCell(aCell) { - aCell.site.unpin(function () executeSoon(TestRunner.next)); +function unpinCell(aIndex) { + whenPagesUpdated(); + getCell(aIndex).site.unpin(); } /** * Simulates a drop and drop operation. - * @param aDropTarget the cell that is the drop target - * @param aDragSource the cell that contains the dragged site (optional) + * @param aDropIndex The cell index of the drop target. + * @param aDragIndex The cell index containing the dragged site (optional). */ -function simulateDrop(aDropTarget, aDragSource) { - let event = { - clientX: 0, - clientY: 0, - dataTransfer: { - mozUserCancelled: false, - setData: function () null, - setDragImage: function () null, - getData: function () "about:blank#99\nblank" +function simulateDrop(aDropIndex, aDragIndex) { + let draggedSite; + let {gDrag: drag, gDrop: drop} = getContentWindow(); + let event = createDragEvent("drop", "about:blank#99\nblank"); + + if (typeof aDragIndex != "undefined") + draggedSite = getCell(aDragIndex).site; + + if (draggedSite) + drag.start(draggedSite, event); + + whenPagesUpdated(); + drop.drop(getCell(aDropIndex), event); + + if (draggedSite) + drag.end(draggedSite); +} + +/** + * Sends a custom drag event to a given DOM element. + * @param aEventType The drag event's type. + * @param aTarget The DOM element that the event is dispatched to. + * @param aData The event's drag data (optional). + */ +function sendDragEvent(aEventType, aTarget, aData) { + let event = createDragEvent(aEventType, aData); + let ifaceReq = getContentWindow().QueryInterface(Ci.nsIInterfaceRequestor); + let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils); + windowUtils.dispatchDOMEventViaPresShell(aTarget, event, true); +} + +/** + * Creates a custom drag event. + * @param aEventType The drag event's type. + * @param aData The event's drag data (optional). + * @return The drag event. + */ +function createDragEvent(aEventType, aData) { + let dataTransfer = { + mozUserCancelled: false, + setData: function () null, + setDragImage: function () null, + getData: function () aData, + + types: { + contains: function (aType) aType == "text/x-moz-url" + }, + + mozGetDataAt: function (aType, aIndex) { + if (aIndex || aType != "text/x-moz-url") + return null; + + return aData; } }; - if (aDragSource) - cw.gDrag.start(aDragSource.site, event); + let event = getContentDocument().createEvent("DragEvents"); + event.initDragEvent(aEventType, true, true, getContentWindow(), 0, 0, 0, 0, 0, + false, false, false, false, 0, null, dataTransfer); - cw.gDrop.drop(aDropTarget, event, function () executeSoon(TestRunner.next)); - - if (aDragSource) - cw.gDrag.end(aDragSource.site); + return event; } /** From 48e5d776e6a4063dcf35ad89feb5f7e8b6c05e1c Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Tue, 27 Mar 2012 12:59:09 +0200 Subject: [PATCH 093/113] Bug 739171 - Don't save tabItem data while updating tabItems; r=dietrich --- browser/components/tabview/storage.js | 14 +++++ browser/components/tabview/tabitems.js | 74 ++++++++++++++++---------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/browser/components/tabview/storage.js b/browser/components/tabview/storage.js index 6f45adfbff5..f28878a0720 100644 --- a/browser/components/tabview/storage.js +++ b/browser/components/tabview/storage.js @@ -123,6 +123,20 @@ let Storage = { return existingData; }, + // ---------- + // Function: getTabState + // Returns the current state of the given tab. + getTabState: function Storage_getTabState(tab) { + Utils.assert(tab, "tab"); + let tabState; + + try { + tabState = JSON.parse(this._sessionStore.getTabState(tab)); + } catch (e) {} + + return tabState; + }, + // ---------- // Function: saveGroupItem // Saves the data for a single groupItem, associated with a specific window. diff --git a/browser/components/tabview/tabitems.js b/browser/components/tabview/tabitems.js index 8d45844ad97..2c5ae9ce2a7 100644 --- a/browser/components/tabview/tabitems.js +++ b/browser/components/tabview/tabitems.js @@ -96,7 +96,6 @@ function TabItem(tab, options) { this._reconnected = false; this.isDragging = false; this.isStacked = false; - this.url = ""; // Read off the total vertical and horizontal padding on the tab container // and cache this value, as it must be the same for every TabItem. @@ -200,21 +199,14 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // be called at browser startup with the cached data avaliable. // // Parameters: - // tabData - the tab data // imageData - the image data - showCachedData: function TabItem_showCachedData(tabData, imageData) { + showCachedData: function TabItem_showCachedData(imageData) { this._cachedImageData = imageData; this.$cachedThumb.attr("src", this._cachedImageData).show(); this.$canvas.css({opacity: 0}); - let label = ""; - let title; - if (tabData.title) { - label = tabData.title; - title = label + "\n" + tabData.url; - } else { - title = tabData.url; - } - this.$tabTitle.text(label).attr("title", title); + + let {title, url} = this.getTabState(); + this.$tabTitle.text(title).attr("title", title ? title + "\n" + url : url); this._sendToSubscribers("showingCachedData"); }, @@ -234,9 +226,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // Get data to be used for persistent storage of this object. getStorageData: function TabItem_getStorageData() { let data = { - url: this.tab.linkedBrowser.currentURI.spec, - groupID: (this.parent ? this.parent.id : 0), - title: this.tab.label + groupID: (this.parent ? this.parent.id : 0) }; if (this.parent && this.parent.getActiveTab() == this) data.active = true; @@ -260,12 +250,46 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { } }, + // ---------- + // Function: _getCurrentTabStateEntry + // Returns the current tab state's active history entry. + _getCurrentTabStateEntry: function TabItem__getCurrentTabStateEntry() { + let tabState = Storage.getTabState(this.tab); + + if (tabState) { + let index = (tabState.index || tabState.entries.length) - 1; + if (index in tabState.entries) + return tabState.entries[index]; + } + + return null; + }, + + // ---------- + // Function: getTabState + // Returns the current tab state, i.e. the title and URL of the active + // history entry. + getTabState: function TabItem_getTabState() { + let entry = this._getCurrentTabStateEntry(); + let title = ""; + let url = ""; + + if (entry) { + if (entry.title) + title = entry.title; + + url = entry.url; + } else { + url = this.tab.linkedBrowser.currentURI.spec; + } + + return {title: title, url: url}; + }, + // ---------- // Function: loadThumbnail // Loads the tabItems thumbnail. - loadThumbnail: function TabItem_loadThumbnail(tabData) { - Utils.assert(tabData, "invalid or missing argument "); - + loadThumbnail: function TabItem_loadThumbnail() { let self = this; function TabItem_loadThumbnail_callback(error, imageData) { @@ -285,11 +309,11 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // what the cache is from, OR the loaded URL is blank, which means // that the page hasn't loaded yet. let currentUrl = self.tab.linkedBrowser.currentURI.spec; - if (tabData.url == currentUrl || currentUrl == "about:blank") - self.showCachedData(tabData, imageData); + if (self.getTabState().url == currentUrl || currentUrl == "about:blank") + self.showCachedData(imageData); } - ThumbnailStorage.loadThumbnail(tabData.url, TabItem_loadThumbnail_callback); + ThumbnailStorage.loadThumbnail(this.getTabState().url, TabItem_loadThumbnail_callback); }, // ---------- @@ -370,7 +394,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { let groupItem; if (tabData && TabItems.storageSanity(tabData)) { - this.loadThumbnail(tabData); + this.loadThumbnail(); if (this.parent) this.parent.remove(this, {immediately: true}); @@ -934,7 +958,7 @@ let TabItems = { return ( tab.linkedBrowser.contentDocument.readyState == 'complete' && !(tab.linkedBrowser.contentDocument.URL == 'about:blank' && - tab._tabViewTabItem.url != 'about:blank') + tab._tabViewTabItem.getTabState().url != 'about:blank') ); }, @@ -1013,10 +1037,6 @@ let TabItems = { // ___ URL let tabUrl = tab.linkedBrowser.currentURI.spec; - if (tabUrl != tabItem.url) { - tabItem.url = tabUrl; - tabItem.save(); - } tabItem.$container.attr("title", label + "\n" + tabUrl); // ___ Make sure the tab is complete and ready for updating. From 56e0212f72599762b540e2c0b957e6f0a6294f59 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Tue, 27 Mar 2012 14:14:00 +0200 Subject: [PATCH 094/113] Bug 738774 - [Page Thumbnails] Channel leaks intermittently; r=dietrich --- .../thumbnails/PageThumbsProtocol.js | 416 ++++++++---------- 1 file changed, 181 insertions(+), 235 deletions(-) diff --git a/browser/components/thumbnails/PageThumbsProtocol.js b/browser/components/thumbnails/PageThumbsProtocol.js index 18a632f7d08..4cf06067b73 100644 --- a/browser/components/thumbnails/PageThumbsProtocol.js +++ b/browser/components/thumbnails/PageThumbsProtocol.js @@ -25,9 +25,6 @@ const Ci = Components.interfaces; Cu.import("resource:///modules/PageThumbs.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", - "resource://gre/modules/NetUtil.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); @@ -104,268 +101,252 @@ function Channel(aURI) { } Channel.prototype = { - /** - * Tracks if the channel has been opened, yet. - */ + _uri: null, + _referrer: null, + _canceled: false, + _status: Cr.NS_OK, + _isPending: false, _wasOpened: false, + _responseText: "OK", + _responseStatus: 200, + _responseHeaders: null, + _requestMethod: "GET", + _requestStarted: false, + _allowPipelining: true, + _requestSucceeded: true, + + /* :::::::: nsIChannel ::::::::::::::: */ + + get URI() this._uri, + owner: null, + notificationCallbacks: null, + get securityInfo() null, + + contentType: PageThumbs.contentType, + contentCharset: null, + contentLength: -1, + + get contentDisposition() { + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); + }, + + get contentDispositionFilename() { + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); + }, + + get contentDispositionHeader() { + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); + }, + + open: function Channel_open() { + throw (Components.returnCode = Cr.NS_ERROR_NOT_IMPLEMENTED); + }, - /** - * Opens this channel asynchronously. - * @param aListener The listener that receives the channel data when available. - * @param aContext A custom context passed to the listener's methods. - */ asyncOpen: function Channel_asyncOpen(aListener, aContext) { + if (this._isPending) + throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS); + if (this._wasOpened) - throw Cr.NS_ERROR_ALREADY_OPENED; + throw (Components.returnCode = Cr.NS_ERROR_ALREADY_OPENED); - if (this.canceled) - return; - - this._listener = aListener; - this._context = aContext; + if (this._canceled) + return (Components.returnCode = this._status); this._isPending = true; this._wasOpened = true; - // Try to read the data from the thumbnail cache. - this._readCache(function (aData) { - let telemetryThumbnailFound = true; + this._listener = aListener; + this._context = aContext; - // Update response if there's no data. - if (!aData) { - this._responseStatus = 404; - this._responseText = "Not Found"; - telemetryThumbnailFound = false; - } + if (this.loadGroup) + this.loadGroup.addRequest(this, null); - Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS") - .add(telemetryThumbnailFound); + if (this._canceled) + return; - this._startRequest(); - - if (!this.canceled) { - this._addToLoadGroup(); - - if (aData) - this._serveData(aData); - - if (!this.canceled) - this._stopRequest(); - } - }.bind(this)); - }, - - /** - * Reads a data stream from the cache entry. - * @param aCallback The callback the data is passed to. - */ - _readCache: function Channel_readCache(aCallback) { let {url} = parseURI(this._uri); - - // Return early if there's no valid URL given. if (!url) { - aCallback(null); + this._serveThumbnailNotFound(); return; } - // Try to get a cache entry. PageThumbsCache.getReadEntry(url, function (aEntry) { let inputStream = aEntry && aEntry.openInputStream(0); - - function closeEntryAndFinish(aData) { - if (aEntry) { - aEntry.close(); - } - aCallback(aData); - } - - // Check if we have a valid entry and if it has any data. if (!inputStream || !inputStream.available()) { - closeEntryAndFinish(); + if (aEntry) + aEntry.close(); + this._serveThumbnailNotFound(); return; } - try { - // Read the cache entry's data. - NetUtil.asyncFetch(inputStream, function (aData, aStatus) { - // We might have been canceled while waiting. - if (this.canceled) - return; + this._entry = aEntry; + this._pump = Cc["@mozilla.org/network/input-stream-pump;1"]. + createInstance(Ci.nsIInputStreamPump); - // Check if we have a valid data stream. - if (!Components.isSuccessCode(aStatus) || !aData.available()) - aData = null; + this._pump.init(inputStream, -1, -1, 0, 0, true); + this._pump.asyncRead(this, null); - closeEntryAndFinish(aData); - }.bind(this)); - } catch (e) { - closeEntryAndFinish(); - } + this._trackThumbnailHitOrMiss(true); }.bind(this)); }, /** - * Calls onStartRequest on the channel listener. + * Serves a "404 Not Found" if we didn't find the requested thumbnail. */ - _startRequest: function Channel_startRequest() { - try { - this._listener.onStartRequest(this, this._context); - } catch (e) { - // The listener might throw if the request has been canceled. - this.cancel(Cr.NS_BINDING_ABORTED); - } + _serveThumbnailNotFound: function Channel_serveThumbnailNotFound() { + this._responseStatus = 404; + this._responseText = "Not Found"; + this._requestSucceeded = false; + + this.onStartRequest(this, null); + this.onStopRequest(this, null, Cr.NS_OK); + + this._trackThumbnailHitOrMiss(false); }, /** - * Calls onDataAvailable on the channel listener and passes the data stream. - * @param aData The data to be delivered. + * Implements telemetry tracking for thumbnail cache hits and misses. + * @param aFound Whether the thumbnail was found. */ - _serveData: function Channel_serveData(aData) { - try { - let available = aData.available(); - this._listener.onDataAvailable(this, this._context, aData, 0, available); - } catch (e) { - // The listener might throw if the request has been canceled. - this.cancel(Cr.NS_BINDING_ABORTED); - } + _trackThumbnailHitOrMiss: function Channel_trackThumbnailHitOrMiss(aFound) { + Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS") + .add(aFound); }, - /** - * Calls onStopRequest on the channel listener. - */ - _stopRequest: function Channel_stopRequest() { - try { - this._listener.onStopRequest(this, this._context, this.status); - } catch (e) { - // This might throw but is generally ignored. - } + /* :::::::: nsIStreamListener ::::::::::::::: */ - // The request has finished, clean up after ourselves. - this._cleanup(); + onStartRequest: function Channel_onStartRequest(aRequest, aContext) { + if (!this.canceled && Components.isSuccessCode(this._status)) + this._status = aRequest.status; + + this._requestStarted = true; + this._listener.onStartRequest(this, this._context); }, - /** - * Adds this request to the load group, if any. - */ - _addToLoadGroup: function Channel_addToLoadGroup() { + onDataAvailable: function Channel_onDataAvailable(aRequest, aContext, + aInStream, aOffset, aCount) { + this._listener.onDataAvailable(this, this._context, aInStream, aOffset, aCount); + }, + + onStopRequest: function Channel_onStopRequest(aRequest, aContext, aStatus) { + this._isPending = false; + this._status = aStatus; + + this._listener.onStopRequest(this, this._context, aStatus); + this._listener = null; + this._context = null; + + if (this._entry) + this._entry.close(); + if (this.loadGroup) - this.loadGroup.addRequest(this, this._context); + this.loadGroup.removeRequest(this, null, aStatus); }, - /** - * Removes this request from its load group, if any. - */ - _removeFromLoadGroup: function Channel_removeFromLoadGroup() { - if (!this.loadGroup) + /* :::::::: nsIRequest ::::::::::::::: */ + + get status() this._status, + get name() this._uri.spec, + isPending: function Channel_isPending() this._isPending, + + loadFlags: Ci.nsIRequest.LOAD_NORMAL, + loadGroup: null, + + cancel: function Channel_cancel(aStatus) { + if (this._canceled) return; - try { - this.loadGroup.removeRequest(this, this._context, this.status); - } catch (e) { - // This might throw but is ignored. - } + this._canceled = true; + this._status = aStatus; + + if (this._pump) + this._pump.cancel(aStatus); }, - /** - * Cleans up the channel when the request has finished. - */ - _cleanup: function Channel_cleanup() { - this._removeFromLoadGroup(); - this.loadGroup = null; - - this._isPending = false; - - delete this._listener; - delete this._context; + suspend: function Channel_suspend() { + if (this._pump) + this._pump.suspend(); }, - /* :::::::: nsIChannel ::::::::::::::: */ - - contentType: PageThumbs.contentType, - contentLength: -1, - owner: null, - contentCharset: null, - notificationCallbacks: null, - - get URI() this._uri, - get securityInfo() null, - - /** - * Opens this channel synchronously. Not supported. - */ - open: function Channel_open() { - // Synchronous data delivery is not implemented. - throw Cr.NS_ERROR_NOT_IMPLEMENTED; + resume: function Channel_resume() { + if (this._pump) + this._pump.resume(); }, /* :::::::: nsIHttpChannel ::::::::::::::: */ - redirectionLimit: 10, - requestMethod: "GET", - allowPipelining: true, - referrer: null, + get referrer() this._referrer, - get requestSucceeded() true, + set referrer(aReferrer) { + if (this._wasOpened) + throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS); - _responseStatus: 200, - get responseStatus() this._responseStatus, - - _responseText: "OK", - get responseStatusText() this._responseText, - - /** - * Checks if the server sent the equivalent of a "Cache-control: no-cache" - * response header. - * @return Always false. - */ - isNoCacheResponse: function () false, - - /** - * Checks if the server sent the equivalent of a "Cache-control: no-cache" - * response header. - * @return Always false. - */ - isNoStoreResponse: function () false, - - /** - * Returns the value of a particular request header. Not implemented. - */ - getRequestHeader: function Channel_getRequestHeader() { - throw Cr.NS_ERROR_NOT_AVAILABLE; + this._referrer = aReferrer; + }, + + get requestMethod() this._requestMethod, + + set requestMethod(aMethod) { + if (this._wasOpened) + throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS); + + this._requestMethod = aMethod.toUpperCase(); + }, + + get allowPipelining() this._allowPipelining, + + set allowPipelining(aAllow) { + if (this._wasOpened) + throw (Components.returnCode = Cr.NS_ERROR_FAILURE); + + this._allowPipelining = aAllow; + }, + + redirectionLimit: 10, + + get responseStatus() { + if (this._requestStarted) + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); + + return this._responseStatus; + }, + + get responseStatusText() { + if (this._requestStarted) + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); + + return this._responseText; + }, + + get requestSucceeded() { + if (this._requestStarted) + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); + + return this._requestSucceeded; + }, + + isNoCacheResponse: function Channel_isNoCacheResponse() false, + isNoStoreResponse: function Channel_isNoStoreResponse() false, + + getRequestHeader: function Channel_getRequestHeader() { + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); }, - /** - * This method is called to set the value of a particular request header. - * Not implemented. - */ setRequestHeader: function Channel_setRequestHeader() { if (this._wasOpened) - throw Cr.NS_ERROR_IN_PROGRESS; + throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS); }, - /** - * Call this method to visit all request headers. Not implemented. - */ - visitRequestHeaders: function () {}, + visitRequestHeaders: function Channel_visitRequestHeaders() {}, - /** - * Gets the value of a particular response header. - * @param aHeader The case-insensitive name of the response header to query. - * @return The header value. - */ getResponseHeader: function Channel_getResponseHeader(aHeader) { let name = aHeader.toLowerCase(); if (name in this._responseHeaders) return this._responseHeaders[name]; - throw Cr.NS_ERROR_NOT_AVAILABLE; + throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE); }, - /** - * This method is called to set the value of a particular response header. - * @param aHeader The case-insensitive name of the response header to query. - * @param aValue The response header value to set. - */ setResponseHeader: function Channel_setResponseHeader(aHeader, aValue, aMerge) { let name = aHeader.toLowerCase(); if (!aValue && !aMerge) @@ -374,10 +355,6 @@ Channel.prototype = { this._responseHeaders[name] = aValue; }, - /** - * Call this method to visit all response headers. - * @param aVisitor The header visitor. - */ visitResponseHeaders: function Channel_visitResponseHeaders(aVisitor) { for (let name in this._responseHeaders) { let value = this._responseHeaders[name]; @@ -391,48 +368,17 @@ Channel.prototype = { } }, - /* :::::::: nsIRequest ::::::::::::::: */ - - loadFlags: Ci.nsIRequest.LOAD_NORMAL, - loadGroup: null, - - get name() this._uri.spec, - - _status: Cr.NS_OK, - get status() this._status, - - _isPending: false, - isPending: function () this._isPending, - - resume: function () {}, - suspend: function () {}, - - /** - * Cancels this request. - * @param aStatus The reason for cancelling. - */ - cancel: function Channel_cancel(aStatus) { - if (this.canceled) - return; - - this._isCanceled = true; - this._status = aStatus; - - this._cleanup(); - }, - /* :::::::: nsIHttpChannelInternal ::::::::::::::: */ documentURI: null, - - _isCanceled: false, - get canceled() this._isCanceled, + get canceled() this._canceled, + allowSpdy: false, QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIHttpChannel, Ci.nsIHttpChannelInternal, Ci.nsIRequest]) -}; +} /** * Parses a given URI and extracts all parameters relevant to this protocol. From 5b23caa031b8d3997d1f68aebb48e6dfff403dcb Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Tue, 27 Mar 2012 15:08:45 +0200 Subject: [PATCH 095/113] Backed out changeset 26051ffdbc34 (bug 739171) --- browser/components/tabview/storage.js | 14 ----- browser/components/tabview/tabitems.js | 74 ++++++++++---------------- 2 files changed, 27 insertions(+), 61 deletions(-) diff --git a/browser/components/tabview/storage.js b/browser/components/tabview/storage.js index f28878a0720..6f45adfbff5 100644 --- a/browser/components/tabview/storage.js +++ b/browser/components/tabview/storage.js @@ -123,20 +123,6 @@ let Storage = { return existingData; }, - // ---------- - // Function: getTabState - // Returns the current state of the given tab. - getTabState: function Storage_getTabState(tab) { - Utils.assert(tab, "tab"); - let tabState; - - try { - tabState = JSON.parse(this._sessionStore.getTabState(tab)); - } catch (e) {} - - return tabState; - }, - // ---------- // Function: saveGroupItem // Saves the data for a single groupItem, associated with a specific window. diff --git a/browser/components/tabview/tabitems.js b/browser/components/tabview/tabitems.js index 2c5ae9ce2a7..8d45844ad97 100644 --- a/browser/components/tabview/tabitems.js +++ b/browser/components/tabview/tabitems.js @@ -96,6 +96,7 @@ function TabItem(tab, options) { this._reconnected = false; this.isDragging = false; this.isStacked = false; + this.url = ""; // Read off the total vertical and horizontal padding on the tab container // and cache this value, as it must be the same for every TabItem. @@ -199,14 +200,21 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // be called at browser startup with the cached data avaliable. // // Parameters: + // tabData - the tab data // imageData - the image data - showCachedData: function TabItem_showCachedData(imageData) { + showCachedData: function TabItem_showCachedData(tabData, imageData) { this._cachedImageData = imageData; this.$cachedThumb.attr("src", this._cachedImageData).show(); this.$canvas.css({opacity: 0}); - - let {title, url} = this.getTabState(); - this.$tabTitle.text(title).attr("title", title ? title + "\n" + url : url); + let label = ""; + let title; + if (tabData.title) { + label = tabData.title; + title = label + "\n" + tabData.url; + } else { + title = tabData.url; + } + this.$tabTitle.text(label).attr("title", title); this._sendToSubscribers("showingCachedData"); }, @@ -226,7 +234,9 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // Get data to be used for persistent storage of this object. getStorageData: function TabItem_getStorageData() { let data = { - groupID: (this.parent ? this.parent.id : 0) + url: this.tab.linkedBrowser.currentURI.spec, + groupID: (this.parent ? this.parent.id : 0), + title: this.tab.label }; if (this.parent && this.parent.getActiveTab() == this) data.active = true; @@ -250,46 +260,12 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { } }, - // ---------- - // Function: _getCurrentTabStateEntry - // Returns the current tab state's active history entry. - _getCurrentTabStateEntry: function TabItem__getCurrentTabStateEntry() { - let tabState = Storage.getTabState(this.tab); - - if (tabState) { - let index = (tabState.index || tabState.entries.length) - 1; - if (index in tabState.entries) - return tabState.entries[index]; - } - - return null; - }, - - // ---------- - // Function: getTabState - // Returns the current tab state, i.e. the title and URL of the active - // history entry. - getTabState: function TabItem_getTabState() { - let entry = this._getCurrentTabStateEntry(); - let title = ""; - let url = ""; - - if (entry) { - if (entry.title) - title = entry.title; - - url = entry.url; - } else { - url = this.tab.linkedBrowser.currentURI.spec; - } - - return {title: title, url: url}; - }, - // ---------- // Function: loadThumbnail // Loads the tabItems thumbnail. - loadThumbnail: function TabItem_loadThumbnail() { + loadThumbnail: function TabItem_loadThumbnail(tabData) { + Utils.assert(tabData, "invalid or missing argument "); + let self = this; function TabItem_loadThumbnail_callback(error, imageData) { @@ -309,11 +285,11 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // what the cache is from, OR the loaded URL is blank, which means // that the page hasn't loaded yet. let currentUrl = self.tab.linkedBrowser.currentURI.spec; - if (self.getTabState().url == currentUrl || currentUrl == "about:blank") - self.showCachedData(imageData); + if (tabData.url == currentUrl || currentUrl == "about:blank") + self.showCachedData(tabData, imageData); } - ThumbnailStorage.loadThumbnail(this.getTabState().url, TabItem_loadThumbnail_callback); + ThumbnailStorage.loadThumbnail(tabData.url, TabItem_loadThumbnail_callback); }, // ---------- @@ -394,7 +370,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { let groupItem; if (tabData && TabItems.storageSanity(tabData)) { - this.loadThumbnail(); + this.loadThumbnail(tabData); if (this.parent) this.parent.remove(this, {immediately: true}); @@ -958,7 +934,7 @@ let TabItems = { return ( tab.linkedBrowser.contentDocument.readyState == 'complete' && !(tab.linkedBrowser.contentDocument.URL == 'about:blank' && - tab._tabViewTabItem.getTabState().url != 'about:blank') + tab._tabViewTabItem.url != 'about:blank') ); }, @@ -1037,6 +1013,10 @@ let TabItems = { // ___ URL let tabUrl = tab.linkedBrowser.currentURI.spec; + if (tabUrl != tabItem.url) { + tabItem.url = tabUrl; + tabItem.save(); + } tabItem.$container.attr("title", label + "\n" + tabUrl); // ___ Make sure the tab is complete and ready for updating. From f190bf2fd1d91b156a084a951b8b9fe46150dc78 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 27 Mar 2012 20:32:49 -0400 Subject: [PATCH 096/113] backout 6e03c7c669b7 due to missing local include causing windows bustage --- accessible/src/atk/Makefile.in | 2 - accessible/src/atk/nsMaiInterfaceTable.cpp | 26 +-- accessible/src/base/Makefile.in | 3 +- accessible/src/base/nsARIAGridAccessible.cpp | 34 ++-- accessible/src/base/nsARIAGridAccessible.h | 14 +- accessible/src/base/nsAccessible.h | 7 - accessible/src/generic/TableAccessible.h | 170 ------------------ accessible/src/html/Makefile.in | 2 - accessible/src/html/nsHTMLTableAccessible.cpp | 49 +++-- accessible/src/html/nsHTMLTableAccessible.h | 25 +-- accessible/src/xpcom/Makefile.in | 2 - accessible/src/xpcom/xpcAccessibleTable.cpp | 34 ---- accessible/src/xpcom/xpcAccessibleTable.h | 63 ------- accessible/src/xul/Makefile.in | 2 - accessible/src/xul/nsXULListboxAccessible.cpp | 30 ++-- accessible/src/xul/nsXULListboxAccessible.h | 17 +- .../src/xul/nsXULTreeGridAccessible.cpp | 24 ++- accessible/src/xul/nsXULTreeGridAccessible.h | 14 +- 18 files changed, 116 insertions(+), 402 deletions(-) delete mode 100644 accessible/src/generic/TableAccessible.h delete mode 100644 accessible/src/xpcom/xpcAccessibleTable.cpp delete mode 100644 accessible/src/xpcom/xpcAccessibleTable.h diff --git a/accessible/src/atk/Makefile.in b/accessible/src/atk/Makefile.in index 2bd347beae8..9fe1f48b857 100644 --- a/accessible/src/atk/Makefile.in +++ b/accessible/src/atk/Makefile.in @@ -99,9 +99,7 @@ endif LOCAL_INCLUDES += \ -I$(srcdir) \ -I$(srcdir)/../base \ - -I$(srcdir)/../generic \ -I$(srcdir)/../html \ - -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(topsrcdir)/other-licenses/atk-1.0 \ $(NULL) diff --git a/accessible/src/atk/nsMaiInterfaceTable.cpp b/accessible/src/atk/nsMaiInterfaceTable.cpp index 158e490dd7a..1c8971d4fbc 100644 --- a/accessible/src/atk/nsMaiInterfaceTable.cpp +++ b/accessible/src/atk/nsMaiInterfaceTable.cpp @@ -42,14 +42,12 @@ #include "nsAccessibleWrap.h" #include "nsAccUtils.h" #include "nsIAccessibleTable.h" -#include "TableAccessible.h" #include "nsMai.h" #include "nsArrayUtils.h" -using namespace mozilla::a11y; - extern "C" { + static AtkObject* refAtCB(AtkTable *aTable, gint aRow, gint aColumn) { @@ -210,17 +208,23 @@ getRowExtentAtCB(AtkTable *aTable, } static AtkObject* -getCaptionCB(AtkTable* aTable) +getCaptionCB(AtkTable *aTable) { - nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable)); - if (!accWrap) - return nsnull; + nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable)); + if (!accWrap) + return nsnull; - TableAccessible* table = accWrap->AsTable(); - NS_ENSURE_TRUE(table, nsnull); + nsCOMPtr accTable; + accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable), + getter_AddRefs(accTable)); + NS_ENSURE_TRUE(accTable, nsnull); - nsAccessible* caption = table->Caption(); - return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull; + nsCOMPtr caption; + nsresult rv = accTable->GetCaption(getter_AddRefs(caption)); + if (NS_FAILED(rv) || !caption) + return nsnull; + + return nsAccessibleWrap::GetAtkObject(caption); } static const gchar* diff --git a/accessible/src/base/Makefile.in b/accessible/src/base/Makefile.in index b71efb0c1ba..7fd861756c4 100644 --- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -104,9 +104,8 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir) \ - -I$(srcdir)/../generic \ - -I$(srcdir)/../html \ -I$(srcdir)/../xpcom \ + -I$(srcdir)/../html \ -I$(srcdir)/../xul \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/style \ diff --git a/accessible/src/base/nsARIAGridAccessible.cpp b/accessible/src/base/nsARIAGridAccessible.cpp index 4a985b7a0fc..ed7304d59aa 100644 --- a/accessible/src/base/nsARIAGridAccessible.cpp +++ b/accessible/src/base/nsARIAGridAccessible.cpp @@ -58,7 +58,7 @@ using namespace mozilla::a11y; nsARIAGridAccessible:: nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) + nsAccessibleWrap(aContent, aDoc) { } @@ -69,19 +69,22 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible, nsAccessible, nsIAccessibleTable) -//////////////////////////////////////////////////////////////////////////////// -//nsAccessNode - -void -nsARIAGridAccessible::Shutdown() -{ - mTable = nsnull; - nsAccessibleWrap::Shutdown(); -} - //////////////////////////////////////////////////////////////////////////////// // nsIAccessibleTable +NS_IMETHODIMP +nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption) +{ + NS_ENSURE_ARG_POINTER(aCaption); + *aCaption = nsnull; + + if (IsDefunct()) + return NS_ERROR_FAILURE; + + // XXX: should be pointed by aria-labelledby on grid? + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP nsARIAGridAccessible::GetSummary(nsAString &aSummary) { @@ -707,6 +710,15 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn) return NS_OK; } +NS_IMETHODIMP +nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) +{ + NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); + *aIsProbablyForLayout = false; + + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// // Protected diff --git a/accessible/src/base/nsARIAGridAccessible.h b/accessible/src/base/nsARIAGridAccessible.h index c17aaa99b4e..9a1806bc701 100644 --- a/accessible/src/base/nsARIAGridAccessible.h +++ b/accessible/src/base/nsARIAGridAccessible.h @@ -42,16 +42,12 @@ #include "nsIAccessibleTable.h" #include "nsHyperTextAccessibleWrap.h" -#include "TableAccessible.h" -#include "xpcAccessibleTable.h" /** * Accessible for ARIA grid and treegrid. */ class nsARIAGridAccessible : public nsAccessibleWrap, - public xpcAccessibleTable, - public nsIAccessibleTable, - public mozilla::a11y::TableAccessible + public nsIAccessibleTable { public: nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc); @@ -60,13 +56,7 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE - - // nsAccessible - virtual mozilla::a11y::TableAccessible* AsTable() { return this; } - - // nsAccessNode - virtual void Shutdown(); + NS_DECL_NSIACCESSIBLETABLE protected: /** diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index daa0696bc33..e4203016756 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -66,11 +66,6 @@ class nsHTMLImageMapAccessible; class nsHTMLLIAccessible; struct nsRoleMapEntry; class Relation; -namespace mozilla { -namespace a11y { -class TableAccessible; -} -} class nsTextAccessible; struct nsRect; @@ -476,8 +471,6 @@ public: inline bool IsRoot() const { return mFlags & eRootAccessible; } nsRootAccessible* AsRoot(); - virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; } - inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; } nsTextAccessible* AsTextLeaf(); diff --git a/accessible/src/generic/TableAccessible.h b/accessible/src/generic/TableAccessible.h deleted file mode 100644 index 694fb02ed15..00000000000 --- a/accessible/src/generic/TableAccessible.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef TABLE_ACCESSIBLE_H -#define TABLE_ACCESSIBLE_H - -#include "nsString.h" -#include "nsTArray.h" -#include "prtypes.h" - -class nsAccessible; - -namespace mozilla { -namespace a11y { - -/** - * Accessible table interface. - */ -class TableAccessible -{ -public: - - /** - * Return the caption accessible if any for this table. - */ - virtual nsAccessible* Caption() { return nsnull; } - - /** - * Get the summary for this table. - */ - virtual void Summary(nsString& aSummary) { aSummary.Truncate(); } - - /** - * Return the number of columns in the table. - */ - virtual PRUint32 ColCount() { return 0; } - - /** - * Return the number of rows in the table. - */ - virtual PRUint32 RowCount() { return 0; } - - /** - * Return the accessible for the cell at the given row and column indices. - */ - virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; } - - /** - * Return the index of the cell at the given row and column. - */ - virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; } - - /** - * Return the column index of the cell with the given index. - */ - virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; } - - /** - * Return the row index of the cell with the given index. - */ - virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; } - - /** - * Get the row and column indices for the cell at the given index. - */ - virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx, - PRInt32* aColIdx) {} - - /** - * Return the number of columns occupied by the cell at the given row and - * column indices. - */ - virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; } - - /** - * Return the number of rows occupied by the cell at the given row and column - * indices. - */ - virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; } - - /** - * Get the description of the given column. - */ - virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription) - { aDescription.Truncate(); } - - /** - * Get the description for the given row. - */ - virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription) - { aDescription.Truncate(); } - - /** - * Return true if the given column is selected. - */ - virtual bool IsColSelected(PRUint32 aColIdx) { return false; } - - /** - * Return true if the given row is selected. - */ - virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; } - - /** - * Return true if the given cell is selected. - */ - virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; } - - /** - * Return the number of selected cells. - */ - virtual PRUint32 SelectedCellCount() { return 0; } - - /** - * Return the number of selected columns. - */ - virtual PRUint32 SelectedColCount() { return 0; } - - /** - * Return the number of selected rows. - */ - virtual PRUint32 SelectedRowCount() { return 0; } - - /** - * Get the set of selected cells. - */ - virtual void SelectedCells(nsTArray* aCells) {} - - /** - * Get the set of selected column indices. - */ - virtual void SelectedColIndices(nsTArray* aCols) {} - - /** - * Get the set of selected row indices. - */ - virtual void SelectedRowIndices(nsTArray* aRows) {} - - /** - * Select the given column unselecting any other selected columns. - */ - virtual void SelectCol(PRUint32 aColIdx) {} - - /** - * Select the given row unselecting all other previously selected rows. - */ - virtual void SelectRow(PRUint32 aRowIdx) {} - - /** - * Unselect the given column leaving other selected columns selected. - */ - virtual void UnselectCol(PRUint32 aColIdx) {} - - /** - * Unselect the given row leaving other selected rows selected. - */ - virtual void UnselectRow(PRUint32 aRowIdx) {} - - /** - * Return true if the table is probably for layout. - */ - virtual bool IsProbablyLayoutTable() { return false; } -}; - -} // namespace a11y -} // namespace mozilla - -#endif diff --git a/accessible/src/html/Makefile.in b/accessible/src/html/Makefile.in index ebd86307696..7820e4a8b1d 100644 --- a/accessible/src/html/Makefile.in +++ b/accessible/src/html/Makefile.in @@ -73,8 +73,6 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir)/../base \ - -I$(srcdir)/../generic \ - -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ $(NULL) diff --git a/accessible/src/html/nsHTMLTableAccessible.cpp b/accessible/src/html/nsHTMLTableAccessible.cpp index a09c2740b68..a5547bb3d1c 100644 --- a/accessible/src/html/nsHTMLTableAccessible.cpp +++ b/accessible/src/html/nsHTMLTableAccessible.cpp @@ -436,7 +436,7 @@ nsHTMLTableHeaderCellAccessible::NativeRole() nsHTMLTableAccessible:: nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) + nsAccessibleWrap(aContent, aDoc) { } @@ -446,16 +446,6 @@ nsHTMLTableAccessible:: NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible, nsHTMLTableAccessible, nsIAccessibleTable) -//////////////////////////////////////////////////////////////////////////////// -//nsAccessNode - -void -nsHTMLTableAccessible::Shutdown() -{ - mTable = nsnull; - nsAccessibleWrap::Shutdown(); -} - //////////////////////////////////////////////////////////////////////////////// // nsHTMLTableAccessible: nsAccessible implementation @@ -521,7 +511,9 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes); NS_ENSURE_SUCCESS(rv, rv); - if (IsProbablyLayoutTable()) { + bool isProbablyForLayout; + IsProbablyForLayout(&isProbablyForLayout); + if (isProbablyForLayout) { nsAutoString oldValueUnused; aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"), NS_LITERAL_STRING("true"), oldValueUnused); @@ -546,11 +538,13 @@ nsHTMLTableAccessible::RelationByType(PRUint32 aType) //////////////////////////////////////////////////////////////////////////////// // nsHTMLTableAccessible: nsIAccessibleTable implementation -nsAccessible* -nsHTMLTableAccessible::Caption() +NS_IMETHODIMP +nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption) { - nsAccessible* child = mChildren.SafeElementAt(0, nsnull); - return child && child->Role() == roles::CAPTION ? child : nsnull; + NS_ENSURE_ARG_POINTER(aCaption); + + NS_IF_ADDREF(*aCaption = Caption()); + return NS_OK; } NS_IMETHODIMP @@ -1313,7 +1307,8 @@ nsHTMLTableAccessible::Description(nsString& aDescription) #ifdef SHOW_LAYOUT_HEURISTIC if (aDescription.IsEmpty()) { - bool isProbablyForLayout = IsProbablyLayoutTable(); + bool isProbablyForLayout; + IsProbablyForLayout(&isProbablyForLayout); aDescription = mLayoutHeuristic; } #ifdef DEBUG_A11Y @@ -1362,8 +1357,8 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName, return !!foundItem; } -bool -nsHTMLTableAccessible::IsProbablyLayoutTable() +NS_IMETHODIMP +nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) { // Implement a heuristic to determine if table is most likely used for layout // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells @@ -1375,16 +1370,18 @@ nsHTMLTableAccessible::IsProbablyLayoutTable() // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release #ifdef SHOW_LAYOUT_HEURISTIC #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \ - { \ - mLayoutHeuristic = isLayout ? \ - NS_LITERAL_STRING("layout table: " heuristic) : \ - NS_LITERAL_STRING("data table: " heuristic); \ - return isLayout; \ - } + { *aIsProbablyForLayout = isLayout; \ + mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \ + mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; } #else -#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; } +#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; } #endif + *aIsProbablyForLayout = false; + + if (IsDefunct()) + return NS_ERROR_FAILURE; + nsDocAccessible* docAccessible = Document(); if (docAccessible) { PRUint64 docState = docAccessible->State(); diff --git a/accessible/src/html/nsHTMLTableAccessible.h b/accessible/src/html/nsHTMLTableAccessible.h index 4691bd9fc6d..bf10061ba03 100644 --- a/accessible/src/html/nsHTMLTableAccessible.h +++ b/accessible/src/html/nsHTMLTableAccessible.h @@ -41,8 +41,6 @@ #include "nsHyperTextAccessibleWrap.h" #include "nsIAccessibleTable.h" -#include "TableAccessible.h" -#include "xpcAccessibleTable.h" class nsITableLayout; class nsITableCellLayout; @@ -123,28 +121,16 @@ public: } class nsHTMLTableAccessible : public nsAccessibleWrap, - public xpcAccessibleTable, - public nsIAccessibleTable, - public mozilla::a11y::TableAccessible + public nsIAccessibleTable { public: nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc); NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIACCESSIBLETABLE NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID) - // nsIAccessible Table - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE - - // TableAccessible - virtual nsAccessible* Caption(); - virtual bool IsProbablyLayoutTable(); - - // nsAccessNode - virtual void Shutdown(); - // nsAccessible - virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual void Description(nsString& aDescription); virtual nsresult GetNameInternal(nsAString& aName); virtual mozilla::a11y::role NativeRole(); @@ -152,6 +138,13 @@ public: virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); virtual Relation RelationByType(PRUint32 aRelationType); + // TableAccessible + inline nsAccessible* Caption() const + { + nsAccessible* child = mChildren.SafeElementAt(0, nsnull); + return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull; + } + // nsHTMLTableAccessible /** diff --git a/accessible/src/xpcom/Makefile.in b/accessible/src/xpcom/Makefile.in index 31ffd6b24f1..d270bd35ab3 100644 --- a/accessible/src/xpcom/Makefile.in +++ b/accessible/src/xpcom/Makefile.in @@ -50,7 +50,6 @@ LIBXUL_LIBRARY = 1 CPPSRCS = \ nsAccEvent.cpp \ nsAccessibleRelation.cpp \ - xpcAccessibleTable.cpp \ $(NULL) # we don't want the shared lib, but we want to force the creation of a static lib. @@ -60,5 +59,4 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir)/../base \ - -I$(srcdir)/../generic \ $(NULL) diff --git a/accessible/src/xpcom/xpcAccessibleTable.cpp b/accessible/src/xpcom/xpcAccessibleTable.cpp deleted file mode 100644 index 9923490ecbe..00000000000 --- a/accessible/src/xpcom/xpcAccessibleTable.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "xpcAccessibleTable.h" - -#include "nsAccessible.h" -#include "TableAccessible.h" - -nsresult -xpcAccessibleTable::GetCaption(nsIAccessible** aCaption) -{ - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - if (!mTable) - return NS_ERROR_FAILURE; - - NS_IF_ADDREF(*aCaption = mTable->Caption()); - return NS_OK; -} - -nsresult -xpcAccessibleTable::IsProbablyForLayout(bool* aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - *aResult = false; - if (!mTable) - return NS_ERROR_FAILURE; - - *aResult = mTable->IsProbablyLayoutTable(); - return NS_OK; -} diff --git a/accessible/src/xpcom/xpcAccessibleTable.h b/accessible/src/xpcom/xpcAccessibleTable.h deleted file mode 100644 index afec1960177..00000000000 --- a/accessible/src/xpcom/xpcAccessibleTable.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ -#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ - -#include "nscore.h" - -class nsIAccessible; -namespace mozilla { -namespace a11y { -class TableAccessible; -} -} - -class xpcAccessibleTable -{ -public: - xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { } - - nsresult GetCaption(nsIAccessible** aCaption); - nsresult IsProbablyForLayout(bool* aIsForLayout); - -protected: - mozilla::a11y::TableAccessible* mTable; -}; - -#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \ - NS_IMETHOD GetCaption(nsIAccessible** aCaption) \ - { return xpcAccessibleTable::GetCaption(aCaption); } \ - NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \ - NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \ - NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \ - NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \ - NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \ - NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \ - NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \ - NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \ - NS_IMETHOD IsProbablyForLayout(bool* aResult) \ - { return xpcAccessibleTable::IsProbablyForLayout(aResult); } \ - -#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ diff --git a/accessible/src/xul/Makefile.in b/accessible/src/xul/Makefile.in index e86dcd64420..05a4bc7492e 100644 --- a/accessible/src/xul/Makefile.in +++ b/accessible/src/xul/Makefile.in @@ -72,9 +72,7 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir) \ -I$(srcdir)/../base \ - -I$(srcdir)/../generic \ -I$(srcdir)/../html \ - -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ $(NULL) diff --git a/accessible/src/xul/nsXULListboxAccessible.cpp b/accessible/src/xul/nsXULListboxAccessible.cpp index 971620d3598..4adcc94d0e7 100644 --- a/accessible/src/xul/nsXULListboxAccessible.cpp +++ b/accessible/src/xul/nsXULListboxAccessible.cpp @@ -134,7 +134,7 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex) nsXULListboxAccessible:: nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this) + XULSelectControlAccessible(aContent, aDoc) { nsIContent* parentContent = mContent->GetParent(); if (parentContent) { @@ -164,16 +164,6 @@ nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) return NS_ERROR_NO_INTERFACE; } -//////////////////////////////////////////////////////////////////////////////// -//nsAccessNode - -void -nsXULListboxAccessible::Shutdown() -{ - mTable = nsnull; - XULSelectControlAccessible::Shutdown(); -} - bool nsXULListboxAccessible::IsMulticolumn() { @@ -239,6 +229,15 @@ nsXULListboxAccessible::NativeRole() //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible. nsIAccessibleTable +NS_IMETHODIMP +nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption) +{ + NS_ENSURE_ARG_POINTER(aCaption); + *aCaption = nsnull; + + return NS_OK; +} + NS_IMETHODIMP nsXULListboxAccessible::GetSummary(nsAString &aSummary) { @@ -821,6 +820,15 @@ nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn) return NS_OK; } +NS_IMETHODIMP +nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) +{ + NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); + *aIsProbablyForLayout = false; + + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible: Widgets diff --git a/accessible/src/xul/nsXULListboxAccessible.h b/accessible/src/xul/nsXULListboxAccessible.h index 06fdd3470c0..be49fadc6c3 100644 --- a/accessible/src/xul/nsXULListboxAccessible.h +++ b/accessible/src/xul/nsXULListboxAccessible.h @@ -40,12 +40,11 @@ #ifndef __nsXULListboxAccessible_h__ #define __nsXULListboxAccessible_h__ +#include "nsIAccessibleTable.h" + #include "nsCOMPtr.h" #include "nsXULMenuAccessible.h" #include "nsBaseWidgetAccessible.h" -#include "nsIAccessibleTable.h" -#include "TableAccessible.h" -#include "xpcAccessibleTable.h" #include "XULSelectControlAccessible.h" class nsIWeakReference; @@ -91,27 +90,19 @@ public: * A class the represents the XUL Listbox widget. */ class nsXULListboxAccessible : public XULSelectControlAccessible, - public xpcAccessibleTable, - public nsIAccessibleTable, - public mozilla::a11y::TableAccessible + public nsIAccessibleTable { public: nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc); virtual ~nsXULListboxAccessible() {} NS_DECL_ISUPPORTS_INHERITED - - // nsIAccessibleTable - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + NS_DECL_NSIACCESSIBLETABLE // nsIAccessible NS_IMETHOD GetValue(nsAString& aValue); - // nsAccessNode - virtual void Shutdown(); - // nsAccessible - virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual mozilla::a11y::role NativeRole(); virtual PRUint64 NativeState(); diff --git a/accessible/src/xul/nsXULTreeGridAccessible.cpp b/accessible/src/xul/nsXULTreeGridAccessible.cpp index acd46c643ff..c3ca0269103 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -58,7 +58,7 @@ using namespace mozilla::a11y; nsXULTreeGridAccessible:: nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this) + nsXULTreeAccessible(aContent, aDoc) { } @@ -72,6 +72,15 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible, //////////////////////////////////////////////////////////////////////////////// // nsXULTreeGridAccessible: nsIAccessibleTable implementation +NS_IMETHODIMP +nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption) +{ + NS_ENSURE_ARG_POINTER(aCaption); + *aCaption = nsnull; + + return IsDefunct() ? NS_ERROR_FAILURE : NS_OK; +} + NS_IMETHODIMP nsXULTreeGridAccessible::GetSummary(nsAString &aSummary) { @@ -561,14 +570,13 @@ nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex) return NS_OK; } -//////////////////////////////////////////////////////////////////////////////// -// nsXULTreeGridAccessible: nsAccessNode implementation - -void -nsXULTreeGridAccessible::Shutdown() +NS_IMETHODIMP +nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) { - mTable = nsnull; - nsXULTreeAccessible::Shutdown(); + NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); + *aIsProbablyForLayout = false; + + return NS_OK; } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/xul/nsXULTreeGridAccessible.h b/accessible/src/xul/nsXULTreeGridAccessible.h index bed9d95a157..0f3771373f8 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.h +++ b/accessible/src/xul/nsXULTreeGridAccessible.h @@ -39,17 +39,15 @@ #ifndef __nsXULTreeGridAccessible_h__ #define __nsXULTreeGridAccessible_h__ +#include "nsIAccessibleTable.h" + #include "nsXULTreeAccessible.h" -#include "TableAccessible.h" -#include "xpcAccessibleTable.h" /** * Represents accessible for XUL tree in the case when it has multiple columns. */ class nsXULTreeGridAccessible : public nsXULTreeAccessible, - public xpcAccessibleTable, - public nsIAccessibleTable, - public mozilla::a11y::TableAccessible + public nsIAccessibleTable { public: nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc); @@ -58,13 +56,9 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable - NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE - - // nsAccessNode - virtual void Shutdown(); + NS_DECL_NSIACCESSIBLETABLE // nsAccessible - virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual mozilla::a11y::role NativeRole(); protected: From 06d539e65a05b8bab62d6561a5d3ab1ddbef744f Mon Sep 17 00:00:00 2001 From: Gavin Sharp Date: Tue, 27 Mar 2012 18:06:10 -0700 Subject: [PATCH 097/113] backout 110452fddc2a (bug 738568) since it broke viewsource --- .../alerts/resources/content/alert.js | 15 ++-- .../components/viewconfig/content/config.js | 2 +- .../viewsource/content/viewSource.js | 75 +++++++++++++------ 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/toolkit/components/alerts/resources/content/alert.js b/toolkit/components/alerts/resources/content/alert.js index 610568c6d12..8e4dcf36906 100644 --- a/toolkit/components/alerts/resources/content/alert.js +++ b/toolkit/components/alerts/resources/content/alert.js @@ -36,8 +36,6 @@ # # ***** END LICENSE BLOCK ***** -Components.utils.import("resource://gre/modules/Services.jsm"); - // Copied from nsILookAndFeel.h, see comments on eMetric_AlertNotificationOrigin const NS_ALERT_HORIZONTAL = 1; const NS_ALERT_LEFT = 2; @@ -95,11 +93,14 @@ function prefillAlertInfo() function onAlertLoad() { - gSlideIncrement = Services.prefs.getIntPref("alerts.slideIncrement"); - gSlideTime = Services.prefs.getIntPref("alerts.slideIncrementTime"); - gOpenTime = Services.prefs.getIntPref("alerts.totalOpenTime"); - gDisableSlideEffect = Services.prefs.getBoolPref("alerts.disableSlidingEffect"); - + var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(); + prefService = prefService.QueryInterface(Components.interfaces.nsIPrefService); + var prefBranch = prefService.getBranch(null); + gSlideIncrement = prefBranch.getIntPref("alerts.slideIncrement"); + gSlideTime = prefBranch.getIntPref("alerts.slideIncrementTime"); + gOpenTime = prefBranch.getIntPref("alerts.totalOpenTime"); + gDisableSlideEffect = prefBranch.getBoolPref("alerts.disableSlidingEffect"); + // Make sure that the contents are fixed at the window edge facing the // screen's center so that the window looks like "sliding in" and not // like "unfolding". The default packing of "start" only works for diff --git a/toolkit/components/viewconfig/content/config.js b/toolkit/components/viewconfig/content/config.js index 04880ba7b30..d6c644fc1ed 100644 --- a/toolkit/components/viewconfig/content/config.js +++ b/toolkit/components/viewconfig/content/config.js @@ -52,7 +52,7 @@ const nsPrefService_CONTRACTID = "@mozilla.org/preferences-service;1"; const nsClipboardHelper_CONTRACTID = "@mozilla.org/widget/clipboardhelper;1"; const nsAtomService_CONTRACTID = "@mozilla.org/atom-service;1"; -const gPrefBranch = Services.prefs; +const gPrefBranch = Services.prefs.getBranch(null); const gClipboardHelper = Components.classes[nsClipboardHelper_CONTRACTID].getService(nsIClipboardHelper); const gAtomService = Components.classes[nsAtomService_CONTRACTID].getService(nsIAtomService); diff --git a/toolkit/components/viewsource/content/viewSource.js b/toolkit/components/viewsource/content/viewSource.js index 82eefc5be9f..537cebc3125 100644 --- a/toolkit/components/viewsource/content/viewSource.js +++ b/toolkit/components/viewsource/content/viewSource.js @@ -38,10 +38,9 @@ # # ***** END LICENSE BLOCK ***** -Components.utils.import("resource://gre/modules/Services.jsm"); - const Cc = Components.classes; const Ci = Components.interfaces; +var gPrefs = null; var gLastLineFound = ''; var gGoToLine = 0; @@ -73,6 +72,13 @@ __defineGetter__("gPageLoader", function () { return this.gPageLoader = webnav.QueryInterface(Ci.nsIWebPageDescriptor); }); +try { + var prefService = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService); + gPrefs = prefService.getBranch(null); +} catch (ex) { +} + var gSelectionListener = { timeout: 0, attached: false, @@ -213,14 +219,22 @@ function viewSource(url) // Check the view_source.wrap_long_lines pref and set the menuitem's checked // attribute accordingly. - var wraplonglinesPrefValue = Services.prefs - .getBoolPref("view_source.wrap_long_lines"); + if (gPrefs) { + try { + var wraplonglinesPrefValue = gPrefs.getBoolPref("view_source.wrap_long_lines"); - if (wraplonglinesPrefValue) - document.getElementById("menu_wrapLongLines").setAttribute("checked", "true"); - - document.getElementById("menu_highlightSyntax").setAttribute("checked", - Services.prefs.getBoolPref("view_source.syntax_highlight")); + if (wraplonglinesPrefValue) + document.getElementById("menu_wrapLongLines").setAttribute("checked", "true"); + } catch (ex) { + } + try { + document.getElementById("menu_highlightSyntax").setAttribute("checked", + gPrefs.getBoolPref("view_source.syntax_highlight")); + } catch (ex) { + } + } else { + document.getElementById("menu_highlightSyntax").setAttribute("hidden", "true"); + } window.addEventListener("AppCommand", HandleAppCommandEvent, true); window.addEventListener("MozSwipeGesture", HandleSwipeGesture, true); @@ -272,13 +286,16 @@ function onClickContent(event) { var target = event.originalTarget; var errorDoc = target.ownerDocument; + + var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"] + .getService(Ci.nsIURLFormatter); if (/^about:blocked/.test(errorDoc.documentURI)) { // The event came from a button on a malware/phishing block page // First check whether it's malware or phishing, so that we can // use the right strings/links var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI); - + if (target == errorDoc.getElementById('getMeOutButton')) { // Instead of loading some safe page, just close the window window.close(); @@ -291,7 +308,7 @@ function onClickContent(event) { // Get the stop badware "why is this blocked" report url, // append the current url, and go there. try { - let reportURL = Services.urlFormatter.formatURLPref("browser.safebrowsing.malware.reportURL", true); + let reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL", true); reportURL += errorDoc.location.href.slice(12); openURL(reportURL); } catch (e) { @@ -299,7 +316,7 @@ function onClickContent(event) { } } else { // It's a phishing site, not malware try { - var infoURL = Services.urlFormatter.formatURLPref("browser.safebrowsing.warning.infoURL", true); + var infoURL = formatter.formatURLPref("browser.safebrowsing.warning.infoURL", true); openURL(infoURL); } catch (e) { Components.utils.reportError("Couldn't get phishing info URL: " + e); @@ -405,9 +422,12 @@ function getWebNavigation() function ViewSourceGoToLine() { + var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Ci.nsIPromptService); + var input = {value:gLastLineFound}; for (;;) { - var ok = Services.prompt.prompt( + var ok = promptService.prompt( window, gViewSourceBundle.getString("goToLineTitle"), gViewSourceBundle.getString("goToLineText"), @@ -421,9 +441,9 @@ function ViewSourceGoToLine() var line = parseInt(input.value, 10); if (!(line > 0)) { - Services.prompt.alert(window, - gViewSourceBundle.getString("invalidInputTitle"), - gViewSourceBundle.getString("invalidInputText")); + promptService.alert(window, + gViewSourceBundle.getString("invalidInputTitle"), + gViewSourceBundle.getString("invalidInputText")); continue; } @@ -433,9 +453,9 @@ function ViewSourceGoToLine() if (found) break; - Services.prompt.alert(window, - gViewSourceBundle.getString("outOfRangeTitle"), - gViewSourceBundle.getString("outOfRangeText")); + promptService.alert(window, + gViewSourceBundle.getString("outOfRangeTitle"), + gViewSourceBundle.getString("outOfRangeText")); } } @@ -663,13 +683,22 @@ function wrapLongLines() if (myWrap.className == '') myWrap.className = 'wrap'; - else - myWrap.className = ''; + else myWrap.className = ''; // Since multiple viewsource windows are possible, another window could have // affected the pref, so instead of determining the new pref value via the current // pref value, we use myWrap.className. - Services.prefs.setBoolPref("view_source.wrap_long_lines", myWrap.className != ''); + if (gPrefs) { + try { + if (myWrap.className == '') { + gPrefs.setBoolPref("view_source.wrap_long_lines", false); + } + else { + gPrefs.setBoolPref("view_source.wrap_long_lines", true); + } + } catch (ex) { + } + } } // Toggles syntax highlighting and sets the view_source.syntax_highlight @@ -678,7 +707,7 @@ function highlightSyntax() { var highlightSyntaxMenu = document.getElementById("menu_highlightSyntax"); var highlightSyntax = (highlightSyntaxMenu.getAttribute("checked") == "true"); - Services.prefs.setBoolPref("view_source.syntax_highlight", highlightSyntax); + gPrefs.setBoolPref("view_source.syntax_highlight", highlightSyntax); gPageLoader.loadPage(gPageLoader.currentDescriptor, gPageLoader.DISPLAY_NORMAL); } From 43bafca2f7fae0768510c2f7d5d0481c2a49e5ce Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Tue, 27 Mar 2012 18:41:34 -0700 Subject: [PATCH 098/113] Bug 709310 - Implement Handling of 5xxs, X-Weave-Backoff, Retry-After. r=rnewman --- mobile/android/base/sync/CryptoRecord.java | 57 +++-------- mobile/android/base/sync/GlobalSession.java | 98 ++++++++++++++----- .../android/base/sync/net/BaseResource.java | 21 ++++ .../base/sync/net/HttpResponseObserver.java | 17 ++++ .../android/base/sync/net/SyncResponse.java | 46 ++------- .../base/sync/stage/ServerSyncStage.java | 20 ++-- mobile/android/sync/java-sources.mn | 2 +- 7 files changed, 144 insertions(+), 117 deletions(-) create mode 100644 mobile/android/base/sync/net/HttpResponseObserver.java diff --git a/mobile/android/base/sync/CryptoRecord.java b/mobile/android/base/sync/CryptoRecord.java index 8f69218caa4..75c5c9e0e2d 100644 --- a/mobile/android/base/sync/CryptoRecord.java +++ b/mobile/android/base/sync/CryptoRecord.java @@ -1,39 +1,6 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Richard Newman - * - * 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 ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync; @@ -54,20 +21,20 @@ import org.mozilla.gecko.sync.repositories.domain.Record; /** * A Sync crypto record has: * - * * a collection of fields which are not encrypted (id and collection) - * * a set of metadata fields (index, modified, ttl) - * * a payload, which is encrypted and decrypted on request. + *
    + *
  • a collection of fields which are not encrypted (id and collection); + *
  • a set of metadata fields (index, modified, ttl); + *
  • a payload, which is encrypted and decrypted on request. + *
* * The payload flips between being a blob of JSON with hmac/IV/ciphertext * attributes and the cleartext itself. * - * Until there's some benefit to the abstraction, we're simply going to - * call this CryptoRecord. - * - * CryptoRecord uses CryptoInfo to do the actual encryption and decryption. - * - * @author rnewman + * Until there's some benefit to the abstraction, we're simply going to call + * this CryptoRecord. * + * CryptoRecord uses CryptoInfo to do the actual + * encryption and decryption. */ public class CryptoRecord extends Record { diff --git a/mobile/android/base/sync/GlobalSession.java b/mobile/android/base/sync/GlobalSession.java index 322e8f15c20..4d193a3af4d 100644 --- a/mobile/android/base/sync/GlobalSession.java +++ b/mobile/android/base/sync/GlobalSession.java @@ -11,6 +11,7 @@ import java.net.URISyntaxException; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; import org.json.simple.parser.ParseException; import org.mozilla.gecko.sync.crypto.CryptoException; @@ -23,6 +24,8 @@ import org.mozilla.gecko.sync.delegates.KeyUploadDelegate; import org.mozilla.gecko.sync.delegates.MetaGlobalDelegate; import org.mozilla.gecko.sync.delegates.WipeServerDelegate; import org.mozilla.gecko.sync.net.BaseResource; +import org.mozilla.gecko.sync.net.HttpResponseObserver; +import org.mozilla.gecko.sync.net.SyncResponse; import org.mozilla.gecko.sync.net.SyncStorageRecordRequest; import org.mozilla.gecko.sync.net.SyncStorageRequest; import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate; @@ -47,15 +50,12 @@ import android.os.Bundle; import android.util.Log; import ch.boye.httpclientandroidlib.HttpResponse; -public class GlobalSession implements CredentialsSource, PrefsSource { +public class GlobalSession implements CredentialsSource, PrefsSource, HttpResponseObserver { private static final String LOG_TAG = "GlobalSession"; public static final String API_VERSION = "1.1"; public static final long STORAGE_VERSION = 5; - private static final String HEADER_RETRY_AFTER = "retry-after"; - private static final String HEADER_X_WEAVE_BACKOFF = "x-weave-backoff"; - public SyncConfiguration config = null; protected Map stages; @@ -218,6 +218,13 @@ public class GlobalSession implements CredentialsSource, PrefsSource { * Move to the next stage in the syncing process. */ public void advance() { + // If we have a backoff, request a backoff and don't advance to next stage. + long existingBackoff = largestBackoffObserved.get(); + if (existingBackoff > 0) { + this.abort(null, "Aborting sync because of backoff of " + existingBackoff + " milliseconds."); + return; + } + this.callback.handleStageCompleted(this.currentState, this); Stage next = nextStage(this.currentState); GlobalSyncStage nextStage; @@ -234,6 +241,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource { } catch (Exception ex) { Logger.warn(LOG_TAG, "Caught exception " + ex + " running stage " + next); this.abort(ex, "Uncaught exception in stage."); + return; } } @@ -261,20 +269,21 @@ public class GlobalSession implements CredentialsSource, PrefsSource { /** * Begin a sync. - * + *

* The caller is responsible for: - * - * * Verifying that any backoffs/minimum next sync are respected - * * Ensuring that the device is online - * * Ensuring that dependencies are ready + *

    + *
  • Verifying that any backoffs/minimum next sync requests are respected.
  • + *
  • Ensuring that the device is online.
  • + *
  • Ensuring that dependencies are ready.
  • + *
* * @throws AlreadySyncingException - * */ public void start() throws AlreadySyncingException { if (this.currentState != GlobalSyncStage.Stage.idle) { throw new AlreadySyncingException(this.currentState); } + installAsHttpResponseObserver(); // Uninstalled by completeSync or abort. this.advance(); } @@ -292,12 +301,18 @@ public class GlobalSession implements CredentialsSource, PrefsSource { } public void completeSync() { + uninstallAsHttpResponseObserver(); this.currentState = GlobalSyncStage.Stage.idle; this.callback.handleSuccess(this); } public void abort(Exception e, String reason) { Logger.warn(LOG_TAG, "Aborting sync: " + reason, e); + uninstallAsHttpResponseObserver(); + long existingBackoff = largestBackoffObserved.get(); + if (existingBackoff > 0) { + callback.requestBackoff(existingBackoff); + } this.callback.handleError(this, e); } @@ -314,21 +329,9 @@ public class GlobalSession implements CredentialsSource, PrefsSource { */ public void interpretHTTPFailure(HttpResponse response) { // TODO: handle permanent rejection. - long retryAfter = 0; - long weaveBackoff = 0; - if (response.containsHeader(HEADER_RETRY_AFTER)) { - // Handles non-decimals just fine. - String headerValue = response.getFirstHeader(HEADER_RETRY_AFTER).getValue(); - retryAfter = Utils.decimalSecondsToMilliseconds(headerValue); - } - if (response.containsHeader(HEADER_X_WEAVE_BACKOFF)) { - // Handles non-decimals just fine. - String headerValue = response.getFirstHeader(HEADER_X_WEAVE_BACKOFF).getValue(); - weaveBackoff = Utils.decimalSecondsToMilliseconds(headerValue); - } - long backoff = Math.max(retryAfter, weaveBackoff); - if (backoff > 0) { - callback.requestBackoff(backoff); + long responseBackoff = (new SyncResponse(response)).totalBackoffInMilliseconds(); + if (responseBackoff > 0) { + callback.requestBackoff(responseBackoff); } if (response.getStatusLine() != null && response.getStatusLine().getStatusCode() == 401) { @@ -705,4 +708,49 @@ public class GlobalSession implements CredentialsSource, PrefsSource { public ClientsDataDelegate getClientsDelegate() { return this.clientsDelegate; } + + /** + * The longest backoff observed to date; -1 means no backoff observed. + */ + protected final AtomicLong largestBackoffObserved = new AtomicLong(-1); + + /** + * Reset any observed backoff and start observing HTTP responses for backoff + * requests. + */ + protected void installAsHttpResponseObserver() { + Logger.debug(LOG_TAG, "Installing " + this + " as BaseResource HttpResponseObserver."); + BaseResource.setHttpResponseObserver(this); + largestBackoffObserved.set(-1); + } + + /** + * Stop observing HttpResponses for backoff requests. + */ + protected void uninstallAsHttpResponseObserver() { + Logger.debug(LOG_TAG, "Uninstalling " + this + " as BaseResource HttpResponseObserver."); + BaseResource.setHttpResponseObserver(null); + } + + /** + * Observe all HTTP response for backoff requests on all status codes, not just errors. + */ + @Override + public void observeHttpResponse(HttpResponse response) { + long responseBackoff = (new SyncResponse(response)).totalBackoffInMilliseconds(); // TODO: don't allocate object? + if (responseBackoff <= 0) { + return; + } + + Logger.debug(LOG_TAG, "Observed " + responseBackoff + " millisecond backoff request."); + while (true) { + long existingBackoff = largestBackoffObserved.get(); + if (existingBackoff >= responseBackoff) { + return; + } + if (largestBackoffObserved.compareAndSet(existingBackoff, responseBackoff)) { + return; + } + } + } } diff --git a/mobile/android/base/sync/net/BaseResource.java b/mobile/android/base/sync/net/BaseResource.java index f2d97edb889..fb0db8fbdd1 100644 --- a/mobile/android/base/sync/net/BaseResource.java +++ b/mobile/android/base/sync/net/BaseResource.java @@ -6,6 +6,7 @@ package org.mozilla.gecko.sync.net; import java.io.BufferedReader; import java.io.IOException; +import java.lang.ref.WeakReference; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyManagementException; @@ -73,6 +74,8 @@ public class BaseResource implements Resource { protected HttpRequestBase request; public String charset = "utf-8"; + protected static WeakReference httpResponseObserver = null; + public BaseResource(String uri) throws URISyntaxException { this(uri, rewriteLocalhost); } @@ -99,6 +102,20 @@ public class BaseResource implements Resource { } } + public static synchronized HttpResponseObserver getHttpResponseObserver() { + if (httpResponseObserver == null) { + return null; + } + return httpResponseObserver.get(); + } + + public static synchronized void setHttpResponseObserver(HttpResponseObserver newHttpResponseObserver) { + if (httpResponseObserver != null) { + httpResponseObserver.clear(); + } + httpResponseObserver = new WeakReference(newHttpResponseObserver); + } + public URI getURI() { return this.uri; } @@ -229,6 +246,10 @@ public class BaseResource implements Resource { try { HttpResponse response = client.execute(request, context); Logger.debug(LOG_TAG, "Response: " + response.getStatusLine().toString()); + HttpResponseObserver observer = getHttpResponseObserver(); + if (observer != null) { + observer.observeHttpResponse(response); + } delegate.handleHttpResponse(response); } catch (ClientProtocolException e) { delegate.handleHttpProtocolException(e); diff --git a/mobile/android/base/sync/net/HttpResponseObserver.java b/mobile/android/base/sync/net/HttpResponseObserver.java new file mode 100644 index 00000000000..d7474f3fbae --- /dev/null +++ b/mobile/android/base/sync/net/HttpResponseObserver.java @@ -0,0 +1,17 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync.net; + +import ch.boye.httpclientandroidlib.HttpResponse; + +public interface HttpResponseObserver { + /** + * Observe an HTTP response. + * + * @param response + * The HttpResponse to observe. + */ + public void observeHttpResponse(HttpResponse response); +} diff --git a/mobile/android/base/sync/net/SyncResponse.java b/mobile/android/base/sync/net/SyncResponse.java index 18a66bcd76c..afbc5cd9566 100644 --- a/mobile/android/base/sync/net/SyncResponse.java +++ b/mobile/android/base/sync/net/SyncResponse.java @@ -1,40 +1,6 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Richard Newman - * Nick Alexander - * - * 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 ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sync.net; @@ -200,7 +166,7 @@ public class SyncResponse { * @return A number of milliseconds, or -1 if neither the 'Retry-After' or * 'X-Weave-Backoff' header was present. */ - public int totalBackoffInMilliseconds() { + public long totalBackoffInMilliseconds() { int retryAfterInSeconds = -1; try { retryAfterInSeconds = retryAfterInSeconds(); @@ -213,7 +179,7 @@ public class SyncResponse { } catch (NumberFormatException e) { } - int totalBackoff = Math.max(retryAfterInSeconds, weaveBackoffInSeconds); + long totalBackoff = (long) Math.max(retryAfterInSeconds, weaveBackoffInSeconds); if (totalBackoff < 0) { return -1; } else { @@ -253,4 +219,4 @@ public class SyncResponse { } return null; } -} \ No newline at end of file +} diff --git a/mobile/android/base/sync/stage/ServerSyncStage.java b/mobile/android/base/sync/stage/ServerSyncStage.java index b71fbb21ebf..c6c97cafc0c 100644 --- a/mobile/android/base/sync/stage/ServerSyncStage.java +++ b/mobile/android/base/sync/stage/ServerSyncStage.java @@ -23,8 +23,6 @@ import org.mozilla.gecko.sync.repositories.Server11Repository; import org.mozilla.gecko.sync.synchronizer.Synchronizer; import org.mozilla.gecko.sync.synchronizer.SynchronizerDelegate; -import android.util.Log; - /** * Fetch from a server collection into a local repository, encrypting * and decrypting along the way. @@ -131,6 +129,7 @@ public abstract class ServerSyncStage implements session.abort(e, "Invalid persisted JSON for config."); return; } + Logger.debug(LOG_TAG, "Invoking synchronizer."); synchronizer.synchronize(session.getContext(), this); Logger.debug(LOG_TAG, "Reached end of execute."); @@ -138,15 +137,23 @@ public abstract class ServerSyncStage implements @Override public void onSynchronized(Synchronizer synchronizer) { - Log.d(LOG_TAG, "onSynchronized."); - synchronizer.save().persist(session.config.getBranch(bundlePrefix())); + Logger.debug(LOG_TAG, "onSynchronized."); + + SynchronizerConfiguration synchronizerConfiguration = synchronizer.save(); + if (synchronizerConfiguration != null) { + synchronizerConfiguration.persist(session.config.getBranch(bundlePrefix())); + } else { + Logger.warn(LOG_TAG, "Didn't get configuration from synchronizer after success"); + } + + Logger.info(LOG_TAG, "Advancing session."); session.advance(); } @Override public void onSynchronizeFailed(Synchronizer synchronizer, Exception lastException, String reason) { - Log.i(LOG_TAG, "onSynchronizeFailed: " + reason); + Logger.debug(LOG_TAG, "onSynchronizeFailed: " + reason); // This failure could be due to a 503 or a 401 and it could have headers. if (lastException instanceof HTTPFailureException) { @@ -158,7 +165,8 @@ public abstract class ServerSyncStage implements @Override public void onSynchronizeAborted(Synchronizer synchronize) { - Log.i(LOG_TAG, "onSynchronizeAborted."); + Logger.info(LOG_TAG, "onSynchronizeAborted."); + session.abort(null, "Synchronization was aborted."); } } diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index 59a311d316a..bdb9c6a0d2e 100644 --- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -1 +1 @@ -sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/HttpResponseObserver.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java From 56b876fb6777b6d221c06c169af3b43bb30527de Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Tue, 27 Mar 2012 21:43:56 -0400 Subject: [PATCH 099/113] Bug 738188. Avoid crashing by disabling the screenshot drawing code. r=kats The crashes seem to be caused by SurfaceChange breaking any future onDrawFrame calls. We don't seem to handle renewing the context at all. I added mController.disposeGLContext(); mController.initGLContext(); to the SizeChange::run() but that doesn't seem to fix it. Bug 739867 will add this support back. --HG-- extra : rebase_source : a4f71b22f381756c4285311cd3288b3ef46d5543 --- mobile/android/base/gfx/LayerRenderer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mobile/android/base/gfx/LayerRenderer.java b/mobile/android/base/gfx/LayerRenderer.java index 76718b1bb39..65881b8712e 100644 --- a/mobile/android/base/gfx/LayerRenderer.java +++ b/mobile/android/base/gfx/LayerRenderer.java @@ -266,6 +266,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer { * Called whenever a new frame is about to be drawn. */ public void onDrawFrame(GL10 gl) { + /* This code is causing crashes when the surface changes. (bug 738188) + * I'm not sure if it actually works, so I'm disabling it now to avoid the crash. RenderContext pageContext = createPageContext(mView.getController().getViewportMetrics()); RenderContext screenContext = createScreenContext(); Frame frame = createFrame(pageContext, screenContext); @@ -276,6 +278,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer { frame.drawForeground(); frame.endDrawing(); } + */ } private void printCheckerboardStats() { From 95fbe9cf81a4fcd652f5f6eed09c8f5b3f050153 Mon Sep 17 00:00:00 2001 From: Marina Samuel Date: Tue, 27 Mar 2012 20:09:14 -0700 Subject: [PATCH 100/113] Bug 732147 - Send tab to device: receiving pushed tabs on Android. r=rnewman --- .../android/base/sync/CommandProcessor.java | 45 +++++++++++++++++++ mobile/android/base/sync/GlobalSession.java | 7 +++ .../base/sync/syncadapter/SyncAdapter.java | 19 -------- mobile/android/sync/strings.xml.in | 2 + 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/mobile/android/base/sync/CommandProcessor.java b/mobile/android/base/sync/CommandProcessor.java index 5d79b624eb6..718c80efb85 100644 --- a/mobile/android/base/sync/CommandProcessor.java +++ b/mobile/android/base/sync/CommandProcessor.java @@ -7,11 +7,21 @@ package org.mozilla.gecko.sync; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import org.json.simple.JSONArray; +import org.mozilla.gecko.R; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; public class CommandProcessor { private static final String LOG_TAG = "Command"; + private static AtomicInteger currentId = new AtomicInteger(); protected ConcurrentHashMap commands = new ConcurrentHashMap(); private final static CommandProcessor processor = new CommandProcessor(); @@ -80,4 +90,39 @@ public class CommandProcessor { return null; } } + + public void displayURI(List args, Context context) { + // These two args are guaranteed to exist by trusting the client sender. + String uri = args.get(0); + String clientId = args.get(1); + + Logger.info(LOG_TAG, "Received a URI for display: " + uri + " from " + clientId); + + String title = null; + if (args.size() == 3) { + title = args.get(2); + } + + // Get NotificationManager. + String ns = Context.NOTIFICATION_SERVICE; + NotificationManager mNotificationManager = (NotificationManager)context.getSystemService(ns); + + // Create a Notficiation. + int icon = R.drawable.sync_ic_launcher; + String notificationTitle = context.getString(R.string.sync_new_tab); + if (title != null) { + notificationTitle = notificationTitle.concat(": " + title); + } + long when = System.currentTimeMillis(); + Notification notification = new Notification(icon, notificationTitle, when); + notification.flags = Notification.FLAG_AUTO_CANCEL; + + // Set pending intent associated with the notification. + Intent notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); + PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); + notification.setLatestEventInfo(context, notificationTitle, uri, contentIntent); + + // Send notification. + mNotificationManager.notify(currentId.getAndIncrement(), notification); + } } diff --git a/mobile/android/base/sync/GlobalSession.java b/mobile/android/base/sync/GlobalSession.java index 4d193a3af4d..a1012094289 100644 --- a/mobile/android/base/sync/GlobalSession.java +++ b/mobile/android/base/sync/GlobalSession.java @@ -176,6 +176,13 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon resetClient(null); } }); + + processor.registerCommand("displayURI", new CommandRunner() { + @Override + public void executeCommand(List args) { + CommandProcessor.getProcessor().displayURI(args, getContext()); + } + }); } protected void prepareStages() { diff --git a/mobile/android/base/sync/syncadapter/SyncAdapter.java b/mobile/android/base/sync/syncadapter/SyncAdapter.java index 538bfe7f94c..a1457f33879 100644 --- a/mobile/android/base/sync/syncadapter/SyncAdapter.java +++ b/mobile/android/base/sync/syncadapter/SyncAdapter.java @@ -7,16 +7,11 @@ package org.mozilla.gecko.sync.syncadapter; import java.io.IOException; import java.net.URI; import java.security.NoSuchAlgorithmException; -import java.util.List; import java.util.concurrent.TimeUnit; - import org.json.simple.parser.ParseException; import org.mozilla.gecko.sync.AlreadySyncingException; -import org.mozilla.gecko.sync.CommandRunner; -import org.mozilla.gecko.sync.CommandProcessor; import org.mozilla.gecko.sync.GlobalConstants; import org.mozilla.gecko.sync.GlobalSession; -import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.NonObjectJSONException; import org.mozilla.gecko.sync.SyncConfiguration; import org.mozilla.gecko.sync.SyncConfigurationException; @@ -66,15 +61,6 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe mContext = context; Log.d(LOG_TAG, "AccountManager.get(" + mContext + ")"); mAccountManager = AccountManager.get(context); - - // Register the displayURI command here so our SyncService - // can receive notifications to open a URI. - CommandProcessor.getProcessor().registerCommand("displayURI", new CommandRunner() { - @Override - public void executeCommand(List args) { - displayURI(args.get(0), args.get(1)); - } - }); } private SharedPreferences getGlobalPrefs() { @@ -493,9 +479,4 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe public void informUnauthorizedResponse(GlobalSession session, URI oldClusterURL) { setClusterURLIsStale(true); } - - public void displayURI(String uri, String clientId) { - Logger.info(LOG_TAG, "Received a URI for display: " + uri + " from " + clientId); - // TODO: Bug 732147 - Send tab to device: receiving pushed tabs - } } diff --git a/mobile/android/sync/strings.xml.in b/mobile/android/sync/strings.xml.in index 17c04a93f91..72cb3ca6fc3 100644 --- a/mobile/android/sync/strings.xml.in +++ b/mobile/android/sync/strings.xml.in @@ -61,3 +61,5 @@ &sync.notification.oneaccount.label; + + &new_tab; From 6996ba57483904aae966bab8b3269a857e3140d4 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 27 Mar 2012 20:09:15 -0700 Subject: [PATCH 101/113] Remove forgotten stale file. NO BUG, r=trivial --- .../repositories/android/PasswordColumns.java | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 mobile/android/base/sync/repositories/android/PasswordColumns.java diff --git a/mobile/android/base/sync/repositories/android/PasswordColumns.java b/mobile/android/base/sync/repositories/android/PasswordColumns.java deleted file mode 100644 index b2fcbe4b81f..00000000000 --- a/mobile/android/base/sync/repositories/android/PasswordColumns.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jason Voll - * - * 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 ***** */ - -package org.mozilla.gecko.sync.repositories.android; - -import android.provider.BaseColumns; - -public final class PasswordColumns implements BaseColumns { - - /* - * IMPORTANT NOTE - * This file takes the column names from mobile/android/base/GeckoPassword.java - * and is included here to avoid creating a compile-time dependency on Fennec. - */ - - public static final String _ID = "id"; - public static final String HOSTNAME = "hostname"; - public static final String HTTP_REALM = "httpRealm"; - public static final String FORM_SUBMIT_URL = "formSubmitURL"; - public static final String USERNAME_FIELD = "usernameField"; - public static final String PASSWORD_FIELD = "passwordField"; - public static final String ENCRYPTED_USERNAME = "encryptedUsername"; - public static final String ENCRYPTED_PASSWORD = "encryptedPassword"; - public static final String GUID = "guid"; - public static final String ENC_TYPE = "encType"; - public static final String TIME_CREATED = "timeCreated"; - public static final String TIME_LAST_USED = "timeLastUsed"; - public static final String TIME_PASSWORD_CHANGED = "timePasswordChanged"; - public static final String TIMES_USED = "timesUsed"; -} From 4dea1e6d49e334f9cb22fc3f7761129d35141afa Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 27 Mar 2012 20:53:58 -0400 Subject: [PATCH 102/113] bug 648265 - non-xpcom accessible table interface and casting r=surkov sr=neil --- accessible/src/atk/Makefile.in | 2 + accessible/src/atk/nsMaiInterfaceTable.cpp | 26 ++- accessible/src/base/Makefile.in | 3 +- accessible/src/base/nsARIAGridAccessible.cpp | 30 +--- accessible/src/base/nsARIAGridAccessible.h | 14 +- accessible/src/base/nsAccessible.h | 7 + accessible/src/generic/TableAccessible.h | 170 ++++++++++++++++++ accessible/src/html/Makefile.in | 2 + accessible/src/html/nsHTMLTableAccessible.cpp | 49 ++--- accessible/src/html/nsHTMLTableAccessible.h | 25 ++- accessible/src/msaa/Makefile.in | 2 + accessible/src/xpcom/Makefile.in | 2 + accessible/src/xpcom/xpcAccessibleTable.cpp | 34 ++++ accessible/src/xpcom/xpcAccessibleTable.h | 63 +++++++ accessible/src/xul/Makefile.in | 2 + accessible/src/xul/nsXULListboxAccessible.cpp | 30 ++-- accessible/src/xul/nsXULListboxAccessible.h | 17 +- .../src/xul/nsXULTreeGridAccessible.cpp | 24 +-- accessible/src/xul/nsXULTreeGridAccessible.h | 14 +- 19 files changed, 402 insertions(+), 114 deletions(-) create mode 100644 accessible/src/generic/TableAccessible.h create mode 100644 accessible/src/xpcom/xpcAccessibleTable.cpp create mode 100644 accessible/src/xpcom/xpcAccessibleTable.h diff --git a/accessible/src/atk/Makefile.in b/accessible/src/atk/Makefile.in index 9fe1f48b857..2bd347beae8 100644 --- a/accessible/src/atk/Makefile.in +++ b/accessible/src/atk/Makefile.in @@ -99,7 +99,9 @@ endif LOCAL_INCLUDES += \ -I$(srcdir) \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(topsrcdir)/other-licenses/atk-1.0 \ $(NULL) diff --git a/accessible/src/atk/nsMaiInterfaceTable.cpp b/accessible/src/atk/nsMaiInterfaceTable.cpp index 1c8971d4fbc..158e490dd7a 100644 --- a/accessible/src/atk/nsMaiInterfaceTable.cpp +++ b/accessible/src/atk/nsMaiInterfaceTable.cpp @@ -42,12 +42,14 @@ #include "nsAccessibleWrap.h" #include "nsAccUtils.h" #include "nsIAccessibleTable.h" +#include "TableAccessible.h" #include "nsMai.h" #include "nsArrayUtils.h" -extern "C" { +using namespace mozilla::a11y; +extern "C" { static AtkObject* refAtCB(AtkTable *aTable, gint aRow, gint aColumn) { @@ -208,23 +210,17 @@ getRowExtentAtCB(AtkTable *aTable, } static AtkObject* -getCaptionCB(AtkTable *aTable) +getCaptionCB(AtkTable* aTable) { - nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable)); - if (!accWrap) - return nsnull; + nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable)); + if (!accWrap) + return nsnull; - nsCOMPtr accTable; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable), - getter_AddRefs(accTable)); - NS_ENSURE_TRUE(accTable, nsnull); + TableAccessible* table = accWrap->AsTable(); + NS_ENSURE_TRUE(table, nsnull); - nsCOMPtr caption; - nsresult rv = accTable->GetCaption(getter_AddRefs(caption)); - if (NS_FAILED(rv) || !caption) - return nsnull; - - return nsAccessibleWrap::GetAtkObject(caption); + nsAccessible* caption = table->Caption(); + return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull; } static const gchar* diff --git a/accessible/src/base/Makefile.in b/accessible/src/base/Makefile.in index 7fd861756c4..b71efb0c1ba 100644 --- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -104,8 +104,9 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir) \ - -I$(srcdir)/../xpcom \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/style \ diff --git a/accessible/src/base/nsARIAGridAccessible.cpp b/accessible/src/base/nsARIAGridAccessible.cpp index ed7304d59aa..4a985b7a0fc 100644 --- a/accessible/src/base/nsARIAGridAccessible.cpp +++ b/accessible/src/base/nsARIAGridAccessible.cpp @@ -58,7 +58,7 @@ using namespace mozilla::a11y; nsARIAGridAccessible:: nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessibleWrap(aContent, aDoc) + nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) { } @@ -70,21 +70,18 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible, nsIAccessibleTable) //////////////////////////////////////////////////////////////////////////////// -// nsIAccessibleTable +//nsAccessNode -NS_IMETHODIMP -nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption) +void +nsARIAGridAccessible::Shutdown() { - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - // XXX: should be pointed by aria-labelledby on grid? - return NS_ERROR_NOT_IMPLEMENTED; + mTable = nsnull; + nsAccessibleWrap::Shutdown(); } +//////////////////////////////////////////////////////////////////////////////// +// nsIAccessibleTable + NS_IMETHODIMP nsARIAGridAccessible::GetSummary(nsAString &aSummary) { @@ -710,15 +707,6 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn) return NS_OK; } -NS_IMETHODIMP -nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) -{ - NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); - *aIsProbablyForLayout = false; - - return NS_OK; -} - //////////////////////////////////////////////////////////////////////////////// // Protected diff --git a/accessible/src/base/nsARIAGridAccessible.h b/accessible/src/base/nsARIAGridAccessible.h index 9a1806bc701..c17aaa99b4e 100644 --- a/accessible/src/base/nsARIAGridAccessible.h +++ b/accessible/src/base/nsARIAGridAccessible.h @@ -42,12 +42,16 @@ #include "nsIAccessibleTable.h" #include "nsHyperTextAccessibleWrap.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" /** * Accessible for ARIA grid and treegrid. */ class nsARIAGridAccessible : public nsAccessibleWrap, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc); @@ -56,7 +60,13 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable - NS_DECL_NSIACCESSIBLETABLE + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + + // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } + + // nsAccessNode + virtual void Shutdown(); protected: /** diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index e4203016756..daa0696bc33 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -66,6 +66,11 @@ class nsHTMLImageMapAccessible; class nsHTMLLIAccessible; struct nsRoleMapEntry; class Relation; +namespace mozilla { +namespace a11y { +class TableAccessible; +} +} class nsTextAccessible; struct nsRect; @@ -471,6 +476,8 @@ public: inline bool IsRoot() const { return mFlags & eRootAccessible; } nsRootAccessible* AsRoot(); + virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; } + inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; } nsTextAccessible* AsTextLeaf(); diff --git a/accessible/src/generic/TableAccessible.h b/accessible/src/generic/TableAccessible.h new file mode 100644 index 00000000000..694fb02ed15 --- /dev/null +++ b/accessible/src/generic/TableAccessible.h @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef TABLE_ACCESSIBLE_H +#define TABLE_ACCESSIBLE_H + +#include "nsString.h" +#include "nsTArray.h" +#include "prtypes.h" + +class nsAccessible; + +namespace mozilla { +namespace a11y { + +/** + * Accessible table interface. + */ +class TableAccessible +{ +public: + + /** + * Return the caption accessible if any for this table. + */ + virtual nsAccessible* Caption() { return nsnull; } + + /** + * Get the summary for this table. + */ + virtual void Summary(nsString& aSummary) { aSummary.Truncate(); } + + /** + * Return the number of columns in the table. + */ + virtual PRUint32 ColCount() { return 0; } + + /** + * Return the number of rows in the table. + */ + virtual PRUint32 RowCount() { return 0; } + + /** + * Return the accessible for the cell at the given row and column indices. + */ + virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; } + + /** + * Return the index of the cell at the given row and column. + */ + virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; } + + /** + * Return the column index of the cell with the given index. + */ + virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; } + + /** + * Return the row index of the cell with the given index. + */ + virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; } + + /** + * Get the row and column indices for the cell at the given index. + */ + virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx, + PRInt32* aColIdx) {} + + /** + * Return the number of columns occupied by the cell at the given row and + * column indices. + */ + virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; } + + /** + * Return the number of rows occupied by the cell at the given row and column + * indices. + */ + virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; } + + /** + * Get the description of the given column. + */ + virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription) + { aDescription.Truncate(); } + + /** + * Get the description for the given row. + */ + virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription) + { aDescription.Truncate(); } + + /** + * Return true if the given column is selected. + */ + virtual bool IsColSelected(PRUint32 aColIdx) { return false; } + + /** + * Return true if the given row is selected. + */ + virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; } + + /** + * Return true if the given cell is selected. + */ + virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; } + + /** + * Return the number of selected cells. + */ + virtual PRUint32 SelectedCellCount() { return 0; } + + /** + * Return the number of selected columns. + */ + virtual PRUint32 SelectedColCount() { return 0; } + + /** + * Return the number of selected rows. + */ + virtual PRUint32 SelectedRowCount() { return 0; } + + /** + * Get the set of selected cells. + */ + virtual void SelectedCells(nsTArray* aCells) {} + + /** + * Get the set of selected column indices. + */ + virtual void SelectedColIndices(nsTArray* aCols) {} + + /** + * Get the set of selected row indices. + */ + virtual void SelectedRowIndices(nsTArray* aRows) {} + + /** + * Select the given column unselecting any other selected columns. + */ + virtual void SelectCol(PRUint32 aColIdx) {} + + /** + * Select the given row unselecting all other previously selected rows. + */ + virtual void SelectRow(PRUint32 aRowIdx) {} + + /** + * Unselect the given column leaving other selected columns selected. + */ + virtual void UnselectCol(PRUint32 aColIdx) {} + + /** + * Unselect the given row leaving other selected rows selected. + */ + virtual void UnselectRow(PRUint32 aRowIdx) {} + + /** + * Return true if the table is probably for layout. + */ + virtual bool IsProbablyLayoutTable() { return false; } +}; + +} // namespace a11y +} // namespace mozilla + +#endif diff --git a/accessible/src/html/Makefile.in b/accessible/src/html/Makefile.in index 7820e4a8b1d..ebd86307696 100644 --- a/accessible/src/html/Makefile.in +++ b/accessible/src/html/Makefile.in @@ -73,6 +73,8 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ $(NULL) diff --git a/accessible/src/html/nsHTMLTableAccessible.cpp b/accessible/src/html/nsHTMLTableAccessible.cpp index a5547bb3d1c..a09c2740b68 100644 --- a/accessible/src/html/nsHTMLTableAccessible.cpp +++ b/accessible/src/html/nsHTMLTableAccessible.cpp @@ -436,7 +436,7 @@ nsHTMLTableHeaderCellAccessible::NativeRole() nsHTMLTableAccessible:: nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsAccessibleWrap(aContent, aDoc) + nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) { } @@ -446,6 +446,16 @@ nsHTMLTableAccessible:: NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible, nsHTMLTableAccessible, nsIAccessibleTable) +//////////////////////////////////////////////////////////////////////////////// +//nsAccessNode + +void +nsHTMLTableAccessible::Shutdown() +{ + mTable = nsnull; + nsAccessibleWrap::Shutdown(); +} + //////////////////////////////////////////////////////////////////////////////// // nsHTMLTableAccessible: nsAccessible implementation @@ -511,9 +521,7 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes); NS_ENSURE_SUCCESS(rv, rv); - bool isProbablyForLayout; - IsProbablyForLayout(&isProbablyForLayout); - if (isProbablyForLayout) { + if (IsProbablyLayoutTable()) { nsAutoString oldValueUnused; aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"), NS_LITERAL_STRING("true"), oldValueUnused); @@ -538,13 +546,11 @@ nsHTMLTableAccessible::RelationByType(PRUint32 aType) //////////////////////////////////////////////////////////////////////////////// // nsHTMLTableAccessible: nsIAccessibleTable implementation -NS_IMETHODIMP -nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption) +nsAccessible* +nsHTMLTableAccessible::Caption() { - NS_ENSURE_ARG_POINTER(aCaption); - - NS_IF_ADDREF(*aCaption = Caption()); - return NS_OK; + nsAccessible* child = mChildren.SafeElementAt(0, nsnull); + return child && child->Role() == roles::CAPTION ? child : nsnull; } NS_IMETHODIMP @@ -1307,8 +1313,7 @@ nsHTMLTableAccessible::Description(nsString& aDescription) #ifdef SHOW_LAYOUT_HEURISTIC if (aDescription.IsEmpty()) { - bool isProbablyForLayout; - IsProbablyForLayout(&isProbablyForLayout); + bool isProbablyForLayout = IsProbablyLayoutTable(); aDescription = mLayoutHeuristic; } #ifdef DEBUG_A11Y @@ -1357,8 +1362,8 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName, return !!foundItem; } -NS_IMETHODIMP -nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) +bool +nsHTMLTableAccessible::IsProbablyLayoutTable() { // Implement a heuristic to determine if table is most likely used for layout // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells @@ -1370,18 +1375,16 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release #ifdef SHOW_LAYOUT_HEURISTIC #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \ - { *aIsProbablyForLayout = isLayout; \ - mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \ - mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; } + { \ + mLayoutHeuristic = isLayout ? \ + NS_LITERAL_STRING("layout table: " heuristic) : \ + NS_LITERAL_STRING("data table: " heuristic); \ + return isLayout; \ + } #else -#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; } +#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; } #endif - *aIsProbablyForLayout = false; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - nsDocAccessible* docAccessible = Document(); if (docAccessible) { PRUint64 docState = docAccessible->State(); diff --git a/accessible/src/html/nsHTMLTableAccessible.h b/accessible/src/html/nsHTMLTableAccessible.h index bf10061ba03..4691bd9fc6d 100644 --- a/accessible/src/html/nsHTMLTableAccessible.h +++ b/accessible/src/html/nsHTMLTableAccessible.h @@ -41,6 +41,8 @@ #include "nsHyperTextAccessibleWrap.h" #include "nsIAccessibleTable.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" class nsITableLayout; class nsITableCellLayout; @@ -121,16 +123,28 @@ public: } class nsHTMLTableAccessible : public nsAccessibleWrap, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLETABLE NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID) + // nsIAccessible Table + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + + // TableAccessible + virtual nsAccessible* Caption(); + virtual bool IsProbablyLayoutTable(); + + // nsAccessNode + virtual void Shutdown(); + // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual void Description(nsString& aDescription); virtual nsresult GetNameInternal(nsAString& aName); virtual mozilla::a11y::role NativeRole(); @@ -138,13 +152,6 @@ public: virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); virtual Relation RelationByType(PRUint32 aRelationType); - // TableAccessible - inline nsAccessible* Caption() const - { - nsAccessible* child = mChildren.SafeElementAt(0, nsnull); - return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull; - } - // nsHTMLTableAccessible /** diff --git a/accessible/src/msaa/Makefile.in b/accessible/src/msaa/Makefile.in index eb45cf2a066..5a2462fd194 100644 --- a/accessible/src/msaa/Makefile.in +++ b/accessible/src/msaa/Makefile.in @@ -114,7 +114,9 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir) \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(srcdir)/../../../content/base/src \ -I$(srcdir)/../../../content/events/src \ diff --git a/accessible/src/xpcom/Makefile.in b/accessible/src/xpcom/Makefile.in index d270bd35ab3..31ffd6b24f1 100644 --- a/accessible/src/xpcom/Makefile.in +++ b/accessible/src/xpcom/Makefile.in @@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1 CPPSRCS = \ nsAccEvent.cpp \ nsAccessibleRelation.cpp \ + xpcAccessibleTable.cpp \ $(NULL) # we don't want the shared lib, but we want to force the creation of a static lib. @@ -59,4 +60,5 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ $(NULL) diff --git a/accessible/src/xpcom/xpcAccessibleTable.cpp b/accessible/src/xpcom/xpcAccessibleTable.cpp new file mode 100644 index 00000000000..9923490ecbe --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTable.cpp @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xpcAccessibleTable.h" + +#include "nsAccessible.h" +#include "TableAccessible.h" + +nsresult +xpcAccessibleTable::GetCaption(nsIAccessible** aCaption) +{ + NS_ENSURE_ARG_POINTER(aCaption); + *aCaption = nsnull; + if (!mTable) + return NS_ERROR_FAILURE; + + NS_IF_ADDREF(*aCaption = mTable->Caption()); + return NS_OK; +} + +nsresult +xpcAccessibleTable::IsProbablyForLayout(bool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = false; + if (!mTable) + return NS_ERROR_FAILURE; + + *aResult = mTable->IsProbablyLayoutTable(); + return NS_OK; +} diff --git a/accessible/src/xpcom/xpcAccessibleTable.h b/accessible/src/xpcom/xpcAccessibleTable.h new file mode 100644 index 00000000000..afec1960177 --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTable.h @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ +#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ + +#include "nscore.h" + +class nsIAccessible; +namespace mozilla { +namespace a11y { +class TableAccessible; +} +} + +class xpcAccessibleTable +{ +public: + xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { } + + nsresult GetCaption(nsIAccessible** aCaption); + nsresult IsProbablyForLayout(bool* aIsForLayout); + +protected: + mozilla::a11y::TableAccessible* mTable; +}; + +#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \ + NS_IMETHOD GetCaption(nsIAccessible** aCaption) \ + { return xpcAccessibleTable::GetCaption(aCaption); } \ + NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \ + NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \ + NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \ + NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \ + NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \ + NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \ + NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \ + NS_IMETHOD IsProbablyForLayout(bool* aResult) \ + { return xpcAccessibleTable::IsProbablyForLayout(aResult); } \ + +#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ diff --git a/accessible/src/xul/Makefile.in b/accessible/src/xul/Makefile.in index 05a4bc7492e..e86dcd64420 100644 --- a/accessible/src/xul/Makefile.in +++ b/accessible/src/xul/Makefile.in @@ -72,7 +72,9 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir) \ -I$(srcdir)/../base \ + -I$(srcdir)/../generic \ -I$(srcdir)/../html \ + -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ $(NULL) diff --git a/accessible/src/xul/nsXULListboxAccessible.cpp b/accessible/src/xul/nsXULListboxAccessible.cpp index 4adcc94d0e7..971620d3598 100644 --- a/accessible/src/xul/nsXULListboxAccessible.cpp +++ b/accessible/src/xul/nsXULListboxAccessible.cpp @@ -134,7 +134,7 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex) nsXULListboxAccessible:: nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - XULSelectControlAccessible(aContent, aDoc) + XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this) { nsIContent* parentContent = mContent->GetParent(); if (parentContent) { @@ -164,6 +164,16 @@ nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) return NS_ERROR_NO_INTERFACE; } +//////////////////////////////////////////////////////////////////////////////// +//nsAccessNode + +void +nsXULListboxAccessible::Shutdown() +{ + mTable = nsnull; + XULSelectControlAccessible::Shutdown(); +} + bool nsXULListboxAccessible::IsMulticolumn() { @@ -229,15 +239,6 @@ nsXULListboxAccessible::NativeRole() //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible. nsIAccessibleTable -NS_IMETHODIMP -nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption) -{ - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - - return NS_OK; -} - NS_IMETHODIMP nsXULListboxAccessible::GetSummary(nsAString &aSummary) { @@ -820,15 +821,6 @@ nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn) return NS_OK; } -NS_IMETHODIMP -nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) -{ - NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); - *aIsProbablyForLayout = false; - - return NS_OK; -} - //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible: Widgets diff --git a/accessible/src/xul/nsXULListboxAccessible.h b/accessible/src/xul/nsXULListboxAccessible.h index be49fadc6c3..06fdd3470c0 100644 --- a/accessible/src/xul/nsXULListboxAccessible.h +++ b/accessible/src/xul/nsXULListboxAccessible.h @@ -40,11 +40,12 @@ #ifndef __nsXULListboxAccessible_h__ #define __nsXULListboxAccessible_h__ -#include "nsIAccessibleTable.h" - #include "nsCOMPtr.h" #include "nsXULMenuAccessible.h" #include "nsBaseWidgetAccessible.h" +#include "nsIAccessibleTable.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" #include "XULSelectControlAccessible.h" class nsIWeakReference; @@ -90,19 +91,27 @@ public: * A class the represents the XUL Listbox widget. */ class nsXULListboxAccessible : public XULSelectControlAccessible, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc); virtual ~nsXULListboxAccessible() {} NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLETABLE + + // nsIAccessibleTable + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE // nsIAccessible NS_IMETHOD GetValue(nsAString& aValue); + // nsAccessNode + virtual void Shutdown(); + // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual mozilla::a11y::role NativeRole(); virtual PRUint64 NativeState(); diff --git a/accessible/src/xul/nsXULTreeGridAccessible.cpp b/accessible/src/xul/nsXULTreeGridAccessible.cpp index c3ca0269103..acd46c643ff 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -58,7 +58,7 @@ using namespace mozilla::a11y; nsXULTreeGridAccessible:: nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : - nsXULTreeAccessible(aContent, aDoc) + nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this) { } @@ -72,15 +72,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible, //////////////////////////////////////////////////////////////////////////////// // nsXULTreeGridAccessible: nsIAccessibleTable implementation -NS_IMETHODIMP -nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption) -{ - NS_ENSURE_ARG_POINTER(aCaption); - *aCaption = nsnull; - - return IsDefunct() ? NS_ERROR_FAILURE : NS_OK; -} - NS_IMETHODIMP nsXULTreeGridAccessible::GetSummary(nsAString &aSummary) { @@ -570,13 +561,14 @@ nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex) return NS_OK; } -NS_IMETHODIMP -nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout) -{ - NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); - *aIsProbablyForLayout = false; +//////////////////////////////////////////////////////////////////////////////// +// nsXULTreeGridAccessible: nsAccessNode implementation - return NS_OK; +void +nsXULTreeGridAccessible::Shutdown() +{ + mTable = nsnull; + nsXULTreeAccessible::Shutdown(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/xul/nsXULTreeGridAccessible.h b/accessible/src/xul/nsXULTreeGridAccessible.h index 0f3771373f8..bed9d95a157 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.h +++ b/accessible/src/xul/nsXULTreeGridAccessible.h @@ -39,15 +39,17 @@ #ifndef __nsXULTreeGridAccessible_h__ #define __nsXULTreeGridAccessible_h__ -#include "nsIAccessibleTable.h" - #include "nsXULTreeAccessible.h" +#include "TableAccessible.h" +#include "xpcAccessibleTable.h" /** * Represents accessible for XUL tree in the case when it has multiple columns. */ class nsXULTreeGridAccessible : public nsXULTreeAccessible, - public nsIAccessibleTable + public xpcAccessibleTable, + public nsIAccessibleTable, + public mozilla::a11y::TableAccessible { public: nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc); @@ -56,9 +58,13 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable - NS_DECL_NSIACCESSIBLETABLE + NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE + + // nsAccessNode + virtual void Shutdown(); // nsAccessible + virtual mozilla::a11y::TableAccessible* AsTable() { return this; } virtual mozilla::a11y::role NativeRole(); protected: From 96fd999a06106013ad95ce02ccf4422c9d115045 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 28 Mar 2012 08:17:53 +0300 Subject: [PATCH 103/113] Bug 717180 - Ignore document.write after window.location. r=smaug. --- content/base/src/nsDocument.cpp | 1 + content/base/src/nsDocument.h | 4 ++ content/html/document/src/nsHTMLDocument.cpp | 8 ++++ parser/htmlparser/tests/mochitest/Makefile.in | 2 + .../tests/mochitest/file_bug717180.html | 1 + .../tests/mochitest/test_bug717180.html | 44 +++++++++++++++++++ 6 files changed, 60 insertions(+) create mode 100644 parser/htmlparser/tests/mochitest/file_bug717180.html create mode 100644 parser/htmlparser/tests/mochitest/test_bug717180.html diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index a2573e0fb08..65c48d1d882 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2547,6 +2547,7 @@ void nsDocument::StopDocumentLoad() { if (mParser) { + mParserAborted = true; mParser->Terminate(); } } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 8bfbfc1802d..28af366c485 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -1188,6 +1188,10 @@ protected: // our presshell. This is used to handle flush reentry correctly. bool mInFlush:1; + // Parser aborted. True if the parser of this document was forcibly + // terminated instead of letting it finish at its own pace. + bool mParserAborted:1; + PRUint8 mXMLDeclarationBits; nsInterfaceHashtable, nsPIBoxObject> *mBoxObjectTable; diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index c8e25d9f499..db6858c87e4 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1559,6 +1559,7 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl, // resetting the document. mSecurityInfo = securityInfo; + mParserAborted = false; bool loadAsHtml5 = nsHtml5Module::sEnabled; if (loadAsHtml5) { mParser = nsHtml5Module::NewHtml5Parser(); @@ -1702,6 +1703,13 @@ nsHTMLDocument::WriteCommon(JSContext *cx, return NS_ERROR_DOM_INVALID_STATE_ERR; } + if (mParserAborted) { + // Hixie says aborting the parser doesn't undefine the insertion point. + // However, since we null out mParser in that case, we track the + // theoretically defined insertion point using mParserAborted. + return NS_OK; + } + nsresult rv = NS_OK; void *key = GenerateParserKey(); diff --git a/parser/htmlparser/tests/mochitest/Makefile.in b/parser/htmlparser/tests/mochitest/Makefile.in index 32a261bcf0d..004096f2ced 100644 --- a/parser/htmlparser/tests/mochitest/Makefile.in +++ b/parser/htmlparser/tests/mochitest/Makefile.in @@ -106,6 +106,8 @@ _TEST_FILES = parser_datreader.js \ test_viewsource.html \ test_bug715112.html \ test_bug715739.html \ + test_bug717180.html \ + file_bug717180.html \ $(NULL) # Test disabled on mobile. See bug 737020. diff --git a/parser/htmlparser/tests/mochitest/file_bug717180.html b/parser/htmlparser/tests/mochitest/file_bug717180.html new file mode 100644 index 00000000000..ff43ca40915 --- /dev/null +++ b/parser/htmlparser/tests/mochitest/file_bug717180.html @@ -0,0 +1 @@ +SUCCESS diff --git a/parser/htmlparser/tests/mochitest/test_bug717180.html b/parser/htmlparser/tests/mochitest/test_bug717180.html new file mode 100644 index 00000000000..13e61b22383 --- /dev/null +++ b/parser/htmlparser/tests/mochitest/test_bug717180.html @@ -0,0 +1,44 @@ + + + + + + Test for Bug 717180 + + + + +Mozilla Bug 717180 +

+ +
+
+
+ + From ee201831b3d5335bc3796d7d87980e75333148a2 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Wed, 28 Mar 2012 00:09:25 -0700 Subject: [PATCH 104/113] Back out 47afa45afdfb and ccb20a1169f1 (bug 697309) and c30bdfd14362 and 618b680315ee (bug 736278) for Android native Talos bustage --- mobile/android/app/mobile.js | 1 - mobile/android/base/DoorHanger.java | 27 +-- .../base/resources/layout/doorhanger.xml | 6 - mobile/android/chrome/content/aboutApps.js | 160 ------------------ mobile/android/chrome/content/aboutApps.xhtml | 46 ----- mobile/android/chrome/content/browser.js | 62 ++----- mobile/android/chrome/content/browser.xul | 1 - mobile/android/chrome/content/webapps.js | 65 ------- mobile/android/chrome/jar.mn | 5 +- mobile/android/components/AboutRedirector.js | 4 - .../components/MobileComponents.manifest | 1 - mobile/android/installer/package-manifest.in | 6 +- .../locales/en-US/chrome/aboutApps.dtd | 8 - .../locales/en-US/chrome/aboutApps.properties | 2 - .../locales/en-US/chrome/browser.properties | 11 +- .../android/locales/en-US/chrome/webapps.dtd | 7 + mobile/android/locales/jar.mn | 3 +- mobile/android/themes/core/aboutApps.css | 43 ----- mobile/android/themes/core/jar.mn | 1 - 19 files changed, 24 insertions(+), 435 deletions(-) delete mode 100644 mobile/android/chrome/content/aboutApps.js delete mode 100644 mobile/android/chrome/content/aboutApps.xhtml delete mode 100644 mobile/android/chrome/content/webapps.js delete mode 100644 mobile/android/locales/en-US/chrome/aboutApps.dtd delete mode 100644 mobile/android/locales/en-US/chrome/aboutApps.properties create mode 100644 mobile/android/locales/en-US/chrome/webapps.dtd delete mode 100644 mobile/android/themes/core/aboutApps.css diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 7895b035815..028e4a6a69a 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -485,7 +485,6 @@ pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/mobile/beta/faq/"); pref("app.featuresURL", "http://www.mozilla.com/%LOCALE%/mobile/features/"); pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/mobile/faq/"); #endif -pref("app.marketplaceURL", "https://marketplace.mozilla.org/"); // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror) pref("security.alternate_certificate_error_page", "certerror"); diff --git a/mobile/android/base/DoorHanger.java b/mobile/android/base/DoorHanger.java index 2f4864aa12b..372fba2f090 100644 --- a/mobile/android/base/DoorHanger.java +++ b/mobile/android/base/DoorHanger.java @@ -43,11 +43,9 @@ import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.style.ForegroundColorSpan; import android.text.style.URLSpan; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; -import android.widget.CheckBox; import android.widget.LinearLayout; import android.widget.TextView; @@ -55,8 +53,6 @@ import org.json.JSONObject; import org.json.JSONException; public class DoorHanger extends LinearLayout implements Button.OnClickListener { - private static final String LOGTAG = "DoorHanger"; - private Context mContext; private LinearLayout mChoicesLayout; private TextView mTextView; @@ -65,9 +61,6 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener { // value used to identify the notification private String mValue; - // Optional checkbox added underneath message text - private CheckBox mCheckBox; - static private LayoutInflater mInflater; private int mPersistence = 0; @@ -106,18 +99,7 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener { } public void onClick(View v) { - JSONObject response = new JSONObject(); - try { - response.put("callback", v.getTag().toString()); - - // If the checkbox is being used, pass its value - if (mCheckBox != null) - response.put("checked", mCheckBox.isChecked()); - } catch (JSONException ex) { - Log.e(LOGTAG, "Error creating onClick response: " + ex); - } - - GeckoEvent e = GeckoEvent.createBroadcastEvent("Doorhanger:Reply", response.toString()); + GeckoEvent e = GeckoEvent.createBroadcastEvent("Doorhanger:Reply", v.getTag().toString()); GeckoAppShell.sendEventToGecko(e); mTab.removeDoorHanger(mValue); @@ -184,13 +166,6 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener { mTextView.setText(titleWithLink); mTextView.setMovementMethod(LinkMovementMethod.getInstance()); } catch (JSONException e) { } - - try { - String checkBoxText = options.getString("checkbox"); - mCheckBox = (CheckBox) findViewById(R.id.doorhanger_checkbox); - mCheckBox.setText(checkBoxText); - mCheckBox.setVisibility(VISIBLE); - } catch (JSONException e) { } } // This method checks with persistence and timeout options to see if diff --git a/mobile/android/base/resources/layout/doorhanger.xml b/mobile/android/base/resources/layout/doorhanger.xml index 1f851610547..9df165dcdf4 100644 --- a/mobile/android/base/resources/layout/doorhanger.xml +++ b/mobile/android/base/resources/layout/doorhanger.xml @@ -9,12 +9,6 @@ android:textColorLink="@color/doorhanger_link" android:padding="10dp"/> - - - -# ***** BEGIN LICENSE BLOCK ***** -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. -# -# ***** END LICENSE BLOCK ***** - - - %htmlDTD; - - %globalDTD; - - %aboutAppsDTD; - - %browserDTD; -]> - - - - &aboutApps.title; - - - - - - - -
-
&aboutApps.title;
- -
-
-
-
-
-
- - diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 851f1a065f0..c5d740b6bd3 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -236,7 +236,6 @@ var BrowserApp = { CharacterEncoding.init(); SearchEngines.init(); ActivityObserver.init(); - WebappsUI.init(); // Init LoginManager Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); @@ -416,7 +415,6 @@ var BrowserApp = { ConsoleAPI.uninit(); CharacterEncoding.uninit(); SearchEngines.uninit(); - WebappsUI.uninit(); }, // This function returns false during periods where the browser displayed document is @@ -1074,15 +1072,10 @@ var NativeWindow = { if (this.menu._callbacks[aData]) this.menu._callbacks[aData](); } else if (aTopic == "Doorhanger:Reply") { - let data = JSON.parse(aData); - let reply_id = data["callback"]; - + let reply_id = aData; if (this.doorhanger._callbacks[reply_id]) { - // Pass the value of the optional checkbox to the callback - let checked = data["checked"]; - this.doorhanger._callbacks[reply_id].cb(checked); - let prompt = this.doorhanger._callbacks[reply_id].prompt; + this.doorhanger._callbacks[reply_id].cb(); for (let id in this.doorhanger._callbacks) { if (this.doorhanger._callbacks[id].prompt == prompt) { delete this.doorhanger._callbacks[id]; @@ -1286,9 +1279,7 @@ var NativeWindow = { let popupNode = aEvent.originalTarget; let title = ""; - if (popupNode.hasAttribute("title")) { - title = popupNode.getAttribute("title") - } else if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || + if ((popupNode instanceof Ci.nsIDOMHTMLAnchorElement && popupNode.href) || (popupNode instanceof Ci.nsIDOMHTMLAreaElement && popupNode.href)) { title = this._getLinkURL(popupNode); } else if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) { @@ -3914,50 +3905,22 @@ var ClipboardHelper = { var PluginHelper = { showDoorHanger: function(aTab) { - if (!aTab.browser) - return; - - let uri = aTab.browser.currentURI; - - // If the user has previously set a plugins permission for this website, - // either play or don't play the plugins instead of showing a doorhanger. - let permValue = Services.perms.testPermission(uri, "plugins"); - if (permValue != Services.perms.UNKNOWN_ACTION) { - if (permValue == Services.perms.ALLOW_ACTION) - PluginHelper.playAllPlugins(aTab); - - return; - } - - let message = Strings.browser.formatStringFromName("clickToPlayPlugins.message1", - [uri.host], 1); + let message = Strings.browser.GetStringFromName("clickToPlayPlugins.message"); let buttons = [ { label: Strings.browser.GetStringFromName("clickToPlayPlugins.yes"), - callback: function(aChecked) { - // If the user checked "Don't ask again", make a permanent exception - if (aChecked) - Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION); - + callback: function() { PluginHelper.playAllPlugins(aTab); } }, { label: Strings.browser.GetStringFromName("clickToPlayPlugins.no"), - callback: function(aChecked) { - // If the user checked "Don't ask again", make a permanent exception - if (aChecked) - Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.DENY_ACTION); - - // Other than that, do nothing + callback: function() { + // Do nothing } } - ]; - - // Add a checkbox with a "Don't ask again" message - let options = { checkbox: Strings.browser.GetStringFromName("clickToPlayPlugins.dontAskAgain") }; - - NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id, options); + ] + NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id); }, playAllPlugins: function(aTab, aEvent) { @@ -4039,7 +4002,7 @@ var PluginHelper = { var PermissionsHelper = { _permissonTypes: ["password", "geolocation", "popup", "indexedDB", - "offline-app", "desktop-notification", "plugins"], + "offline-app", "desktop-notification"], _permissionStrings: { "password": { label: "password.rememberPassword", @@ -4070,11 +4033,6 @@ var PermissionsHelper = { label: "desktopNotification.useNotifications", allowed: "desktopNotification.allow", denied: "desktopNotification.dontAllow" - }, - "plugins": { - label: "clickToPlayPlugins.playPlugins", - allowed: "clickToPlayPlugins.yes", - denied: "clickToPlayPlugins.no" } }, diff --git a/mobile/android/chrome/content/browser.xul b/mobile/android/chrome/content/browser.xul index f803a05bc79..30aa819f16e 100644 --- a/mobile/android/chrome/content/browser.xul +++ b/mobile/android/chrome/content/browser.xul @@ -9,7 +9,6 @@