From c332098d8541aa99728d94aac487649d5781d92a Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Fri, 2 May 2014 10:01:11 +0200 Subject: [PATCH 01/50] Bug 1004933 - do not use nsVoidArray in nsChromeRegistry; r=bsmedberg --HG-- extra : rebase_source : 56ef377a1c12b3b799cbaab71ab3251b3fbb6aa7 --- chrome/src/nsChromeRegistryChrome.cpp | 27 +++++---------------------- chrome/src/nsChromeRegistryChrome.h | 8 +++----- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/chrome/src/nsChromeRegistryChrome.cpp b/chrome/src/nsChromeRegistryChrome.cpp index 82ab6f4ceda..ec7d3b977ad 100644 --- a/chrome/src/nsChromeRegistryChrome.cpp +++ b/chrome/src/nsChromeRegistryChrome.cpp @@ -614,7 +614,7 @@ nsChromeRegistryChrome::kTableOps = { nsChromeRegistryChrome::ProviderEntry* nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType) { - int32_t i = mArray.Count(); + int32_t i = mArray.Length(); if (!i) return nullptr; @@ -622,7 +622,7 @@ nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferre ProviderEntry* entry; while (i--) { - entry = reinterpret_cast(mArray[i]); + entry = &mArray[i]; if (aPreferred.Equals(entry->provider)) return entry; @@ -677,35 +677,18 @@ nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, ns } // no existing entries, add a new one - provider = new ProviderEntry(aProvider, aBaseURL); - if (!provider) - return; // It's safe to silently fail on OOM - - mArray.AppendElement(provider); + mArray.AppendElement(ProviderEntry(aProvider, aBaseURL)); } void nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray *a) { - int32_t i = mArray.Count(); + int32_t i = mArray.Length(); while (i--) { - ProviderEntry *entry = reinterpret_cast(mArray[i]); - a->AppendElement(entry->provider); + a->AppendElement(mArray[i].provider); } } -void -nsChromeRegistryChrome::nsProviderArray::Clear() -{ - int32_t i = mArray.Count(); - while (i--) { - ProviderEntry* entry = reinterpret_cast(mArray[i]); - delete entry; - } - - mArray.Clear(); -} - void nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI) { diff --git a/chrome/src/nsChromeRegistryChrome.h b/chrome/src/nsChromeRegistryChrome.h index 90eba76b505..f9340d32fc8 100644 --- a/chrome/src/nsChromeRegistryChrome.h +++ b/chrome/src/nsChromeRegistryChrome.h @@ -8,7 +8,7 @@ #include "nsCOMArray.h" #include "nsChromeRegistry.h" -#include "nsVoidArray.h" +#include "nsTArray.h" #include "mozilla/Move.h" namespace mozilla { @@ -85,8 +85,7 @@ class nsChromeRegistryChrome : public nsChromeRegistry public: nsProviderArray() : mArray(1) { } - ~nsProviderArray() - { Clear(); } + ~nsProviderArray() { } // When looking up locales and skins, the "selected" locale is not always // available. This enum identifies what kind of match is desired/found. @@ -100,12 +99,11 @@ class nsChromeRegistryChrome : public nsChromeRegistry const nsACString& GetSelected(const nsACString& aPreferred, MatchType aType); void SetBase(const nsACString& aProvider, nsIURI* base); void EnumerateToArray(nsTArray *a); - void Clear(); private: ProviderEntry* GetProvider(const nsACString& aPreferred, MatchType aType); - nsVoidArray mArray; + nsTArray mArray; }; struct PackageEntry : public PLDHashEntryHdr From a7147dc432b7ab3c7c9c9f81fc2bc1aedbedb4ae Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 28 Apr 2014 16:17:31 +1200 Subject: [PATCH 02/50] Bug 1001845 - Simplify invalid regions to avoid spending excessive amounts of time in region code. r=roc --- gfx/layers/LayerTreeInvalidation.cpp | 2 ++ gfx/layers/basic/BasicThebesLayer.h | 1 + gfx/layers/client/ClientThebesLayer.h | 1 + gfx/layers/d3d10/ThebesLayerD3D10.cpp | 2 +- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gfx/layers/LayerTreeInvalidation.cpp b/gfx/layers/LayerTreeInvalidation.cpp index 8cbf5d59995..2f376af2d11 100644 --- a/gfx/layers/LayerTreeInvalidation.cpp +++ b/gfx/layers/LayerTreeInvalidation.cpp @@ -59,12 +59,14 @@ AddTransformedRegion(nsIntRegion& aDest, const nsIntRegion& aSource, const gfx3D while ((r = iter.Next())) { aDest.Or(aDest, TransformRect(*r, aTransform)); } + aDest.SimplifyOutward(20); } static void AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource) { aDest.Or(aDest, aSource); + aDest.SimplifyOutward(20); } static nsIntRegion diff --git a/gfx/layers/basic/BasicThebesLayer.h b/gfx/layers/basic/BasicThebesLayer.h index a4ba138a8cc..04d7ff862a3 100644 --- a/gfx/layers/basic/BasicThebesLayer.h +++ b/gfx/layers/basic/BasicThebesLayer.h @@ -53,6 +53,7 @@ public: NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); mInvalidRegion.Or(mInvalidRegion, aRegion); + mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } diff --git a/gfx/layers/client/ClientThebesLayer.h b/gfx/layers/client/ClientThebesLayer.h index 7ee9b9c4c8c..098013167ac 100644 --- a/gfx/layers/client/ClientThebesLayer.h +++ b/gfx/layers/client/ClientThebesLayer.h @@ -60,6 +60,7 @@ public: NS_ASSERTION(ClientManager()->InConstruction(), "Can only set properties in construction phase"); mInvalidRegion.Or(mInvalidRegion, aRegion); + mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.cpp b/gfx/layers/d3d10/ThebesLayerD3D10.cpp index 47781cecfdf..e2dcdb94b2b 100644 --- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp +++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp @@ -47,7 +47,7 @@ void ThebesLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion) { mInvalidRegion.Or(mInvalidRegion, aRegion); - mInvalidRegion.SimplifyOutward(10); + mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index f7cb25abdc6..296d2fb259f 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -50,6 +50,7 @@ void ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion) { mInvalidRegion.Or(mInvalidRegion, aRegion); + mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } From 2575422e86f536f30f7f5bc63684ee2019470bd6 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Tue, 6 May 2014 09:45:13 +0000 Subject: [PATCH 03/50] Bug 994592 - Make 'row' the initial value for 'grid-auto-flow' and remove 'none' as a valid value. And add the 'stack' variants. r=simon.sapin --- layout/style/Declaration.cpp | 2 +- layout/style/nsCSSKeywordList.h | 1 + layout/style/nsCSSParser.cpp | 45 ++++++------------- layout/style/nsCSSProps.cpp | 4 +- layout/style/nsCSSValue.cpp | 2 +- layout/style/nsComputedDOMStyle.cpp | 2 +- layout/style/nsRuleNode.cpp | 2 +- layout/style/nsStyleConsts.h | 6 +-- layout/style/nsStyleStruct.cpp | 2 +- layout/style/test/property_database.js | 18 ++++---- .../test/test_grid_container_shorthands.html | 11 +++-- .../test_grid_shorthand_serialization.html | 4 +- 12 files changed, 44 insertions(+), 55 deletions(-) diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index eef5049257b..d946fa1b220 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -994,7 +994,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, aValue, aSerialization); break; } else if (!(autoFlowValue.GetUnit() == eCSSUnit_Enumerated && - autoFlowValue.GetIntValue() == NS_STYLE_GRID_AUTO_FLOW_NONE && + autoFlowValue.GetIntValue() == NS_STYLE_GRID_AUTO_FLOW_ROW && autoColumnsValue.GetUnit() == eCSSUnit_Auto && autoRowsValue.GetUnit() == eCSSUnit_Auto)) { // Not serializable, bail. diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 9c563557769..5f6830593d2 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -508,6 +508,7 @@ CSS_KEY(space-around, space_around) CSS_KEY(space-between, space_between) CSS_KEY(span, span) CSS_KEY(square, square) +CSS_KEY(stack, stack) CSS_KEY(stacked-fractions, stacked_fractions) CSS_KEY(start, start) CSS_KEY(static, static) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index d3d06f72d00..ee319b33698 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -6952,7 +6952,8 @@ CSSParserImpl::ParseGridAutoFlow() } static const int32_t mask[] = { - NS_STYLE_GRID_AUTO_FLOW_COLUMN | NS_STYLE_GRID_AUTO_FLOW_ROW, + NS_STYLE_GRID_AUTO_FLOW_ROW | NS_STYLE_GRID_AUTO_FLOW_COLUMN, + NS_STYLE_GRID_AUTO_FLOW_DENSE | NS_STYLE_GRID_AUTO_FLOW_STACK, MASK_END_VALUE }; if (!ParseBitmaskValues(value, nsCSSProps::kGridAutoFlowKTable, mask)) { @@ -6961,16 +6962,16 @@ CSSParserImpl::ParseGridAutoFlow() int32_t bitField = value.GetIntValue(); // Requires one of these - if (!(bitField & NS_STYLE_GRID_AUTO_FLOW_NONE || + if (!(bitField & NS_STYLE_GRID_AUTO_FLOW_ROW || bitField & NS_STYLE_GRID_AUTO_FLOW_COLUMN || - bitField & NS_STYLE_GRID_AUTO_FLOW_ROW)) { + bitField & NS_STYLE_GRID_AUTO_FLOW_STACK)) { return false; } - // 'none' is only valid if it occurs alone: - if (bitField & NS_STYLE_GRID_AUTO_FLOW_NONE && - bitField != NS_STYLE_GRID_AUTO_FLOW_NONE) { - return false; + // 'stack' without 'row' or 'column' defaults to 'stack row' + if (bitField == NS_STYLE_GRID_AUTO_FLOW_STACK) { + value.SetIntValue(bitField | NS_STYLE_GRID_AUTO_FLOW_ROW, + eCSSUnit_Enumerated); } AppendValue(eCSSProperty_grid_auto_flow, value); @@ -7825,37 +7826,17 @@ CSSParserImpl::ParseGrid() return true; } - // 'none' at the beginning could be a <'grid-auto-flow'> - // (which also covers 'none' by itself) - // or a <'grid-template-columns'> (as part of <'grid-template'>) - if (ParseVariant(value, VARIANT_NONE, nullptr)) { - if (ExpectSymbol('/', true)) { - AppendValue(eCSSProperty_grid_template_columns, value); - - // Set grid-auto-* subproperties to their initial values. - value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_NONE, eCSSUnit_Enumerated); - AppendValue(eCSSProperty_grid_auto_flow, value); - value.SetAutoValue(); - AppendValue(eCSSProperty_grid_auto_columns, value); - AppendValue(eCSSProperty_grid_auto_rows, value); - - return ParseGridTemplateAfterSlash(/* aColumnsIsTrackList = */ false); - } - value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_NONE, eCSSUnit_Enumerated); - AppendValue(eCSSProperty_grid_auto_flow, value); - return ParseGridShorthandAutoProps(); - } - // An empty value is always invalid. if (!GetToken(true)) { return false; } - // If the value starts with a 'dense', 'column' or 'row' keyword, - // it can only start with a <'grid-auto-flow'> + // The values starts with a <'grid-auto-flow'> if and only if + // it starts with a 'stack', 'dense', 'column' or 'row' keyword. if (mToken.mType == eCSSToken_Ident) { nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent); - if (keyword == eCSSKeyword_dense || + if (keyword == eCSSKeyword_stack || + keyword == eCSSKeyword_dense || keyword == eCSSKeyword_column || keyword == eCSSKeyword_row) { UngetToken(); @@ -7866,7 +7847,7 @@ CSSParserImpl::ParseGrid() // Set other subproperties to their initial values // and parse <'grid-template'>. - value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_NONE, eCSSUnit_Enumerated); + value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_ROW, eCSSUnit_Enumerated); AppendValue(eCSSProperty_grid_auto_flow, value); value.SetAutoValue(); AppendValue(eCSSProperty_grid_auto_columns, value); diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 47792b1d309..45a54881832 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -1238,9 +1238,9 @@ const KTableValue nsCSSProps::kFontWeightKTable[] = { }; const KTableValue nsCSSProps::kGridAutoFlowKTable[] = { - eCSSKeyword_none, NS_STYLE_GRID_AUTO_FLOW_NONE, - eCSSKeyword_column, NS_STYLE_GRID_AUTO_FLOW_COLUMN, + eCSSKeyword_stack, NS_STYLE_GRID_AUTO_FLOW_STACK, eCSSKeyword_row, NS_STYLE_GRID_AUTO_FLOW_ROW, + eCSSKeyword_column, NS_STYLE_GRID_AUTO_FLOW_COLUMN, eCSSKeyword_dense, NS_STYLE_GRID_AUTO_FLOW_DENSE, eCSSKeyword_UNKNOWN,-1 }; diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index bd9747590e3..8e84413a2f6 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -1032,7 +1032,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult, case eCSSProperty_grid_auto_flow: nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue, - NS_STYLE_GRID_AUTO_FLOW_NONE, + NS_STYLE_GRID_AUTO_FLOW_STACK, NS_STYLE_GRID_AUTO_FLOW_DENSE, aResult); break; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index c1eb96592fa..6f299aa9810 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -2398,7 +2398,7 @@ nsComputedDOMStyle::DoGetGridAutoFlow() nsAutoString str; nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_grid_auto_flow, StylePosition()->mGridAutoFlow, - NS_STYLE_GRID_AUTO_FLOW_NONE, + NS_STYLE_GRID_AUTO_FLOW_STACK, NS_STYLE_GRID_AUTO_FLOW_DENSE, str); nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue; diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 4c45bcfe5ef..d05a83cf33e 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -7505,7 +7505,7 @@ nsRuleNode::ComputePositionData(void* aStartStruct, break; case eCSSUnit_Initial: case eCSSUnit_Unset: - pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_NONE; + pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW; break; default: NS_ASSERTION(gridAutoFlow.GetUnit() == eCSSUnit_Enumerated, diff --git a/layout/style/nsStyleConsts.h b/layout/style/nsStyleConsts.h index 0e6a0cab1ae..3f166d7b559 100644 --- a/layout/style/nsStyleConsts.h +++ b/layout/style/nsStyleConsts.h @@ -544,9 +544,9 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_FONT_FIELD 16 // grid-auto-flow keywords -#define NS_STYLE_GRID_AUTO_FLOW_NONE (1 << 0) -#define NS_STYLE_GRID_AUTO_FLOW_COLUMN (1 << 1) -#define NS_STYLE_GRID_AUTO_FLOW_ROW (1 << 2) +#define NS_STYLE_GRID_AUTO_FLOW_STACK (1 << 0) +#define NS_STYLE_GRID_AUTO_FLOW_ROW (1 << 1) +#define NS_STYLE_GRID_AUTO_FLOW_COLUMN (1 << 2) #define NS_STYLE_GRID_AUTO_FLOW_DENSE (1 << 3) // 'subgrid' keyword in grid-template-{columns,rows} diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 3a3ecc1b55e..a543954c5b5 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1243,7 +1243,7 @@ nsStylePosition::nsStylePosition(void) mGridAutoRowsMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT, eStyleUnit_Enumerated); - mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_NONE; + mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW; mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT; mAlignContent = NS_STYLE_ALIGN_CONTENT_STRETCH; mAlignItems = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE; diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index fa20f3abeab..0c1cc83c58e 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -4802,22 +4802,26 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) { domProp: "gridAutoFlow", inherited: false, type: CSS_TYPE_LONGHAND, - initial_values: [ "none" ], + initial_values: [ "row" ], other_values: [ "column", - "row", "column dense", "row dense", "dense column", "dense row", + "stack column", + "stack row", + "stack", ], invalid_values: [ "", "auto", + "none", "10px", "dense", - "none row", - "none dense", + "stack dense", + "stack stack", + "stack row stack", "column row", "dense row dense", ] @@ -5046,12 +5050,9 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) { initial_values: [ "none", "none / none", - "none auto", - "none auto / auto", ], other_values: [ - "row", - "none 40px", + "stack 40px", "column dense auto", "dense row minmax(min-content, 2fr)", "row 40px / 100px", @@ -5067,6 +5068,7 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) { ].concat( gCSSProperties["grid-template"].invalid_values, gCSSProperties["grid-auto-flow"].invalid_values + .filter((v) => v != 'none') ) }; diff --git a/layout/style/test/test_grid_container_shorthands.html b/layout/style/test/test_grid_container_shorthands.html index 22ca8aa76a7..23a412d8927 100644 --- a/layout/style/test/test_grid_container_shorthands.html +++ b/layout/style/test/test_grid_container_shorthands.html @@ -16,7 +16,7 @@ var initial_values = { gridTemplateAreas: "none", gridTemplateColumns: "none", gridTemplateRows: "none", - gridAutoFlow: "none", + gridAutoFlow: "row", // Computed value for 'auto' gridAutoColumns: "minmax(min-content, max-content)", gridAutoRows: "minmax(min-content, max-content)", @@ -179,8 +179,13 @@ grid_test_cases = grid_template_test_cases.concat([ gridAutoFlow: "row", }, { - specified: "none 40px", - gridAutoFlow: "none", + specified: "stack 40px", + gridAutoFlow: "stack row", + gridAutoColumns: "40px", + }, + { + specified: "stack column 40px", + gridAutoFlow: "stack column", gridAutoColumns: "40px", }, { diff --git a/layout/style/test/test_grid_shorthand_serialization.html b/layout/style/test/test_grid_shorthand_serialization.html index e8f37367e91..d2d34d69282 100644 --- a/layout/style/test/test_grid_shorthand_serialization.html +++ b/layout/style/test/test_grid_shorthand_serialization.html @@ -16,7 +16,7 @@ var initial_values = { gridTemplateAreas: "none", gridTemplateColumns: "none", gridTemplateRows: "none", - gridAutoFlow: "none", + gridAutoFlow: "row", gridAutoColumns: "auto", gridAutoRows: "auto", }; @@ -88,7 +88,7 @@ grid_test_cases = grid_template_test_cases.concat([ }, { gridAutoColumns: "40px", - shorthand: "none 40px / auto", + shorthand: "row 40px / auto", }, { gridAutoFlow: "column dense", From a023718b82606be863aa14baa6bc0a3626f43c63 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Tue, 6 May 2014 09:45:13 +0000 Subject: [PATCH 04/50] Bug 1005567 - Remove the obsolete 'grid-auto-position' property. r=simon.sapin --- .../devtools/sourceeditor/codemirror/css.js | 2 +- layout/style/nsCSSParser.cpp | 23 --------- layout/style/nsCSSPropList.h | 10 ---- layout/style/nsCSSValue.cpp | 5 -- layout/style/nsComputedDOMStyle.cpp | 18 ------- layout/style/nsComputedDOMStyle.h | 1 - layout/style/nsComputedDOMStylePropertyList.h | 1 - layout/style/nsRuleNode.cpp | 27 ---------- layout/style/nsStyleStruct.cpp | 6 --- layout/style/nsStyleStruct.h | 4 -- layout/style/test/property_database.js | 51 +++++-------------- 11 files changed, 14 insertions(+), 134 deletions(-) diff --git a/browser/devtools/sourceeditor/codemirror/css.js b/browser/devtools/sourceeditor/codemirror/css.js index f8fc5cea219..c87518a191b 100644 --- a/browser/devtools/sourceeditor/codemirror/css.js +++ b/browser/devtools/sourceeditor/codemirror/css.js @@ -404,7 +404,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position", "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", - "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end", + "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-start", "grid-row", "grid-row-end", "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns", "grid-template-rows", "hanging-punctuation", "height", "hyphens", diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index ee319b33698..d0da89507bf 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -694,7 +694,6 @@ protected: bool ParseGrid(); bool ParseGridShorthandAutoProps(); bool ParseGridLine(nsCSSValue& aValue); - bool ParseGridAutoPosition(); bool ParseGridColumnRowStartEnd(nsCSSProperty aPropID); bool ParseGridColumnRow(nsCSSProperty aStartPropID, nsCSSProperty aEndPropID); @@ -7991,26 +7990,6 @@ CSSParserImpl::ParseGridLine(nsCSSValue& aValue) return true; } -bool -CSSParserImpl::ParseGridAutoPosition() -{ - nsCSSValue value; - if (ParseVariant(value, VARIANT_INHERIT, nullptr)) { - AppendValue(eCSSProperty_grid_auto_position, value); - return true; - } - nsCSSValue columnStartValue; - nsCSSValue rowStartValue; - if (ParseGridLine(columnStartValue) && - ExpectSymbol('/', true) && - ParseGridLine(rowStartValue)) { - value.SetPairValue(columnStartValue, rowStartValue); - AppendValue(eCSSProperty_grid_auto_position, value); - return true; - } - return false; -} - bool CSSParserImpl::ParseGridColumnRowStartEnd(nsCSSProperty aPropID) { @@ -9160,8 +9139,6 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID) return ParseGridTemplate(); case eCSSProperty_grid: return ParseGrid(); - case eCSSProperty_grid_auto_position: - return ParseGridAutoPosition(); case eCSSProperty_grid_column_start: case eCSSProperty_grid_column_end: case eCSSProperty_grid_row_start: diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index cae2fce55d6..6311ac74082 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2034,16 +2034,6 @@ CSS_PROP_POSITION( kGridTrackBreadthKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_None) -CSS_PROP_POSITION( - grid-auto-position, - grid_auto_position, - GridAutoPosition, - CSS_PROPERTY_PARSE_FUNCTION, - "layout.css.grid.enabled", - 0, - nullptr, - CSS_PROP_NO_OFFSET, - eStyleAnimType_None) CSS_PROP_POSITION( grid-template-areas, grid_template_areas, diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index 8e84413a2f6..27dc9e04783 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -1037,7 +1037,6 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult, aResult); break; - case eCSSProperty_grid_auto_position: case eCSSProperty_grid_column_start: case eCSSProperty_grid_column_end: case eCSSProperty_grid_row_start: @@ -1326,10 +1325,6 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult, nsStyleUtil::ComputeFunctionalAlternates(list, altValues); nsStyleUtil::SerializeFunctionalAlternates(altValues, out); aResult.Append(out); - } else if (eCSSProperty_grid_auto_position == aProperty) { - GetPairValue().mXValue.AppendToString(aProperty, aResult, aSerialization); - aResult.AppendLiteral(" / "); - GetPairValue().mYValue.AppendToString(aProperty, aResult, aSerialization); } else { GetPairValue().AppendToString(aProperty, aResult, aSerialization); } diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 6f299aa9810..daff16e9cd4 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -2468,24 +2468,6 @@ nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine) return valueList; } -CSSValue* -nsComputedDOMStyle::DoGetGridAutoPosition() -{ - nsDOMCSSValueList* valueList = GetROCSSValueList(false); - - valueList->AppendCSSValue( - GetGridLine(StylePosition()->mGridAutoPositionColumn)); - - nsROCSSPrimitiveValue* slash = new nsROCSSPrimitiveValue; - slash->SetString(NS_LITERAL_STRING("/")); - valueList->AppendCSSValue(slash); - - valueList->AppendCSSValue( - GetGridLine(StylePosition()->mGridAutoPositionRow)); - - return valueList; -} - CSSValue* nsComputedDOMStyle::DoGetGridColumnStart() { diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 48183456dd2..9576a3b4ed1 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -268,7 +268,6 @@ private: mozilla::dom::CSSValue* DoGetGridAutoFlow(); mozilla::dom::CSSValue* DoGetGridAutoColumns(); mozilla::dom::CSSValue* DoGetGridAutoRows(); - mozilla::dom::CSSValue* DoGetGridAutoPosition(); mozilla::dom::CSSValue* DoGetGridTemplateAreas(); mozilla::dom::CSSValue* DoGetGridTemplateColumns(); mozilla::dom::CSSValue* DoGetGridTemplateRows(); diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h index c66cc7c692d..eea77d1b891 100644 --- a/layout/style/nsComputedDOMStylePropertyList.h +++ b/layout/style/nsComputedDOMStylePropertyList.h @@ -132,7 +132,6 @@ COMPUTED_STYLE_PROP(font_variant_position, FontVariantPosition) COMPUTED_STYLE_PROP(font_weight, FontWeight) COMPUTED_STYLE_PROP(grid_auto_columns, GridAutoColumns) COMPUTED_STYLE_PROP(grid_auto_flow, GridAutoFlow) -COMPUTED_STYLE_PROP(grid_auto_position, GridAutoPosition) COMPUTED_STYLE_PROP(grid_auto_rows, GridAutoRows) COMPUTED_STYLE_PROP(grid_column_end, GridColumnEnd) COMPUTED_STYLE_PROP(grid_column_start, GridColumnStart) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index d05a83cf33e..12aec2a2eeb 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -7545,33 +7545,6 @@ nsRuleNode::ComputePositionData(void* aStartStruct, parentPos->mGridTemplateAreas, canStoreInRuleTree); - // grid-auto-position - const nsCSSValue& gridAutoPosition = *aRuleData->ValueForGridAutoPosition(); - switch (gridAutoPosition.GetUnit()) { - case eCSSUnit_Null: - break; - case eCSSUnit_Inherit: - canStoreInRuleTree = false; - pos->mGridAutoPositionColumn = parentPos->mGridAutoPositionColumn; - pos->mGridAutoPositionRow = parentPos->mGridAutoPositionRow; - break; - case eCSSUnit_Initial: - case eCSSUnit_Unset: - // '1 / 1' - pos->mGridAutoPositionColumn.SetToInteger(1); - pos->mGridAutoPositionRow.SetToInteger(1); - break; - default: - SetGridLine(gridAutoPosition.GetPairValue().mXValue, - pos->mGridAutoPositionColumn, - parentPos->mGridAutoPositionColumn, - canStoreInRuleTree); - SetGridLine(gridAutoPosition.GetPairValue().mYValue, - pos->mGridAutoPositionRow, - parentPos->mGridAutoPositionRow, - canStoreInRuleTree); - } - // grid-column-start SetGridLine(*aRuleData->ValueForGridColumnStart(), pos->mGridColumnStart, diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index a543954c5b5..839b753f3ed 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1255,8 +1255,6 @@ nsStylePosition::nsStylePosition(void) mFlexGrow = 0.0f; mFlexShrink = 1.0f; mZIndex.SetAutoValue(); - mGridAutoPositionColumn.SetToInteger(1); - mGridAutoPositionRow.SetToInteger(1); // Other members get their default constructors // which initialize them to representations of their respective initial value. // mGridTemplateAreas: nullptr for 'none' @@ -1273,8 +1271,6 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource) : mGridTemplateColumns(aSource.mGridTemplateColumns) , mGridTemplateRows(aSource.mGridTemplateRows) , mGridTemplateAreas(aSource.mGridTemplateAreas) - , mGridAutoPositionColumn(aSource.mGridAutoPositionColumn) - , mGridAutoPositionRow(aSource.mGridAutoPositionRow) , mGridColumnStart(aSource.mGridColumnStart) , mGridColumnEnd(aSource.mGridColumnEnd) , mGridRowStart(aSource.mGridRowStart) @@ -1292,8 +1288,6 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource) sizeof(mGridTemplateColumns) + sizeof(mGridTemplateRows) + sizeof(mGridTemplateAreas) + - sizeof(mGridAutoPositionColumn) + - sizeof(mGridAutoPositionRow) + sizeof(mGridColumnStart) + sizeof(mGridColumnEnd) + sizeof(mGridRowStart) + diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 5e05bf83282..f6396a3b0bf 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1316,10 +1316,6 @@ struct nsStylePosition { // nullptr for 'none' nsRefPtr mGridTemplateAreas; - // We represent the "grid-auto-position" property in two parts: - nsStyleGridLine mGridAutoPositionColumn; - nsStyleGridLine mGridAutoPositionRow; - nsStyleGridLine mGridColumnStart; nsStyleGridLine mGridColumnEnd; nsStyleGridLine mGridRowStart; diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 0c1cc83c58e..96fa14e8ee7 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -5146,46 +5146,21 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) { invalid_values: gridLineInvalidValues }; - var gridAutoPositionOtherValues = []; - gridLineOtherValues.concat([ "auto" ]).forEach(function(val) { - gridAutoPositionOtherValues.push(" foo / " + val); - gridAutoPositionOtherValues.push(val + "/2"); - }); - var gridAutoPositionInvalidValues = [ - "foo", - "foo, bar", - "foo / bar / baz", - ]; - gridLineInvalidValues.forEach(function(val) { - gridAutoPositionInvalidValues.push("span 3 / " + val); - gridAutoPositionInvalidValues.push(val + " / foo"); - }); - gCSSProperties["grid-auto-position"] = { - domProp: "gridAutoPosition", - inherited: false, - type: CSS_TYPE_LONGHAND, - initial_values: [ "1 / 1" ], - other_values: gridAutoPositionOtherValues, - invalid_values: gridAutoPositionInvalidValues - }; - // The grid-column and grid-row shorthands take values of the form // [ / ]? - // which is equivalent to: - // | [ / ] - // which is equivalent to: - // | <'grid-auto-position'> - var gridColumnRowOtherValues = [].concat( - gridLineOtherValues, - gridAutoPositionOtherValues); - var gridColumnRowInvalidValues = [].concat( - gridLineInvalidValues, - gridAutoPositionInvalidValues); - // A single is invalid for grid-auto-position, - // but not for grid-column or grid-row: - gridColumnRowInvalidValues.splice( - gridColumnRowInvalidValues.indexOf("foo"), - 1); + var gridColumnRowOtherValues = [].concat(gridLineOtherValues); + gridLineOtherValues.concat([ "auto" ]).forEach(function(val) { + gridColumnRowOtherValues.push(" foo / " + val); + gridColumnRowOtherValues.push(val + "/2"); + }); + var gridColumnRowInvalidValues = [ + "foo, bar", + "foo / bar / baz", + ].concat(gridLineInvalidValues); + gridLineInvalidValues.forEach(function(val) { + gridColumnRowInvalidValues.push("span 3 / " + val); + gridColumnRowInvalidValues.push(val + " / foo"); + }); gCSSProperties["grid-column"] = { domProp: "gridColumn", inherited: false, From b7694df1607a530682fb75be2cf084df15c7747e Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 6 May 2014 10:50:12 +0100 Subject: [PATCH 05/50] Bug 1004814 - console.time/timeEnd work in workers, r=bz --- dom/base/Console.cpp | 28 ++++++++++----- dom/tests/browser/browser.ini | 3 ++ dom/tests/browser/browser_bug1004814.js | 46 +++++++++++++++++++++++++ dom/tests/browser/test_bug1004814.html | 14 ++++++++ dom/tests/browser/worker_bug1004814.js | 6 ++++ dom/workers/WorkerPrivate.cpp | 3 +- dom/workers/WorkerPrivate.h | 6 ++++ 7 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 dom/tests/browser/browser_bug1004814.js create mode 100644 dom/tests/browser/test_bug1004814.html create mode 100644 dom/tests/browser/worker_bug1004814.js diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index 53545689c9a..48b35ccef66 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -900,17 +900,27 @@ Console::Method(JSContext* aCx, MethodName aMethodName, } // Monotonic timer for 'time' and 'timeEnd' - if ((aMethodName == MethodTime || aMethodName == MethodTimeEnd) && mWindow) { - nsGlobalWindow *win = static_cast(mWindow.get()); - MOZ_ASSERT(win); + if ((aMethodName == MethodTime || aMethodName == MethodTimeEnd)) { + if (mWindow) { + nsGlobalWindow *win = static_cast(mWindow.get()); + MOZ_ASSERT(win); - ErrorResult rv; - nsRefPtr performance = win->GetPerformance(rv); - if (rv.Failed()) { - return; + ErrorResult rv; + nsRefPtr performance = win->GetPerformance(rv); + if (rv.Failed()) { + return; + } + + callData->mMonotonicTimer = performance->Now(); + } else { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + + TimeDuration duration = + mozilla::TimeStamp::Now() - workerPrivate->CreationTimeStamp(); + + callData->mMonotonicTimer = duration.ToMilliseconds(); } - - callData->mMonotonicTimer = performance->Now(); } // The operation is completed. RAII class has to be disabled. diff --git a/dom/tests/browser/browser.ini b/dom/tests/browser/browser.ini index c377494268e..1ea02bf58d1 100644 --- a/dom/tests/browser/browser.ini +++ b/dom/tests/browser/browser.ini @@ -6,6 +6,8 @@ support-files = network_geolocation.sjs page_privatestorageevent.html test-console-api.html + test_bug1004814.html + worker_bug1004814.js [browser_test__content.js] [browser_ConsoleAPITests.js] @@ -30,3 +32,4 @@ support-files = [browser_webapps_perms_reinstall.js] disabled = re-enable when bug 794920 is fixed [browser_xhr_sandbox.js] +[browser_bug1004814.js] diff --git a/dom/tests/browser/browser_bug1004814.js b/dom/tests/browser/browser_bug1004814.js new file mode 100644 index 00000000000..0b6f79a3053 --- /dev/null +++ b/dom/tests/browser/browser_bug1004814.js @@ -0,0 +1,46 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* 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/. */ + +const TEST_URI = "http://example.com/browser/dom/tests/browser/test_bug1004814.html"; + +function test() { + waitForExplicitFinish(); + + ConsoleObserver.init(); + + var tab = gBrowser.addTab(TEST_URI); + gBrowser.selectedTab = tab; + + registerCleanupFunction(function () { + gBrowser.removeTab(tab); + }); +} + +var ConsoleObserver = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), + + init: function() { + Services.obs.addObserver(this, "console-api-log-event", false); + }, + + destroy: function() { + Services.obs.removeObserver(this, "console-api-log-event"); + }, + + observe: function(aSubject, aTopic, aData) { + var obj = aSubject.wrappedJSObject; + if (obj.arguments.length != 1 || obj.arguments[0] != 'bug1004814' || + obj.level != 'timeEnd') { + return; + } + + ok("timer" in obj, "ConsoleEvent contains 'timer' property"); + ok("duration" in obj.timer, "ConsoleEvent.timer contains 'duration' property"); + ok(obj.timer.duration > 0, "ConsoleEvent.timer.duration > 0: " + obj.timer.duration + " ~ 200ms"); + + this.destroy(); + finish(); + } +}; diff --git a/dom/tests/browser/test_bug1004814.html b/dom/tests/browser/test_bug1004814.html new file mode 100644 index 00000000000..64d056ecfd8 --- /dev/null +++ b/dom/tests/browser/test_bug1004814.html @@ -0,0 +1,14 @@ + + + + Console API test bug 1004814 + + + + + diff --git a/dom/tests/browser/worker_bug1004814.js b/dom/tests/browser/worker_bug1004814.js new file mode 100644 index 00000000000..f49fe8dc8c3 --- /dev/null +++ b/dom/tests/browser/worker_bug1004814.js @@ -0,0 +1,6 @@ +onmessage = function(evt) { + console.time('bug1004814'); + setTimeout(function() { + console.timeEnd('bug1004814'); + }, 200); +} diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 23510ffd383..6c8355487b2 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -2111,7 +2111,8 @@ WorkerPrivateParent::WorkerPrivateParent( mSharedWorkerName(aSharedWorkerName), mBusyCount(0), mMessagePortSerial(0), mParentStatus(Pending), mParentSuspended(false), mIsChromeWorker(aIsChromeWorker), mMainThreadObjectsForgotten(false), - mWorkerType(aWorkerType) + mWorkerType(aWorkerType), + mCreationTimeStamp(TimeStamp::Now()) { SetIsDOMBinding(); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 625428d5dd3..f8922b71404 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -241,6 +241,7 @@ private: bool mIsChromeWorker; bool mMainThreadObjectsForgotten; WorkerType mWorkerType; + TimeStamp mCreationTimeStamp; protected: // The worker is owned by its thread, which is represented here. This is set @@ -508,6 +509,11 @@ public: return mLoadInfo.mResolvedScriptURI; } + TimeStamp CreationTimeStamp() const + { + return mCreationTimeStamp; + } + nsIPrincipal* GetPrincipal() const { From eb0730a6143b0796aa4e5650a900e0aaa9004091 Mon Sep 17 00:00:00 2001 From: juhsu Date: Mon, 28 Apr 2014 15:39:03 +0800 Subject: [PATCH 06/50] Bug 969779 - Use SpecialPowers to enable preference setting in oop. r=seth * * * 1. Use |SpecialPowers.pushPrefEnv| to enable preference setting in oop. 2. Set the time of redrawing to be the time right after the image is discarded. 3. Modify the assertion to make the comparison non-trivial. 4. Remove . 5. Move drawCanvas() on the image loadComplete. --HG-- extra : amend_source : 2c9b4164ed5f10242cf4e7c4a784579706b91a21 --- image/test/mochitest/mochitest.ini | 1 - image/test/mochitest/test_bug399925.html | 84 +++++++++++++----------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/image/test/mochitest/mochitest.ini b/image/test/mochitest/mochitest.ini index d5cc633c5cc..0ead0dbecfe 100644 --- a/image/test/mochitest/mochitest.ini +++ b/image/test/mochitest/mochitest.ini @@ -59,7 +59,6 @@ support-files = [test_ImageContentLoaded.html] [test_bug399925.html] -skip-if = e10s || buildapp == 'b2g' #Bug 969779 - should set preference via SpecialPowers.pushPrefEnv() # [test_bug435296.html] # disabled - See bug 578591 [test_bug466586.html] diff --git a/image/test/mochitest/test_bug399925.html b/image/test/mochitest/test_bug399925.html index b738384e4c0..06497c381b6 100644 --- a/image/test/mochitest/test_bug399925.html +++ b/image/test/mochitest/test_bug399925.html @@ -13,7 +13,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=399925 Mozilla Bug 399925

@@ -21,56 +20,61 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=399925
 
 /** Test for Bug 399925. **/
 var pngResults = new Array();
-var oldTimeoutPref;
-var oldDiscardPref;
 SimpleTest.waitForExplicitFinish();
-window.onload = runTest;
 
-function runTest()
-{
-  // Get the old discard timeout
-  oldTimeoutPref = getImagePref(DISCARD_TIMEOUT_PREF);
-
-  // We're testing discarding here, so we should make sure it's flipped on
-  oldDiscardPref = getImagePref(DISCARD_ENABLED_PREF);
-
-  // Enable Discarding
-  setImagePref(DISCARD_ENABLED_PREF, true);
-
-  // Sets the discard timer to 500ms so we don't have to wait so long. The
-  // actual time is nondeterministic, but is bounded by 2 * timer = 1 second.
-  setImagePref(DISCARD_TIMEOUT_PREF, 1000);
+window.onload = function() {
+  // 1. Enable Discarding
+  // 2. Sets the discard timer to 500ms so we don't have to wait so long. The
+  //    actual time is nondeterministic, but is bounded by 2 * timer = 1 second.
+  SpecialPowers.pushPrefEnv({
+    'set':[['image.mem.discardable',true],
+           ['image.mem.min_discard_timeout_ms',1000]]
+  }, runTest);
+}
 
+function runTest() {
   // Create the image _after_ setting the discard timer pref
   var image = new Image();
   image.setAttribute("id", "gif");
   image.src = "bug399925.gif";
   document.getElementById("content").appendChild(image);
 
-  // draw the canvas once
-  drawCanvas();
-
-  // Set the timeout to draw it after discard
-  setTimeout('drawCanvas(); allDone();', 3000);
-}
-
-function drawCanvas()
-{
-    var canvas = document.getElementById('canvas');
-    var context = canvas.getContext('2d');
-    var gif = document.getElementById('gif');
-
-    context.drawImage(gif, 0, 0);
-    ok(true, "we got through the drawImage call without an exception being thrown");
-    pngResults.push(canvas.toDataURL);
-}
-
-function allDone()
-{
+  // 1. Draw the canvas once on loadComplete
+  // 2. Redraw the canvas and compare the results right on discard
+  addCallbacks(image, drawCanvas, function() {
+    drawCanvas();
     is(pngResults[0], pngResults[1], "got different rendered results");
-    setImagePref(DISCARD_TIMEOUT_PREF, oldTimeoutPref);
-    setImagePref(DISCARD_ENABLED_PREF, oldDiscardPref);
     SimpleTest.finish();
+  });
+}
+
+function addCallbacks(anImage, loadCompleteCallback, discardCallback) {
+  var observer = new ImageDecoderObserverStub();
+  observer.discard = function () {
+    imgLoadingContent.removeObserver(scriptedObserver);
+    discardCallback();
+  }
+  observer.loadComplete = loadCompleteCallback;
+  observer = SpecialPowers.wrapCallbackObject(observer);
+
+  var scriptedObserver = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
+                           .getService(SpecialPowers.Ci.imgITools)
+                           .createScriptedObserver(observer);
+
+  var imgLoadingContent =
+    SpecialPowers.wrap(anImage)
+                 .QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent);
+  imgLoadingContent.addObserver(scriptedObserver);
+}
+
+function drawCanvas() {
+  var canvas = document.getElementById('canvas');
+  var context = canvas.getContext('2d');
+  var gif = document.getElementById('gif');
+
+  context.drawImage(gif, 0, 0);
+  ok(true, "we got through the drawImage call without an exception being thrown");
+  pngResults.push(canvas.toDataURL());
 }
 
 

From 4d42e4ced65931efa6362e89a0cf7950d68cd98c Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Fri, 25 Apr 2014 13:34:42 +0300
Subject: [PATCH 07/50] Bug 1000959 - nsHTMLEditor.cpp cleanup; r=ehsan

---
 editor/libeditor/html/nsHTMLDataTransfer.cpp |   7 +-
 editor/libeditor/html/nsHTMLEditRules.cpp    |  33 ++--
 editor/libeditor/html/nsHTMLEditor.cpp       | 170 ++++++++++---------
 editor/libeditor/html/nsHTMLEditor.h         |   2 +
 editor/libeditor/text/nsTextEditUtils.cpp    |   7 +
 editor/libeditor/text/nsTextEditUtils.h      |   1 +
 6 files changed, 117 insertions(+), 103 deletions(-)

diff --git a/editor/libeditor/html/nsHTMLDataTransfer.cpp b/editor/libeditor/html/nsHTMLDataTransfer.cpp
index 55e4dd22a2d..dc928445f8d 100644
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -568,10 +568,9 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
           curNode->GetFirstChild(getter_AddRefs(child));
         }
 
-      }
-      // Check for pre's going into pre's.
-      else if (nsHTMLEditUtils::IsPre(parentBlock) && nsHTMLEditUtils::IsPre(curNode))
-      {
+      } else if (parentBlock && nsHTMLEditUtils::IsPre(parentBlock) &&
+                 nsHTMLEditUtils::IsPre(curNode)) {
+        // Check for pre's going into pre's.
         nsCOMPtr child, tmp;
         curNode->GetFirstChild(getter_AddRefs(child));
         while (child)
diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp
index 6782904452b..7d8f79b3278 100644
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1275,8 +1275,7 @@ nsHTMLEditRules::WillInsert(nsISelection *aSelection, bool *aCancel)
     NS_ENSURE_STATE(mHTMLEditor);
     block2 = mHTMLEditor->GetBlockNodeParent(priorNode);
   
-    if (block1 == block2)
-    {
+    if (block1 && block1 == block2) {
       // if we are here then the selection is right after a mozBR
       // that is in the same block as the selection.  We need to move
       // the selection start to be before the mozBR.
@@ -2392,8 +2391,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
       }
         
       // are endpoint block parents the same?  use default deletion
-      if (leftParent == rightParent) 
-      {
+      if (leftParent && leftParent == rightParent) {
         NS_ENSURE_STATE(mHTMLEditor);
         res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
       }
@@ -2692,6 +2690,7 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
     nsCOMPtr realRight = mHTMLEditor->GetBlockNodeParent(aRightBlock);
     aRightBlock = realRight;
   }
+  NS_ENSURE_STATE(aLeftBlock && aRightBlock);
 
   // bail if both blocks the same
   if (aLeftBlock == aRightBlock) {
@@ -5089,18 +5088,20 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
   else
     block = mHTMLEditor->GetBlockNodeParent(aStartNode);
   bool bIsEmptyNode;
-  if (block != aBodyNode)  // efficiency hack. avoiding IsEmptyNode() call when in body
-  {
+  if (block && block != aBodyNode) {
+    // efficiency hack. avoiding IsEmptyNode() call when in body
     NS_ENSURE_STATE(mHTMLEditor);
     res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
     NS_ENSURE_SUCCESS(res, res);
-    while (bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(block) && (block != aBodyNode))
-    {
+    while (block && bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(block) &&
+           block != aBodyNode) {
       emptyBlock = block;
       block = mHTMLEditor->GetBlockNodeParent(emptyBlock);
       NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
-      NS_ENSURE_SUCCESS(res, res);
+      if (block) {
+        res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
+        NS_ENSURE_SUCCESS(res, res);
+      }
     }
   }
 
@@ -5284,6 +5285,7 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection)
   NS_ENSURE_SUCCESS(res, res);
   if (!IsBlockNode(selCommon))
     selCommon = nsHTMLEditor::GetBlockNodeParent(selCommon);
+  NS_ENSURE_STATE(selCommon);
 
   // set up for loops and cache our root element
   bool stillLooking = true;
@@ -5395,7 +5397,10 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection)
     
     // check if block is entirely inside range
     nsCOMPtr brContentBlock = do_QueryInterface(brBlock);
-    res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore, &nodeAfter);
+    if (brContentBlock) {
+      res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore,
+                                        &nodeAfter);
+    }
     
     // if block isn't contained, forgo grabbing the br in the expanded selection
     if (nodeBefore || nodeAfter)
@@ -7200,8 +7205,7 @@ nsHTMLEditRules::RemoveBlockStyle(nsCOMArray& arrayOfNodes)
       }
       NS_ENSURE_STATE(mHTMLEditor);
       curBlock = mHTMLEditor->GetBlockNodeParent(curNode);
-      if (nsHTMLEditUtils::IsFormatNode(curBlock))
-      {
+      if (curBlock && nsHTMLEditUtils::IsFormatNode(curBlock)) {
         firstNode = curNode;  
         lastNode = curNode;
       }
@@ -7932,8 +7936,7 @@ nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection
     }
     NS_ENSURE_STATE(mHTMLEditor);
     nearBlock = mHTMLEditor->GetBlockNodeParent(nearNode);
-    if (block == nearBlock)
-    {
+    if (block && block == nearBlock) {
       if (nearNode && nsTextEditUtils::IsBreak(nearNode) )
       {   
         NS_ENSURE_STATE(mHTMLEditor);
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index 16a5f2f73e0..02ef3239f0d 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -74,6 +74,7 @@
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "nsTextFragment.h"
+#include "nsContentList.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -629,18 +630,14 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
         return NS_OK;
       }
 
-      nsCOMPtr selection;
-      nsresult rv = GetSelection(getter_AddRefs(selection));
-      NS_ENSURE_SUCCESS(rv, rv);
-      int32_t offset;
-      nsCOMPtr node, blockParent;
-      rv = GetStartNodeAndOffset(selection, getter_AddRefs(node), &offset);
-      NS_ENSURE_SUCCESS(rv, rv);
-      NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
+      nsRefPtr selection = GetSelection();
+      NS_ENSURE_TRUE(selection && selection->RangeCount(), NS_ERROR_FAILURE);
 
-      bool isBlock = false;
-      NodeIsBlock(node, &isBlock);
-      if (isBlock) {
+      nsCOMPtr node = selection->GetRangeAt(0)->GetStartParent();
+      MOZ_ASSERT(node);
+
+      nsCOMPtr blockParent;
+      if (IsBlockNode(node)) {
         blockParent = node;
       } else {
         blockParent = GetBlockNodeParent(node);
@@ -651,15 +648,16 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
       }
 
       bool handled = false;
+      nsresult rv;
       if (nsHTMLEditUtils::IsTableElement(blockParent)) {
         rv = TabInTable(nativeKeyEvent->IsShift(), &handled);
         if (handled) {
           ScrollSelectionIntoView(false);
         }
       } else if (nsHTMLEditUtils::IsListItem(blockParent)) {
-        rv = Indent(nativeKeyEvent->IsShift() ?
-                      NS_LITERAL_STRING("outdent") :
-                      NS_LITERAL_STRING("indent"));
+        rv = Indent(nativeKeyEvent->IsShift()
+                    ? NS_LITERAL_STRING("outdent")
+                    : NS_LITERAL_STRING("indent"));
         handled = true;
       }
       NS_ENSURE_SUCCESS(rv, rv);
@@ -829,31 +827,39 @@ nsHTMLEditor::SetDocumentTitle(const nsAString &aTitle)
 ///////////////////////////////////////////////////////////////////////////
 // GetBlockNodeParent: returns enclosing block level ancestor, if any
 //
+already_AddRefed
+nsHTMLEditor::GetBlockNodeParent(nsINode* aNode)
+{
+  MOZ_ASSERT(aNode);
+
+  nsCOMPtr p = aNode->GetParentNode();
+
+  while (p) {
+    if (p->IsElement() && NodeIsBlockStatic(p->AsElement())) {
+      return p.forget().downcast();
+    }
+    p = p->GetParentNode();
+  }
+
+  return nullptr;
+}
+
 already_AddRefed
 nsHTMLEditor::GetBlockNodeParent(nsIDOMNode *aNode)
 {
-  if (!aNode)
-  {
+  nsCOMPtr node = do_QueryInterface(aNode);
+
+  if (!node) {
     NS_NOTREACHED("null node passed to GetBlockNodeParent()");
     return nullptr;
   }
 
-  nsCOMPtr p;
-  if (NS_FAILED(aNode->GetParentNode(getter_AddRefs(p))))  // no parent, ran off top of tree
+  nsCOMPtr parent = GetBlockNodeParent(node);
+  if (!parent) {
     return nullptr;
-
-  nsCOMPtr tmp;
-  while (p)
-  {
-    bool isBlock;
-    if (NS_FAILED(NodeIsBlockStatic(p, &isBlock)) || isBlock)
-      break;
-    if (NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
-      break;
-
-    p = tmp;
   }
-  return p.forget();
+  nsCOMPtr ret = dont_AddRef(parent.forget().take()->AsDOMNode());
+  return ret.forget();
 }
 
 static const char16_t nbsp = 160;
@@ -928,37 +934,45 @@ nsHTMLEditor::IsPrevCharInNodeWhitespace(nsIContent* aContent,
 /* ------------ End Block methods -------------- */
 
 
-bool nsHTMLEditor::IsVisBreak(nsIDOMNode *aNode)
+bool
+nsHTMLEditor::IsVisBreak(nsINode* aNode)
 {
-  NS_ENSURE_TRUE(aNode, false);
-  if (!nsTextEditUtils::IsBreak(aNode)) 
+  MOZ_ASSERT(aNode);
+  if (!nsTextEditUtils::IsBreak(aNode)) {
     return false;
-  // check if there is a later node in block after br
-  nsCOMPtr priorNode, nextNode;
-  GetPriorHTMLNode(aNode, address_of(priorNode), true); 
-  GetNextHTMLNode(aNode, address_of(nextNode), true); 
-  // if we are next to another break, we are visible
-  if (priorNode && nsTextEditUtils::IsBreak(priorNode))
+  }
+  // Check if there is a later node in block after br
+  nsCOMPtr priorNode = GetPriorHTMLNode(aNode, true);
+  if (priorNode && nsTextEditUtils::IsBreak(priorNode)) {
     return true;
-  if (nextNode && nsTextEditUtils::IsBreak(nextNode))
+  }
+  nsCOMPtr nextNode = GetNextHTMLNode(aNode, true);
+  if (nextNode && nsTextEditUtils::IsBreak(nextNode)) {
     return true;
+  }
   
-  // if we are right before block boundary, then br not visible
-  NS_ENSURE_TRUE(nextNode, false);  // this break is trailer in block, it's not visible
-  if (IsBlockNode(nextNode))
-    return false; // break is right before a block, it's not visible
+  // If we are right before block boundary, then br not visible
+  if (!nextNode) {
+    // This break is trailer in block, it's not visible
+    return false;
+  }
+  if (IsBlockNode(nextNode)) {
+    // Break is right before a block, it's not visible
+    return false;
+  }
     
-  // sigh.  We have to use expensive whitespace calculation code to 
+  // Sigh.  We have to use expensive whitespace calculation code to 
   // determine what is going on
-  nsCOMPtr selNode, tmp;
   int32_t selOffset;
-  selNode = GetNodeLocation(aNode, &selOffset);
-  selOffset++; // lets look after the break
-  nsWSRunObject wsObj(this, selNode, selOffset);
+  nsCOMPtr selNode = GetNodeLocation(aNode, &selOffset);
+  // Let's look after the break
+  selOffset++;
+  nsWSRunObject wsObj(this, selNode->AsDOMNode(), selOffset);
   nsCOMPtr visNode;
-  int32_t visOffset=0;
+  int32_t visOffset = 0;
   WSType visType;
-  wsObj.NextVisibleNode(selNode, selOffset, address_of(visNode), &visOffset, &visType);
+  wsObj.NextVisibleNode(selNode->AsDOMNode(), selOffset, address_of(visNode),
+                        &visOffset, &visType);
   if (visType & WSType::block) {
     return false;
   }
@@ -966,6 +980,15 @@ bool nsHTMLEditor::IsVisBreak(nsIDOMNode *aNode)
   return true;
 }
 
+
+bool
+nsHTMLEditor::IsVisBreak(nsIDOMNode* aNode)
+{
+  nsCOMPtr node = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(node, false);
+  return IsVisBreak(node);
+}
+
 NS_IMETHODIMP
 nsHTMLEditor::BreakIsVisible(nsIDOMNode *aNode, bool *aIsVisible)
 {
@@ -996,32 +1019,16 @@ bool nsHTMLEditor::IsModifiable()
 NS_IMETHODIMP
 nsHTMLEditor::UpdateBaseURL()
 {
-  nsCOMPtr domDoc = GetDOMDocument();
-  NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
+  nsCOMPtr doc = GetDocument();
+  NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   // Look for an HTML  tag
-  nsCOMPtr nodeList;
-  nsresult rv = domDoc->GetElementsByTagName(NS_LITERAL_STRING("base"), getter_AddRefs(nodeList));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr baseNode;
-  if (nodeList)
-  {
-    uint32_t count;
-    nodeList->GetLength(&count);
-    if (count >= 1)
-    {
-      rv = nodeList->Item(0, getter_AddRefs(baseNode));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-  // If no base tag, then set baseURL to the document's URL
-  // This is very important, else relative URLs for links and images are wrong
-  if (!baseNode)
-  {
-    nsCOMPtr doc = do_QueryInterface(domDoc);
-    NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+  nsRefPtr nodeList =
+    doc->GetElementsByTagName(NS_LITERAL_STRING("base"));
 
+  // If no base tag, then set baseURL to the document's URL.  This is very
+  // important, else relative URLs for links and images are wrong
+  if (!nodeList || !nodeList->Item(0)) {
     return doc->SetBaseURI(doc->GetDocumentURI());
   }
   return NS_OK;
@@ -4705,8 +4712,7 @@ nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
         nsCOMPtr blockParent;
         blockParent = GetBlockNodeParent(startNode);
         // and apply the background color to that block container
-        if (cachedBlockParent != blockParent)
-        {
+        if (blockParent && cachedBlockParent != blockParent) {
           cachedBlockParent = blockParent;
           nsCOMPtr element = do_QueryInterface(blockParent);
           int32_t count;
@@ -4734,8 +4740,7 @@ nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
         if (!isBlock) {
           blockParent = GetBlockNodeParent(selectedNode);
         }
-        if (cachedBlockParent != blockParent)
-        {
+        if (blockParent && cachedBlockParent != blockParent) {
           cachedBlockParent = blockParent;
           nsCOMPtr element = do_QueryInterface(blockParent);
           int32_t count;
@@ -4792,8 +4797,7 @@ nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
         {
           nsCOMPtr blockParent;
           blockParent = GetBlockNodeParent(startNode);
-          if (cachedBlockParent != blockParent)
-          {
+          if (blockParent && cachedBlockParent != blockParent) {
             cachedBlockParent = blockParent;
             nsCOMPtr element = do_QueryInterface(blockParent);
             int32_t count;
@@ -4817,8 +4821,7 @@ nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
             // no we don't, let's find the block ancestor
             blockParent = GetBlockNodeParent(node);
           }
-          if (cachedBlockParent != blockParent)
-          {
+          if (blockParent && cachedBlockParent != blockParent) {
             cachedBlockParent = blockParent;
             nsCOMPtr element = do_QueryInterface(blockParent);
             int32_t count;
@@ -4836,8 +4839,7 @@ nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
         {
           nsCOMPtr blockParent;
           blockParent = GetBlockNodeParent(endNode);
-          if (cachedBlockParent != blockParent)
-          {
+          if (blockParent && cachedBlockParent != blockParent) {
             cachedBlockParent = blockParent;
             nsCOMPtr element = do_QueryInterface(blockParent);
             int32_t count;
diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h
index 368cfcfa844..0dfd31cf337 100644
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -229,6 +229,7 @@ public:
   NS_IMETHOD SetHTMLBackgroundColor(const nsAString& aColor);
 
   /* ------------ Block methods moved from nsEditor -------------- */
+  static already_AddRefed GetBlockNodeParent(nsINode* aNode);
   static already_AddRefed GetBlockNodeParent(nsIDOMNode *aNode);
 
   void IsNextCharInNodeWhitespace(nsIContent* aContent,
@@ -608,6 +609,7 @@ protected:
   nsIDOMNode* GetArrayEndpoint(bool aEnd, nsCOMArray& aNodeArray);
 
   /* small utility routine to test if a break node is visible to user */
+  bool     IsVisBreak(nsINode* aNode);
   bool     IsVisBreak(nsIDOMNode *aNode);
 
   /* utility routine to possibly adjust the insertion position when 
diff --git a/editor/libeditor/text/nsTextEditUtils.cpp b/editor/libeditor/text/nsTextEditUtils.cpp
index 3f6b1cb8a69..8be7767b3e2 100644
--- a/editor/libeditor/text/nsTextEditUtils.cpp
+++ b/editor/libeditor/text/nsTextEditUtils.cpp
@@ -38,6 +38,13 @@ nsTextEditUtils::IsBreak(nsIDOMNode *node)
 {
   return nsEditor::NodeIsType(node, nsGkAtoms::br);
 }
+ 
+bool 
+nsTextEditUtils::IsBreak(nsINode* aNode)
+{
+  MOZ_ASSERT(aNode);
+  return aNode->IsElement() && aNode->AsElement()->IsHTML(nsGkAtoms::br);
+}
 
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/editor/libeditor/text/nsTextEditUtils.h b/editor/libeditor/text/nsTextEditUtils.h
index 30e7aa9cdc5..d55383f2a90 100644
--- a/editor/libeditor/text/nsTextEditUtils.h
+++ b/editor/libeditor/text/nsTextEditUtils.h
@@ -23,6 +23,7 @@ public:
   // from nsTextEditRules:
   static bool IsBody(nsIDOMNode* aNode);
   static bool IsBreak(nsIDOMNode* aNode);
+  static bool IsBreak(nsINode* aNode);
   static bool IsMozBR(nsIDOMNode* aNode);
   static bool IsMozBR(nsINode* aNode);
   static bool HasMozAttr(nsIDOMNode* aNode);

From 7881636ecec19109046ea9bffaa310e7e03c1bbb Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Fri, 25 Apr 2014 13:34:42 +0300
Subject: [PATCH 08/50] Bug 1001351 - Allow null-safe conversion from nsINode
 to nsIDOMNode; r=smaug

---
 content/base/public/nsINode.h          | 5 +++++
 editor/libeditor/html/nsHTMLEditor.cpp | 7 ++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h
index 8c2c55b3e88..058e04a258f 100644
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1826,6 +1826,11 @@ protected:
   nsSlots* mSlots;
 };
 
+inline nsIDOMNode* GetAsDOMNode(nsINode* aNode)
+{
+  return aNode ? aNode->AsDOMNode() : nullptr;
+}
+
 // Useful inline function for getting a node given an nsIContent and an
 // nsIDocument.  Returns the first argument cast to nsINode if it is non-null,
 // otherwise returns the second (which may be null).  We use type variables
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index 02ef3239f0d..a1c6b79b128 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -854,11 +854,8 @@ nsHTMLEditor::GetBlockNodeParent(nsIDOMNode *aNode)
     return nullptr;
   }
 
-  nsCOMPtr parent = GetBlockNodeParent(node);
-  if (!parent) {
-    return nullptr;
-  }
-  nsCOMPtr ret = dont_AddRef(parent.forget().take()->AsDOMNode());
+  nsCOMPtr ret =
+    dont_AddRef(GetAsDOMNode(GetBlockNodeParent(node).take()));
   return ret.forget();
 }
 

From 260eded4ba506c65800448b53335bbff4b947158 Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:46 +0300
Subject: [PATCH 09/50] Bug 1002429 part 1 - Clean up
 nsHTMLEditor::GetElementOrParentByTagName; r=ehsan

---
 editor/libeditor/html/nsHTMLEditUtils.cpp |  13 +-
 editor/libeditor/html/nsHTMLEditUtils.h   |   1 +
 editor/libeditor/html/nsHTMLEditor.cpp    | 187 +++++++++++-----------
 editor/libeditor/html/nsHTMLEditor.h      |   2 +
 4 files changed, 106 insertions(+), 97 deletions(-)

diff --git a/editor/libeditor/html/nsHTMLEditUtils.cpp b/editor/libeditor/html/nsHTMLEditUtils.cpp
index ba8cf8a4a14..136e4a7e051 100644
--- a/editor/libeditor/html/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/html/nsHTMLEditUtils.cpp
@@ -359,13 +359,22 @@ nsHTMLEditUtils::IsImage(nsIDOMNode* aNode)
 bool 
 nsHTMLEditUtils::IsLink(nsIDOMNode *aNode)
 {
-  NS_ENSURE_TRUE(aNode, false);
+  nsCOMPtr node = do_QueryInterface(aNode);
+  return node && IsLink(node);
+}
+
+bool
+nsHTMLEditUtils::IsLink(nsINode* aNode)
+{
+  MOZ_ASSERT(aNode);
+
   nsCOMPtr anchor = do_QueryInterface(aNode);
   if (anchor)
   {
     nsAutoString tmpText;
-    if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty())
+    if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty()) {
       return true;
+    }
   }
   return false;
 }
diff --git a/editor/libeditor/html/nsHTMLEditUtils.h b/editor/libeditor/html/nsHTMLEditUtils.h
index 47f62d993c1..03bb77f463c 100644
--- a/editor/libeditor/html/nsHTMLEditUtils.h
+++ b/editor/libeditor/html/nsHTMLEditUtils.h
@@ -46,6 +46,7 @@ public:
   static bool IsAnchor(nsIDOMNode *aNode);
   static bool IsImage(nsIDOMNode *aNode);
   static bool IsLink(nsIDOMNode *aNode);
+  static bool IsLink(nsINode* aNode);
   static bool IsNamedAnchor(nsINode* aNode);
   static bool IsNamedAnchor(nsIDOMNode *aNode);
   static bool IsDiv(nsIDOMNode *aNode);
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index a1c6b79b128..382fedbca71 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1051,14 +1051,14 @@ nsHTMLEditor::TypedText(const nsAString& aString, ETypingAction aAction)
   return nsPlaintextEditor::TypedText(aString, aAction);
 }
 
-NS_IMETHODIMP nsHTMLEditor::TabInTable(bool inIsShift, bool *outHandled)
+NS_IMETHODIMP
+nsHTMLEditor::TabInTable(bool inIsShift, bool* outHandled)
 {
   NS_ENSURE_TRUE(outHandled, NS_ERROR_NULL_POINTER);
   *outHandled = false;
 
-  // Find enclosing table cell from the selection (cell may be the selected element)
+  // Find enclosing table cell from selection (cell may be selected element)
   nsCOMPtr cellElement;
-    // can't use |NS_LITERAL_STRING| here until |GetElementOrParentByTagName| is fixed to accept readables
   nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr, getter_AddRefs(cellElement));
   NS_ENSURE_SUCCESS(res, res);
   // Do nothing -- we didn't find a table cell
@@ -2278,107 +2278,104 @@ nsHTMLEditor::Align(const nsAString& aAlignType)
   return res;
 }
 
+already_AddRefed
+nsHTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName,
+                                          nsINode* aNode)
+{
+  MOZ_ASSERT(!aTagName.IsEmpty());
+
+  nsCOMPtr node = aNode;
+  if (!node) {
+    // If no node supplied, get it from anchor node of current selection
+    nsRefPtr selection = GetSelection();
+    NS_ENSURE_TRUE(selection, nullptr);
+
+    nsCOMPtr anchorNode = selection->GetAnchorNode();
+    NS_ENSURE_TRUE(anchorNode, nullptr);
+
+    // Try to get the actual selected node
+    if (anchorNode->HasChildNodes() && anchorNode->IsContent()) {
+      node = anchorNode->GetChildAt(selection->AnchorOffset());
+    }
+    // Anchor node is probably a text node - just use that
+    if (!node) {
+      node = anchorNode;
+    }
+  }
+
+  nsCOMPtr current;
+  if (node->IsElement()) {
+    current = node->AsElement();
+  } else if (node->GetParentElement()) {
+    current = node->GetParentElement();
+  } else {
+    // Neither aNode nor its parent is an element, so no ancestor is
+    MOZ_ASSERT(!node->GetParentNode() ||
+               !node->GetParentNode()->GetParentNode());
+    return nullptr;
+  }
+
+  nsAutoString tagName(aTagName);
+  ToLowerCase(tagName);
+  bool getLink = IsLinkTag(tagName);
+  bool getNamedAnchor = IsNamedAnchorTag(tagName);
+  if (getLink || getNamedAnchor) {
+    tagName.AssignLiteral("a");
+  }
+  bool findTableCell = tagName.EqualsLiteral("td");
+  bool findList = tagName.EqualsLiteral("list");
+
+  for (; current; current = current->GetParentElement()) {
+    // Test if we have a link (an anchor with href set)
+    if ((getLink && nsHTMLEditUtils::IsLink(current)) ||
+        (getNamedAnchor && nsHTMLEditUtils::IsNamedAnchor(current))) {
+      return current.forget();
+    }
+    if (findList) {
+      // Match "ol", "ul", or "dl" for lists
+      if (nsHTMLEditUtils::IsList(current)) {
+        return current.forget();
+      }
+    } else if (findTableCell) {
+      // Table cells are another special case: match either "td" or "th"
+      if (nsHTMLEditUtils::IsTableCell(current)) {
+        return current.forget();
+      }
+    } else if (current->NodeName().Equals(tagName,
+                   nsCaseInsensitiveStringComparator())) {
+      return current.forget();
+    }
+
+    // Stop searching if parent is a body tag.  Note: Originally used IsRoot to
+    // stop at table cells, but that's too messy when you are trying to find
+    // the parent table
+    if (current->GetParentElement() &&
+        current->GetParentElement()->Tag() == nsGkAtoms::body) {
+      break;
+    }
+  }
+
+  return nullptr;
+}
+
 NS_IMETHODIMP
-nsHTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName, nsIDOMNode *aNode, nsIDOMElement** aReturn)
+nsHTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName,
+                                          nsIDOMNode* aNode,
+                                          nsIDOMElement** aReturn)
 {
   NS_ENSURE_TRUE(!aTagName.IsEmpty(), NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aReturn, NS_ERROR_NULL_POINTER);
 
-  nsCOMPtr current = do_QueryInterface(aNode);
-  if (!current) {
-    // If no node supplied, get it from anchor node of current selection
-    nsRefPtr selection = GetSelection();
-    NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
+  nsCOMPtr node = do_QueryInterface(aNode);
+  nsCOMPtr parent =
+    GetElementOrParentByTagName(aTagName, node);
+  nsCOMPtr ret = do_QueryInterface(parent);
 
-    nsCOMPtr anchorNode = selection->GetAnchorNode();
-    NS_ENSURE_TRUE(anchorNode, NS_ERROR_FAILURE);
-
-    // Try to get the actual selected node
-    if (anchorNode->HasChildNodes() && anchorNode->IsContent()) {
-      uint32_t offset = selection->AnchorOffset();
-      current = anchorNode->GetChildAt(offset);
-    }
-    // anchor node is probably a text node - just use that
-    if (!current) {
-      current = anchorNode;
-    }
-  }
-
-  nsCOMPtr currentNode = current->AsDOMNode();
-
-  nsAutoString TagName(aTagName);
-  ToLowerCase(TagName);
-  bool getLink = IsLinkTag(TagName);
-  bool getNamedAnchor = IsNamedAnchorTag(TagName);
-  if ( getLink || getNamedAnchor)
-  {
-    TagName.AssignLiteral("a");  
-  }
-  bool findTableCell = TagName.EqualsLiteral("td");
-  bool findList = TagName.EqualsLiteral("list");
-
-  // default is null - no element found
-  *aReturn = nullptr;
-  
-  nsCOMPtr parent;
-  bool bNodeFound = false;
-
-  while (true)
-  {
-    nsAutoString currentTagName; 
-    // Test if we have a link (an anchor with href set)
-    if ( (getLink && nsHTMLEditUtils::IsLink(currentNode)) ||
-         (getNamedAnchor && nsHTMLEditUtils::IsNamedAnchor(currentNode)) )
-    {
-      bNodeFound = true;
-      break;
-    } else {
-      if (findList)
-      {
-        // Match "ol", "ul", or "dl" for lists
-        if (nsHTMLEditUtils::IsList(currentNode))
-          goto NODE_FOUND;
-
-      } else if (findTableCell)
-      {
-        // Table cells are another special case:
-        // Match either "td" or "th" for them
-        if (nsHTMLEditUtils::IsTableCell(currentNode))
-          goto NODE_FOUND;
-
-      } else {
-        currentNode->GetNodeName(currentTagName);
-        if (currentTagName.Equals(TagName, nsCaseInsensitiveStringComparator()))
-        {
-NODE_FOUND:
-          bNodeFound = true;
-          break;
-        } 
-      }
-    }
-    // Search up the parent chain
-    // We should never fail because of root test below, but lets be safe
-    // XXX: ERROR_HANDLING error return code lost
-    if (NS_FAILED(currentNode->GetParentNode(getter_AddRefs(parent))) || !parent)
-      break;
-
-    // Stop searching if parent is a body tag
-    nsAutoString parentTagName;
-    parent->GetNodeName(parentTagName);
-    // Note: Originally used IsRoot to stop at table cells,
-    //  but that's too messy when you are trying to find the parent table
-    if(parentTagName.LowerCaseEqualsLiteral("body"))
-      break;
-
-    currentNode = parent;
-  }
-
-  if (!bNodeFound) {
+  if (!ret) {
     return NS_EDITOR_ELEMENT_NOT_FOUND;
   }
 
-  nsCOMPtr currentElement = do_QueryInterface(currentNode);
-  currentElement.forget(aReturn);
+  ret.forget(aReturn);
   return NS_OK;
 }
 
diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h
index 0dfd31cf337..bc9a1b7e20a 100644
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -958,6 +958,8 @@ private:
   void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
                          nsIContent* aChild, int32_t aIndexInContainer,
                          InsertedOrAppended aInsertedOrAppended);
+  already_AddRefed GetElementOrParentByTagName(
+                                    const nsAString& aTagName, nsINode* aNode);
 };
 #endif //nsHTMLEditor_h__
 

From 78ca193f10cd67aa16bac23fb268f7166c3ca1ef Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:46 +0300
Subject: [PATCH 10/50] Bug 1002429 part 2 - Clean up
 nsHTMLEditor::GetEnclosingTable; r=ehsan

---
 editor/libeditor/html/nsHTMLEditUtils.cpp |  8 +++++-
 editor/libeditor/html/nsHTMLEditUtils.h   |  1 +
 editor/libeditor/html/nsHTMLEditor.cpp    | 34 +++++++++++++++--------
 editor/libeditor/html/nsHTMLEditor.h      |  2 ++
 4 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/editor/libeditor/html/nsHTMLEditUtils.cpp b/editor/libeditor/html/nsHTMLEditUtils.cpp
index 136e4a7e051..c46e04a09c9 100644
--- a/editor/libeditor/html/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/html/nsHTMLEditUtils.cpp
@@ -234,12 +234,18 @@ nsHTMLEditUtils::IsTableElementButNotTable(nsINode* aNode)
 ///////////////////////////////////////////////////////////////////////////
 // IsTable: true if node an html table
 //                  
-bool 
+bool
 nsHTMLEditUtils::IsTable(nsIDOMNode* aNode)
 {
   return nsEditor::NodeIsType(aNode, nsEditProperty::table);
 }
 
+bool
+nsHTMLEditUtils::IsTable(nsINode* aNode)
+{
+  return aNode && aNode->IsElement() && aNode->Tag() == nsGkAtoms::table;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // IsTableRow: true if node an html tr
 //                  
diff --git a/editor/libeditor/html/nsHTMLEditUtils.h b/editor/libeditor/html/nsHTMLEditUtils.h
index 03bb77f463c..bdf9148af8f 100644
--- a/editor/libeditor/html/nsHTMLEditUtils.h
+++ b/editor/libeditor/html/nsHTMLEditUtils.h
@@ -29,6 +29,7 @@ public:
   static bool IsListItem(nsINode* aNode);
   static bool IsListItem(nsIDOMNode *aNode);
   static bool IsTable(nsIDOMNode *aNode);
+  static bool IsTable(nsINode* aNode);
   static bool IsTableRow(nsIDOMNode *aNode);
   static bool IsTableElement(nsINode* aNode);
   static bool IsTableElement(nsIDOMNode *aNode);
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index 382fedbca71..c7b4814e29f 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -3736,21 +3736,31 @@ nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement)
 
 ///////////////////////////////////////////////////////////////////////////
 // GetEnclosingTable: find ancestor who is a table, if any
-//                  
-nsCOMPtr 
+//
+already_AddRefed
+nsHTMLEditor::GetEnclosingTable(nsINode* aNode)
+{
+  MOZ_ASSERT(aNode);
+
+  for (nsCOMPtr block = GetBlockNodeParent(aNode);
+       block;
+       block = GetBlockNodeParent(block)) {
+    if (nsHTMLEditUtils::IsTable(block)) {
+      return block.forget();
+    }
+  }
+  return nullptr;
+}
+
+nsCOMPtr
 nsHTMLEditor::GetEnclosingTable(nsIDOMNode *aNode)
 {
   NS_PRECONDITION(aNode, "null node passed to nsHTMLEditor::GetEnclosingTable");
-  nsCOMPtr tbl, tmp, node = aNode;
-
-  while (!tbl)
-  {
-    tmp = GetBlockNodeParent(node);
-    if (!tmp) break;
-    if (nsHTMLEditUtils::IsTable(tmp)) tbl = tmp;
-    node = tmp;
-  }
-  return tbl;
+  nsCOMPtr node = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(node, nullptr);
+  nsCOMPtr table = GetEnclosingTable(node);
+  nsCOMPtr ret = do_QueryInterface(table);
+  return ret;
 }
 
 
diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h
index bc9a1b7e20a..21754a5ca0c 100644
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -486,6 +486,8 @@ protected:
 
 // End of Table Editing utilities
   
+  static already_AddRefed
+    GetEnclosingTable(nsINode* aNode);
   static nsCOMPtr GetEnclosingTable(nsIDOMNode *aNode);
 
   /** content-based query returns true if  effects aNode

From 02bcb38d448ffef154aa0aa0190711240a73f57d Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:46 +0300
Subject: [PATCH 11/50] Bug 1002429 part 3 - Clean up nsEditor::IsContainer;
 r=ehsan

---
 editor/libeditor/base/nsEditor.cpp     | 10 +++++++--
 editor/libeditor/base/nsEditor.h       |  3 ++-
 editor/libeditor/html/nsHTMLEditor.cpp | 30 ++++++++++++++------------
 editor/libeditor/html/nsHTMLEditor.h   |  3 ++-
 4 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp
index 5fe55ec00dd..1802d1629b2 100644
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -3481,8 +3481,14 @@ nsEditor::IsDescendantOfEditorRoot(nsINode* aNode)
   return nsContentUtils::ContentIsDescendantOf(aNode, root);
 }
 
-bool 
-nsEditor::IsContainer(nsIDOMNode *aNode)
+bool
+nsEditor::IsContainer(nsINode* aNode)
+{
+  return aNode ? true : false;
+}
+
+bool
+nsEditor::IsContainer(nsIDOMNode* aNode)
 {
   return aNode ? true : false;
 }
diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h
index 5caaad957ec..380862152b6 100644
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -585,7 +585,8 @@ public:
   bool IsDescendantOfEditorRoot(nsINode* aNode);
 
   /** returns true if aNode is a container */
-  virtual bool IsContainer(nsIDOMNode *aNode);
+  virtual bool IsContainer(nsINode* aNode);
+  virtual bool IsContainer(nsIDOMNode* aNode);
 
   /** returns true if aNode is an editable node */
   bool IsEditable(nsIDOMNode *aNode);
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index c7b4814e29f..0705f1c4c61 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -3526,29 +3526,31 @@ nsHTMLEditor::TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag)
 }
 
 bool
-nsHTMLEditor::IsContainer(nsIDOMNode *aNode)
-{
-  if (!aNode) {
-    return false;
-  }
-
-  nsAutoString stringTag;
-
-  nsresult rv = aNode->GetNodeName(stringTag);
-  NS_ENSURE_SUCCESS(rv, false);
+nsHTMLEditor::IsContainer(nsINode* aNode) {
+  MOZ_ASSERT(aNode);
 
   int32_t tagEnum;
   // XXX Should this handle #cdata-section too?
-  if (stringTag.EqualsLiteral("#text")) {
+  if (aNode->IsNodeOfType(nsINode::eTEXT)) {
     tagEnum = eHTMLTag_text;
-  }
-  else {
-    tagEnum = nsContentUtils::GetParserService()->HTMLStringTagToId(stringTag);
+  } else {
+    tagEnum =
+      nsContentUtils::GetParserService()->HTMLStringTagToId(aNode->NodeName());
   }
 
   return nsHTMLEditUtils::IsContainer(tagEnum);
 }
 
+bool
+nsHTMLEditor::IsContainer(nsIDOMNode *aNode)
+{
+  nsCOMPtr node = do_QueryInterface(aNode);
+  if (!node) {
+    return false;
+  }
+  return IsContainer(node);
+}
+
 
 NS_IMETHODIMP 
 nsHTMLEditor::SelectEntireDocument(nsISelection *aSelection)
diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h
index 21754a5ca0c..9293790baaa 100644
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -287,7 +287,8 @@ public:
   virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag);
   
   /** returns true if aNode is a container */
-  virtual bool IsContainer(nsIDOMNode *aNode);
+  virtual bool IsContainer(nsINode* aNode) MOZ_OVERRIDE;
+  virtual bool IsContainer(nsIDOMNode* aNode) MOZ_OVERRIDE;
 
   /** make the given selection span the entire document */
   NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);

From 66a2731d0fa98739c162731137533b3c22be03b7 Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:46 +0300
Subject: [PATCH 12/50] Bug 1002429 part 4 - Clean up
 nsHTMLEditor::CollapseSelectionToDeepestNonTableFirstChild; r=ehsan

---
 editor/libeditor/html/nsHTMLEditor.cpp  | 57 +++++++++++--------------
 editor/libeditor/html/nsHTMLEditor.h    |  3 +-
 editor/libeditor/html/nsTableEditor.cpp | 11 +++--
 3 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index 0705f1c4c61..dee92ecf741 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1095,8 +1095,8 @@ nsHTMLEditor::TabInTable(bool inIsShift, bool* outHandled)
     if (node && nsHTMLEditUtils::IsTableCell(node) &&
         GetEnclosingTable(node) == tbl)
     {
-      res = CollapseSelectionToDeepestNonTableFirstChild(nullptr, node);
-      NS_ENSURE_SUCCESS(res, res);
+      CollapseSelectionToDeepestNonTableFirstChild(nullptr,
+                                                   iter->GetCurrentNode());
       *outHandled = true;
       return NS_OK;
     }
@@ -1142,41 +1142,34 @@ NS_IMETHODIMP nsHTMLEditor::CreateBR(nsIDOMNode *aNode, int32_t aOffset, nsCOMPt
   return CreateBRImpl(address_of(parent), &offset, outBRNode, aSelect);
 }
 
-nsresult 
-nsHTMLEditor::CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode)
+void
+nsHTMLEditor::CollapseSelectionToDeepestNonTableFirstChild(
+                                         Selection* aSelection, nsINode* aNode)
 {
-  NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-  nsresult res;
+  MOZ_ASSERT(aNode);
 
-  nsCOMPtr selection;
-  if (aSelection)
-  {
-    selection = aSelection;
-  } else {
-    res = GetSelection(getter_AddRefs(selection));
-    NS_ENSURE_SUCCESS(res, res);
-    NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
+  nsRefPtr selection = aSelection;
+  if (!selection) {
+    selection = GetSelection();
   }
-  nsCOMPtr node = aNode;
-  nsCOMPtr child;
-  
-  do {
-    node->GetFirstChild(getter_AddRefs(child));
-    
-    if (child)
-    {
-      // Stop if we find a table
-      // don't want to go into nested tables
-      if (nsHTMLEditUtils::IsTable(child)) break;
-      // hey, it'g gotta be a container too!
-      if (!IsContainer(child)) break;
-      node = child;
+  if (!selection) {
+    // Nothing to do
+    return;
+  }
+
+  nsCOMPtr node = aNode;
+
+  for (nsCOMPtr child = node->GetFirstChild();
+       child;
+       child = child->GetFirstChild()) {
+    // Stop if we find a table, don't want to go into nested tables
+    if (nsHTMLEditUtils::IsTable(child) || !IsContainer(child)) {
+      break;
     }
-  }
-  while (child);
+    node = child;
+  };
 
-  selection->Collapse(node,0);
-  return NS_OK;
+  selection->Collapse(node, 0);
 }
 
 
diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h
index 9293790baaa..4705a852477 100644
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -344,7 +344,8 @@ public:
   // This will stop at a table, however, since we don't want to
   //  "drill down" into nested tables.
   // aSelection is optional -- if null, we get current seletion
-  nsresult CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode);
+  void CollapseSelectionToDeepestNonTableFirstChild(
+                          mozilla::dom::Selection* aSelection, nsINode* aNode);
 
   /**
    * aNode must be a non-null text node.
diff --git a/editor/libeditor/html/nsTableEditor.cpp b/editor/libeditor/html/nsTableEditor.cpp
index bcbd6d9aa49..259c9da4f98 100644
--- a/editor/libeditor/html/nsTableEditor.cpp
+++ b/editor/libeditor/html/nsTableEditor.cpp
@@ -3086,9 +3086,8 @@ nsHTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow, in
 {
   NS_ENSURE_TRUE(aTable, NS_ERROR_NOT_INITIALIZED);
 
-  nsCOMPtrselection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr selection = GetSelection();
+  nsresult res;
   
   if (!selection)
   {
@@ -3117,7 +3116,11 @@ nsHTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow, in
           //   but don't go into nested tables
           // TODO: Should we really be placing the caret at the END
           //  of the cell content?
-          return CollapseSelectionToDeepestNonTableFirstChild(selection, cell);
+          nsCOMPtr cellNode = do_QueryInterface(cell);
+          if (cellNode) {
+            CollapseSelectionToDeepestNonTableFirstChild(selection, cellNode);
+          }
+          return NS_OK;
         }
       } else {
         // Setup index to find another cell in the 

From c08efe28ef781d122122fd676643b3e21fadfac8 Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:46 +0300
Subject: [PATCH 13/50] Bug 1002429 part 5 - Clean up nsHTMLEditor::TabInTable;
 r=ehsan

---
 editor/libeditor/html/nsHTMLEditor.cpp | 68 +++++++++++---------------
 1 file changed, 29 insertions(+), 39 deletions(-)

diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index dee92ecf741..b9601414572 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1058,62 +1058,52 @@ nsHTMLEditor::TabInTable(bool inIsShift, bool* outHandled)
   *outHandled = false;
 
   // Find enclosing table cell from selection (cell may be selected element)
-  nsCOMPtr cellElement;
-  nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr, getter_AddRefs(cellElement));
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr cellElement =
+    GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr);
   // Do nothing -- we didn't find a table cell
   NS_ENSURE_TRUE(cellElement, NS_OK);
 
   // find enclosing table
-  nsCOMPtr tbl = GetEnclosingTable(cellElement);
-  NS_ENSURE_TRUE(tbl, res);
+  nsCOMPtr table = GetEnclosingTable(cellElement);
+  NS_ENSURE_TRUE(table, NS_OK);
 
   // advance to next cell
   // first create an iterator over the table
-  nsCOMPtr iter =
-      do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res);
-  NS_ENSURE_SUCCESS(res, res);
-  NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
-  nsCOMPtr cTbl = do_QueryInterface(tbl);
-  nsCOMPtr cBlock = do_QueryInterface(cellElement);
-  res = iter->Init(cTbl);
+  nsCOMPtr iter = NS_NewContentIterator();
+  nsresult res = iter->Init(table);
   NS_ENSURE_SUCCESS(res, res);
   // position iter at block
-  res = iter->PositionAt(cBlock);
+  res = iter->PositionAt(cellElement);
   NS_ENSURE_SUCCESS(res, res);
 
-  nsCOMPtr node;
-  do
-  {
-    if (inIsShift)
+  nsCOMPtr node;
+  do {
+    if (inIsShift) {
       iter->Prev();
-    else
+    } else {
       iter->Next();
+    }
 
-    node = do_QueryInterface(iter->GetCurrentNode());
+    node = iter->GetCurrentNode();
 
     if (node && nsHTMLEditUtils::IsTableCell(node) &&
-        GetEnclosingTable(node) == tbl)
-    {
-      CollapseSelectionToDeepestNonTableFirstChild(nullptr,
-                                                   iter->GetCurrentNode());
+        nsCOMPtr(GetEnclosingTable(node)) == table) {
+      CollapseSelectionToDeepestNonTableFirstChild(nullptr, node);
       *outHandled = true;
       return NS_OK;
     }
   } while (!iter->IsDone());
   
-  if (!(*outHandled) && !inIsShift)
-  {
-    // if we havent handled it yet then we must have run off the end of
-    // the table.  Insert a new row.
+  if (!(*outHandled) && !inIsShift) {
+    // If we haven't handled it yet, then we must have run off the end of the
+    // table.  Insert a new row.
     res = InsertTableRow(1, true);
     NS_ENSURE_SUCCESS(res, res);
     *outHandled = true;
-    // put selection in right place
-    // Use table code to get selection and index to new row...
-    nsCOMPtrselection;
-    nsCOMPtr tblElement;
-    nsCOMPtr cell;
+    // Put selection in right place.  Use table code to get selection and index
+    // to new row...
+    nsCOMPtr selection;
+    nsCOMPtr tblElement, cell;
     int32_t row;
     res = GetCellContext(getter_AddRefs(selection), 
                          getter_AddRefs(tblElement),
@@ -1124,15 +1114,15 @@ nsHTMLEditor::TabInTable(bool inIsShift, bool* outHandled)
     // ...so that we can ask for first cell in that row...
     res = GetCellAt(tblElement, row, 0, getter_AddRefs(cell));
     NS_ENSURE_SUCCESS(res, res);
-    // ...and then set selection there.
-    // (Note that normally you should use CollapseSelectionToDeepestNonTableFirstChild(),
-    //  but we know cell is an empty new cell, so this works fine)
-    node = do_QueryInterface(cell);
-    if (node) selection->Collapse(node,0);
-    return NS_OK;
+    // ...and then set selection there.  (Note that normally you should use
+    // CollapseSelectionToDeepestNonTableFirstChild(), but we know cell is an
+    // empty new cell, so this works fine)
+    if (cell) {
+      selection->Collapse(cell, 0);
+    }
   }
   
-  return res;
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsHTMLEditor::CreateBR(nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr *outBRNode, EDirection aSelect)

From 1a41adda96c86c530626265f54de945f7b035c09 Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:46 +0300
Subject: [PATCH 14/50] Bug 1002429 part 6 - Clean up
 nsHTMLEditor::ReplaceHeadContentsWithHTML; r=ehsan

---
 editor/libeditor/base/nsEditor.cpp     |  7 ++
 editor/libeditor/base/nsEditor.h       |  2 +
 editor/libeditor/html/nsHTMLEditor.cpp | 95 ++++++++++----------------
 3 files changed, 44 insertions(+), 60 deletions(-)

diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp
index 1802d1629b2..c093c297fa0 100644
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -1379,6 +1379,13 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsAString& aTag,
 }
 
 
+nsresult
+nsEditor::InsertNode(nsIContent* aContent, nsINode* aParent, int32_t aPosition)
+{
+  MOZ_ASSERT(aContent && aParent);
+  return InsertNode(GetAsDOMNode(aContent), GetAsDOMNode(aParent), aPosition);
+}
+
 NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
                                    nsIDOMNode * aParent,
                                    int32_t      aPosition)
diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h
index 380862152b6..cc6a5427f7f 100644
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -206,6 +206,8 @@ public:
 
   /* helper routines for node/parent manipulations */
   nsresult DeleteNode(nsINode* aNode);
+  nsresult InsertNode(nsIContent* aContent, nsINode* aParent,
+                      int32_t aPosition);
   nsresult ReplaceContainer(nsINode* inNode,
                             mozilla::dom::Element** outNode,
                             const nsAString& aNodeType,
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index b9601414572..91aef065477 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -46,7 +46,6 @@
 #include "nsISupportsArray.h"
 #include "nsContentUtils.h"
 #include "nsIDocumentEncoder.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "SetDocTitleTxn.h"
@@ -70,6 +69,7 @@
 #include "nsIFrame.h"
 #include "nsIParserService.h"
 #include "mozilla/dom/Selection.h"
+#include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/HTMLBodyElement.h"
@@ -1163,42 +1163,36 @@ nsHTMLEditor::CollapseSelectionToDeepestNonTableFirstChild(
 }
 
 
-// This is mostly like InsertHTMLWithCharsetAndContext, 
-//  but we can't use that because it is selection-based and 
-//  the rules code won't let us edit under the  node
+/**
+ * This is mostly like InsertHTMLWithCharsetAndContext, but we can't use that
+ * because it is selection-based and the rules code won't let us edit under the
+ *  node
+ */
 NS_IMETHODIMP
 nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
 {
-  nsAutoRules beginRulesSniffing(this, EditAction::ignore, nsIEditor::eNone); // don't do any post processing, rules get confused
-  nsCOMPtr selection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  // don't do any post processing, rules get confused
+  nsAutoRules beginRulesSniffing(this, EditAction::ignore, nsIEditor::eNone);
+  nsRefPtr selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   ForceCompositionEnd();
 
-  // Do not use nsAutoRules -- rules code won't let us insert in 
-  // Use the head node as a parent and delete/insert directly
-  nsCOMPtr doc = do_QueryReferent(mDocWeak);
+  // Do not use nsAutoRules -- rules code won't let us insert in .  Use
+  // the head node as a parent and delete/insert directly.
+  nsCOMPtr doc = do_QueryReferent(mDocWeak);
   NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
 
-  nsCOMPtrnodeList; 
-  res = doc->GetElementsByTagName(NS_LITERAL_STRING("head"), getter_AddRefs(nodeList));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr nodeList =
+    doc->GetElementsByTagName(NS_LITERAL_STRING("head"));
   NS_ENSURE_TRUE(nodeList, NS_ERROR_NULL_POINTER);
 
-  uint32_t count; 
-  nodeList->GetLength(&count);
-  if (count < 1) return NS_ERROR_FAILURE;
-
-  nsCOMPtr headNode;
-  res = nodeList->Item(0, getter_AddRefs(headNode)); 
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr headNode = nodeList->Item(0);
   NS_ENSURE_TRUE(headNode, NS_ERROR_NULL_POINTER);
 
-  // First, make sure there are no return chars in the source.
-  // Bad things happen if you insert returns (instead of dom newlines, \n)
-  // into an editor document.
+  // First, make sure there are no return chars in the source.  Bad things
+  // happen if you insert returns (instead of dom newlines, \n) into an editor
+  // document.
   nsAutoString inputString (aSourceToInsert);  // hope this does copy-on-write
  
   // Windows linebreaks: Map CRLF to LF:
@@ -1211,61 +1205,42 @@ nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
 
   nsAutoEditBatch beginBatching(this);
 
-  res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
   // Get the first range in the selection, for context:
-  nsCOMPtr range;
-  res = selection->GetRangeAt(0, getter_AddRefs(range));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr range = selection->GetRangeAt(0);
+  NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
 
-  nsCOMPtr docfrag;
-  res = range->CreateContextualFragment(inputString,
-                                        getter_AddRefs(docfrag));
+  ErrorResult err;
+  nsRefPtr docfrag =
+    range->CreateContextualFragment(inputString, err);
 
-  //XXXX BUG 50965: This is not returning the text between  ... 
-  // Special code is needed in JS to handle title anyway, so it really doesn't matter!
+  // XXXX BUG 50965: This is not returning the text between ...
+  // Special code is needed in JS to handle title anyway, so it doesn't matter!
 
-  if (NS_FAILED(res))
-  {
+  if (err.Failed()) {
 #ifdef DEBUG
     printf("Couldn't create contextual fragment: error was %X\n",
-           static_cast(res));
+           static_cast(err.ErrorCode()));
 #endif
-    return res;
+    return err.ErrorCode();
   }
   NS_ENSURE_TRUE(docfrag, NS_ERROR_NULL_POINTER);
 
-  nsCOMPtr child;
-
   // First delete all children in head
-  do {
-    res = headNode->GetFirstChild(getter_AddRefs(child));
+  while (nsCOMPtr child = headNode->GetFirstChild()) {
+    nsresult res = DeleteNode(child);
     NS_ENSURE_SUCCESS(res, res);
-    if (child)
-    {
-      res = DeleteNode(child);
-      NS_ENSURE_SUCCESS(res, res);
-    }
-  } while (child);
+  }
 
   // Now insert the new nodes
   int32_t offsetOfNewNode = 0;
-  nsCOMPtr fragmentAsNode (do_QueryInterface(docfrag));
 
   // Loop over the contents of the fragment and move into the document
-  do {
-    res = fragmentAsNode->GetFirstChild(getter_AddRefs(child));
+  while (nsCOMPtr child = docfrag->GetFirstChild()) {
+    nsresult res = InsertNode(child, headNode, offsetOfNewNode++);
     NS_ENSURE_SUCCESS(res, res);
-    if (child)
-    {
-      res = InsertNode(child, headNode, offsetOfNewNode++);
-      NS_ENSURE_SUCCESS(res, res);
-    }
-  } while (child);
+  }
 
-  return res;
+  return NS_OK;
 }
 
 NS_IMETHODIMP

From aaab3d158ea1d4a16a1efc8aecb953b451b1b70c Mon Sep 17 00:00:00 2001
From: Aryeh Gregor 
Date: Mon, 28 Apr 2014 14:54:47 +0300
Subject: [PATCH 15/50] Bug 1002429 part 7 - Clean up
 nsEditor::CreateHTMLContent; r=ehsan

---
 editor/libeditor/base/CreateElementTxn.cpp    | 13 +++----
 editor/libeditor/base/nsEditor.cpp            | 37 ++++++++++++-------
 editor/libeditor/base/nsEditor.h              |  6 +--
 .../libeditor/html/nsHTMLAnonymousUtils.cpp   |  8 ++--
 editor/libeditor/html/nsHTMLEditor.cpp        |  7 ++--
 editor/libeditor/html/nsHTMLEditorStyle.cpp   |  9 ++---
 editor/libeditor/text/nsTextEditRules.cpp     |  9 +++--
 7 files changed, 49 insertions(+), 40 deletions(-)

diff --git a/editor/libeditor/base/CreateElementTxn.cpp b/editor/libeditor/base/CreateElementTxn.cpp
index 5192fc309a8..cab3cf90dc3 100644
--- a/editor/libeditor/base/CreateElementTxn.cpp
+++ b/editor/libeditor/base/CreateElementTxn.cpp
@@ -24,6 +24,7 @@
 #include 
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 CreateElementTxn::CreateElementTxn()
   : EditTxn()
@@ -60,11 +61,9 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
   NS_ASSERTION(mEditor && mParent, "bad state");
   NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
 
-  nsCOMPtr newContent;
-
-  //new call to use instead to get proper HTML element, bug# 39919
-  nsresult result = mEditor->CreateHTMLContent(mTag, getter_AddRefs(newContent));
-  NS_ENSURE_SUCCESS(result, result);
+  ErrorResult rv;
+  nsCOMPtr newContent = mEditor->CreateHTMLContent(mTag, rv);
+  NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
   NS_ENSURE_STATE(newContent);
 
   mNewNode = newContent;
@@ -73,7 +72,6 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
 
   // insert the new node
   if (CreateElementTxn::eAppend == int32_t(mOffsetInParent)) {
-    ErrorResult rv;
     mParent->AppendChild(*mNewNode, rv);
     return rv.ErrorCode();
   }
@@ -84,7 +82,6 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
   // note, it's ok for mRefNode to be null.  that means append
   mRefNode = mParent->GetChildAt(mOffsetInParent);
 
-  ErrorResult rv;
   mParent->InsertBefore(*mNewNode, mRefNode, rv);
   NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
 
@@ -97,7 +94,7 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
   }
 
   nsCOMPtr selection;
-  result = mEditor->GetSelection(getter_AddRefs(selection));
+  nsresult result = mEditor->GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp
index c093c297fa0..b3b314b7f5a 100644
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -1578,15 +1578,16 @@ nsEditor::ReplaceContainer(nsINode* aNode,
   int32_t offset = parent->IndexOf(aNode);
 
   // create new container
-  //new call to use instead to get proper HTML element, bug# 39919
-  nsresult res = CreateHTMLContent(aNodeType, outNode);
-  NS_ENSURE_SUCCESS(res, res);
+  ErrorResult rv;
+  *outNode = CreateHTMLContent(aNodeType, rv).take();
+  NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
 
   nsCOMPtr elem = do_QueryInterface(*outNode);
   
   nsIDOMNode* inNode = aNode->AsDOMNode();
 
   // set attribute if needed
+  nsresult res;
   if (aAttribute && aValue && !aAttribute->IsEmpty()) {
     res = elem->SetAttribute(*aAttribute, *aValue);
     NS_ENSURE_SUCCESS(res, res);
@@ -1701,13 +1702,12 @@ nsEditor::InsertContainerAbove(nsIContent* aNode,
   int32_t offset = parent->IndexOf(aNode);
 
   // create new container
-  nsCOMPtr newContent;
-
-  //new call to use instead to get proper HTML element, bug# 39919
-  nsresult res = CreateHTMLContent(aNodeType, getter_AddRefs(newContent));
-  NS_ENSURE_SUCCESS(res, res);
+  ErrorResult rv;
+  nsCOMPtr newContent = CreateHTMLContent(aNodeType, rv);
+  NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
 
   // set attribute if needed
+  nsresult res;
   if (aAttribute && aValue && !aAttribute->IsEmpty()) {
     nsIDOMNode* elem = newContent->AsDOMNode();
     res = static_cast(elem)->SetAttribute(*aAttribute, *aValue);
@@ -4749,22 +4749,31 @@ nsresult nsEditor::ClearSelection()
   return selection->RemoveAllRanges();  
 }
 
-nsresult
-nsEditor::CreateHTMLContent(const nsAString& aTag, dom::Element** aContent)
+already_AddRefed
+nsEditor::CreateHTMLContent(const nsAString& aTag, ErrorResult& rv)
 {
   nsCOMPtr doc = GetDocument();
-  NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+  if (!doc) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
   // XXX Wallpaper over editor bug (editor tries to create elements with an
   //     empty nodename).
   if (aTag.IsEmpty()) {
     NS_ERROR("Don't pass an empty tag to nsEditor::CreateHTMLContent, "
              "check caller.");
-    return NS_ERROR_FAILURE;
+    rv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
 
-  return doc->CreateElem(aTag, nullptr, kNameSpaceID_XHTML,
-                         reinterpret_cast(aContent));
+  nsCOMPtr ret;
+  nsresult res = doc->CreateElem(aTag, nullptr, kNameSpaceID_XHTML,
+                                 getter_AddRefs(ret));
+  if (NS_FAILED(res)) {
+    rv.Throw(res);
+  }
+  return dont_AddRef(ret.forget().take()->AsElement());
 }
 
 nsresult
diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h
index cc6a5427f7f..334da4dd7d1 100644
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -67,6 +67,7 @@ class nsString;
 class nsTransactionManager;
 
 namespace mozilla {
+class ErrorResult;
 class TextComposition;
 
 namespace dom {
@@ -240,10 +241,9 @@ public:
   /* Method to replace certain CreateElementNS() calls. 
      Arguments:
       nsString& aTag          - tag you want
-      nsIContent** aContent   - returned Content that was created with above namespace.
   */
-  nsresult CreateHTMLContent(const nsAString& aTag,
-                             mozilla::dom::Element** aContent);
+  already_AddRefed
+    CreateHTMLContent(const nsAString& aTag, mozilla::ErrorResult& rv);
 
   // IME event handlers
   virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
diff --git a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
index da2632de592..345424232ba 100644
--- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
@@ -49,6 +49,7 @@ class nsIDOMEventListener;
 class nsISelection;
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 // retrieve an integer stored into a CSS computed float value
 static int32_t GetCSSFloatValue(nsIDOMCSSStyleDeclaration * aDecl,
@@ -146,14 +147,15 @@ nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode *  aPare
   NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
 
   // Create a new node through the element factory
-  nsCOMPtr newContent;
-  nsresult res = CreateHTMLContent(aTag, getter_AddRefs(newContent));
-  NS_ENSURE_SUCCESS(res, res);
+  ErrorResult rv;
+  nsCOMPtr newContent = CreateHTMLContent(aTag, rv);
+  NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
 
   nsCOMPtr newElement = do_QueryInterface(newContent);
   NS_ENSURE_TRUE(newElement, NS_ERROR_FAILURE);
 
   // add the "hidden" class if needed
+  nsresult res;
   if (aIsCreatedHidden) {
     res = newElement->SetAttribute(NS_LITERAL_STRING("class"),
                                    NS_LITERAL_STRING("hidden"));
diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp
index 91aef065477..574c9cea186 100644
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -2570,11 +2570,12 @@ nsHTMLEditor::CreateElementWithDefaults(const nsAString& aTagName, nsIDOMElement
   nsCOMPtr doc = do_QueryReferent(mDocWeak);
   NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
 
-  //new call to use instead to get proper HTML element, bug# 39919
-  res = CreateHTMLContent(realTagName, getter_AddRefs(newContent));
+  ErrorResult rv;
+  newContent = CreateHTMLContent(realTagName, rv);
   newElement = do_QueryInterface(newContent);
-  if (NS_FAILED(res) || !newElement)
+  if (rv.Failed() || !newElement) {
     return NS_ERROR_FAILURE;
+  }
 
   // Mark the new element dirty, so it will be formatted
   newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString());
diff --git a/editor/libeditor/html/nsHTMLEditorStyle.cpp b/editor/libeditor/html/nsHTMLEditorStyle.cpp
index 123ed8ffb0c..0e0716eb906 100644
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -312,11 +312,10 @@ nsHTMLEditor::IsSimpleModifiableNode(nsIContent* aContent,
   // "text-decoration: underline", which decomposes into four different text-*
   // properties.  So for now, we just create a span, add the desired style, and
   // see if it matches.
-  nsCOMPtr newSpan;
-  nsresult res = CreateHTMLContent(NS_LITERAL_STRING("span"),
-                                   getter_AddRefs(newSpan));
-  NS_ASSERTION(NS_SUCCEEDED(res), "CreateHTMLContent failed");
-  NS_ENSURE_SUCCESS(res, false);
+  ErrorResult rv;
+  nsCOMPtr newSpan = CreateHTMLContent(NS_LITERAL_STRING("span"), rv);
+  NS_ASSERTION(!rv.Failed(), "CreateHTMLContent failed");
+  NS_ENSURE_SUCCESS(rv.ErrorCode(), false);
   mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(newSpan, aProperty,
                                              aAttribute, aValue,
                                              /*suppress transaction*/ true);
diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp
index bd49f8e888d..22e04e8cb58 100644
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -1158,9 +1158,10 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
   }
 
   // Create a br.
-  nsCOMPtr newContent;
-  nsresult rv = mEditor->CreateHTMLContent(NS_LITERAL_STRING("br"), getter_AddRefs(newContent));
-  NS_ENSURE_SUCCESS(rv, rv);
+  ErrorResult res;
+  nsCOMPtr newContent =
+    mEditor->CreateHTMLContent(NS_LITERAL_STRING("br"), res);
+  NS_ENSURE_SUCCESS(res.ErrorCode(), res.ErrorCode());
 
   // set mBogusNode to be the newly created 
mBogusNode = do_QueryInterface(newContent); @@ -1172,7 +1173,7 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection) // Put the node in the document. nsCOMPtr bodyNode = do_QueryInterface(body); - rv = mEditor->InsertNode(mBogusNode, bodyNode, 0); + nsresult rv = mEditor->InsertNode(mBogusNode, bodyNode, 0); NS_ENSURE_SUCCESS(rv, rv); // Set selection. From 7968de819d730e18a134e92ede292ba43ce463c8 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 14:54:47 +0300 Subject: [PATCH 16/50] Bug 1002429 part 8 - Clean up nsHTMLEditor::CreateElementWithDefaults; r=ehsan --- editor/libeditor/html/nsHTMLEditor.cpp | 83 +++++++++++++------------- editor/libeditor/html/nsHTMLEditor.h | 4 +- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 574c9cea186..759ae21e16f 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -2542,66 +2542,67 @@ nsHTMLEditor::GetSelectedElement(const nsAString& aTagName, nsIDOMElement** aRet return res; } -NS_IMETHODIMP -nsHTMLEditor::CreateElementWithDefaults(const nsAString& aTagName, nsIDOMElement** aReturn) +already_AddRefed +nsHTMLEditor::CreateElementWithDefaults(const nsAString& aTagName) { - nsresult res=NS_ERROR_NOT_INITIALIZED; - if (aReturn) - *aReturn = nullptr; + MOZ_ASSERT(!aTagName.IsEmpty()); -// NS_ENSURE_TRUE(aTagName && aReturn, NS_ERROR_NULL_POINTER); - NS_ENSURE_TRUE(!aTagName.IsEmpty() && aReturn, NS_ERROR_NULL_POINTER); - - nsAutoString TagName(aTagName); - ToLowerCase(TagName); + nsAutoString tagName(aTagName); + ToLowerCase(tagName); nsAutoString realTagName; - if (IsLinkTag(TagName) || IsNamedAnchorTag(TagName)) - { + if (IsLinkTag(tagName) || IsNamedAnchorTag(tagName)) { realTagName.AssignLiteral("a"); } else { - realTagName = TagName; + realTagName = tagName; } - //We don't use editor's CreateElement because we don't want to - // go through the transaction system - - nsCOMPtrnewElement; - nsCOMPtr newContent; - nsCOMPtr doc = do_QueryReferent(mDocWeak); - NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED); + // We don't use editor's CreateElement because we don't want to go through + // the transaction system + // New call to use instead to get proper HTML element, bug 39919 ErrorResult rv; - newContent = CreateHTMLContent(realTagName, rv); - newElement = do_QueryInterface(newContent); + nsCOMPtr newElement = CreateHTMLContent(realTagName, rv); if (rv.Failed() || !newElement) { - return NS_ERROR_FAILURE; + return nullptr; } // Mark the new element dirty, so it will be formatted - newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString()); + newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString(), rv); // Set default values for new elements - if (TagName.EqualsLiteral("table")) { - res = newElement->SetAttribute(NS_LITERAL_STRING("cellpadding"),NS_LITERAL_STRING("2")); - NS_ENSURE_SUCCESS(res, res); - res = newElement->SetAttribute(NS_LITERAL_STRING("cellspacing"),NS_LITERAL_STRING("2")); - NS_ENSURE_SUCCESS(res, res); - res = newElement->SetAttribute(NS_LITERAL_STRING("border"),NS_LITERAL_STRING("1")); - } else if (TagName.EqualsLiteral("td")) - { - res = SetAttributeOrEquivalent(newElement, NS_LITERAL_STRING("valign"), - NS_LITERAL_STRING("top"), true); + if (tagName.EqualsLiteral("table")) { + newElement->SetAttribute(NS_LITERAL_STRING("cellpadding"), + NS_LITERAL_STRING("2"), rv); + NS_ENSURE_SUCCESS(rv.ErrorCode(), nullptr); + newElement->SetAttribute(NS_LITERAL_STRING("cellspacing"), + NS_LITERAL_STRING("2"), rv); + NS_ENSURE_SUCCESS(rv.ErrorCode(), nullptr); + newElement->SetAttribute(NS_LITERAL_STRING("border"), + NS_LITERAL_STRING("1"), rv); + NS_ENSURE_SUCCESS(rv.ErrorCode(), nullptr); + } else if (tagName.EqualsLiteral("td")) { + nsresult res = SetAttributeOrEquivalent( + static_cast(newElement->AsDOMNode()), + NS_LITERAL_STRING("valign"), NS_LITERAL_STRING("top"), true); + NS_ENSURE_SUCCESS(res, nullptr); } // ADD OTHER TAGS HERE - if (NS_SUCCEEDED(res)) - { - *aReturn = newElement; - // Getters must addref - NS_ADDREF(*aReturn); - } + return newElement.forget(); +} - return res; +NS_IMETHODIMP +nsHTMLEditor::CreateElementWithDefaults(const nsAString& aTagName, nsIDOMElement** aReturn) +{ + NS_ENSURE_TRUE(!aTagName.IsEmpty() && aReturn, NS_ERROR_NULL_POINTER); + *aReturn = nullptr; + + nsCOMPtr newElement = CreateElementWithDefaults(aTagName); + nsCOMPtr ret = do_QueryInterface(newElement); + NS_ENSURE_TRUE(ret, NS_ERROR_FAILURE); + + ret.forget(aReturn); + return NS_OK; } NS_IMETHODIMP diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 4705a852477..b3e43017cc1 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -963,7 +963,9 @@ private: nsIContent* aChild, int32_t aIndexInContainer, InsertedOrAppended aInsertedOrAppended); already_AddRefed GetElementOrParentByTagName( - const nsAString& aTagName, nsINode* aNode); + const nsAString& aTagName, nsINode* aNode); + already_AddRefed CreateElementWithDefaults( + const nsAString& aTagName); }; #endif //nsHTMLEditor_h__ From 62b85e51b99a321d0da31f82ddb41ca7e22ae806 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 14:54:47 +0300 Subject: [PATCH 17/50] Bug 1002429 part 9 - Clean up nsHTMLEditor::RebuildDocumentFromSource; r=ehsan --- editor/libeditor/html/nsHTMLEditor.cpp | 109 +++++++++++++------------ 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 759ae21e16f..8900b2496cf 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -1248,11 +1248,10 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString) { ForceCompositionEnd(); - nsCOMPtrselection; - nsresult res = GetSelection(getter_AddRefs(selection)); - NS_ENSURE_SUCCESS(res, res); + nsRefPtr selection = GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); - nsCOMPtr bodyElement = do_QueryInterface(GetRoot()); + nsCOMPtr bodyElement = GetRoot(); NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER); // Find where the tag starts. @@ -1261,17 +1260,18 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString) aSourceString.BeginReading(beginbody); aSourceString.EndReading(endbody); bool foundbody = CaseInsensitiveFindInReadable(NS_LITERAL_STRING(" beginhead; nsReadingIterator endhead; aSourceString.BeginReading(beginhead); aSourceString.EndReading(endhead); bool foundhead = CaseInsensitiveFindInReadable(NS_LITERAL_STRING(" beginbody.get()) + if (foundbody && beginhead.get() > beginbody.get()) { foundhead = false; + } nsReadingIterator beginclosehead; nsReadingIterator endclosehead; @@ -1282,11 +1282,13 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString) bool foundclosehead = CaseInsensitiveFindInReadable( NS_LITERAL_STRING(""), beginclosehead, endclosehead); // a valid close head appears after a found head - if (foundhead && beginhead.get() > beginclosehead.get()) + if (foundhead && beginhead.get() > beginclosehead.get()) { foundclosehead = false; + } // a valid close head appears before a found body - if (foundbody && beginclosehead.get() > beginbody.get()) + if (foundbody && beginclosehead.get() > beginbody.get()) { foundclosehead = false; + } // Time to change the document nsAutoEditBatch beginBatching(this); @@ -1294,29 +1296,34 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString) nsReadingIterator endtotal; aSourceString.EndReading(endtotal); + nsresult res; if (foundhead) { - if (foundclosehead) + if (foundclosehead) { res = ReplaceHeadContentsWithHTML(Substring(beginhead, beginclosehead)); - else if (foundbody) + } else if (foundbody) { res = ReplaceHeadContentsWithHTML(Substring(beginhead, beginbody)); - else - // XXX Without recourse to some parser/content sink/docshell hackery - // we don't really know where the head ends and the body begins - // so we assume that there is no body + } else { + // XXX Without recourse to some parser/content sink/docshell hackery we + // don't really know where the head ends and the body begins so we assume + // that there is no body res = ReplaceHeadContentsWithHTML(Substring(beginhead, endtotal)); + } } else { nsReadingIterator begintotal; aSourceString.BeginReading(begintotal); NS_NAMED_LITERAL_STRING(head, ""); - if (foundclosehead) - res = ReplaceHeadContentsWithHTML(head + Substring(begintotal, beginclosehead)); - else if (foundbody) - res = ReplaceHeadContentsWithHTML(head + Substring(begintotal, beginbody)); - else - // XXX Without recourse to some parser/content sink/docshell hackery - // we don't really know where the head ends and the body begins - // so we assume that there is no head + if (foundclosehead) { + res = ReplaceHeadContentsWithHTML(head + Substring(begintotal, + beginclosehead)); + } else if (foundbody) { + res = ReplaceHeadContentsWithHTML(head + Substring(begintotal, + beginbody)); + } else { + // XXX Without recourse to some parser/content sink/docshell hackery we + // don't really know where the head ends and the body begins so we assume + // that there is no head res = ReplaceHeadContentsWithHTML(head); + } } NS_ENSURE_SUCCESS(res, res); @@ -1325,22 +1332,25 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString) if (!foundbody) { NS_NAMED_LITERAL_STRING(body, ""); - // XXX Without recourse to some parser/content sink/docshell hackery - // we don't really know where the head ends and the body begins - if (foundclosehead) // assume body starts after the head ends + // XXX Without recourse to some parser/content sink/docshell hackery we + // don't really know where the head ends and the body begins + if (foundclosehead) { + // assume body starts after the head ends res = LoadHTML(body + Substring(endclosehead, endtotal)); - else if (foundhead) // assume there is no body + } else if (foundhead) { + // assume there is no body res = LoadHTML(body); - else // assume there is no head, the entire source is body + } else { + // assume there is no head, the entire source is body res = LoadHTML(body + aSourceString); + } NS_ENSURE_SUCCESS(res, res); - nsCOMPtr divElement; - res = CreateElementWithDefaults(NS_LITERAL_STRING("div"), getter_AddRefs(divElement)); - NS_ENSURE_SUCCESS(res, res); + nsCOMPtr divElement = + CreateElementWithDefaults(NS_LITERAL_STRING("div")); + NS_ENSURE_TRUE(divElement, NS_ERROR_FAILURE); - res = CloneAttributes(bodyElement, divElement); - NS_ENSURE_SUCCESS(res, res); + CloneAttributes(bodyElement->AsDOMNode(), divElement->AsDOMNode()); return BeginningOfDocument(); } @@ -1349,40 +1359,37 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString) NS_ENSURE_SUCCESS(res, res); // Now we must copy attributes user might have edited on the tag - // because InsertHTML (actually, CreateContextualFragment()) - // will never return a body node in the DOM fragment + // because InsertHTML (actually, CreateContextualFragment()) will never + // return a body node in the DOM fragment // We already know where " beginclosebody = beginbody; nsReadingIterator endclosebody; aSourceString.EndReading(endclosebody); - if (!FindInReadable(NS_LITERAL_STRING(">"),beginclosebody,endclosebody)) + if (!FindInReadable(NS_LITERAL_STRING(">"), beginclosebody, endclosebody)) { return NS_ERROR_FAILURE; + } - // Truncate at the end of the body tag - // Kludge of the year: fool the parser by replacing "body" with "div" so we get a node + // Truncate at the end of the body tag. Kludge of the year: fool the parser + // by replacing "body" with "div" so we get a node nsAutoString bodyTag; bodyTag.AssignLiteral("
range; - res = selection->GetRangeAt(0, getter_AddRefs(range)); - NS_ENSURE_SUCCESS(res, res); + nsRefPtr range = selection->GetRangeAt(0); + NS_ENSURE_TRUE(range, NS_ERROR_FAILURE); - nsCOMPtr docfrag; - res = range->CreateContextualFragment(bodyTag, getter_AddRefs(docfrag)); - NS_ENSURE_SUCCESS(res, res); + ErrorResult rv; + nsRefPtr docfrag = + range->CreateContextualFragment(bodyTag, rv); + NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode()); + NS_ENSURE_TRUE(docfrag, NS_ERROR_NULL_POINTER); - nsCOMPtr fragmentAsNode (do_QueryInterface(docfrag)); - NS_ENSURE_TRUE(fragmentAsNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr child; - res = fragmentAsNode->GetFirstChild(getter_AddRefs(child)); - NS_ENSURE_SUCCESS(res, res); + nsCOMPtr child = docfrag->GetFirstChild(); NS_ENSURE_TRUE(child, NS_ERROR_NULL_POINTER); // Copy all attributes from the div child to current body element - res = CloneAttributes(bodyElement, child); + res = CloneAttributes(bodyElement->AsDOMNode(), child->AsDOMNode()); NS_ENSURE_SUCCESS(res, res); // place selection at first editable content From 1b1fb53eb979bf73f649a11f765a3c4cc673cb95 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 18:34:05 +0300 Subject: [PATCH 18/50] Bug 1003808 part 1 - Clean up DOMPoint; r=ehsan --- editor/libeditor/base/nsEditorUtils.h | 24 +++++++++++------ editor/libeditor/html/nsHTMLEditRules.cpp | 18 +++---------- editor/libeditor/html/nsWSRunObject.cpp | 33 ++++++++++++----------- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/editor/libeditor/base/nsEditorUtils.h b/editor/libeditor/base/nsEditorUtils.h index 6d1828db12d..ce6bc979c23 100644 --- a/editor/libeditor/base/nsEditorUtils.h +++ b/editor/libeditor/base/nsEditorUtils.h @@ -204,19 +204,27 @@ class nsTrivialFunctor : public nsBoolDomIterFunctor *****************************************************************************/ struct MOZ_STACK_CLASS DOMPoint { - nsCOMPtr node; + nsCOMPtr node; int32_t offset; - DOMPoint() : node(0),offset(0) {} - DOMPoint(nsIDOMNode *aNode, int32_t aOffset) : - node(aNode),offset(aOffset) {} - void SetPoint(nsIDOMNode *aNode, int32_t aOffset) + DOMPoint(nsINode* aNode, int32_t aOffset) + : node(aNode) + , offset(aOffset) + {} + DOMPoint(nsIDOMNode* aNode, int32_t aOffset) + : node(do_QueryInterface(aNode)) + , offset(aOffset) + {} + + void SetPoint(nsINode* aNode, int32_t aOffset) { - node = aNode; offset = aOffset; + node = aNode; + offset = aOffset; } - void GetPoint(nsCOMPtr &aNode, int32_t &aOffset) + void SetPoint(nsIDOMNode* aNode, int32_t aOffset) { - aNode = node; aOffset = offset; + node = do_QueryInterface(aNode); + offset = aOffset; } }; diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 7d8f79b3278..e24befe88d4 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -6470,22 +6470,10 @@ nsHTMLEditRules::GetNodesFromPoint(::DOMPoint point, nsCOMArray &arrayOfNodes, bool dontTouchContent) { - nsresult res; - - // get our point - nsCOMPtr node; - int32_t offset; - point.GetPoint(node, offset); - - // use it to make a range - nsCOMPtr nativeNode = do_QueryInterface(node); - NS_ENSURE_STATE(nativeNode); - nsRefPtr range = new nsRange(nativeNode); - res = range->SetStart(node, offset); + NS_ENSURE_STATE(point.node); + nsRefPtr range = new nsRange(point.node); + nsresult res = range->SetStart(point.node, point.offset); NS_ENSURE_SUCCESS(res, res); - /* SetStart() will also set the end for this new range - res = range->SetEnd(node, offset); - NS_ENSURE_SUCCESS(res, res); */ // expand the range to include adjacent inlines res = PromoteRange(range, operation); diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 2c9b162269f..2fc397f641a 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -668,7 +668,8 @@ nsWSRunObject::GetWSNodes() mLastNBSPOffset = pos; } } - start.SetPoint(mNode,pos); + start.node = do_QueryInterface(mNode); + start.offset = pos; } } } @@ -683,7 +684,8 @@ nsWSRunObject::GetWSNodes() { if (IsBlockNode(priorNode)) { - start.GetPoint(mStartNode, mStartOffset); + mStartNode = GetAsDOMNode(start.node); + mStartOffset = start.offset; mStartReason = WSType::otherBlock; mStartReasonNode = priorNode; } @@ -744,7 +746,8 @@ nsWSRunObject::GetWSNodes() { // it's a break or a special node, like , that is not a block and not // a break but still serves as a terminator to ws runs. - start.GetPoint(mStartNode, mStartOffset); + mStartNode = GetAsDOMNode(start.node); + mStartOffset = start.offset; if (nsTextEditUtils::IsBreak(priorNode)) mStartReason = WSType::br; else @@ -755,7 +758,8 @@ nsWSRunObject::GetWSNodes() else { // no prior node means we exhausted wsBoundingParent - start.GetPoint(mStartNode, mStartOffset); + mStartNode = GetAsDOMNode(start.node); + mStartOffset = start.offset; mStartReason = WSType::thisBlock; mStartReasonNode = wsBoundingParent; } @@ -817,7 +821,8 @@ nsWSRunObject::GetWSNodes() if (IsBlockNode(nextNode)) { // we encountered a new block. therefore no more ws. - end.GetPoint(mEndNode, mEndOffset); + mEndNode = GetAsDOMNode(end.node); + mEndOffset = end.offset; mEndReason = WSType::otherBlock; mEndReasonNode = nextNode; } @@ -879,7 +884,8 @@ nsWSRunObject::GetWSNodes() // we encountered a break or a special node, like , // that is not a block and not a break but still // serves as a terminator to ws runs. - end.GetPoint(mEndNode, mEndOffset); + mEndNode = GetAsDOMNode(end.node); + mEndOffset = end.offset; if (nsTextEditUtils::IsBreak(nextNode)) mEndReason = WSType::br; else @@ -890,7 +896,8 @@ nsWSRunObject::GetWSNodes() else { // no next node means we exhausted wsBoundingParent - end.GetPoint(mEndNode, mEndOffset); + mEndNode = GetAsDOMNode(end.node); + mEndOffset = end.offset; mEndReason = WSType::thisBlock; mEndReasonNode = wsBoundingParent; } @@ -1128,10 +1135,8 @@ nsWSRunObject::GetPreviousWSNode(DOMPoint aPoint, nsIDOMNode *aBlockParent, nsCOMPtr *aPriorNode) { - nsCOMPtr node; - int32_t offset; - aPoint.GetPoint(node, offset); - return GetPreviousWSNode(node,offset,aBlockParent,aPriorNode); + return GetPreviousWSNode(GetAsDOMNode(aPoint.node), aPoint.offset, aBlockParent, + aPriorNode); } nsresult @@ -1236,10 +1241,8 @@ nsWSRunObject::GetNextWSNode(DOMPoint aPoint, nsIDOMNode *aBlockParent, nsCOMPtr *aNextNode) { - nsCOMPtr node; - int32_t offset; - aPoint.GetPoint(node, offset); - return GetNextWSNode(node,offset,aBlockParent,aNextNode); + return GetNextWSNode(GetAsDOMNode(aPoint.node), aPoint.offset, aBlockParent, + aNextNode); } nsresult From 22dae1beb557d6639ddd8f34cd842ce5253aeae9 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 18:34:05 +0300 Subject: [PATCH 19/50] Bug 1003808 part 2 - Clean up nsEditorUtils::IsDescendantOf; r=ehsan --- editor/libeditor/base/nsEditorUtils.cpp | 47 ++++++++++++------------- editor/libeditor/base/nsEditorUtils.h | 1 + 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/editor/libeditor/base/nsEditorUtils.cpp b/editor/libeditor/base/nsEditorUtils.cpp index 6e3e93f78a4..57c82fc876d 100644 --- a/editor/libeditor/base/nsEditorUtils.cpp +++ b/editor/libeditor/base/nsEditorUtils.cpp @@ -138,38 +138,35 @@ nsDOMSubtreeIterator::Init(nsIDOMRange* aRange) * some general purpose editor utils *****************************************************************************/ -bool -nsEditorUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t *aOffset) +bool +nsEditorUtils::IsDescendantOf(nsINode* aNode, nsINode* aParent, int32_t* aOffset) { - NS_ENSURE_TRUE(aNode || aParent, false); - if (aNode == aParent) return false; - - nsCOMPtr parent, node = do_QueryInterface(aNode); - nsresult res; - - do - { - res = node->GetParentNode(getter_AddRefs(parent)); - NS_ENSURE_SUCCESS(res, false); - if (parent == aParent) - { - if (aOffset) - { - nsCOMPtr pCon(do_QueryInterface(parent)); - nsCOMPtr cCon(do_QueryInterface(node)); - if (pCon) - { - *aOffset = pCon->IndexOf(cCon); - } + MOZ_ASSERT(aNode && aParent); + if (aNode == aParent) { + return false; + } + + for (nsCOMPtr node = aNode; node; node = node->GetParentNode()) { + if (node->GetParentNode() == aParent) { + if (aOffset) { + *aOffset = aParent->IndexOf(node); } return true; } - node = parent; - } while (parent); - + } + return false; } +bool +nsEditorUtils::IsDescendantOf(nsIDOMNode* aNode, nsIDOMNode* aParent, int32_t* aOffset) +{ + nsCOMPtr node = do_QueryInterface(aNode); + nsCOMPtr parent = do_QueryInterface(aParent); + NS_ENSURE_TRUE(node && parent, false); + return IsDescendantOf(node, parent, aOffset); +} + bool nsEditorUtils::IsLeafNode(nsIDOMNode *aNode) { diff --git a/editor/libeditor/base/nsEditorUtils.h b/editor/libeditor/base/nsEditorUtils.h index ce6bc979c23..a929b420a9b 100644 --- a/editor/libeditor/base/nsEditorUtils.h +++ b/editor/libeditor/base/nsEditorUtils.h @@ -232,6 +232,7 @@ struct MOZ_STACK_CLASS DOMPoint class nsEditorUtils { public: + static bool IsDescendantOf(nsINode* aNode, nsINode* aParent, int32_t* aOffset = 0); static bool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t *aOffset = 0); static bool IsLeafNode(nsIDOMNode *aNode); }; From 8d1b35692589026b03616139017cae1591a381cb Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 18:34:05 +0300 Subject: [PATCH 20/50] Bug 1003808 part 3 - Clean up nsRangeStore; r=ehsan --- editor/libeditor/base/nsSelectionState.cpp | 476 ++++++++++++--------- editor/libeditor/base/nsSelectionState.h | 36 +- editor/libeditor/html/nsHTMLEditRules.cpp | 67 ++- 3 files changed, 316 insertions(+), 263 deletions(-) diff --git a/editor/libeditor/base/nsSelectionState.cpp b/editor/libeditor/base/nsSelectionState.cpp index 1a0d6aa3cf7..6e93a725bdd 100644 --- a/editor/libeditor/base/nsSelectionState.cpp +++ b/editor/libeditor/base/nsSelectionState.cpp @@ -12,6 +12,7 @@ #include "nsEditor.h" // for nsEditor #include "nsEditorUtils.h" // for nsEditorUtils #include "nsError.h" // for NS_OK, etc +#include "nsIContent.h" // for nsIContent #include "nsIDOMCharacterData.h" // for nsIDOMCharacterData #include "nsIDOMNode.h" // for nsIDOMNode #include "nsIDOMRange.h" // for nsIDOMRange, etc @@ -89,8 +90,7 @@ nsSelectionState::RestoreSelection(nsISelection *aSel) // set the selection ranges anew for (i=0; i range; - mArray[i]->GetRange(getter_AddRefs(range)); + nsRefPtr range = mArray[i]->GetRange(); NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED); res = aSel->AddRange(range); @@ -104,8 +104,7 @@ bool nsSelectionState::IsCollapsed() { if (1 != mArray.Length()) return false; - nsRefPtr range; - mArray[0]->GetRange(getter_AddRefs(range)); + nsRefPtr range = mArray[0]->GetRange(); NS_ENSURE_TRUE(range, false); bool bIsCollapsed = false; range->GetCollapsed(&bIsCollapsed); @@ -122,9 +121,8 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState) for (i=0; i myRange, itsRange; - mArray[i]->GetRange(getter_AddRefs(myRange)); - aSelState->mArray[i]->GetRange(getter_AddRefs(itsRange)); + nsRefPtr myRange = mArray[i]->GetRange(); + nsRefPtr itsRange = aSelState->mArray[i]->GetRange(); NS_ENSURE_TRUE(myRange && itsRange, false); int16_t compResult; @@ -212,30 +210,45 @@ nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState) // gravity methods: nsresult -nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition) +nsRangeUpdater::SelAdjCreateNode(nsINode* aParent, int32_t aPosition) { - if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... + if (mLock) { + // lock set by Will/DidReplaceParent, etc... + return NS_OK; + } NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER); - uint32_t i, count = mArray.Length(); + uint32_t count = mArray.Length(); if (!count) { return NS_OK; } - nsRangeStore *item; - - for (i=0; istartNode.get() == aParent) && (item->startOffset > aPosition)) + + if (item->startNode == aParent && item->startOffset > aPosition) { item->startOffset++; - if ((item->endNode.get() == aParent) && (item->endOffset > aPosition)) + } + if (item->endNode == aParent && item->endOffset > aPosition) { item->endOffset++; + } } return NS_OK; } +nsresult +nsRangeUpdater::SelAdjCreateNode(nsIDOMNode* aParent, int32_t aPosition) +{ + nsCOMPtr parent = do_QueryInterface(aParent); + return SelAdjCreateNode(parent, aPosition); +} + +nsresult +nsRangeUpdater::SelAdjInsertNode(nsINode* aParent, int32_t aPosition) +{ + return SelAdjCreateNode(aParent, aPosition); +} + nsresult nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition) { @@ -243,49 +256,46 @@ nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition) } void -nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode) +nsRangeUpdater::SelAdjDeleteNode(nsINode* aNode) { if (mLock) { // lock set by Will/DidReplaceParent, etc... return; } MOZ_ASSERT(aNode); - uint32_t i, count = mArray.Length(); + uint32_t count = mArray.Length(); if (!count) { return; } - int32_t offset = 0; - nsCOMPtr parent = nsEditor::GetNodeLocation(aNode, &offset); - + nsCOMPtr parent = aNode->GetParentNode(); + int32_t offset = parent ? parent->IndexOf(aNode) : -1; + // check for range endpoints that are after aNode and in the same parent - nsRangeStore *item; - for (i=0; istartNode.get() == parent) && (item->startOffset > offset)) + + if (item->startNode == parent && item->startOffset > offset) { item->startOffset--; - if ((item->endNode.get() == parent) && (item->endOffset > offset)) + } + if (item->endNode == parent && item->endOffset > offset) { item->endOffset--; - + } + // check for range endpoints that are in aNode - if (item->startNode == aNode) - { + if (item->startNode == aNode) { item->startNode = parent; item->startOffset = offset; } - if (item->endNode == aNode) - { + if (item->endNode == aNode) { item->endNode = parent; item->endOffset = offset; } // check for range endpoints that are in descendants of aNode - nsCOMPtr oldStart; - if (nsEditorUtils::IsDescendantOf(item->startNode, aNode)) - { + nsCOMPtr oldStart; + if (nsEditorUtils::IsDescendantOf(item->startNode, aNode)) { oldStart = item->startNode; // save for efficiency hack below. item->startNode = parent; item->startOffset = offset; @@ -300,51 +310,52 @@ nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode) } } +void +nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode) +{ + nsCOMPtr node = do_QueryInterface(aNode); + NS_ENSURE_TRUE(node, ); + return SelAdjDeleteNode(node); +} + nsresult -nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode) +nsRangeUpdater::SelAdjSplitNode(nsINode* aOldRightNode, int32_t aOffset, + nsINode* aNewLeftNode) { - if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... + if (mLock) { + // lock set by Will/DidReplaceParent, etc... + return NS_OK; + } NS_ENSURE_TRUE(aOldRightNode && aNewLeftNode, NS_ERROR_NULL_POINTER); - uint32_t i, count = mArray.Length(); + uint32_t count = mArray.Length(); if (!count) { return NS_OK; } - int32_t offset; - nsCOMPtr parent = nsEditor::GetNodeLocation(aOldRightNode, &offset); - + nsCOMPtr parent = aOldRightNode->GetParentNode(); + int32_t offset = parent ? parent->IndexOf(aOldRightNode) : -1; + // first part is same as inserting aNewLeftnode - nsresult result = SelAdjInsertNode(parent,offset-1); + nsresult result = SelAdjInsertNode(parent, offset - 1); NS_ENSURE_SUCCESS(result, result); // next step is to check for range enpoints inside aOldRightNode - nsRangeStore *item; - - for (i=0; istartNode.get() == aOldRightNode) - { - if (item->startOffset > aOffset) - { + + if (item->startNode == aOldRightNode) { + if (item->startOffset > aOffset) { item->startOffset -= aOffset; - } - else - { + } else { item->startNode = aNewLeftNode; } } - if (item->endNode.get() == aOldRightNode) - { - if (item->endOffset > aOffset) - { + if (item->endNode == aOldRightNode) { + if (item->endOffset > aOffset) { item->endOffset -= aOffset; - } - else - { + } else { item->endNode = aNewLeftNode; } } @@ -352,143 +363,171 @@ nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsID return NS_OK; } - nsresult -nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode, - nsIDOMNode *aRightNode, - nsIDOMNode *aParent, - int32_t aOffset, - int32_t aOldLeftNodeLength) +nsRangeUpdater::SelAdjSplitNode(nsIDOMNode* aOldRightNode, int32_t aOffset, + nsIDOMNode* aNewLeftNode) { - if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... - NS_ENSURE_TRUE(aLeftNode && aRightNode && aParent, NS_ERROR_NULL_POINTER); - uint32_t i, count = mArray.Length(); - if (!count) { - return NS_OK; - } - - nsRangeStore *item; - - for (i=0; istartNode.get() == aParent) - { - // adjust start point in aParent - if (item->startOffset > aOffset) - { - item->startOffset--; - } - else if (item->startOffset == aOffset) - { - // join keeps right hand node - item->startNode = aRightNode; - item->startOffset = aOldLeftNodeLength; - } - } - else if (item->startNode.get() == aRightNode) - { - // adjust start point in aRightNode - item->startOffset += aOldLeftNodeLength; - } - else if (item->startNode.get() == aLeftNode) - { - // adjust start point in aLeftNode - item->startNode = aRightNode; - } - - if (item->endNode.get() == aParent) - { - // adjust end point in aParent - if (item->endOffset > aOffset) - { - item->endOffset--; - } - else if (item->endOffset == aOffset) - { - // join keeps right hand node - item->endNode = aRightNode; - item->endOffset = aOldLeftNodeLength; - } - } - else if (item->endNode.get() == aRightNode) - { - // adjust end point in aRightNode - item->endOffset += aOldLeftNodeLength; - } - else if (item->endNode.get() == aLeftNode) - { - // adjust end point in aLeftNode - item->endNode = aRightNode; - } - } - - return NS_OK; + nsCOMPtr oldRightNode = do_QueryInterface(aOldRightNode); + nsCOMPtr newLeftNode = do_QueryInterface(aNewLeftNode); + return SelAdjSplitNode(oldRightNode, aOffset, newLeftNode); } nsresult -nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString) +nsRangeUpdater::SelAdjJoinNodes(nsINode* aLeftNode, + nsINode* aRightNode, + nsINode* aParent, + int32_t aOffset, + int32_t aOldLeftNodeLength) { - if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... + if (mLock) { + // lock set by Will/DidReplaceParent, etc... + return NS_OK; + } + NS_ENSURE_TRUE(aLeftNode && aRightNode && aParent, NS_ERROR_NULL_POINTER); + uint32_t count = mArray.Length(); + if (!count) { + return NS_OK; + } + + for (uint32_t i = 0; i < count; i++) { + nsRangeStore* item = mArray[i]; + NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER); + + if (item->startNode == aParent) { + // adjust start point in aParent + if (item->startOffset > aOffset) { + item->startOffset--; + } else if (item->startOffset == aOffset) { + // join keeps right hand node + item->startNode = aRightNode; + item->startOffset = aOldLeftNodeLength; + } + } else if (item->startNode == aRightNode) { + // adjust start point in aRightNode + item->startOffset += aOldLeftNodeLength; + } else if (item->startNode == aLeftNode) { + // adjust start point in aLeftNode + item->startNode = aRightNode; + } + + if (item->endNode == aParent) { + // adjust end point in aParent + if (item->endOffset > aOffset) { + item->endOffset--; + } else if (item->endOffset == aOffset) { + // join keeps right hand node + item->endNode = aRightNode; + item->endOffset = aOldLeftNodeLength; + } + } else if (item->endNode == aRightNode) { + // adjust end point in aRightNode + item->endOffset += aOldLeftNodeLength; + } else if (item->endNode == aLeftNode) { + // adjust end point in aLeftNode + item->endNode = aRightNode; + } + } + + return NS_OK; +} + +nsresult +nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode* aLeftNode, + nsIDOMNode* aRightNode, + nsIDOMNode* aParent, + int32_t aOffset, + int32_t aOldLeftNodeLength) +{ + nsCOMPtr leftNode = do_QueryInterface(aLeftNode); + nsCOMPtr rightNode = do_QueryInterface(aRightNode); + nsCOMPtr parent = do_QueryInterface(aParent); + return SelAdjJoinNodes(leftNode, rightNode, parent, aOffset, aOldLeftNodeLength); +} + + +nsresult +nsRangeUpdater::SelAdjInsertText(nsIContent* aTextNode, int32_t aOffset, + const nsAString &aString) +{ + if (mLock) { + // lock set by Will/DidReplaceParent, etc... + return NS_OK; + } uint32_t count = mArray.Length(); if (!count) { return NS_OK; } - nsCOMPtr node(do_QueryInterface(aTextNode)); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - - uint32_t len=aString.Length(), i; - nsRangeStore *item; - for (i=0; istartNode.get() == node) && (item->startOffset > aOffset)) + + if (item->startNode == aTextNode && item->startOffset > aOffset) { item->startOffset += len; - if ((item->endNode.get() == node) && (item->endOffset > aOffset)) + } + if (item->endNode == aTextNode && item->endOffset > aOffset) { item->endOffset += len; + } } return NS_OK; } +nsresult +nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData* aTextNode, + int32_t aOffset, const nsAString &aString) +{ + nsCOMPtr textNode = do_QueryInterface(aTextNode); + return SelAdjInsertText(textNode, aOffset, aString); +} + nsresult -nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength) +nsRangeUpdater::SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset, + int32_t aLength) { - if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc... + if (mLock) { + // lock set by Will/DidReplaceParent, etc... + return NS_OK; + } - uint32_t i, count = mArray.Length(); + uint32_t count = mArray.Length(); if (!count) { return NS_OK; } - nsRangeStore *item; - nsCOMPtr node(do_QueryInterface(aTextNode)); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - - for (i=0; istartNode.get() == node) && (item->startOffset > aOffset)) - { + + if (item->startNode == aTextNode && item->startOffset > aOffset) { item->startOffset -= aLength; - if (item->startOffset < 0) item->startOffset = 0; + if (item->startOffset < 0) { + item->startOffset = 0; + } } - if ((item->endNode.get() == node) && (item->endOffset > aOffset)) - { + if (item->endNode == aTextNode && item->endOffset > aOffset) { item->endOffset -= aLength; - if (item->endOffset < 0) item->endOffset = 0; + if (item->endOffset < 0) { + item->endOffset = 0; + } } } return NS_OK; } +nsresult +nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData* aTextNode, + int32_t aOffset, int32_t aLength) +{ + nsCOMPtr textNode = do_QueryInterface(aTextNode); + return SelAdjDeleteText(textNode, aOffset, aLength); +} + nsresult nsRangeUpdater::WillReplaceContainer() @@ -500,32 +539,40 @@ nsRangeUpdater::WillReplaceContainer() nsresult -nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) +nsRangeUpdater::DidReplaceContainer(nsINode* aOriginalNode, nsINode* aNewNode) { - NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); + NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); mLock = false; NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER); - uint32_t i, count = mArray.Length(); + uint32_t count = mArray.Length(); if (!count) { return NS_OK; } - nsRangeStore *item; - - for (i=0; istartNode.get() == aOriginalNode) + if (item->startNode == aOriginalNode) { item->startNode = aNewNode; - if (item->endNode.get() == aOriginalNode) + } + if (item->endNode == aOriginalNode) { item->endNode = aNewNode; + } } return NS_OK; } +nsresult +nsRangeUpdater::DidReplaceContainer(nsIDOMNode* aOriginalNode, + nsIDOMNode* aNewNode) +{ + nsCOMPtr originalNode = do_QueryInterface(aOriginalNode); + nsCOMPtr newNode = do_QueryInterface(aNewNode); + return DidReplaceContainer(originalNode, newNode); +} + nsresult nsRangeUpdater::WillRemoveContainer() @@ -537,43 +584,48 @@ nsRangeUpdater::WillRemoveContainer() nsresult -nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen) +nsRangeUpdater::DidRemoveContainer(nsINode* aNode, nsINode* aParent, + int32_t aOffset, uint32_t aNodeOrigLen) { - NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); + NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED); mLock = false; NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER); - uint32_t i, count = mArray.Length(); + uint32_t count = mArray.Length(); if (!count) { return NS_OK; } - nsRangeStore *item; - - for (i=0; istartNode.get() == aNode) - { + if (item->startNode == aNode) { item->startNode = aParent; item->startOffset += aOffset; + } else if (item->startNode == aParent && item->startOffset > aOffset) { + item->startOffset += (int32_t)aNodeOrigLen - 1; } - else if ((item->startNode.get() == aParent) && (item->startOffset > aOffset)) - item->startOffset += (int32_t)aNodeOrigLen-1; - if (item->endNode.get() == aNode) - { + if (item->endNode == aNode) { item->endNode = aParent; item->endOffset += aOffset; + } else if (item->endNode == aParent && item->endOffset > aOffset) { + item->endOffset += (int32_t)aNodeOrigLen - 1; } - else if ((item->endNode.get() == aParent) && (item->endOffset > aOffset)) - item->endOffset += (int32_t)aNodeOrigLen-1; } return NS_OK; } +nsresult +nsRangeUpdater::DidRemoveContainer(nsIDOMNode* aNode, nsIDOMNode* aParent, + int32_t aOffset, uint32_t aNodeOrigLen) +{ + nsCOMPtr node = do_QueryInterface(aNode); + nsCOMPtr parent = do_QueryInterface(aParent); + return DidRemoveContainer(node, parent, aOffset, aNodeOrigLen); +} + nsresult nsRangeUpdater::WillInsertContainer() @@ -609,26 +661,23 @@ nsRangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset, NS_ENSURE_TRUE_VOID(mLock); mLock = false; - nsIDOMNode* oldParent = aOldParent->AsDOMNode(); - nsIDOMNode* newParent = aNewParent->AsDOMNode(); - for (uint32_t i = 0, count = mArray.Length(); i < count; ++i) { nsRangeStore* item = mArray[i]; NS_ENSURE_TRUE_VOID(item); // like a delete in aOldParent - if (item->startNode == oldParent && item->startOffset > aOldOffset) { + if (item->startNode == aOldParent && item->startOffset > aOldOffset) { item->startOffset--; } - if (item->endNode == oldParent && item->endOffset > aOldOffset) { + if (item->endNode == aOldParent && item->endOffset > aOldOffset) { item->endOffset--; } // and like an insert in aNewParent - if (item->startNode == newParent && item->startOffset > aNewOffset) { + if (item->startNode == aNewParent && item->startOffset > aNewOffset) { item->startOffset++; } - if (item->endNode == newParent && item->endOffset > aNewOffset) { + if (item->endNode == aNewParent && item->endOffset > aNewOffset) { item->endOffset++; } } @@ -640,29 +689,28 @@ nsRangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset, * helper class for nsSelectionState. nsRangeStore stores range endpoints. */ - // DEBUG: int32_t nsRangeStore::n = 0; - nsRangeStore::nsRangeStore() { - // DEBUG: n++; printf("range store alloc count=%d\n", n); } nsRangeStore::~nsRangeStore() { - // DEBUG: n--; printf("range store alloc count=%d\n", n); } -nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange) +void +nsRangeStore::StoreRange(nsRange* aRange) { - NS_ENSURE_TRUE(aRange, NS_ERROR_NULL_POINTER); - aRange->GetStartContainer(getter_AddRefs(startNode)); - aRange->GetEndContainer(getter_AddRefs(endNode)); - aRange->GetStartOffset(&startOffset); - aRange->GetEndOffset(&endOffset); - return NS_OK; + MOZ_ASSERT(aRange); + startNode = aRange->GetStartParent(); + startOffset = aRange->StartOffset(); + endNode = aRange->GetEndParent(); + endOffset = aRange->EndOffset(); } -nsresult nsRangeStore::GetRange(nsRange** outRange) +already_AddRefed +nsRangeStore::GetRange() { - return nsRange::CreateRange(startNode, startOffset, endNode, endOffset, - outRange); + nsRefPtr range = new nsRange(startNode); + nsresult res = range->Set(startNode, startOffset, endNode, endOffset); + NS_ENSURE_SUCCESS(res, nullptr); + return range.forget(); } diff --git a/editor/libeditor/base/nsSelectionState.h b/editor/libeditor/base/nsSelectionState.h index c0ba5fbba04..bade710083f 100644 --- a/editor/libeditor/base/nsSelectionState.h +++ b/editor/libeditor/base/nsSelectionState.h @@ -39,16 +39,15 @@ private: ~nsRangeStore(); public: - nsresult StoreRange(nsIDOMRange *aRange); - nsresult GetRange(nsRange** outRange); + void StoreRange(nsRange* aRange); + already_AddRefed GetRange(); NS_INLINE_DECL_REFCOUNTING(nsRangeStore) - nsCOMPtr startNode; - int32_t startOffset; - nsCOMPtr endNode; - int32_t endOffset; - // DEBUG: static int32_t n; + nsCOMPtr startNode; + int32_t startOffset; + nsCOMPtr endNode; + int32_t endOffset; }; class nsSelectionState @@ -90,22 +89,39 @@ class nsRangeUpdater // if you move a node, that corresponds to deleting it and reinserting it. // DOM Range gravity will promote the selection out of the node on deletion, // which is not what you want if you know you are reinserting it. + nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition); nsresult SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition); + nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition); nsresult SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition); + void SelAdjDeleteNode(nsINode* aNode); void SelAdjDeleteNode(nsIDOMNode *aNode); + nsresult SelAdjSplitNode(nsINode* aOldRightNode, int32_t aOffset, + nsINode* aNewLeftNode); nsresult SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode); + nsresult SelAdjJoinNodes(nsINode* aLeftNode, + nsINode* aRightNode, + nsINode* aParent, + int32_t aOffset, + int32_t aOldLeftNodeLength); nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMNode *aParent, int32_t aOffset, int32_t aOldLeftNodeLength); + nsresult SelAdjInsertText(nsIContent* aTextNode, int32_t aOffset, + const nsAString &aString); nsresult SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString); + nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset, + int32_t aLength); nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength); // the following gravity routines need will/did sandwiches, because the other gravity // routines will be called inside of these sandwiches, but should be ignored. nsresult WillReplaceContainer(); + nsresult DidReplaceContainer(nsINode* aOriginalNode, nsINode* aNewNode); nsresult DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode); nsresult WillRemoveContainer(); + nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent, + int32_t aOffset, uint32_t aNodeOrigLen); nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen); nsresult WillInsertContainer(); nsresult DidInsertContainer(); @@ -137,8 +153,8 @@ class MOZ_STACK_CLASS nsAutoTrackDOMPoint ,mOffset(aOffset) { mRangeItem = new nsRangeStore(); - mRangeItem->startNode = *mNode; - mRangeItem->endNode = *mNode; + mRangeItem->startNode = do_QueryInterface(*mNode); + mRangeItem->endNode = do_QueryInterface(*mNode); mRangeItem->startOffset = *mOffset; mRangeItem->endOffset = *mOffset; mRU.RegisterRangeItem(mRangeItem); @@ -147,7 +163,7 @@ class MOZ_STACK_CLASS nsAutoTrackDOMPoint ~nsAutoTrackDOMPoint() { mRU.DropRangeItem(mRangeItem); - *mNode = mRangeItem->startNode; + *mNode = GetAsDOMNode(mRangeItem->startNode); *mOffset = mRangeItem->startOffset; } }; diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index e24befe88d4..ad3fa6c6fba 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -304,26 +304,17 @@ nsHTMLEditRules::BeforeEdit(EditAction action, // remember where our selection was before edit action took place: // get selection - nsCOMPtr selection; NS_ENSURE_STATE(mHTMLEditor); - nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection)); - NS_ENSURE_SUCCESS(res, res); - - // get the selection start location - nsCOMPtr selStartNode, selEndNode; - int32_t selOffset; - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selStartNode), &selOffset); - NS_ENSURE_SUCCESS(res, res); - mRangeItem->startNode = selStartNode; - mRangeItem->startOffset = selOffset; + nsRefPtr selection = mHTMLEditor->GetSelection(); - // get the selection end location - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->GetEndNodeAndOffset(selection, getter_AddRefs(selEndNode), &selOffset); - NS_ENSURE_SUCCESS(res, res); - mRangeItem->endNode = selEndNode; - mRangeItem->endOffset = selOffset; + // get the selection location + NS_ENSURE_STATE(selection->GetRangeCount()); + mRangeItem->startNode = selection->GetRangeAt(0)->GetStartParent(); + mRangeItem->startOffset = selection->GetRangeAt(0)->StartOffset(); + mRangeItem->endNode = selection->GetRangeAt(0)->GetEndParent(); + mRangeItem->endOffset = selection->GetRangeAt(0)->EndOffset(); + nsCOMPtr selStartNode = GetAsDOMNode(mRangeItem->startNode); + nsCOMPtr selEndNode = GetAsDOMNode(mRangeItem->endNode); // register this range with range updater to track this as we perturb the doc NS_ENSURE_STATE(mHTMLEditor); @@ -352,7 +343,7 @@ nsHTMLEditRules::BeforeEdit(EditAction action, nsCOMPtr selNode = selStartNode; if (aDirection == nsIEditor::eNext) selNode = selEndNode; - res = CacheInlineStyles(selNode); + nsresult res = CacheInlineStyles(selNode); NS_ENSURE_SUCCESS(res, res); } @@ -490,13 +481,13 @@ nsHTMLEditRules::AfterEditInner(EditAction action, // also do this for original selection endpoints. NS_ENSURE_STATE(mHTMLEditor); - nsWSRunObject(mHTMLEditor, mRangeItem->startNode, + nsWSRunObject(mHTMLEditor, GetAsDOMNode(mRangeItem->startNode), mRangeItem->startOffset).AdjustWhitespace(); // we only need to handle old selection endpoint if it was different from start if (mRangeItem->startNode != mRangeItem->endNode || mRangeItem->startOffset != mRangeItem->endOffset) { NS_ENSURE_STATE(mHTMLEditor); - nsWSRunObject(mHTMLEditor, mRangeItem->endNode, + nsWSRunObject(mHTMLEditor, GetAsDOMNode(mRangeItem->endNode), mRangeItem->endOffset).AdjustWhitespace(); } } @@ -536,7 +527,7 @@ nsHTMLEditRules::AfterEditInner(EditAction action, NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->HandleInlineSpellCheck(action, selection, - mRangeItem->startNode, + GetAsDOMNode(mRangeItem->startNode), mRangeItem->startOffset, rangeStartParent, rangeStartOffset, rangeEndParent, rangeEndOffset); @@ -5942,7 +5933,7 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray& inArrayOfRanges, { opRange = inArrayOfRanges[0]; rangeItemArray[i] = new nsRangeStore(); - rangeItemArray[i]->StoreRange(opRange); + rangeItemArray[i]->StoreRange(static_cast(opRange.get())); NS_ENSURE_STATE(mHTMLEditor); mHTMLEditor->mRangeUpdater.RegisterRangeItem(rangeItemArray[i]); inArrayOfRanges.RemoveObjectAt(0); @@ -5959,14 +5950,7 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray& inArrayOfRanges, nsRangeStore* item = rangeItemArray[i]; NS_ENSURE_STATE(mHTMLEditor); mHTMLEditor->mRangeUpdater.DropRangeItem(item); - nsRefPtr range; - nsresult res2 = item->GetRange(getter_AddRefs(range)); - opRange = range; - if (NS_FAILED(res2) && NS_SUCCEEDED(res)) { - // Remember the failure, but keep going so we make sure to unregister - // all our range items. - res = res2; - } + opRange = item->GetRange(); inArrayOfRanges.AppendObject(opRange); } NS_ENSURE_SUCCESS(res, res); @@ -6331,7 +6315,8 @@ nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item) nsresult res = NS_OK; bool isCollapsed = ((item.startNode == item.endNode) && (item.startOffset == item.endOffset)); - nsCOMPtr endInline = GetHighestInlineParent(item.endNode); + nsCOMPtr endInline = + GetHighestInlineParent(GetAsDOMNode(item.endNode)); // if we have inline parents above range endpoints, split them if (endInline && !isCollapsed) @@ -6340,14 +6325,16 @@ nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item) int32_t resultEndOffset; endInline->GetParentNode(getter_AddRefs(resultEndNode)); NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->SplitNodeDeep(endInline, item.endNode, item.endOffset, - &resultEndOffset, true); + res = mHTMLEditor->SplitNodeDeep(endInline, GetAsDOMNode(item.endNode), + item.endOffset, &resultEndOffset, true); NS_ENSURE_SUCCESS(res, res); // reset range - item.endNode = resultEndNode; item.endOffset = resultEndOffset; + item.endNode = do_QueryInterface(resultEndNode); + item.endOffset = resultEndOffset; } - nsCOMPtr startInline = GetHighestInlineParent(item.startNode); + nsCOMPtr startInline = + GetHighestInlineParent(GetAsDOMNode(item.startNode)); if (startInline) { @@ -6355,11 +6342,13 @@ nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item) int32_t resultStartOffset; startInline->GetParentNode(getter_AddRefs(resultStartNode)); NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->SplitNodeDeep(startInline, item.startNode, item.startOffset, - &resultStartOffset, true); + res = mHTMLEditor->SplitNodeDeep(startInline, GetAsDOMNode(item.startNode), + item.startOffset, &resultStartOffset, + true); NS_ENSURE_SUCCESS(res, res); // reset range - item.startNode = resultStartNode; item.startOffset = resultStartOffset; + item.startNode = do_QueryInterface(resultStartNode); + item.startOffset = resultStartOffset; } return res; From ba48c57163eb6777dda53cc8ead744e596b8fd8f Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 18:40:28 +0300 Subject: [PATCH 21/50] Bug 1003808 part 4 - Clean up nsAutoTrackDOMPoint; r=ehsan --- editor/libeditor/base/nsSelectionState.h | 43 ++++++++++++++++++------ 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/editor/libeditor/base/nsSelectionState.h b/editor/libeditor/base/nsSelectionState.h index bade710083f..d93f5f9b9fd 100644 --- a/editor/libeditor/base/nsSelectionState.h +++ b/editor/libeditor/base/nsSelectionState.h @@ -143,27 +143,50 @@ class MOZ_STACK_CLASS nsAutoTrackDOMPoint { private: nsRangeUpdater &mRU; - nsCOMPtr *mNode; - int32_t *mOffset; + // Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone + nsCOMPtr* mNode; + nsCOMPtr* mDOMNode; + int32_t* mOffset; nsRefPtr mRangeItem; public: - nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr *aNode, int32_t *aOffset) : - mRU(aRangeUpdater) - ,mNode(aNode) - ,mOffset(aOffset) + nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, + nsCOMPtr* aNode, int32_t* aOffset) + : mRU(aRangeUpdater) + , mNode(aNode) + , mDOMNode(nullptr) + , mOffset(aOffset) { mRangeItem = new nsRangeStore(); - mRangeItem->startNode = do_QueryInterface(*mNode); - mRangeItem->endNode = do_QueryInterface(*mNode); + mRangeItem->startNode = *mNode; + mRangeItem->endNode = *mNode; mRangeItem->startOffset = *mOffset; mRangeItem->endOffset = *mOffset; mRU.RegisterRangeItem(mRangeItem); } - + + nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, + nsCOMPtr* aNode, int32_t* aOffset) + : mRU(aRangeUpdater) + , mNode(nullptr) + , mDOMNode(aNode) + , mOffset(aOffset) + { + mRangeItem = new nsRangeStore(); + mRangeItem->startNode = do_QueryInterface(*mDOMNode); + mRangeItem->endNode = do_QueryInterface(*mDOMNode); + mRangeItem->startOffset = *mOffset; + mRangeItem->endOffset = *mOffset; + mRU.RegisterRangeItem(mRangeItem); + } + ~nsAutoTrackDOMPoint() { mRU.DropRangeItem(mRangeItem); - *mNode = GetAsDOMNode(mRangeItem->startNode); + if (mNode) { + *mNode = mRangeItem->startNode; + } else { + *mDOMNode = GetAsDOMNode(mRangeItem->startNode); + } *mOffset = mRangeItem->startOffset; } }; From d48aa32574a48b1a048bba0ccdaae7df7a404ed4 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Mon, 28 Apr 2014 19:03:12 +0300 Subject: [PATCH 22/50] Bug 1003808 part 5 - Allow nsEditor::IsEditable to take nsINode*; r=ehsan --- editor/libeditor/base/nsEditor.cpp | 16 ++++++++++------ editor/libeditor/base/nsEditor.h | 4 ++-- editor/libeditor/html/nsHTMLEditor.cpp | 2 +- editor/libeditor/html/nsHTMLEditor.h | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index b3b314b7f5a..629f60e65e0 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -3566,11 +3566,14 @@ nsEditor::IsEditable(nsIDOMNode *aNode) } bool -nsEditor::IsEditable(nsIContent *aNode) +nsEditor::IsEditable(nsINode* aNode) { NS_ENSURE_TRUE(aNode, false); - if (IsMozEditorBogusNode(aNode) || !IsModifiableNode(aNode)) return false; + if (!aNode->IsNodeOfType(nsINode::eCONTENT) || IsMozEditorBogusNode(aNode) || + !IsModifiableNode(aNode)) { + return false; + } // see if it has a frame. If so, we'll edit it. // special case for textnodes: frame must have width. @@ -3590,11 +3593,12 @@ nsEditor::IsEditable(nsIContent *aNode) } bool -nsEditor::IsMozEditorBogusNode(nsIContent *element) +nsEditor::IsMozEditorBogusNode(nsINode* element) { - return element && - element->AttrValueIs(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom, - kMOZEditorBogusNodeValue, eCaseMatters); + return element && element->IsElement() && + element->AsElement()->AttrValueIs(kNameSpaceID_None, + kMOZEditorBogusNodeAttrAtom, kMOZEditorBogusNodeValue, + eCaseMatters); } uint32_t diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index 334da4dd7d1..824e3c7bfaa 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -592,10 +592,10 @@ public: /** returns true if aNode is an editable node */ bool IsEditable(nsIDOMNode *aNode); - virtual bool IsEditable(nsIContent *aNode); + virtual bool IsEditable(nsINode* aNode); /** returns true if aNode is a MozEditorBogus node */ - bool IsMozEditorBogusNode(nsIContent *aNode); + bool IsMozEditorBogusNode(nsINode* aNode); /** counts number of editable child nodes */ uint32_t CountEditableChildren(nsINode* aNode); diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 8900b2496cf..cdda2cf31e9 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -5427,7 +5427,7 @@ nsHTMLEditor::GetInputEventTargetContent() } bool -nsHTMLEditor::IsEditable(nsIContent* aNode) { +nsHTMLEditor::IsEditable(nsINode* aNode) { if (!nsPlaintextEditor::IsEditable(aNode)) { return false; } diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index b3e43017cc1..7f207e58518 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -111,7 +111,7 @@ public: virtual already_AddRefed FindSelectionRoot(nsINode *aNode); virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent); virtual already_AddRefed GetInputEventTargetContent(); - virtual bool IsEditable(nsIContent *aNode); + virtual bool IsEditable(nsINode* aNode) MOZ_OVERRIDE; using nsEditor::IsEditable; /* ------------ nsStubMutationObserver overrides --------- */ From 9886b7ea2545724b81e9876f1fd1f04440c008a2 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 23/50] Bug 1003808 part 6 - Convert nsWSRunObject members to nsINode; r=ehsan --- editor/libeditor/html/nsHTMLDataTransfer.cpp | 4 +- editor/libeditor/html/nsHTMLEditRules.cpp | 30 ++-- editor/libeditor/html/nsWSRunObject.cpp | 144 ++++++++++--------- editor/libeditor/html/nsWSRunObject.h | 38 ++--- 4 files changed, 109 insertions(+), 107 deletions(-) diff --git a/editor/libeditor/html/nsHTMLDataTransfer.cpp b/editor/libeditor/html/nsHTMLDataTransfer.cpp index dc928445f8d..f3a0a479b15 100644 --- a/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -676,7 +676,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString, { // don't leave selection past an invisible break; // reset {selNode,selOffset} to point before break - selNode = GetNodeLocation(wsRunObj.mStartReasonNode, &selOffset); + selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset); // we want to be inside any inline style prior to break nsWSRunObject wsRunObj(this, selNode, selOffset); wsRunObj.PriorVisibleNode(selNode, selOffset, address_of(visNode), @@ -687,7 +687,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString, } else if (visType == WSType::special) { // prior visible thing is an image or some other non-text thingy. // We want to be right after it. - selNode = GetNodeLocation(wsRunObj.mStartReasonNode, &selOffset); + selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset); ++selOffset; } } diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index ad3fa6c6fba..44e77dbe2a3 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -5186,7 +5186,7 @@ nsHTMLEditRules::CheckForInvisibleBR(nsIDOMNode *aBlock, { nsWSRunObject wsTester(mHTMLEditor, testNode, testOffset); if (WSType::br == wsTester.mStartReason) { - *outBRNode = wsTester.mStartReasonNode; + *outBRNode = GetAsDOMNode(wsTester.mStartReasonNode); } } @@ -5298,15 +5298,14 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection) if (wsType == WSType::thisBlock) { // we want to keep looking up. But stop if we are crossing table element // boundaries, or if we hit the root. - if ( nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) || - (selCommon == wsObj.mStartReasonNode) || - (rootElement == wsObj.mStartReasonNode) ) - { + if (nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) || + selCommon == GetAsDOMNode(wsObj.mStartReasonNode) || + rootElement == GetAsDOMNode(wsObj.mStartReasonNode)) { stillLooking = false; } else { - selStartNode = nsEditor::GetNodeLocation(wsObj.mStartReasonNode, + selStartNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mStartReasonNode), &selStartOffset); } } @@ -5338,21 +5337,20 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection) firstBRParent = selEndNode; firstBROffset = selEndOffset; } - selEndNode = nsEditor::GetNodeLocation(wsObj.mEndReasonNode, &selEndOffset); + selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset); ++selEndOffset; } } else if (wsType == WSType::thisBlock) { // we want to keep looking up. But stop if we are crossing table element // boundaries, or if we hit the root. - if ( nsHTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) || - (selCommon == wsObj.mEndReasonNode) || - (rootElement == wsObj.mEndReasonNode) ) - { + if (nsHTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) || + selCommon == GetAsDOMNode(wsObj.mEndReasonNode) || + rootElement == GetAsDOMNode(wsObj.mEndReasonNode)) { stillLooking = false; } else { - selEndNode = nsEditor::GetNodeLocation(wsObj.mEndReasonNode, &selEndOffset); + selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset); ++selEndOffset; } } @@ -5475,7 +5473,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection) // of going "down" into a block and "up" out of a block. if (wsEndObj.mStartReason == WSType::otherBlock) { // endpoint is just after the close of a block. - nsCOMPtr child = mHTMLEditor->GetRightmostChild(wsEndObj.mStartReasonNode, true); + nsCOMPtr child = mHTMLEditor->GetRightmostChild(GetAsDOMNode(wsEndObj.mStartReasonNode), true); if (child) { newEndNode = nsEditor::GetNodeLocation(child, &newEndOffset); @@ -5495,7 +5493,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection) // else block is empty - we can leave selection alone here, i think. } else if (wsEndObj.mStartReason == WSType::br) { // endpoint is just after break. lets adjust it to before it. - newEndNode = nsEditor::GetNodeLocation(wsEndObj.mStartReasonNode, + newEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsEndObj.mStartReasonNode), &newEndOffset); } } @@ -5512,7 +5510,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection) // of going "down" into a block and "up" out of a block. if (wsStartObj.mEndReason == WSType::otherBlock) { // startpoint is just before the start of a block. - nsCOMPtr child = mHTMLEditor->GetLeftmostChild(wsStartObj.mEndReasonNode, true); + nsCOMPtr child = mHTMLEditor->GetLeftmostChild(GetAsDOMNode(wsStartObj.mEndReasonNode), true); if (child) { newStartNode = nsEditor::GetNodeLocation(child, &newStartOffset); @@ -5530,7 +5528,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection) // else block is empty - we can leave selection alone here, i think. } else if (wsStartObj.mEndReason == WSType::br) { // startpoint is just before a break. lets adjust it to after it. - newStartNode = nsEditor::GetNodeLocation(wsStartObj.mEndReasonNode, + newStartNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsStartObj.mEndReasonNode), &newStartOffset); ++newStartOffset; // offset *after* break } diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 2fc397f641a..15f01a64da5 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -36,7 +36,7 @@ static bool IsBlockNode(nsIDOMNode* node) //- constructor / destructor ----------------------------------------------- nsWSRunObject::nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, int32_t aOffset) : -mNode(aNode) +mNode(do_QueryInterface(aNode)) ,mOffset(aOffset) ,mPRE(false) ,mStartNode() @@ -370,7 +370,7 @@ nsresult nsWSRunObject::DeleteWSBackward() { nsresult res = NS_OK; - WSPoint point = GetCharBefore(mNode, mOffset); + WSPoint point = GetCharBefore(GetAsDOMNode(mNode), mOffset); NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete if (mPRE) // easy case, preformatted ws @@ -422,7 +422,7 @@ nsresult nsWSRunObject::DeleteWSForward() { nsresult res = NS_OK; - WSPoint point = GetCharAfter(mNode, mOffset); + WSPoint point = GetCharAfter(GetAsDOMNode(mNode), mOffset); NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete if (mPRE) // easy case, preformatted ws @@ -516,7 +516,7 @@ nsWSRunObject::PriorVisibleNode(nsIDOMNode *aNode, } // if we get here then nothing in ws data to find. return start reason - *outVisNode = mStartReasonNode; + *outVisNode = GetAsDOMNode(mStartReasonNode); *outVisOffset = mStartOffset; // this really isn't meaningful if mStartReasonNode!=mStartNode *outType = mStartReason; } @@ -567,7 +567,7 @@ nsWSRunObject::NextVisibleNode (nsIDOMNode *aNode, } // if we get here then nothing in ws data to find. return end reason - *outVisNode = mEndReasonNode; + *outVisNode = GetAsDOMNode(mEndReasonNode); *outVisOffset = mEndOffset; // this really isn't meaningful if mEndReasonNode!=mEndNode *outType = mEndReason; } @@ -605,7 +605,7 @@ already_AddRefed nsWSRunObject::GetWSBoundingParent() { NS_ENSURE_TRUE(mNode, nullptr); - nsCOMPtr wsBoundingParent = mNode; + nsCOMPtr wsBoundingParent = GetAsDOMNode(mNode); while (!IsBlockNode(wsBoundingParent)) { nsCOMPtr parent; @@ -634,7 +634,7 @@ nsWSRunObject::GetWSNodes() nsCOMPtr textNode(do_QueryInterface(mNode)); const nsTextFragment *textFrag = textNode->GetText(); - res = PrependNodeToList(mNode); + res = PrependNodeToList(GetAsDOMNode(mNode)); NS_ENSURE_SUCCESS(res, res); if (mOffset) { @@ -684,10 +684,10 @@ nsWSRunObject::GetWSNodes() { if (IsBlockNode(priorNode)) { - mStartNode = GetAsDOMNode(start.node); + mStartNode = start.node; mStartOffset = start.offset; mStartReason = WSType::otherBlock; - mStartReasonNode = priorNode; + mStartReasonNode = do_QueryInterface(priorNode); } else if (mHTMLEditor->IsTextNode(priorNode)) { @@ -722,19 +722,19 @@ nsWSRunObject::GetWSNodes() { if (theChar != nbsp) { - mStartNode = priorNode; + mStartNode = do_QueryInterface(priorNode); mStartOffset = pos+1; mStartReason = WSType::text; - mStartReasonNode = priorNode; + mStartReasonNode = do_QueryInterface(priorNode); break; } // as we look backwards update our earliest found nbsp - mFirstNBSPNode = priorNode; + mFirstNBSPNode = do_QueryInterface(priorNode); mFirstNBSPOffset = pos; // also keep track of latest nbsp so far if (!mLastNBSPNode) { - mLastNBSPNode = priorNode; + mLastNBSPNode = do_QueryInterface(priorNode); mLastNBSPOffset = pos; } } @@ -746,22 +746,22 @@ nsWSRunObject::GetWSNodes() { // it's a break or a special node, like , that is not a block and not // a break but still serves as a terminator to ws runs. - mStartNode = GetAsDOMNode(start.node); + mStartNode = start.node; mStartOffset = start.offset; if (nsTextEditUtils::IsBreak(priorNode)) mStartReason = WSType::br; else mStartReason = WSType::special; - mStartReasonNode = priorNode; + mStartReasonNode = do_QueryInterface(priorNode); } } else { // no prior node means we exhausted wsBoundingParent - mStartNode = GetAsDOMNode(start.node); + mStartNode = start.node; mStartOffset = start.offset; mStartReason = WSType::thisBlock; - mStartReasonNode = wsBoundingParent; + mStartReasonNode = do_QueryInterface(wsBoundingParent); } } @@ -821,10 +821,10 @@ nsWSRunObject::GetWSNodes() if (IsBlockNode(nextNode)) { // we encountered a new block. therefore no more ws. - mEndNode = GetAsDOMNode(end.node); + mEndNode = end.node; mEndOffset = end.offset; mEndReason = WSType::otherBlock; - mEndReasonNode = nextNode; + mEndReasonNode = do_QueryInterface(nextNode); } else if (mHTMLEditor->IsTextNode(nextNode)) { @@ -859,19 +859,19 @@ nsWSRunObject::GetWSNodes() { if (theChar != nbsp) { - mEndNode = nextNode; + mEndNode = do_QueryInterface(nextNode); mEndOffset = pos; mEndReason = WSType::text; - mEndReasonNode = nextNode; + mEndReasonNode = do_QueryInterface(nextNode); break; } // as we look forwards update our latest found nbsp - mLastNBSPNode = nextNode; + mLastNBSPNode = do_QueryInterface(nextNode); mLastNBSPOffset = pos; // also keep track of earliest nbsp so far if (!mFirstNBSPNode) { - mFirstNBSPNode = nextNode; + mFirstNBSPNode = do_QueryInterface(nextNode); mFirstNBSPOffset = pos; } } @@ -884,22 +884,22 @@ nsWSRunObject::GetWSNodes() // we encountered a break or a special node, like , // that is not a block and not a break but still // serves as a terminator to ws runs. - mEndNode = GetAsDOMNode(end.node); + mEndNode = end.node; mEndOffset = end.offset; if (nsTextEditUtils::IsBreak(nextNode)) mEndReason = WSType::br; else mEndReason = WSType::special; - mEndReasonNode = nextNode; + mEndReasonNode = do_QueryInterface(nextNode); } } else { // no next node means we exhausted wsBoundingParent - mEndNode = GetAsDOMNode(end.node); + mEndNode = end.node; mEndOffset = end.offset; mEndReason = WSType::thisBlock; - mEndReasonNode = wsBoundingParent; + mEndReasonNode = do_QueryInterface(wsBoundingParent); } } @@ -912,7 +912,7 @@ nsWSRunObject::GetRuns() ClearRuns(); // handle some easy cases first - mHTMLEditor->IsPreformatted(mNode, &mPRE); + mHTMLEditor->IsPreformatted(GetAsDOMNode(mNode), &mPRE); // if it's preformatedd, or if we are surrounded by text or special, it's all one // big normal ws run if (mPRE || @@ -941,13 +941,13 @@ nsWSRunObject::GetRuns() // otherwise a little trickier. shucks. mStartRun = new WSFragment(); - mStartRun->mStartNode = mStartNode; + mStartRun->mStartNode = GetAsDOMNode(mStartNode); mStartRun->mStartOffset = mStartOffset; if (mStartReason & WSType::block || mStartReason == WSType::br) { // set up mStartRun mStartRun->mType = WSType::leadingWS; - mStartRun->mEndNode = mFirstNBSPNode; + mStartRun->mEndNode = GetAsDOMNode(mFirstNBSPNode); mStartRun->mEndOffset = mFirstNBSPOffset; mStartRun->mLeftType = mStartReason; mStartRun->mRightType = WSType::normalWS; @@ -956,14 +956,14 @@ nsWSRunObject::GetRuns() WSFragment *normalRun = new WSFragment(); mStartRun->mRight = normalRun; normalRun->mType = WSType::normalWS; - normalRun->mStartNode = mFirstNBSPNode; + normalRun->mStartNode = GetAsDOMNode(mFirstNBSPNode); normalRun->mStartOffset = mFirstNBSPOffset; normalRun->mLeftType = WSType::leadingWS; normalRun->mLeft = mStartRun; if (mEndReason != WSType::block) { // then no trailing ws. this normal run ends the overall ws run. normalRun->mRightType = mEndReason; - normalRun->mEndNode = mEndNode; + normalRun->mEndNode = GetAsDOMNode(mEndNode); normalRun->mEndOffset = mEndOffset; mEndRun = normalRun; } @@ -977,22 +977,22 @@ nsWSRunObject::GetRuns() { // normal ws runs right up to adjacent block (nbsp next to block) normalRun->mRightType = mEndReason; - normalRun->mEndNode = mEndNode; + normalRun->mEndNode = GetAsDOMNode(mEndNode); normalRun->mEndOffset = mEndOffset; mEndRun = normalRun; } else { - normalRun->mEndNode = mLastNBSPNode; + normalRun->mEndNode = GetAsDOMNode(mLastNBSPNode); normalRun->mEndOffset = mLastNBSPOffset+1; normalRun->mRightType = WSType::trailingWS; // set up next run WSFragment *lastRun = new WSFragment(); lastRun->mType = WSType::trailingWS; - lastRun->mStartNode = mLastNBSPNode; + lastRun->mStartNode = GetAsDOMNode(mLastNBSPNode); lastRun->mStartOffset = mLastNBSPOffset+1; - lastRun->mEndNode = mEndNode; + lastRun->mEndNode = GetAsDOMNode(mEndNode); lastRun->mEndOffset = mEndOffset; lastRun->mLeftType = WSType::normalWS; lastRun->mLeft = normalRun; @@ -1004,7 +1004,7 @@ nsWSRunObject::GetRuns() } else { // mStartReason is not WSType::block or WSType::br; set up mStartRun mStartRun->mType = WSType::normalWS; - mStartRun->mEndNode = mLastNBSPNode; + mStartRun->mEndNode = GetAsDOMNode(mLastNBSPNode); mStartRun->mEndOffset = mLastNBSPOffset+1; mStartRun->mLeftType = mStartReason; @@ -1015,7 +1015,7 @@ nsWSRunObject::GetRuns() if ((mLastNBSPNode == mEndNode) && (mLastNBSPOffset == (mEndOffset-1))) { mStartRun->mRightType = mEndReason; - mStartRun->mEndNode = mEndNode; + mStartRun->mEndNode = GetAsDOMNode(mEndNode); mStartRun->mEndOffset = mEndOffset; mEndRun = mStartRun; } @@ -1024,7 +1024,7 @@ nsWSRunObject::GetRuns() // set up next run WSFragment *lastRun = new WSFragment(); lastRun->mType = WSType::trailingWS; - lastRun->mStartNode = mLastNBSPNode; + lastRun->mStartNode = GetAsDOMNode(mLastNBSPNode); lastRun->mStartOffset = mLastNBSPOffset+1; lastRun->mLeftType = WSType::normalWS; lastRun->mLeft = mStartRun; @@ -1056,10 +1056,10 @@ nsWSRunObject::MakeSingleWSRun(WSType aType) { mStartRun = new WSFragment(); - mStartRun->mStartNode = mStartNode; + mStartRun->mStartNode = GetAsDOMNode(mStartNode); mStartRun->mStartOffset = mStartOffset; mStartRun->mType = aType; - mStartRun->mEndNode = mEndNode; + mStartRun->mEndNode = GetAsDOMNode(mEndNode); mStartRun->mEndOffset = mEndOffset; mStartRun->mLeftType = mStartReason; mStartRun->mRightType = mEndReason; @@ -1070,8 +1070,9 @@ nsWSRunObject::MakeSingleWSRun(WSType aType) nsresult nsWSRunObject::PrependNodeToList(nsIDOMNode *aNode) { - NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); - if (!mNodeArray.InsertObjectAt(aNode, 0)) + nsCOMPtr node(do_QueryInterface(aNode)); + NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); + if (!mNodeArray.InsertObjectAt(node, 0)) return NS_ERROR_FAILURE; return NS_OK; } @@ -1079,8 +1080,9 @@ nsWSRunObject::PrependNodeToList(nsIDOMNode *aNode) nsresult nsWSRunObject::AppendNodeToList(nsIDOMNode *aNode) { - NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); - if (!mNodeArray.AppendObject(aNode)) + nsCOMPtr node(do_QueryInterface(aNode)); + NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); + if (!mNodeArray.AppendObject(node)) return NS_ERROR_FAILURE; return NS_OK; } @@ -1308,12 +1310,12 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) // get the runs before and after selection WSFragment *beforeRun, *afterRun; - FindRun(mNode, mOffset, &beforeRun, false); - aEndObject->FindRun(aEndObject->mNode, aEndObject->mOffset, &afterRun, true); + FindRun(GetAsDOMNode(mNode), mOffset, &beforeRun, false); + aEndObject->FindRun(GetAsDOMNode(aEndObject->mNode), aEndObject->mOffset, &afterRun, true); // trim after run of any leading ws if (afterRun && (afterRun->mType & WSType::leadingWS)) { - res = aEndObject->DeleteChars(aEndObject->mNode, aEndObject->mOffset, afterRun->mEndNode, afterRun->mEndOffset, + res = aEndObject->DeleteChars(GetAsDOMNode(aEndObject->mNode), aEndObject->mOffset, afterRun->mEndNode, afterRun->mEndOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } @@ -1323,7 +1325,7 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) (!beforeRun && ((mStartReason & WSType::block) || mStartReason == WSType::br))) { // make sure leading char of following ws is an nbsp, so that it will show up - WSPoint point = aEndObject->GetCharAfter(aEndObject->mNode, + WSPoint point = aEndObject->GetCharAfter(GetAsDOMNode(aEndObject->mNode), aEndObject->mOffset); if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) { @@ -1334,7 +1336,7 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) } // trim before run of any trailing ws if (beforeRun && (beforeRun->mType & WSType::trailingWS)) { - res = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset, mNode, mOffset, + res = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset, GetAsDOMNode(mNode), mOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } else if (beforeRun && beforeRun->mType == WSType::normalWS && !mPRE) { @@ -1342,12 +1344,12 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) (afterRun && afterRun->mType == WSType::normalWS) || (!afterRun && (aEndObject->mEndReason & WSType::block))) { // make sure trailing char of starting ws is an nbsp, so that it will show up - WSPoint point = GetCharBefore(mNode, mOffset); + WSPoint point = GetCharBefore(GetAsDOMNode(mNode), mOffset); if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) { nsCOMPtr wsStartNode, wsEndNode; int32_t wsStartOffset, wsEndOffset; - GetAsciiWSBounds(eBoth, mNode, mOffset, address_of(wsStartNode), + GetAsciiWSBounds(eBoth, GetAsDOMNode(mNode), mOffset, address_of(wsStartNode), &wsStartOffset, address_of(wsEndNode), &wsEndOffset); point.mTextNode = do_QueryInterface(wsStartNode); if (!point.mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { @@ -1374,13 +1376,13 @@ nsWSRunObject::PrepareToSplitAcrossBlocksPriv() // get the runs before and after selection WSFragment *beforeRun, *afterRun; - FindRun(mNode, mOffset, &beforeRun, false); - FindRun(mNode, mOffset, &afterRun, true); + FindRun(GetAsDOMNode(mNode), mOffset, &beforeRun, false); + FindRun(GetAsDOMNode(mNode), mOffset, &afterRun, true); // adjust normal ws in afterRun if needed if (afterRun && afterRun->mType == WSType::normalWS) { // make sure leading char of following ws is an nbsp, so that it will show up - WSPoint point = GetCharAfter(mNode, mOffset); + WSPoint point = GetCharAfter(GetAsDOMNode(mNode), mOffset); if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) { res = ConvertToNBSP(point); @@ -1391,12 +1393,12 @@ nsWSRunObject::PrepareToSplitAcrossBlocksPriv() // adjust normal ws in beforeRun if needed if (beforeRun && beforeRun->mType == WSType::normalWS) { // make sure trailing char of starting ws is an nbsp, so that it will show up - WSPoint point = GetCharBefore(mNode, mOffset); + WSPoint point = GetCharBefore(GetAsDOMNode(mNode), mOffset); if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) { nsCOMPtr wsStartNode, wsEndNode; int32_t wsStartOffset, wsEndOffset; - GetAsciiWSBounds(eBoth, mNode, mOffset, address_of(wsStartNode), + GetAsciiWSBounds(eBoth, GetAsDOMNode(mNode), mOffset, address_of(wsStartNode), &wsStartOffset, address_of(wsEndNode), &wsEndOffset); point.mTextNode = do_QueryInterface(wsStartNode); if (!point.mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { @@ -1439,7 +1441,8 @@ nsWSRunObject::DeleteChars(nsIDOMNode *aStartNode, int32_t aStartOffset, return NS_OK; // nothing to delete nsresult res = NS_OK; - int32_t idx = mNodeArray.IndexOf(aStartNode); + nsCOMPtr startNode = do_QueryInterface(aStartNode); + int32_t idx = mNodeArray.IndexOf(startNode); if (idx==-1) idx = 0; // if our strarting point wasn't one of our ws text nodes, // then just go through them from the beginning. nsCOMPtr node; @@ -1459,7 +1462,7 @@ nsWSRunObject::DeleteChars(nsIDOMNode *aStartNode, int32_t aStartOffset, int32_t count = mNodeArray.Count(); while (idx < count) { - node = mNodeArray[idx]; + node = GetAsDOMNode(mNodeArray[idx]); if (!node) break; // we ran out of ws nodes; must have been deleting to end if (node == aStartNode) @@ -1507,7 +1510,8 @@ nsWSRunObject::DeleteChars(nsIDOMNode *aStartNode, int32_t aStartOffset, { res = mHTMLEditor->DeleteNode(node); NS_ENSURE_SUCCESS(res, res); - mNodeArray.RemoveObject(node); + nsCOMPtr node_ = do_QueryInterface(node); + mNodeArray.RemoveObject(node_); --count; --idx; } @@ -1522,7 +1526,8 @@ nsWSRunObject::GetCharAfter(nsIDOMNode *aNode, int32_t aOffset) { MOZ_ASSERT(aNode); - int32_t idx = mNodeArray.IndexOf(aNode); + nsCOMPtr node(do_QueryInterface(aNode)); + int32_t idx = mNodeArray.IndexOf(node); if (idx == -1) { // use range comparisons to get right ws node @@ -1541,7 +1546,8 @@ nsWSRunObject::GetCharBefore(nsIDOMNode *aNode, int32_t aOffset) { MOZ_ASSERT(aNode); - int32_t idx = mNodeArray.IndexOf(aNode); + nsCOMPtr node(do_QueryInterface(aNode)); + int32_t idx = mNodeArray.IndexOf(node); if (idx == -1) { // use range comparisons to get right ws node @@ -1565,8 +1571,7 @@ nsWSRunObject::GetCharAfter(const WSPoint &aPoint) outPoint.mOffset = 0; outPoint.mChar = 0; - nsCOMPtr pointTextNode(do_QueryInterface(aPoint.mTextNode)); - int32_t idx = mNodeArray.IndexOf(pointTextNode); + int32_t idx = mNodeArray.IndexOf(aPoint.mTextNode); if (idx == -1) { // can't find point, but it's not an error return outPoint; @@ -1579,7 +1584,7 @@ nsWSRunObject::GetCharAfter(const WSPoint &aPoint) outPoint.mChar = GetCharAt(aPoint.mTextNode, aPoint.mOffset); return outPoint; } else if (idx + 1 < (int32_t)numNodes) { - nsIDOMNode* node = mNodeArray[idx+1]; + nsIDOMNode* node = GetAsDOMNode(mNodeArray[idx+1]); MOZ_ASSERT(node); outPoint.mTextNode = do_QueryInterface(node); if (!outPoint.mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { @@ -1603,8 +1608,7 @@ nsWSRunObject::GetCharBefore(const WSPoint &aPoint) outPoint.mOffset = 0; outPoint.mChar = 0; - nsCOMPtr pointTextNode(do_QueryInterface(aPoint.mTextNode)); - int32_t idx = mNodeArray.IndexOf(pointTextNode); + int32_t idx = mNodeArray.IndexOf(aPoint.mTextNode); if (idx == -1) { // can't find point, but it's not an error return outPoint; @@ -1619,7 +1623,7 @@ nsWSRunObject::GetCharBefore(const WSPoint &aPoint) } else if (idx) { - nsIDOMNode* node = mNodeArray[idx-1]; + nsIDOMNode* node = GetAsDOMNode(mNodeArray[idx-1]); MOZ_ASSERT(node); outPoint.mTextNode = do_QueryInterface(node); @@ -1842,7 +1846,7 @@ nsWSRunObject::GetWSPointAfter(nsIDOMNode *aNode, int32_t aOffset) // which is mongo expensive while (curNum != lastNum) { - curNode = mNodeArray[curNum]; + curNode = GetAsDOMNode(mNodeArray[curNum]); cmp = nsContentUtils::ComparePoints(aNode, aOffset, curNode, 0); if (cmp < 0) lastNum = curNum; @@ -1895,7 +1899,7 @@ nsWSRunObject::GetWSPointBefore(nsIDOMNode *aNode, int32_t aOffset) // which is mongo expensive while (curNum != lastNum) { - curNode = mNodeArray[curNum]; + curNode = GetAsDOMNode(mNodeArray[curNum]); cmp = nsContentUtils::ComparePoints(aNode, aOffset, curNode, 0); if (cmp < 0) lastNum = curNum; diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 5da09b61b14..591f468fcba 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -378,33 +378,33 @@ class MOZ_STACK_CLASS nsWSRunObject // member variables --------------------------------------------------------- - nsCOMPtr mNode; // the node passed to our constructor - int32_t mOffset; // the offset passed to our contructor + nsCOMPtr mNode; // the node passed to our constructor + int32_t mOffset; // the offset passed to our contructor // together, the above represent the point at which we are building up ws info. - bool mPRE; // true if we are in preformatted whitespace context - nsCOMPtr mStartNode; // node/offset where ws starts - int32_t mStartOffset; // ... - WSType mStartReason; // reason why ws starts (eText, eOtherBlock, etc) - nsCOMPtr mStartReasonNode;// the node that implicated by start reason + bool mPRE; // true if we are in preformatted whitespace context + nsCOMPtr mStartNode; // node/offset where ws starts + int32_t mStartOffset; // ... + WSType mStartReason; // reason why ws starts (eText, eOtherBlock, etc) + nsCOMPtr mStartReasonNode;// the node that implicated by start reason - nsCOMPtr mEndNode; // node/offset where ws ends - int32_t mEndOffset; // ... - WSType mEndReason; // reason why ws ends (eText, eOtherBlock, etc) - nsCOMPtr mEndReasonNode; // the node that implicated by end reason + nsCOMPtr mEndNode; // node/offset where ws ends + int32_t mEndOffset; // ... + WSType mEndReason; // reason why ws ends (eText, eOtherBlock, etc) + nsCOMPtr mEndReasonNode; // the node that implicated by end reason - nsCOMPtr mFirstNBSPNode; // location of first nbsp in ws run, if any - int32_t mFirstNBSPOffset; // ... + nsCOMPtr mFirstNBSPNode; // location of first nbsp in ws run, if any + int32_t mFirstNBSPOffset; // ... - nsCOMPtr mLastNBSPNode; // location of last nbsp in ws run, if any - int32_t mLastNBSPOffset; // ... + nsCOMPtr mLastNBSPNode; // location of last nbsp in ws run, if any + int32_t mLastNBSPOffset; // ... - nsCOMArray mNodeArray;//the list of nodes containing ws in this run + nsCOMArray mNodeArray; //the list of nodes containing ws in this run - WSFragment *mStartRun; // the first WSFragment in the run - WSFragment *mEndRun; // the last WSFragment in the run, may be same as first + WSFragment *mStartRun; // the first WSFragment in the run + WSFragment *mEndRun; // the last WSFragment in the run, may be same as first - nsHTMLEditor *mHTMLEditor; // non-owning. + nsHTMLEditor *mHTMLEditor; // non-owning. friend class nsHTMLEditRules; // opening this class up for pillaging friend class nsHTMLEditor; // opening this class up for more pillaging From 434783808aa89ec29dba11807b8868afa8e203d0 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 24/50] Bug 1003808 part 7 - Convert WSFragment members to nsINode; r=ehsan --- editor/libeditor/html/nsWSRunObject.cpp | 50 ++++++++++++------------- editor/libeditor/html/nsWSRunObject.h | 8 ++-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 15f01a64da5..46cbdba1cfd 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -183,7 +183,7 @@ nsWSRunObject::InsertBreak(nsCOMPtr *aInOutParent, // delete the leading ws that is after insertion point. We don't // have to (it would still not be significant after br), but it's // just more aesthetically pleasing to. - res = DeleteChars(*aInOutParent, *aInOutOffset, afterRun->mEndNode, afterRun->mEndOffset, + res = DeleteChars(*aInOutParent, *aInOutOffset, GetAsDOMNode(afterRun->mEndNode), afterRun->mEndOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } else if (afterRun->mType == WSType::normalWS) { @@ -208,7 +208,7 @@ nsWSRunObject::InsertBreak(nsCOMPtr *aInOutParent, } else if (beforeRun->mType & WSType::trailingWS) { // need to delete the trailing ws that is before insertion point, because it // would become significant after break inserted. - res = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset, *aInOutParent, *aInOutOffset, + res = DeleteChars(GetAsDOMNode(beforeRun->mStartNode), beforeRun->mStartOffset, *aInOutParent, *aInOutOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } else if (beforeRun->mType == WSType::normalWS) { @@ -260,7 +260,7 @@ nsWSRunObject::InsertText(const nsAString& aStringToInsert, } else if (afterRun->mType & WSType::leadingWS) { // delete the leading ws that is after insertion point, because it // would become significant after text inserted. - res = DeleteChars(*aInOutParent, *aInOutOffset, afterRun->mEndNode, afterRun->mEndOffset, + res = DeleteChars(*aInOutParent, *aInOutOffset, GetAsDOMNode(afterRun->mEndNode), afterRun->mEndOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } else if (afterRun->mType == WSType::normalWS) { @@ -277,7 +277,7 @@ nsWSRunObject::InsertText(const nsAString& aStringToInsert, } else if (beforeRun->mType & WSType::trailingWS) { // need to delete the trailing ws that is before insertion point, because it // would become significant after text inserted. - res = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset, *aInOutParent, *aInOutOffset, + res = DeleteChars(GetAsDOMNode(beforeRun->mStartNode), beforeRun->mStartOffset, *aInOutParent, *aInOutOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } else if (beforeRun->mType == WSType::normalWS) { @@ -941,13 +941,13 @@ nsWSRunObject::GetRuns() // otherwise a little trickier. shucks. mStartRun = new WSFragment(); - mStartRun->mStartNode = GetAsDOMNode(mStartNode); + mStartRun->mStartNode = mStartNode; mStartRun->mStartOffset = mStartOffset; if (mStartReason & WSType::block || mStartReason == WSType::br) { // set up mStartRun mStartRun->mType = WSType::leadingWS; - mStartRun->mEndNode = GetAsDOMNode(mFirstNBSPNode); + mStartRun->mEndNode = mFirstNBSPNode; mStartRun->mEndOffset = mFirstNBSPOffset; mStartRun->mLeftType = mStartReason; mStartRun->mRightType = WSType::normalWS; @@ -956,14 +956,14 @@ nsWSRunObject::GetRuns() WSFragment *normalRun = new WSFragment(); mStartRun->mRight = normalRun; normalRun->mType = WSType::normalWS; - normalRun->mStartNode = GetAsDOMNode(mFirstNBSPNode); + normalRun->mStartNode = mFirstNBSPNode; normalRun->mStartOffset = mFirstNBSPOffset; normalRun->mLeftType = WSType::leadingWS; normalRun->mLeft = mStartRun; if (mEndReason != WSType::block) { // then no trailing ws. this normal run ends the overall ws run. normalRun->mRightType = mEndReason; - normalRun->mEndNode = GetAsDOMNode(mEndNode); + normalRun->mEndNode = mEndNode; normalRun->mEndOffset = mEndOffset; mEndRun = normalRun; } @@ -977,22 +977,22 @@ nsWSRunObject::GetRuns() { // normal ws runs right up to adjacent block (nbsp next to block) normalRun->mRightType = mEndReason; - normalRun->mEndNode = GetAsDOMNode(mEndNode); + normalRun->mEndNode = mEndNode; normalRun->mEndOffset = mEndOffset; mEndRun = normalRun; } else { - normalRun->mEndNode = GetAsDOMNode(mLastNBSPNode); + normalRun->mEndNode = mLastNBSPNode; normalRun->mEndOffset = mLastNBSPOffset+1; normalRun->mRightType = WSType::trailingWS; // set up next run WSFragment *lastRun = new WSFragment(); lastRun->mType = WSType::trailingWS; - lastRun->mStartNode = GetAsDOMNode(mLastNBSPNode); + lastRun->mStartNode = mLastNBSPNode; lastRun->mStartOffset = mLastNBSPOffset+1; - lastRun->mEndNode = GetAsDOMNode(mEndNode); + lastRun->mEndNode = mEndNode; lastRun->mEndOffset = mEndOffset; lastRun->mLeftType = WSType::normalWS; lastRun->mLeft = normalRun; @@ -1004,7 +1004,7 @@ nsWSRunObject::GetRuns() } else { // mStartReason is not WSType::block or WSType::br; set up mStartRun mStartRun->mType = WSType::normalWS; - mStartRun->mEndNode = GetAsDOMNode(mLastNBSPNode); + mStartRun->mEndNode = mLastNBSPNode; mStartRun->mEndOffset = mLastNBSPOffset+1; mStartRun->mLeftType = mStartReason; @@ -1015,7 +1015,7 @@ nsWSRunObject::GetRuns() if ((mLastNBSPNode == mEndNode) && (mLastNBSPOffset == (mEndOffset-1))) { mStartRun->mRightType = mEndReason; - mStartRun->mEndNode = GetAsDOMNode(mEndNode); + mStartRun->mEndNode = mEndNode; mStartRun->mEndOffset = mEndOffset; mEndRun = mStartRun; } @@ -1024,7 +1024,7 @@ nsWSRunObject::GetRuns() // set up next run WSFragment *lastRun = new WSFragment(); lastRun->mType = WSType::trailingWS; - lastRun->mStartNode = GetAsDOMNode(mLastNBSPNode); + lastRun->mStartNode = mLastNBSPNode; lastRun->mStartOffset = mLastNBSPOffset+1; lastRun->mLeftType = WSType::normalWS; lastRun->mLeft = mStartRun; @@ -1056,10 +1056,10 @@ nsWSRunObject::MakeSingleWSRun(WSType aType) { mStartRun = new WSFragment(); - mStartRun->mStartNode = GetAsDOMNode(mStartNode); + mStartRun->mStartNode = mStartNode; mStartRun->mStartOffset = mStartOffset; mStartRun->mType = aType; - mStartRun->mEndNode = GetAsDOMNode(mEndNode); + mStartRun->mEndNode = mEndNode; mStartRun->mEndOffset = mEndOffset; mStartRun->mLeftType = mStartReason; mStartRun->mRightType = mEndReason; @@ -1315,7 +1315,7 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) // trim after run of any leading ws if (afterRun && (afterRun->mType & WSType::leadingWS)) { - res = aEndObject->DeleteChars(GetAsDOMNode(aEndObject->mNode), aEndObject->mOffset, afterRun->mEndNode, afterRun->mEndOffset, + res = aEndObject->DeleteChars(GetAsDOMNode(aEndObject->mNode), aEndObject->mOffset, GetAsDOMNode(afterRun->mEndNode), afterRun->mEndOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } @@ -1336,7 +1336,7 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) } // trim before run of any trailing ws if (beforeRun && (beforeRun->mType & WSType::trailingWS)) { - res = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset, GetAsDOMNode(mNode), mOffset, + res = DeleteChars(GetAsDOMNode(beforeRun->mStartNode), beforeRun->mStartOffset, GetAsDOMNode(mNode), mOffset, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); } else if (beforeRun && beforeRun->mType == WSType::normalWS && !mPRE) { @@ -1758,7 +1758,7 @@ nsWSRunObject::FindRun(nsIDOMNode *aNode, int32_t aOffset, WSFragment **outRun, WSFragment *run = mStartRun; while (run) { - int16_t comp = nsContentUtils::ComparePoints(aNode, aOffset, run->mStartNode, + int16_t comp = nsContentUtils::ComparePoints(aNode, aOffset, GetAsDOMNode(run->mStartNode), run->mStartOffset); if (comp <= 0) { @@ -1773,7 +1773,7 @@ nsWSRunObject::FindRun(nsIDOMNode *aNode, int32_t aOffset, WSFragment **outRun, return; } comp = nsContentUtils::ComparePoints(aNode, aOffset, - run->mEndNode, run->mEndOffset); + GetAsDOMNode(run->mEndNode), run->mEndOffset); if (comp < 0) { *outRun = run; @@ -1945,7 +1945,7 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun) } // first check for trailing nbsp - WSPoint thePoint = GetCharBefore(aRun->mEndNode, aRun->mEndOffset); + WSPoint thePoint = GetCharBefore(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset); if (thePoint.mTextNode && thePoint.mChar == nbsp) { // now check that what is to the left of it is compatible with replacing nbsp with space WSPoint prevPoint = GetCharBefore(thePoint); @@ -1990,11 +1990,11 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun) // soft wrapped lines, and lets the user see 2 spaces when they type 2 spaces. nsCOMPtr brNode; - res = mHTMLEditor->CreateBR(aRun->mEndNode, aRun->mEndOffset, address_of(brNode)); + res = mHTMLEditor->CreateBR(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset, address_of(brNode)); NS_ENSURE_SUCCESS(res, res); // refresh thePoint, prevPoint - thePoint = GetCharBefore(aRun->mEndNode, aRun->mEndOffset); + thePoint = GetCharBefore(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset); prevPoint = GetCharBefore(thePoint); rightCheck = true; } @@ -2153,7 +2153,7 @@ nsWSRunObject::Scrub() while (run) { if (run->mType & (WSType::leadingWS | WSType::trailingWS)) { - nsresult res = DeleteChars(run->mStartNode, run->mStartOffset, run->mEndNode, run->mEndOffset); + nsresult res = DeleteChars(GetAsDOMNode(run->mStartNode), run->mStartOffset, GetAsDOMNode(run->mEndNode), run->mEndOffset); NS_ENSURE_SUCCESS(res, res); } run = run->mRight; diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 591f468fcba..659534aad76 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -266,10 +266,10 @@ class MOZ_STACK_CLASS nsWSRunObject // still span multiple nodes. struct WSFragment { - nsCOMPtr mStartNode; // node where ws run starts - nsCOMPtr mEndNode; // node where ws run ends - int32_t mStartOffset; // offset where ws run starts - int32_t mEndOffset; // offset where ws run ends + nsCOMPtr mStartNode; // node where ws run starts + nsCOMPtr mEndNode; // node where ws run ends + int32_t mStartOffset; // offset where ws run starts + int32_t mEndOffset; // offset where ws run ends // type of ws, and what is to left and right of it WSType mType, mLeftType, mRightType; // other ws runs to left or right. may be null. From ea5532693ab1043e4c265a6df19bedb67932443a Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 25/50] Bug 1003808 part 8 - Use some more nsINode in nsWSRunObject; r=ehsan --- editor/libeditor/html/nsWSRunObject.cpp | 60 +++++++++++++++++++------ editor/libeditor/html/nsWSRunObject.h | 3 +- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 46cbdba1cfd..0ff8a418301 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -35,6 +35,31 @@ static bool IsBlockNode(nsIDOMNode* node) } //- constructor / destructor ----------------------------------------------- +nsWSRunObject::nsWSRunObject(nsHTMLEditor* aEd, nsINode* aNode, int32_t aOffset) + : mNode(aNode) + , mOffset(aOffset) + , mPRE(false) + , mStartNode() + , mStartOffset(0) + , mStartReason() + , mStartReasonNode() + , mEndNode() + , mEndOffset(0) + , mEndReason() + , mEndReasonNode() + , mFirstNBSPNode() + , mFirstNBSPOffset(0) + , mLastNBSPNode() + , mLastNBSPOffset(0) + , mNodeArray() + , mStartRun(nullptr) + , mEndRun(nullptr) + , mHTMLEditor(aEd) +{ + GetWSNodes(); + GetRuns(); +} + nsWSRunObject::nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, int32_t aOffset) : mNode(do_QueryInterface(aNode)) ,mOffset(aOffset) @@ -94,11 +119,12 @@ nsWSRunObject::PrepareToJoinBlocks(nsHTMLEditor *aHTMLEd, nsIDOMNode *aLeftParent, nsIDOMNode *aRightParent) { - NS_ENSURE_TRUE(aLeftParent && aRightParent && aHTMLEd, NS_ERROR_NULL_POINTER); - uint32_t count; - aHTMLEd->GetLengthOfDOMNode(aLeftParent, count); - nsWSRunObject leftWSObj(aHTMLEd, aLeftParent, count); - nsWSRunObject rightWSObj(aHTMLEd, aRightParent, 0); + nsCOMPtr leftParent(do_QueryInterface(aLeftParent)); + nsCOMPtr rightParent(do_QueryInterface(aRightParent)); + NS_ENSURE_TRUE(leftParent && rightParent && aHTMLEd, NS_ERROR_NULL_POINTER); + + nsWSRunObject leftWSObj(aHTMLEd, leftParent, leftParent->Length()); + nsWSRunObject rightWSObj(aHTMLEd, rightParent, 0); return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj); } @@ -110,13 +136,17 @@ nsWSRunObject::PrepareToDeleteRange(nsHTMLEditor *aHTMLEd, nsCOMPtr *aEndNode, int32_t *aEndOffset) { - NS_ENSURE_TRUE(aStartNode && aEndNode && *aStartNode && *aEndNode && aStartOffset && aEndOffset && aHTMLEd, NS_ERROR_NULL_POINTER); + NS_ENSURE_TRUE(aStartNode && aEndNode && aStartOffset && aEndOffset && + aHTMLEd, NS_ERROR_NULL_POINTER); + nsCOMPtr startNode(do_QueryInterface(*aStartNode)); + nsCOMPtr endNode(do_QueryInterface(*aEndNode)); + NS_ENSURE_TRUE(startNode && endNode, NS_ERROR_NULL_POINTER); nsAutoTrackDOMPoint trackerStart(aHTMLEd->mRangeUpdater, aStartNode, aStartOffset); nsAutoTrackDOMPoint trackerEnd(aHTMLEd->mRangeUpdater, aEndNode, aEndOffset); - nsWSRunObject leftWSObj(aHTMLEd, *aStartNode, *aStartOffset); - nsWSRunObject rightWSObj(aHTMLEd, *aEndNode, *aEndOffset); + nsWSRunObject leftWSObj(aHTMLEd, startNode, *aStartOffset); + nsWSRunObject rightWSObj(aHTMLEd, endNode, *aEndOffset); return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj); } @@ -125,11 +155,13 @@ nsresult nsWSRunObject::PrepareToDeleteNode(nsHTMLEditor *aHTMLEd, nsIDOMNode *aNode) { - NS_ENSURE_TRUE(aNode && aHTMLEd, NS_ERROR_NULL_POINTER); - - int32_t offset; - nsCOMPtr parent = aHTMLEd->GetNodeLocation(aNode, &offset); + nsCOMPtr node(do_QueryInterface(aNode)); + NS_ENSURE_TRUE(node && aHTMLEd, NS_ERROR_NULL_POINTER); + nsCOMPtr parent = node->GetParentNode(); + NS_ENSURE_STATE(parent); + int32_t offset = parent->IndexOf(node); + nsWSRunObject leftWSObj(aHTMLEd, parent, offset); nsWSRunObject rightWSObj(aHTMLEd, parent, offset+1); @@ -1536,7 +1568,7 @@ nsWSRunObject::GetCharAfter(nsIDOMNode *aNode, int32_t aOffset) else { // use wspoint version of GetCharAfter() - WSPoint point(aNode,aOffset,0); + WSPoint point(node, aOffset, 0); return GetCharAfter(point); } } @@ -1556,7 +1588,7 @@ nsWSRunObject::GetCharBefore(nsIDOMNode *aNode, int32_t aOffset) else { // use wspoint version of GetCharBefore() - WSPoint point(aNode,aOffset,0); + WSPoint point(node, aOffset, 0); return GetCharBefore(point); } } diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 659534aad76..55b215d0a11 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -153,6 +153,7 @@ class MOZ_STACK_CLASS nsWSRunObject enum {eBoth = eBefore | eAfter}; // constructor / destructor ----------------------------------------------- + nsWSRunObject(nsHTMLEditor* aEd, nsINode* aNode, int32_t aOffset); nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, int32_t aOffset); ~nsWSRunObject(); @@ -295,7 +296,7 @@ class MOZ_STACK_CLASS nsWSRunObject char16_t mChar; WSPoint() : mTextNode(0),mOffset(0),mChar(0) {} - WSPoint(nsIDOMNode *aNode, int32_t aOffset, char16_t aChar) : + WSPoint(nsINode* aNode, int32_t aOffset, char16_t aChar) : mTextNode(do_QueryInterface(aNode)),mOffset(aOffset),mChar(aChar) { if (!mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { From d8a7fc45ab4fa38c5b1d3a8c3294ced93cc44787 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 26/50] Bug 1003808 part 9 - Clean up nsWSRunObject::GetRuns; r=ehsan --- editor/libeditor/html/nsWSRunObject.cpp | 238 ++++++++++-------------- editor/libeditor/html/nsWSRunObject.h | 6 +- 2 files changed, 102 insertions(+), 142 deletions(-) diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 0ff8a418301..33945ed865a 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -27,6 +27,12 @@ const char16_t nbsp = 160; +static bool IsBlockNode(nsINode* node) +{ + return node && node->IsElement() && + nsHTMLEditor::NodeIsBlockStatic(node->AsElement()); +} + static bool IsBlockNode(nsIDOMNode* node) { bool isBlock (false); @@ -633,17 +639,16 @@ nsWSRunObject::AdjustWhitespace() // protected methods //-------------------------------------------------------------------------------------------- -already_AddRefed +already_AddRefed nsWSRunObject::GetWSBoundingParent() { NS_ENSURE_TRUE(mNode, nullptr); - nsCOMPtr wsBoundingParent = GetAsDOMNode(mNode); - while (!IsBlockNode(wsBoundingParent)) - { - nsCOMPtr parent; - wsBoundingParent->GetParentNode(getter_AddRefs(parent)); - if (!parent || !mHTMLEditor->IsEditable(parent)) + nsCOMPtr wsBoundingParent = mNode; + while (!IsBlockNode(wsBoundingParent)) { + nsCOMPtr parent = wsBoundingParent->GetParentNode(); + if (!parent || !mHTMLEditor->IsEditable(parent)) { break; + } wsBoundingParent.swap(parent); } return wsBoundingParent.forget(); @@ -658,34 +663,27 @@ nsWSRunObject::GetWSNodes() nsresult res = NS_OK; DOMPoint start(mNode, mOffset), end(mNode, mOffset); - nsCOMPtr wsBoundingParent = GetWSBoundingParent(); + nsCOMPtr wsBoundingParent = GetWSBoundingParent(); // first look backwards to find preceding ws nodes - if (mHTMLEditor->IsTextNode(mNode)) - { + if (mNode->NodeType() == nsIDOMNode::TEXT_NODE) { nsCOMPtr textNode(do_QueryInterface(mNode)); - const nsTextFragment *textFrag = textNode->GetText(); + const nsTextFragment* textFrag = textNode->GetText(); - res = PrependNodeToList(GetAsDOMNode(mNode)); + res = PrependNodeToList(mNode); NS_ENSURE_SUCCESS(res, res); - if (mOffset) - { - int32_t pos; - for (pos=mOffset-1; pos>=0; pos--) - { + if (mOffset) { + for (int32_t pos = mOffset - 1; pos >= 0; pos--) { // sanity bounds check the char position. bug 136165 - if (uint32_t(pos) >= textFrag->GetLength()) - { + if (uint32_t(pos) >= textFrag->GetLength()) { NS_NOTREACHED("looking beyond end of text fragment"); continue; } char16_t theChar = textFrag->CharAt(pos); - if (!nsCRT::IsAsciiSpace(theChar)) - { - if (theChar != nbsp) - { + if (!nsCRT::IsAsciiSpace(theChar)) { + if (theChar != nbsp) { mStartNode = mNode; - mStartOffset = pos+1; + mStartOffset = pos + 1; mStartReason = WSType::text; mStartReasonNode = mNode; break; @@ -694,35 +692,32 @@ nsWSRunObject::GetWSNodes() mFirstNBSPNode = mNode; mFirstNBSPOffset = pos; // also keep track of latest nbsp so far - if (!mLastNBSPNode) - { + if (!mLastNBSPNode) { mLastNBSPNode = mNode; mLastNBSPOffset = pos; } } - start.node = do_QueryInterface(mNode); + start.node = mNode; start.offset = pos; } } } - nsCOMPtr priorNode; - while (!mStartNode) - { + while (!mStartNode) { // we haven't found the start of ws yet. Keep looking - res = GetPreviousWSNode(start, wsBoundingParent, address_of(priorNode)); + nsCOMPtr priorDOMNode; + res = GetPreviousWSNode(start, GetAsDOMNode(wsBoundingParent), + address_of(priorDOMNode)); NS_ENSURE_SUCCESS(res, res); - if (priorNode) - { - if (IsBlockNode(priorNode)) - { + nsCOMPtr priorNode = do_QueryInterface(priorDOMNode); + if (priorNode) { + if (IsBlockNode(priorNode)) { mStartNode = start.node; mStartOffset = start.offset; mStartReason = WSType::otherBlock; - mStartReasonNode = do_QueryInterface(priorNode); + mStartReasonNode = priorNode; } - else if (mHTMLEditor->IsTextNode(priorNode)) - { + else if (priorNode->NodeType() == nsIDOMNode::TEXT_NODE) { res = PrependNodeToList(priorNode); NS_ENSURE_SUCCESS(res, res); nsCOMPtr textNode(do_QueryInterface(priorNode)); @@ -732,95 +727,76 @@ nsWSRunObject::GetWSNodes() } uint32_t len = textNode->TextLength(); - if (len < 1) - { + if (len < 1) { // Zero length text node. Set start point to it // so we can get past it! - start.SetPoint(priorNode,0); - } - else - { - int32_t pos; - for (pos=len-1; pos>=0; pos--) - { + start.SetPoint(priorNode, 0); + } else { + for (int32_t pos = len - 1; pos >= 0; pos--) { // sanity bounds check the char position. bug 136165 - if (uint32_t(pos) >= textFrag->GetLength()) - { + if (uint32_t(pos) >= textFrag->GetLength()) { NS_NOTREACHED("looking beyond end of text fragment"); continue; } char16_t theChar = textFrag->CharAt(pos); - if (!nsCRT::IsAsciiSpace(theChar)) - { - if (theChar != nbsp) - { - mStartNode = do_QueryInterface(priorNode); - mStartOffset = pos+1; + if (!nsCRT::IsAsciiSpace(theChar)) { + if (theChar != nbsp) { + mStartNode = priorNode; + mStartOffset = pos + 1; mStartReason = WSType::text; - mStartReasonNode = do_QueryInterface(priorNode); + mStartReasonNode = priorNode; break; } // as we look backwards update our earliest found nbsp - mFirstNBSPNode = do_QueryInterface(priorNode); + mFirstNBSPNode = priorNode; mFirstNBSPOffset = pos; // also keep track of latest nbsp so far - if (!mLastNBSPNode) - { - mLastNBSPNode = do_QueryInterface(priorNode); + if (!mLastNBSPNode) { + mLastNBSPNode = priorNode; mLastNBSPOffset = pos; } } - start.SetPoint(priorNode,pos); + start.SetPoint(priorNode, pos); } } - } - else - { + } else { // it's a break or a special node, like , that is not a block and not // a break but still serves as a terminator to ws runs. mStartNode = start.node; mStartOffset = start.offset; - if (nsTextEditUtils::IsBreak(priorNode)) + if (nsTextEditUtils::IsBreak(priorNode)) { mStartReason = WSType::br; - else + } else { mStartReason = WSType::special; - mStartReasonNode = do_QueryInterface(priorNode); + } + mStartReasonNode = priorNode; } - } - else - { + } else { // no prior node means we exhausted wsBoundingParent mStartNode = start.node; mStartOffset = start.offset; mStartReason = WSType::thisBlock; - mStartReasonNode = do_QueryInterface(wsBoundingParent); + mStartReasonNode = wsBoundingParent; } } // then look ahead to find following ws nodes - if (mHTMLEditor->IsTextNode(mNode)) - { + if (mNode->NodeType() == nsIDOMNode::TEXT_NODE) { // don't need to put it on list. it already is from code above nsCOMPtr textNode(do_QueryInterface(mNode)); const nsTextFragment *textFrag = textNode->GetText(); uint32_t len = textNode->TextLength(); - if (uint16_t(mOffset)=textFrag->GetLength())) - { + if (pos >= textFrag->GetLength()) { NS_NOTREACHED("looking beyond end of text fragment"); continue; } char16_t theChar = textFrag->CharAt(pos); - if (!nsCRT::IsAsciiSpace(theChar)) - { - if (theChar != nbsp) - { + if (!nsCRT::IsAsciiSpace(theChar)) { + if (theChar != nbsp) { mEndNode = mNode; mEndOffset = pos; mEndReason = WSType::text; @@ -831,35 +807,31 @@ nsWSRunObject::GetWSNodes() mLastNBSPNode = mNode; mLastNBSPOffset = pos; // also keep track of earliest nbsp so far - if (!mFirstNBSPNode) - { + if (!mFirstNBSPNode) { mFirstNBSPNode = mNode; mFirstNBSPOffset = pos; } } - end.SetPoint(mNode,pos+1); + end.SetPoint(mNode, pos + 1); } } } - nsCOMPtr nextNode; - while (!mEndNode) - { + while (!mEndNode) { // we haven't found the end of ws yet. Keep looking - res = GetNextWSNode(end, wsBoundingParent, address_of(nextNode)); + nsCOMPtr nextDOMNode; + res = GetNextWSNode(end, GetAsDOMNode(wsBoundingParent), + address_of(nextDOMNode)); NS_ENSURE_SUCCESS(res, res); - if (nextNode) - { - if (IsBlockNode(nextNode)) - { + nsCOMPtr nextNode = do_QueryInterface(nextDOMNode); + if (nextNode) { + if (IsBlockNode(nextNode)) { // we encountered a new block. therefore no more ws. mEndNode = end.node; mEndOffset = end.offset; mEndReason = WSType::otherBlock; - mEndReasonNode = do_QueryInterface(nextNode); - } - else if (mHTMLEditor->IsTextNode(nextNode)) - { + mEndReasonNode = nextNode; + } else if (mHTMLEditor->IsTextNode(nextNode)) { res = AppendNodeToList(nextNode); NS_ENSURE_SUCCESS(res, res); nsCOMPtr textNode(do_QueryInterface(nextNode)); @@ -869,69 +841,57 @@ nsWSRunObject::GetWSNodes() } uint32_t len = textNode->TextLength(); - if (len < 1) - { + if (len < 1) { // Zero length text node. Set end point to it // so we can get past it! end.SetPoint(nextNode,0); - } - else - { - int32_t pos; - for (pos=0; uint32_t(pos)= textFrag->GetLength()) - { + if (pos >= textFrag->GetLength()) { NS_NOTREACHED("looking beyond end of text fragment"); continue; } char16_t theChar = textFrag->CharAt(pos); - if (!nsCRT::IsAsciiSpace(theChar)) - { - if (theChar != nbsp) - { - mEndNode = do_QueryInterface(nextNode); + if (!nsCRT::IsAsciiSpace(theChar)) { + if (theChar != nbsp) { + mEndNode = nextNode; mEndOffset = pos; mEndReason = WSType::text; - mEndReasonNode = do_QueryInterface(nextNode); + mEndReasonNode = nextNode; break; } // as we look forwards update our latest found nbsp - mLastNBSPNode = do_QueryInterface(nextNode); + mLastNBSPNode = nextNode; mLastNBSPOffset = pos; // also keep track of earliest nbsp so far - if (!mFirstNBSPNode) - { - mFirstNBSPNode = do_QueryInterface(nextNode); + if (!mFirstNBSPNode) { + mFirstNBSPNode = nextNode; mFirstNBSPOffset = pos; } } - end.SetPoint(nextNode,pos+1); + end.SetPoint(nextNode, pos + 1); } } - } - else - { + } else { // we encountered a break or a special node, like , // that is not a block and not a break but still // serves as a terminator to ws runs. mEndNode = end.node; mEndOffset = end.offset; - if (nsTextEditUtils::IsBreak(nextNode)) + if (nsTextEditUtils::IsBreak(nextNode)) { mEndReason = WSType::br; - else + } else { mEndReason = WSType::special; - mEndReasonNode = do_QueryInterface(nextNode); + } + mEndReasonNode = nextNode; } - } - else - { + } else { // no next node means we exhausted wsBoundingParent mEndNode = end.node; mEndOffset = end.offset; mEndReason = WSType::thisBlock; - mEndReasonNode = do_QueryInterface(wsBoundingParent); + mEndReasonNode = wsBoundingParent; } } @@ -1100,22 +1060,22 @@ nsWSRunObject::MakeSingleWSRun(WSType aType) } nsresult -nsWSRunObject::PrependNodeToList(nsIDOMNode *aNode) +nsWSRunObject::PrependNodeToList(nsINode *aNode) { - nsCOMPtr node(do_QueryInterface(aNode)); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - if (!mNodeArray.InsertObjectAt(node, 0)) + NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); + if (!mNodeArray.InsertObjectAt(aNode, 0)) { return NS_ERROR_FAILURE; + } return NS_OK; } nsresult -nsWSRunObject::AppendNodeToList(nsIDOMNode *aNode) +nsWSRunObject::AppendNodeToList(nsINode* aNode) { - nsCOMPtr node(do_QueryInterface(aNode)); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - if (!mNodeArray.AppendObject(node)) + NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); + if (!mNodeArray.AppendObject(aNode)) { return NS_ERROR_FAILURE; + } return NS_OK; } @@ -2002,7 +1962,7 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun) rightCheck = true; } if ((aRun->mRightType & WSType::block) && - IsBlockNode(nsCOMPtr(GetWSBoundingParent()))) { + IsBlockNode(nsCOMPtr(GetWSBoundingParent()))) { // we are at a block boundary. Insert a
. Why? Well, first note that // the br will have no visible effect since it is up against a block boundary. // |foo

bar| renders like |foo

bar| and similarly diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 55b215d0a11..5b1a25953e2 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -322,14 +322,14 @@ class MOZ_STACK_CLASS nsWSRunObject * closest block within the DOM subtree we're editing, or if none is * found, the (inline) root of the editable subtree. */ - already_AddRefed GetWSBoundingParent(); + already_AddRefed GetWSBoundingParent(); nsresult GetWSNodes(); void GetRuns(); void ClearRuns(); void MakeSingleWSRun(WSType aType); - nsresult PrependNodeToList(nsIDOMNode *aNode); - nsresult AppendNodeToList(nsIDOMNode *aNode); + nsresult PrependNodeToList(nsINode* aNode); + nsresult AppendNodeToList(nsINode* aNode); nsresult GetPreviousWSNode(nsIDOMNode *aStartNode, nsIDOMNode *aBlockParent, nsCOMPtr *aPriorNode); From 8cf8ed9b5d2f665961f000a66d6320b87f402706 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 27/50] Bug 1003808 part 10 - Clean up nsWSRunObject::GetPrevious/NextWSNode; r=ehsan --- editor/libeditor/html/nsWSRunObject.cpp | 224 ++++++++++-------------- editor/libeditor/html/nsWSRunObject.h | 26 +-- 2 files changed, 101 insertions(+), 149 deletions(-) diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 33945ed865a..ea78a4793cd 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -33,13 +33,6 @@ static bool IsBlockNode(nsINode* node) nsHTMLEditor::NodeIsBlockStatic(node->AsElement()); } -static bool IsBlockNode(nsIDOMNode* node) -{ - bool isBlock (false); - nsHTMLEditor::NodeIsBlockStatic(node, &isBlock); - return isBlock; -} - //- constructor / destructor ----------------------------------------------- nsWSRunObject::nsWSRunObject(nsHTMLEditor* aEd, nsINode* aNode, int32_t aOffset) : mNode(aNode) @@ -705,11 +698,9 @@ nsWSRunObject::GetWSNodes() while (!mStartNode) { // we haven't found the start of ws yet. Keep looking - nsCOMPtr priorDOMNode; - res = GetPreviousWSNode(start, GetAsDOMNode(wsBoundingParent), - address_of(priorDOMNode)); + nsCOMPtr priorNode; + res = GetPreviousWSNode(start, wsBoundingParent, address_of(priorNode)); NS_ENSURE_SUCCESS(res, res); - nsCOMPtr priorNode = do_QueryInterface(priorDOMNode); if (priorNode) { if (IsBlockNode(priorNode)) { mStartNode = start.node; @@ -819,11 +810,9 @@ nsWSRunObject::GetWSNodes() while (!mEndNode) { // we haven't found the end of ws yet. Keep looking - nsCOMPtr nextDOMNode; - res = GetNextWSNode(end, GetAsDOMNode(wsBoundingParent), - address_of(nextDOMNode)); + nsCOMPtr nextNode; + res = GetNextWSNode(end, wsBoundingParent, address_of(nextNode)); NS_ENSURE_SUCCESS(res, res); - nsCOMPtr nextNode = do_QueryInterface(nextDOMNode); if (nextNode) { if (IsBlockNode(nextNode)) { // we encountered a new block. therefore no more ws. @@ -1080,44 +1069,40 @@ nsWSRunObject::AppendNodeToList(nsINode* aNode) } nsresult -nsWSRunObject::GetPreviousWSNode(nsIDOMNode *aStartNode, - nsIDOMNode *aBlockParent, - nsCOMPtr *aPriorNode) +nsWSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode, + nsINode* aBlockParent, + nsCOMPtr* aPriorNode) { - // can't really recycle various getnext/prior routines because we - // have special needs here. Need to step into inline containers but - // not block containers. + // can't really recycle various getnext/prior routines because we have + // special needs here. Need to step into inline containers but not block + // containers. NS_ENSURE_TRUE(aStartNode && aBlockParent && aPriorNode, NS_ERROR_NULL_POINTER); - nsresult res = aStartNode->GetPreviousSibling(getter_AddRefs(*aPriorNode)); - NS_ENSURE_SUCCESS(res, res); - nsCOMPtr temp, curNode = aStartNode; - while (!*aPriorNode) - { + *aPriorNode = aStartNode->GetPreviousSibling(); + nsCOMPtr temp, curNode(aStartNode); + while (!*aPriorNode) { // we have exhausted nodes in parent of aStartNode. - res = curNode->GetParentNode(getter_AddRefs(temp)); - NS_ENSURE_SUCCESS(res, res); + temp = curNode->GetParentNode(); NS_ENSURE_TRUE(temp, NS_ERROR_NULL_POINTER); - if (temp == aBlockParent) - { - // we have exhausted nodes in the block parent. The convention here is to return null. + if (temp == aBlockParent) { + // we have exhausted nodes in the block parent. The convention here is + // to return null. *aPriorNode = nullptr; return NS_OK; } // we have a parent: look for previous sibling - res = temp->GetPreviousSibling(getter_AddRefs(*aPriorNode)); - NS_ENSURE_SUCCESS(res, res); + *aPriorNode = temp->GetPreviousSibling(); curNode = temp; } // we have a prior node. If it's a block, return it. - if (IsBlockNode(*aPriorNode)) + if (IsBlockNode(*aPriorNode)) { return NS_OK; - // else if it's a container, get deep rightmost child - else if (mHTMLEditor->IsContainer(*aPriorNode)) - { + } else if (mHTMLEditor->IsContainer(*aPriorNode)) { + // else if it's a container, get deep rightmost child temp = mHTMLEditor->GetRightmostChild(*aPriorNode); - if (temp) + if (temp) { *aPriorNode = temp; + } return NS_OK; } // else return the node itself @@ -1126,57 +1111,48 @@ nsWSRunObject::GetPreviousWSNode(nsIDOMNode *aStartNode, nsresult nsWSRunObject::GetPreviousWSNode(DOMPoint aPoint, - nsIDOMNode *aBlockParent, - nsCOMPtr *aPriorNode) -{ - return GetPreviousWSNode(GetAsDOMNode(aPoint.node), aPoint.offset, aBlockParent, - aPriorNode); -} - -nsresult -nsWSRunObject::GetPreviousWSNode(nsIDOMNode *aStartNode, - int32_t aOffset, - nsIDOMNode *aBlockParent, - nsCOMPtr *aPriorNode) + nsINode* aBlockParent, + nsCOMPtr* aPriorNode) { // can't really recycle various getnext/prior routines because we // have special needs here. Need to step into inline containers but // not block containers. - NS_ENSURE_TRUE(aStartNode && aBlockParent && aPriorNode, NS_ERROR_NULL_POINTER); - *aPriorNode = 0; + NS_ENSURE_TRUE(aPoint.node && aBlockParent && aPriorNode, + NS_ERROR_NULL_POINTER); + *aPriorNode = nullptr; - if (mHTMLEditor->IsTextNode(aStartNode)) - return GetPreviousWSNode(aStartNode, aBlockParent, aPriorNode); - if (!mHTMLEditor->IsContainer(aStartNode)) - return GetPreviousWSNode(aStartNode, aBlockParent, aPriorNode); + if (aPoint.node->NodeType() == nsIDOMNode::TEXT_NODE) { + return GetPreviousWSNodeInner(aPoint.node, aBlockParent, aPriorNode); + } + if (!mHTMLEditor->IsContainer(aPoint.node)) { + return GetPreviousWSNodeInner(aPoint.node, aBlockParent, aPriorNode); + } - if (!aOffset) - { - if (aStartNode==aBlockParent) - { + if (!aPoint.offset) { + if (aPoint.node == aBlockParent) { // we are at start of the block. return NS_OK; } // we are at start of non-block container - return GetPreviousWSNode(aStartNode, aBlockParent, aPriorNode); + return GetPreviousWSNodeInner(aPoint.node, aBlockParent, aPriorNode); } - nsCOMPtr startContent( do_QueryInterface(aStartNode) ); + nsCOMPtr startContent(do_QueryInterface(aPoint.node)); NS_ENSURE_STATE(startContent); - nsIContent *priorContent = startContent->GetChildAt(aOffset - 1); + nsIContent* priorContent = startContent->GetChildAt(aPoint.offset - 1); NS_ENSURE_TRUE(priorContent, NS_ERROR_NULL_POINTER); - *aPriorNode = do_QueryInterface(priorContent); + *aPriorNode = priorContent; // we have a prior node. If it's a block, return it. - if (IsBlockNode(*aPriorNode)) + if (IsBlockNode(*aPriorNode)) { return NS_OK; - // else if it's a container, get deep rightmost child - else if (mHTMLEditor->IsContainer(*aPriorNode)) - { - nsCOMPtr temp; + } else if (mHTMLEditor->IsContainer(*aPriorNode)) { + // else if it's a container, get deep rightmost child + nsCOMPtr temp; temp = mHTMLEditor->GetRightmostChild(*aPriorNode); - if (temp) + if (temp) { *aPriorNode = temp; + } return NS_OK; } // else return the node itself @@ -1184,46 +1160,41 @@ nsWSRunObject::GetPreviousWSNode(nsIDOMNode *aStartNode, } nsresult -nsWSRunObject::GetNextWSNode(nsIDOMNode *aStartNode, - nsIDOMNode *aBlockParent, - nsCOMPtr *aNextNode) +nsWSRunObject::GetNextWSNodeInner(nsINode* aStartNode, + nsINode* aBlockParent, + nsCOMPtr* aNextNode) { - // can't really recycle various getnext/prior routines because we - // have special needs here. Need to step into inline containers but - // not block containers. - NS_ENSURE_TRUE(aStartNode && aBlockParent && aNextNode, NS_ERROR_NULL_POINTER); + // can't really recycle various getnext/prior routines because we have + // special needs here. Need to step into inline containers but not block + // containers. + NS_ENSURE_TRUE(aStartNode && aBlockParent && aNextNode, + NS_ERROR_NULL_POINTER); - *aNextNode = 0; - nsresult res = aStartNode->GetNextSibling(getter_AddRefs(*aNextNode)); - NS_ENSURE_SUCCESS(res, res); - nsCOMPtr temp, curNode = aStartNode; - while (!*aNextNode) - { + *aNextNode = aStartNode->GetNextSibling(); + nsCOMPtr temp, curNode(aStartNode); + while (!*aNextNode) { // we have exhausted nodes in parent of aStartNode. - res = curNode->GetParentNode(getter_AddRefs(temp)); - NS_ENSURE_SUCCESS(res, res); + temp = curNode->GetParentNode(); NS_ENSURE_TRUE(temp, NS_ERROR_NULL_POINTER); - if (temp == aBlockParent) - { - // we have exhausted nodes in the block parent. The convention - // here is to return null. + if (temp == aBlockParent) { + // we have exhausted nodes in the block parent. The convention here is + // to return null. *aNextNode = nullptr; return NS_OK; } // we have a parent: look for next sibling - res = temp->GetNextSibling(getter_AddRefs(*aNextNode)); - NS_ENSURE_SUCCESS(res, res); + *aNextNode = temp->GetNextSibling(); curNode = temp; } // we have a next node. If it's a block, return it. - if (IsBlockNode(*aNextNode)) + if (IsBlockNode(*aNextNode)) { return NS_OK; - // else if it's a container, get deep leftmost child - else if (mHTMLEditor->IsContainer(*aNextNode)) - { + } else if (mHTMLEditor->IsContainer(*aNextNode)) { + // else if it's a container, get deep leftmost child temp = mHTMLEditor->GetLeftmostChild(*aNextNode); - if (temp) + if (temp) { *aNextNode = temp; + } return NS_OK; } // else return the node itself @@ -1232,55 +1203,46 @@ nsWSRunObject::GetNextWSNode(nsIDOMNode *aStartNode, nsresult nsWSRunObject::GetNextWSNode(DOMPoint aPoint, - nsIDOMNode *aBlockParent, - nsCOMPtr *aNextNode) + nsINode* aBlockParent, + nsCOMPtr* aNextNode) { - return GetNextWSNode(GetAsDOMNode(aPoint.node), aPoint.offset, aBlockParent, - aNextNode); -} + // can't really recycle various getnext/prior routines because we have + // special needs here. Need to step into inline containers but not block + // containers. + NS_ENSURE_TRUE(aPoint.node && aBlockParent && aNextNode, + NS_ERROR_NULL_POINTER); + *aNextNode = nullptr; -nsresult -nsWSRunObject::GetNextWSNode(nsIDOMNode *aStartNode, - int32_t aOffset, - nsIDOMNode *aBlockParent, - nsCOMPtr *aNextNode) -{ - // can't really recycle various getnext/prior routines because we have special needs - // here. Need to step into inline containers but not block containers. - NS_ENSURE_TRUE(aStartNode && aBlockParent && aNextNode, NS_ERROR_NULL_POINTER); - *aNextNode = 0; - - if (mHTMLEditor->IsTextNode(aStartNode)) - return GetNextWSNode(aStartNode, aBlockParent, aNextNode); - if (!mHTMLEditor->IsContainer(aStartNode)) - return GetNextWSNode(aStartNode, aBlockParent, aNextNode); + if (aPoint.node->NodeType() == nsIDOMNode::TEXT_NODE) { + return GetNextWSNodeInner(aPoint.node, aBlockParent, aNextNode); + } + if (!mHTMLEditor->IsContainer(aPoint.node)) { + return GetNextWSNodeInner(aPoint.node, aBlockParent, aNextNode); + } - nsCOMPtr startContent( do_QueryInterface(aStartNode) ); + nsCOMPtr startContent(do_QueryInterface(aPoint.node)); NS_ENSURE_STATE(startContent); - nsIContent *nextContent = startContent->GetChildAt(aOffset); - if (!nextContent) - { - if (aStartNode==aBlockParent) - { + nsIContent *nextContent = startContent->GetChildAt(aPoint.offset); + if (!nextContent) { + if (aPoint.node == aBlockParent) { // we are at end of the block. return NS_OK; } // we are at end of non-block container - return GetNextWSNode(aStartNode, aBlockParent, aNextNode); + return GetNextWSNodeInner(aPoint.node, aBlockParent, aNextNode); } - *aNextNode = do_QueryInterface(nextContent); + *aNextNode = nextContent; // we have a next node. If it's a block, return it. - if (IsBlockNode(*aNextNode)) + if (IsBlockNode(*aNextNode)) { return NS_OK; - // else if it's a container, get deep leftmost child - else if (mHTMLEditor->IsContainer(*aNextNode)) - { - nsCOMPtr temp; - temp = mHTMLEditor->GetLeftmostChild(*aNextNode); - if (temp) + } else if (mHTMLEditor->IsContainer(*aNextNode)) { + // else if it's a container, get deep leftmost child + nsCOMPtr temp = mHTMLEditor->GetLeftmostChild(*aNextNode); + if (temp) { *aNextNode = temp; + } return NS_OK; } // else return the node itself diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 5b1a25953e2..db28ce7a7f4 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -330,26 +330,12 @@ class MOZ_STACK_CLASS nsWSRunObject void MakeSingleWSRun(WSType aType); nsresult PrependNodeToList(nsINode* aNode); nsresult AppendNodeToList(nsINode* aNode); - nsresult GetPreviousWSNode(nsIDOMNode *aStartNode, - nsIDOMNode *aBlockParent, - nsCOMPtr *aPriorNode); - nsresult GetPreviousWSNode(nsIDOMNode *aStartNode, - int32_t aOffset, - nsIDOMNode *aBlockParent, - nsCOMPtr *aPriorNode); nsresult GetPreviousWSNode(::DOMPoint aPoint, - nsIDOMNode *aBlockParent, - nsCOMPtr *aPriorNode); - nsresult GetNextWSNode(nsIDOMNode *aStartNode, - nsIDOMNode *aBlockParent, - nsCOMPtr *aNextNode); - nsresult GetNextWSNode(nsIDOMNode *aStartNode, - int32_t aOffset, - nsIDOMNode *aBlockParent, - nsCOMPtr *aNextNode); + nsINode* aBlockParent, + nsCOMPtr* aPriorNode); nsresult GetNextWSNode(::DOMPoint aPoint, - nsIDOMNode *aBlockParent, - nsCOMPtr *aNextNode); + nsINode* aBlockParent, + nsCOMPtr* aNextNode); nsresult PrepareToDeleteRangePriv(nsWSRunObject* aEndObject); nsresult PrepareToSplitAcrossBlocksPriv(); nsresult DeleteChars(nsIDOMNode *aStartNode, int32_t aStartOffset, @@ -376,6 +362,10 @@ class MOZ_STACK_CLASS nsWSRunObject nsCOMPtr *aBlock, BlockBoundary aBoundary); nsresult Scrub(); + nsresult GetPreviousWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent, + nsCOMPtr* aPriorNode); + nsresult GetNextWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent, + nsCOMPtr* aNextNode); // member variables --------------------------------------------------------- From b7b3ce0b2c314da2786d26bbef9b107d0543247d Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 28/50] Bug 1003894 part 1 - Change WSPoint.mTextNode to Text; r=ehsan --- editor/libeditor/html/nsWSRunObject.cpp | 15 --------------- editor/libeditor/html/nsWSRunObject.h | 12 ++++-------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index ea78a4793cd..3de9009f237 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -1306,11 +1306,6 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject) GetAsciiWSBounds(eBoth, GetAsDOMNode(mNode), mOffset, address_of(wsStartNode), &wsStartOffset, address_of(wsEndNode), &wsEndOffset); point.mTextNode = do_QueryInterface(wsStartNode); - if (!point.mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { - // Not sure if this is needed, but it'll maintain the same - // functionality - point.mTextNode = nullptr; - } point.mOffset = wsStartOffset; res = ConvertToNBSP(point, eOutsideUserSelectAll); NS_ENSURE_SUCCESS(res, res); @@ -1355,11 +1350,6 @@ nsWSRunObject::PrepareToSplitAcrossBlocksPriv() GetAsciiWSBounds(eBoth, GetAsDOMNode(mNode), mOffset, address_of(wsStartNode), &wsStartOffset, address_of(wsEndNode), &wsEndOffset); point.mTextNode = do_QueryInterface(wsStartNode); - if (!point.mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { - // Not sure if this is needed, but it'll maintain the same - // functionality - point.mTextNode = nullptr; - } point.mOffset = wsStartOffset; res = ConvertToNBSP(point); NS_ENSURE_SUCCESS(res, res); @@ -1541,11 +1531,6 @@ nsWSRunObject::GetCharAfter(const WSPoint &aPoint) nsIDOMNode* node = GetAsDOMNode(mNodeArray[idx+1]); MOZ_ASSERT(node); outPoint.mTextNode = do_QueryInterface(node); - if (!outPoint.mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { - // Not sure if this is needed, but it'll maintain the same - // functionality - outPoint.mTextNode = nullptr; - } outPoint.mOffset = 0; outPoint.mChar = GetCharAt(outPoint.mTextNode, 0); } diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index db28ce7a7f4..5cd5d9c1de5 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -8,11 +8,11 @@ #include "nsCOMArray.h" #include "nsCOMPtr.h" -#include "nsIContent.h" #include "nsIDOMNode.h" #include "nsIEditor.h" #include "nsINode.h" #include "nscore.h" +#include "mozilla/dom/Text.h" class nsHTMLEditor; class nsIDOMDocument; @@ -291,7 +291,7 @@ class MOZ_STACK_CLASS nsWSRunObject // stored in the struct. struct MOZ_STACK_CLASS WSPoint { - nsCOMPtr mTextNode; + nsCOMPtr mTextNode; uint32_t mOffset; char16_t mChar; @@ -299,13 +299,9 @@ class MOZ_STACK_CLASS nsWSRunObject WSPoint(nsINode* aNode, int32_t aOffset, char16_t aChar) : mTextNode(do_QueryInterface(aNode)),mOffset(aOffset),mChar(aChar) { - if (!mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) { - // Not sure if this is needed, but it'll maintain the same - // functionality - mTextNode = nullptr; - } + MOZ_ASSERT(mTextNode->IsNodeOfType(nsINode::eTEXT)); } - WSPoint(nsIContent *aTextNode, int32_t aOffset, char16_t aChar) : + WSPoint(mozilla::dom::Text* aTextNode, int32_t aOffset, char16_t aChar) : mTextNode(aTextNode),mOffset(aOffset),mChar(aChar) {} }; From 48bbf8a27c8c70b7b6e70fccde9907c8d9ad89a6 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 29/50] Bug 1003894 part 2 - Clean up nsWSRunObject::CheckTrailingNBSPOfRun; r=ehsan --- editor/libeditor/base/nsEditor.cpp | 11 ++ editor/libeditor/base/nsEditor.h | 5 + editor/libeditor/html/nsHTMLEditor.cpp | 12 ++ editor/libeditor/html/nsHTMLEditor.h | 2 + editor/libeditor/html/nsWSRunObject.cpp | 168 +++++++++++++----------- editor/libeditor/html/nsWSRunObject.h | 5 + 6 files changed, 128 insertions(+), 75 deletions(-) diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 629f60e65e0..8339886c08c 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -31,6 +31,7 @@ #include "mozilla/TextComposition.h" // for TextComposition #include "mozilla/TextEvents.h" #include "mozilla/dom/Element.h" // for Element, nsINode::AsElement +#include "mozilla/dom/Text.h" #include "mozilla/mozalloc.h" // for operator new, etc #include "nsAString.h" // for nsAString_internal::Length, etc #include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker @@ -2442,6 +2443,16 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert, } +nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, + Text* aTextNode, + int32_t aOffset, + bool aSuppressIME) +{ + return InsertTextIntoTextNodeImpl(aStringToInsert, + static_cast(GetAsDOMNode(aTextNode)), + aOffset, aSuppressIME); +} + nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, nsIDOMCharacterData *aTextNode, int32_t aOffset, diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index 824e3c7bfaa..5730346529f 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -75,6 +75,7 @@ class DataTransfer; class Element; class EventTarget; class Selection; +class Text; } // namespace dom } // namespace mozilla @@ -196,6 +197,10 @@ public: nsCOMPtr *aInOutNode, int32_t *aInOutOffset, nsIDOMDocument *aDoc); + nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, + mozilla::dom::Text* aTextNode, + int32_t aOffset, + bool aSuppressIME = false); nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, nsIDOMCharacterData *aTextNode, int32_t aOffset, diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index cdda2cf31e9..90050f286c4 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -1125,6 +1125,18 @@ nsHTMLEditor::TabInTable(bool inIsShift, bool* outHandled) return NS_OK; } +already_AddRefed +nsHTMLEditor::CreateBR(nsINode* aNode, int32_t aOffset, EDirection aSelect) +{ + nsCOMPtr parent = GetAsDOMNode(aNode); + int32_t offset = aOffset; + nsCOMPtr outBRNode; + // We assume everything is fine if the br is not null, irrespective of retval + CreateBRImpl(address_of(parent), &offset, address_of(outBRNode), aSelect); + nsCOMPtr ret = do_QueryInterface(outBRNode); + return ret.forget(); +} + NS_IMETHODIMP nsHTMLEditor::CreateBR(nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr *outBRNode, EDirection aSelect) { nsCOMPtr parent = aNode; diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 7f207e58518..99e09c01b43 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -420,6 +420,8 @@ protected: // key event helpers NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled); + already_AddRefed CreateBR(nsINode* aNode, + int32_t aOffset, EDirection aSelect = eNone); NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone); diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 3de9009f237..7fa6f71e287 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -25,6 +25,9 @@ #include "nsTextFragment.h" #include "nsWSRunObject.h" +using namespace mozilla; +using namespace mozilla::dom; + const char16_t nbsp = 160; static bool IsBlockNode(nsINode* node) @@ -655,7 +658,7 @@ nsWSRunObject::GetWSNodes() // block boundary. nsresult res = NS_OK; - DOMPoint start(mNode, mOffset), end(mNode, mOffset); + ::DOMPoint start(mNode, mOffset), end(mNode, mOffset); nsCOMPtr wsBoundingParent = GetWSBoundingParent(); // first look backwards to find preceding ws nodes @@ -1110,7 +1113,7 @@ nsWSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode, } nsresult -nsWSRunObject::GetPreviousWSNode(DOMPoint aPoint, +nsWSRunObject::GetPreviousWSNode(::DOMPoint aPoint, nsINode* aBlockParent, nsCOMPtr* aPriorNode) { @@ -1202,7 +1205,7 @@ nsWSRunObject::GetNextWSNodeInner(nsINode* aStartNode, } nsresult -nsWSRunObject::GetNextWSNode(DOMPoint aPoint, +nsWSRunObject::GetNextWSNode(::DOMPoint aPoint, nsINode* aBlockParent, nsCOMPtr* aNextNode) { @@ -1621,6 +1624,21 @@ nsWSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR) return res; } +void +nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset, + Text** outStartNode, int32_t* outStartOffset, + Text** outEndNode, int32_t* outEndOffset) +{ + nsCOMPtr outStartDOMNode, outEndDOMNode; + GetAsciiWSBounds(aDir, GetAsDOMNode(aNode), aOffset, + address_of(outStartDOMNode), outStartOffset, + address_of(outEndDOMNode), outEndOffset); + nsCOMPtr start(do_QueryInterface(outStartDOMNode)); + nsCOMPtr end(do_QueryInterface(outEndDOMNode)); + start.forget(outStartNode); + end.forget(outEndNode); +} + void nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr *outStartNode, int32_t *outStartOffset, @@ -1869,114 +1887,114 @@ nsWSRunObject::GetWSPointBefore(nsIDOMNode *aNode, int32_t aOffset) nsresult nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun) -{ - // try to change an nbsp to a space, if possible, just to prevent nbsp proliferation. - // examine what is before and after the trailing nbsp, if any. +{ + // Try to change an nbsp to a space, if possible, just to prevent nbsp + // proliferation. Examine what is before and after the trailing nbsp, if + // any. NS_ENSURE_TRUE(aRun, NS_ERROR_NULL_POINTER); nsresult res; bool leftCheck = false; bool spaceNBSP = false; bool rightCheck = false; - + // confirm run is normalWS if (aRun->mType != WSType::normalWS) { return NS_ERROR_FAILURE; } - + // first check for trailing nbsp WSPoint thePoint = GetCharBefore(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset); if (thePoint.mTextNode && thePoint.mChar == nbsp) { // now check that what is to the left of it is compatible with replacing nbsp with space WSPoint prevPoint = GetCharBefore(thePoint); if (prevPoint.mTextNode) { - if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) leftCheck = true; - else spaceNBSP = true; - } else if (aRun->mLeftType == WSType::text) { - leftCheck = true; - } else if (aRun->mLeftType == WSType::special) { + if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) { + leftCheck = true; + } else { + spaceNBSP = true; + } + } else if (aRun->mLeftType == WSType::text || + aRun->mLeftType == WSType::special) { leftCheck = true; } - if (leftCheck || spaceNBSP) - { - // now check that what is to the right of it is compatible with replacing nbsp with space - if (aRun->mRightType == WSType::text) { - rightCheck = true; - } - if (aRun->mRightType == WSType::special) { - rightCheck = true; - } - if (aRun->mRightType == WSType::br) { + if (leftCheck || spaceNBSP) { + // now check that what is to the right of it is compatible with replacing + // nbsp with space + if (aRun->mRightType == WSType::text || + aRun->mRightType == WSType::special || + aRun->mRightType == WSType::br) { rightCheck = true; } if ((aRun->mRightType & WSType::block) && IsBlockNode(nsCOMPtr(GetWSBoundingParent()))) { - // we are at a block boundary. Insert a
. Why? Well, first note that - // the br will have no visible effect since it is up against a block boundary. - // |foo

bar| renders like |foo

bar| and similarly - // |

foo

bar| renders like |

foo

bar|. What this
addition - // gets us is the ability to convert a trailing nbsp to a space. Consider: - // |foo. '|, where ' represents selection. User types space attempting - // to put 2 spaces after the end of their sentence. We used to do this as: - // |foo.  | This caused problems with soft wrapping: the nbsp - // would wrap to the next line, which looked attrocious. If you try to do: - // |foo.  | instead, the trailing space is invisible because it - // is against a block boundary. If you do: |foo.  | then - // you get an even uglier soft wrapping problem, where foo is on one line until - // you type the final space, and then "foo " jumps down to the next line. Ugh. - // The best way I can find out of this is to throw in a harmless
- // here, which allows us to do: |foo. 
|, which doesn't - // cause foo to jump lines, doesn't cause spaces to show up at the beginning of - // soft wrapped lines, and lets the user see 2 spaces when they type 2 spaces. + // We are at a block boundary. Insert a
. Why? Well, first note + // that the br will have no visible effect since it is up against a + // block boundary. |foo

bar| renders like |foo

bar| and + // similarly |

foo

bar| renders like |

foo

bar|. What + // this
addition gets us is the ability to convert a trailing nbsp + // to a space. Consider: |foo. '|, where ' represents + // selection. User types space attempting to put 2 spaces after the + // end of their sentence. We used to do this as: |foo. + //  | This caused problems with soft wrapping: the nbsp + // would wrap to the next line, which looked attrocious. If you try to + // do: |foo.  | instead, the trailing space is + // invisible because it is against a block boundary. If you do: + // |foo.  | then you get an even uglier soft + // wrapping problem, where foo is on one line until you type the final + // space, and then "foo " jumps down to the next line. Ugh. The best + // way I can find out of this is to throw in a harmless
here, + // which allows us to do: |foo. 
|, which doesn't + // cause foo to jump lines, doesn't cause spaces to show up at the + // beginning of soft wrapped lines, and lets the user see 2 spaces when + // they type 2 spaces. - nsCOMPtr brNode; - res = mHTMLEditor->CreateBR(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset, address_of(brNode)); - NS_ENSURE_SUCCESS(res, res); + nsCOMPtr brNode = + mHTMLEditor->CreateBR(aRun->mEndNode, aRun->mEndOffset); + NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE); - // refresh thePoint, prevPoint + // Refresh thePoint, prevPoint thePoint = GetCharBefore(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset); prevPoint = GetCharBefore(thePoint); rightCheck = true; } } - if (leftCheck && rightCheck) - { - // now replace nbsp with space - // first, insert a space - nsCOMPtr textNode(do_QueryInterface(thePoint.mTextNode)); - NS_ENSURE_TRUE(textNode, NS_ERROR_NULL_POINTER); + if (leftCheck && rightCheck) { + // Now replace nbsp with space. First, insert a space nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); nsAutoString spaceStr(char16_t(32)); - res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, textNode, thePoint.mOffset, true); + res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, + thePoint.mTextNode, + thePoint.mOffset, true); NS_ENSURE_SUCCESS(res, res); - - // finally, delete that nbsp - nsCOMPtr delNode(do_QueryInterface(thePoint.mTextNode)); - res = DeleteChars(delNode, thePoint.mOffset+1, delNode, thePoint.mOffset+2); + + // Finally, delete that nbsp + res = DeleteChars(GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset + 1, + GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset + 2); NS_ENSURE_SUCCESS(res, res); - } - else if (!mPRE && spaceNBSP && rightCheck) // don't mess with this preformatted for now. - { - // we have a run of ascii whitespace (which will render as one space) - // followed by an nbsp (which is at the end of the whitespace run). Let's - // switch their order. This will insure that if someone types two spaces - // after a sentence, and the editor softwraps at this point, the spaces wont - // be split across lines, which looks ugly and is bad for the moose. - - nsCOMPtr startNode, endNode, thenode(do_QueryInterface(prevPoint.mTextNode)); + } else if (!mPRE && spaceNBSP && rightCheck) { + // Don't mess with this preformatted for now. We have a run of ASCII + // whitespace (which will render as one space) followed by an nbsp (which + // is at the end of the whitespace run). Let's switch their order. This + // will ensure that if someone types two spaces after a sentence, and the + // editor softwraps at this point, the spaces won't be split across lines, + // which looks ugly and is bad for the moose. + + nsCOMPtr startNode, endNode; int32_t startOffset, endOffset; - GetAsciiWSBounds(eBoth, thenode, prevPoint.mOffset+1, address_of(startNode), - &startOffset, address_of(endNode), &endOffset); - - // delete that nbsp - nsCOMPtr delNode(do_QueryInterface(thePoint.mTextNode)); - res = DeleteChars(delNode, thePoint.mOffset, delNode, thePoint.mOffset+1); + GetAsciiWSBounds(eBoth, prevPoint.mTextNode, prevPoint.mOffset + 1, + getter_AddRefs(startNode), &startOffset, + getter_AddRefs(endNode), &endOffset); + + // Delete that nbsp + res = DeleteChars(GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset, + GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset + 1); NS_ENSURE_SUCCESS(res, res); - - // finally, insert that nbsp before the ascii ws run + + // Finally, insert that nbsp before the ASCII ws run nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); nsAutoString nbspStr(nbsp); - nsCOMPtr textNode(do_QueryInterface(startNode)); - res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, textNode, startOffset, true); + res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, startNode, + startOffset, true); NS_ENSURE_SUCCESS(res, res); } } diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 5cd5d9c1de5..6b46aff8b20 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -343,6 +343,11 @@ class MOZ_STACK_CLASS nsWSRunObject WSPoint GetCharBefore(const WSPoint &aPoint); nsresult ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR = eAnywhere); + void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset, + mozilla::dom::Text** outStartNode, + int32_t* outStartOffset, + mozilla::dom::Text** outEndNode, + int32_t* outEndOffset); void GetAsciiWSBounds(int16_t aDir, nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr *outStartNode, int32_t *outStartOffset, nsCOMPtr *outEndNode, int32_t *outEndOffset); From e9e01fda8a08b5a8bdd284a336e0e4c710411a97 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 30/50] Bug 1003894 part 3 - Clean up nsWSRunObject::InsertBreak; r=ehsan --- editor/libeditor/html/nsHTMLEditRules.cpp | 15 +++- editor/libeditor/html/nsWSRunObject.cpp | 81 ++++++++++----------- editor/libeditor/html/nsWSRunObject.h | 7 +- editor/libeditor/text/nsPlaintextEditor.cpp | 14 ++++ editor/libeditor/text/nsPlaintextEditor.h | 3 + 5 files changed, 71 insertions(+), 49 deletions(-) diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 44e77dbe2a3..778c4b31dcb 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -1480,8 +1480,11 @@ nsHTMLEditRules::WillInsertText(EditAction aAction, // is it a return? else if (subStr.Equals(newlineStr)) { - res = wsObj.InsertBreak(address_of(curNode), &curOffset, address_of(unused), nsIEditor::eNone); - NS_ENSURE_SUCCESS(res, res); + nsCOMPtr node(do_QueryInterface(curNode)); + nsCOMPtr br = + wsObj.InsertBreak(address_of(node), &curOffset, nsIEditor::eNone); + NS_ENSURE_TRUE(br, NS_ERROR_FAILURE); + curNode = GetAsDOMNode(node); pos++; } else @@ -1696,8 +1699,12 @@ nsHTMLEditRules::StandardBreakImpl(nsIDOMNode* aNode, int32_t aOffset, node = linkParent; aOffset = newOffset; } - res = wsObj.InsertBreak(address_of(node), &aOffset, - address_of(brNode), nsIEditor::eNone); + nsCOMPtr node_ = do_QueryInterface(node); + nsCOMPtr br = + wsObj.InsertBreak(address_of(node_), &aOffset, nsIEditor::eNone); + node = GetAsDOMNode(node_); + brNode = GetAsDOMNode(br); + NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE); } NS_ENSURE_SUCCESS(res, res); node = nsEditor::GetNodeLocation(brNode, &aOffset); diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index 7fa6f71e287..be42fe61dff 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -188,72 +188,71 @@ nsWSRunObject::PrepareToSplitAcrossBlocks(nsHTMLEditor *aHTMLEd, // public instance methods //-------------------------------------------------------------------------------------------- -nsresult -nsWSRunObject::InsertBreak(nsCOMPtr *aInOutParent, - int32_t *aInOutOffset, - nsCOMPtr *outBRNode, +already_AddRefed +nsWSRunObject::InsertBreak(nsCOMPtr* aInOutParent, + int32_t* aInOutOffset, nsIEditor::EDirection aSelect) { // MOOSE: for now, we always assume non-PRE formatting. Fix this later. - // meanwhile, the pre case is handled in WillInsertText in nsHTMLEditRules.cpp - NS_ENSURE_TRUE(aInOutParent && aInOutOffset && outBRNode, NS_ERROR_NULL_POINTER); + // meanwhile, the pre case is handled in WillInsertText in + // nsHTMLEditRules.cpp + NS_ENSURE_TRUE(aInOutParent && aInOutOffset, nullptr); nsresult res = NS_OK; WSFragment *beforeRun, *afterRun; - FindRun(*aInOutParent, *aInOutOffset, &beforeRun, false); - FindRun(*aInOutParent, *aInOutOffset, &afterRun, true); - - { - // some scoping for nsAutoTrackDOMPoint. This will track our insertion point - // while we tweak any surrounding whitespace - nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, aInOutParent, aInOutOffset); + FindRun(GetAsDOMNode(*aInOutParent), *aInOutOffset, &beforeRun, false); + FindRun(GetAsDOMNode(*aInOutParent), *aInOutOffset, &afterRun, true); - // handle any changes needed to ws run after inserted br - if (!afterRun) { - // don't need to do anything. just insert break. ws won't change. - } else if (afterRun->mType & WSType::trailingWS) { - // don't need to do anything. just insert break. ws won't change. + { + // Some scoping for nsAutoTrackDOMPoint. This will track our insertion + // point while we tweak any surrounding whitespace + nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, aInOutParent, + aInOutOffset); + + // Handle any changes needed to ws run after inserted br + if (!afterRun || (afterRun->mType & WSType::trailingWS)) { + // Don't need to do anything. Just insert break. ws won't change. } else if (afterRun->mType & WSType::leadingWS) { - // delete the leading ws that is after insertion point. We don't - // have to (it would still not be significant after br), but it's + // Delete the leading ws that is after insertion point. We don't + // have to (it would still not be significant after br), but it's // just more aesthetically pleasing to. - res = DeleteChars(*aInOutParent, *aInOutOffset, GetAsDOMNode(afterRun->mEndNode), afterRun->mEndOffset, + res = DeleteChars(GetAsDOMNode(*aInOutParent), *aInOutOffset, + GetAsDOMNode(afterRun->mEndNode), afterRun->mEndOffset, eOutsideUserSelectAll); - NS_ENSURE_SUCCESS(res, res); + NS_ENSURE_SUCCESS(res, nullptr); } else if (afterRun->mType == WSType::normalWS) { - // need to determine if break at front of non-nbsp run. if so - // convert run to nbsp. - WSPoint thePoint = GetCharAfter(*aInOutParent, *aInOutOffset); + // Need to determine if break at front of non-nbsp run. If so, convert + // run to nbsp. + WSPoint thePoint = GetCharAfter(GetAsDOMNode(*aInOutParent), *aInOutOffset); if (thePoint.mTextNode && nsCRT::IsAsciiSpace(thePoint.mChar)) { WSPoint prevPoint = GetCharBefore(thePoint); if (prevPoint.mTextNode && !nsCRT::IsAsciiSpace(prevPoint.mChar)) { - // we are at start of non-nbsps. convert to a single nbsp. + // We are at start of non-nbsps. Convert to a single nbsp. res = ConvertToNBSP(thePoint); - NS_ENSURE_SUCCESS(res, res); + NS_ENSURE_SUCCESS(res, nullptr); } } } - - // handle any changes needed to ws run before inserted br - if (!beforeRun) { - // don't need to do anything. just insert break. ws won't change. - } else if (beforeRun->mType & WSType::leadingWS) { - // don't need to do anything. just insert break. ws won't change. + + // Handle any changes needed to ws run before inserted br + if (!beforeRun || (beforeRun->mType & WSType::leadingWS)) { + // Don't need to do anything. Just insert break. ws won't change. } else if (beforeRun->mType & WSType::trailingWS) { - // need to delete the trailing ws that is before insertion point, because it + // Need to delete the trailing ws that is before insertion point, because it // would become significant after break inserted. - res = DeleteChars(GetAsDOMNode(beforeRun->mStartNode), beforeRun->mStartOffset, *aInOutParent, *aInOutOffset, + res = DeleteChars(GetAsDOMNode(beforeRun->mStartNode), beforeRun->mStartOffset, + GetAsDOMNode(*aInOutParent), *aInOutOffset, eOutsideUserSelectAll); - NS_ENSURE_SUCCESS(res, res); + NS_ENSURE_SUCCESS(res, nullptr); } else if (beforeRun->mType == WSType::normalWS) { - // try to change an nbsp to a space, if possible, just to prevent nbsp proliferation - res = CheckTrailingNBSP(beforeRun, *aInOutParent, *aInOutOffset); - NS_ENSURE_SUCCESS(res, res); + // Try to change an nbsp to a space, just to prevent nbsp proliferation + res = CheckTrailingNBSP(beforeRun, GetAsDOMNode(*aInOutParent), *aInOutOffset); + NS_ENSURE_SUCCESS(res, nullptr); } } - + // ready, aim, fire! - return mHTMLEditor->CreateBRImpl(aInOutParent, aInOutOffset, outBRNode, aSelect); + return mHTMLEditor->CreateBRImpl(aInOutParent, aInOutOffset, aSelect); } nsresult diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 6b46aff8b20..829fa1b2ade 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -207,10 +207,9 @@ class MOZ_STACK_CLASS nsWSRunObject // and makes any needed adjustments to ws around that point. // example of fixup: normalws after {aInOutParent,aInOutOffset} // needs to begin with nbsp. - nsresult InsertBreak(nsCOMPtr *aInOutParent, - int32_t *aInOutOffset, - nsCOMPtr *outBRNode, - nsIEditor::EDirection aSelect); + already_AddRefed + InsertBreak(nsCOMPtr* aInOutParent, int32_t* aInOutOffset, + nsIEditor::EDirection aSelect); // InsertText inserts a string at {aInOutParent,aInOutOffset} // and makes any needed adjustments to ws around that point. diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 6569aa83338..cd9a3c63cd6 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -438,6 +438,20 @@ nsPlaintextEditor::TypedText(const nsAString& aString, ETypingAction aAction) } } +already_AddRefed +nsPlaintextEditor::CreateBRImpl(nsCOMPtr* aInOutParent, + int32_t* aInOutOffset, + EDirection aSelect) +{ + nsCOMPtr parent(GetAsDOMNode(*aInOutParent)); + nsCOMPtr br; + // We ignore the retval, and assume it's fine if the br is non-null + CreateBRImpl(address_of(parent), aInOutOffset, address_of(br), aSelect); + *aInOutParent = do_QueryInterface(parent); + nsCOMPtr ret(do_QueryInterface(br)); + return ret.forget(); +} + nsresult nsPlaintextEditor::CreateBRImpl(nsCOMPtr* aInOutParent, int32_t* aInOutOffset, diff --git a/editor/libeditor/text/nsPlaintextEditor.h b/editor/libeditor/text/nsPlaintextEditor.h index 70263d0dca8..4f2c3a5b75e 100644 --- a/editor/libeditor/text/nsPlaintextEditor.h +++ b/editor/libeditor/text/nsPlaintextEditor.h @@ -176,6 +176,9 @@ protected: // key event helpers NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr *outBRNode, EDirection aSelect = eNone); + already_AddRefed + CreateBRImpl(nsCOMPtr* aInOutParent, int32_t* aInOutOffset, + EDirection aSelect); nsresult CreateBRImpl(nsCOMPtr* aInOutParent, int32_t* aInOutOffset, nsCOMPtr* outBRNode, From 7e742b3ebe065c85aa155b993e86ee9ee384fcc6 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 31/50] Bug 1003894 part 4 - Clean up nsWSRunObject::DeleteWSBackward; r=ehsan --- editor/libeditor/html/nsWSRunObject.cpp | 73 +++++++++++++++---------- editor/libeditor/html/nsWSRunObject.h | 5 ++ 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index be42fe61dff..ff5386acd97 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -131,6 +131,23 @@ nsWSRunObject::PrepareToJoinBlocks(nsHTMLEditor *aHTMLEd, return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj); } +nsresult +nsWSRunObject::PrepareToDeleteRange(nsHTMLEditor* aHTMLEd, + nsCOMPtr* aStartNode, + int32_t* aStartOffset, + nsCOMPtr* aEndNode, + int32_t* aEndOffset) +{ + nsCOMPtr startNode(GetAsDOMNode(*aStartNode)); + nsCOMPtr endNode(GetAsDOMNode(*aEndNode)); + nsresult res = + PrepareToDeleteRange(aHTMLEd, address_of(startNode), aStartOffset, + address_of(endNode), aEndOffset); + *aStartNode = do_QueryInterface(startNode); + *aEndNode = do_QueryInterface(endNode); + return res; +} + nsresult nsWSRunObject::PrepareToDeleteRange(nsHTMLEditor *aHTMLEd, nsCOMPtr *aStartNode, @@ -402,51 +419,51 @@ nsWSRunObject::InsertText(const nsAString& aStringToInsert, nsresult nsWSRunObject::DeleteWSBackward() { - nsresult res = NS_OK; WSPoint point = GetCharBefore(GetAsDOMNode(mNode), mOffset); NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete - if (mPRE) // easy case, preformatted ws - { - if (nsCRT::IsAsciiSpace(point.mChar) || (point.mChar == nbsp)) - { - nsCOMPtr node(do_QueryInterface(point.mTextNode)); - int32_t startOffset = point.mOffset; - int32_t endOffset = point.mOffset+1; - return DeleteChars(node, startOffset, node, endOffset); + if (mPRE) { + // easy case, preformatted ws + if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == nbsp) { + return DeleteChars(GetAsDOMNode(point.mTextNode), point.mOffset, + GetAsDOMNode(point.mTextNode), point.mOffset + 1); } } - // callers job to insure that previous char is really ws. - // If it is normal ws, we need to delete the whole run - if (nsCRT::IsAsciiSpace(point.mChar)) - { - nsCOMPtr startNode, endNode, node(do_QueryInterface(point.mTextNode)); + // Caller's job to ensure that previous char is really ws. If it is normal + // ws, we need to delete the whole run. + if (nsCRT::IsAsciiSpace(point.mChar)) { + nsCOMPtr startNodeText, endNodeText; int32_t startOffset, endOffset; - GetAsciiWSBounds(eBoth, node, point.mOffset+1, address_of(startNode), - &startOffset, address_of(endNode), &endOffset); + GetAsciiWSBounds(eBoth, point.mTextNode, point.mOffset + 1, + getter_AddRefs(startNodeText), &startOffset, + getter_AddRefs(endNodeText), &endOffset); // adjust surrounding ws - res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor, address_of(startNode), &startOffset, - address_of(endNode), &endOffset); + nsCOMPtr startNode = startNodeText.get(); + nsCOMPtr endNode = endNodeText.get(); + nsresult res = + nsWSRunObject::PrepareToDeleteRange(mHTMLEditor, + address_of(startNode), &startOffset, + address_of(endNode), &endOffset); NS_ENSURE_SUCCESS(res, res); // finally, delete that ws - return DeleteChars(startNode, startOffset, endNode, endOffset); - } - else if (point.mChar == nbsp) - { - nsCOMPtr node(do_QueryInterface(point.mTextNode)); + return DeleteChars(GetAsDOMNode(startNode), startOffset, + GetAsDOMNode(endNode), endOffset); + } else if (point.mChar == nbsp) { + nsCOMPtr node(point.mTextNode); // adjust surrounding ws int32_t startOffset = point.mOffset; - int32_t endOffset = point.mOffset+1; - res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor, address_of(node), &startOffset, - address_of(node), &endOffset); + int32_t endOffset = point.mOffset + 1; + nsresult res = + nsWSRunObject::PrepareToDeleteRange(mHTMLEditor, + address_of(node), &startOffset, + address_of(node), &endOffset); NS_ENSURE_SUCCESS(res, res); // finally, delete that ws - return DeleteChars(node, startOffset, node, endOffset); - + return DeleteChars(GetAsDOMNode(node), startOffset, GetAsDOMNode(node), endOffset); } return NS_OK; } diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 829fa1b2ade..9bc3f2d3fc8 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -180,6 +180,11 @@ class MOZ_STACK_CLASS nsWSRunObject // adjusting ws. // example of fixup: trailingws before {aStartNode,aStartOffset} // needs to be removed. + static nsresult PrepareToDeleteRange(nsHTMLEditor* aHTMLEd, + nsCOMPtr* aStartNode, + int32_t* aStartOffset, + nsCOMPtr* aEndNode, + int32_t* aEndOffset); static nsresult PrepareToDeleteRange(nsHTMLEditor *aHTMLEd, nsCOMPtr *aStartNode, int32_t *aStartOffset, From 947f4fcb3a0c943355216127b13bf36769ac618b Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 2 May 2014 14:11:26 +0300 Subject: [PATCH 32/50] Bug 1003894 part 5 - Clean up nsWSRunObject::ScrubBlockBoundary; r=ehsan --- editor/libeditor/html/nsHTMLEditRules.cpp | 40 ++++++++++++-------- editor/libeditor/html/nsWSRunObject.cpp | 46 +++++++++-------------- editor/libeditor/html/nsWSRunObject.h | 9 ++--- 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 778c4b31dcb..ed5b8f48288 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -2748,16 +2748,21 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode, // Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining. rightOffset++; NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr leftBlock(do_QueryInterface(aLeftBlock)); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, - address_of(aLeftBlock), - nsWSRunObject::kBlockEnd); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_STATE(mHTMLEditor); - res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, - address_of(aRightBlock), - nsWSRunObject::kAfterBlock, - &rightOffset); + nsWSRunObject::kBlockEnd, + leftBlock); NS_ENSURE_SUCCESS(res, res); + + { + nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, + address_of(aRightBlock), &rightOffset); + nsCOMPtr rightBlock(do_QueryInterface(aRightBlock)); + res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, + nsWSRunObject::kAfterBlock, + rightBlock, rightOffset); + NS_ENSURE_SUCCESS(res, res); + } // Do br adjustment. nsCOMPtr brNode; res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode)); @@ -2793,16 +2798,21 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode, // tricky case. right block is inside left block. // Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining. NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr rightBlock(do_QueryInterface(aRightBlock)); res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, - address_of(aRightBlock), - nsWSRunObject::kBlockStart); + nsWSRunObject::kBlockStart, + rightBlock); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); - res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, - address_of(aLeftBlock), - nsWSRunObject::kBeforeBlock, - &leftOffset); - NS_ENSURE_SUCCESS(res, res); + { + nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, + address_of(aLeftBlock), &leftOffset); + nsCOMPtr leftBlock(do_QueryInterface(aLeftBlock)); + res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor, + nsWSRunObject::kBeforeBlock, + leftBlock, leftOffset); + NS_ENSURE_SUCCESS(res, res); + } // Do br adjustment. nsCOMPtr brNode; res = CheckForInvisibleBR(aLeftBlock, kBeforeBlock, address_of(brNode), diff --git a/editor/libeditor/html/nsWSRunObject.cpp b/editor/libeditor/html/nsWSRunObject.cpp index ff5386acd97..79d4d504883 100644 --- a/editor/libeditor/html/nsWSRunObject.cpp +++ b/editor/libeditor/html/nsWSRunObject.cpp @@ -99,20 +99,26 @@ nsWSRunObject::~nsWSRunObject() //-------------------------------------------------------------------------------------------- nsresult -nsWSRunObject::ScrubBlockBoundary(nsHTMLEditor *aHTMLEd, - nsCOMPtr *aBlock, +nsWSRunObject::ScrubBlockBoundary(nsHTMLEditor* aHTMLEd, BlockBoundary aBoundary, - int32_t *aOffset) + nsINode* aBlock, + int32_t aOffset) { - NS_ENSURE_TRUE(aBlock && aHTMLEd, NS_ERROR_NULL_POINTER); - if ((aBoundary == kBlockStart) || (aBoundary == kBlockEnd)) - return ScrubBlockBoundaryInner(aHTMLEd, aBlock, aBoundary); + NS_ENSURE_TRUE(aHTMLEd && aBlock, NS_ERROR_NULL_POINTER); + + int32_t offset; + if (aBoundary == kBlockStart) { + offset = 0; + } else if (aBoundary == kBlockEnd) { + offset = aBlock->Length(); + } else { + // Else we are scrubbing an outer boundary - just before or after a block + // element. + NS_ENSURE_STATE(aOffset >= 0); + offset = aOffset; + } - // else we are scrubbing an outer boundary - just before or after - // a block element. - NS_ENSURE_TRUE(aOffset, NS_ERROR_NULL_POINTER); - nsAutoTrackDOMPoint tracker(aHTMLEd->mRangeUpdater, aBlock, aOffset); - nsWSRunObject theWSObj(aHTMLEd, *aBlock, *aOffset); + nsWSRunObject theWSObj(aHTMLEd, aBlock, offset); return theWSObj.Scrub(); } @@ -2101,24 +2107,6 @@ nsWSRunObject::CheckLeadingNBSP(WSFragment *aRun, nsIDOMNode *aNode, int32_t aOf } -nsresult -nsWSRunObject::ScrubBlockBoundaryInner(nsHTMLEditor *aHTMLEd, - nsCOMPtr *aBlock, - BlockBoundary aBoundary) -{ - NS_ENSURE_TRUE(aBlock && aHTMLEd, NS_ERROR_NULL_POINTER); - int32_t offset=0; - if (aBoundary == kBlockEnd) - { - uint32_t uOffset; - aHTMLEd->GetLengthOfDOMNode(*aBlock, uOffset); - offset = uOffset; - } - nsWSRunObject theWSObj(aHTMLEd, *aBlock, offset); - return theWSObj.Scrub(); -} - - nsresult nsWSRunObject::Scrub() { diff --git a/editor/libeditor/html/nsWSRunObject.h b/editor/libeditor/html/nsWSRunObject.h index 9bc3f2d3fc8..75c4f7a50e3 100644 --- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -161,10 +161,10 @@ class MOZ_STACK_CLASS nsWSRunObject // ScrubBlockBoundary removes any non-visible whitespace at the specified // location relative to a block node. - static nsresult ScrubBlockBoundary(nsHTMLEditor *aHTMLEd, - nsCOMPtr *aBlock, + static nsresult ScrubBlockBoundary(nsHTMLEditor* aHTMLEd, BlockBoundary aBoundary, - int32_t *aOffset = 0); + nsINode* aBlock, + int32_t aOffset = -1); // PrepareToJoinBlocks fixes up ws at the end of aLeftParent and the // beginning of aRightParent in preperation for them to be joined. @@ -363,9 +363,6 @@ class MOZ_STACK_CLASS nsWSRunObject nsresult CheckTrailingNBSP(WSFragment *aRun, nsIDOMNode *aNode, int32_t aOffset); nsresult CheckLeadingNBSP(WSFragment *aRun, nsIDOMNode *aNode, int32_t aOffset); - static nsresult ScrubBlockBoundaryInner(nsHTMLEditor *aHTMLEd, - nsCOMPtr *aBlock, - BlockBoundary aBoundary); nsresult Scrub(); nsresult GetPreviousWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent, nsCOMPtr* aPriorNode); From 71063cf18c4d213e87d0133e6d84992f236947e2 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Tue, 6 May 2014 14:09:56 +0200 Subject: [PATCH 33/50] Backed out changeset 6efbbdf09c63 (bug 1001845) for refest failures --- gfx/layers/LayerTreeInvalidation.cpp | 2 -- gfx/layers/basic/BasicThebesLayer.h | 1 - gfx/layers/client/ClientThebesLayer.h | 1 - gfx/layers/d3d10/ThebesLayerD3D10.cpp | 2 +- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/gfx/layers/LayerTreeInvalidation.cpp b/gfx/layers/LayerTreeInvalidation.cpp index 2f376af2d11..8cbf5d59995 100644 --- a/gfx/layers/LayerTreeInvalidation.cpp +++ b/gfx/layers/LayerTreeInvalidation.cpp @@ -59,14 +59,12 @@ AddTransformedRegion(nsIntRegion& aDest, const nsIntRegion& aSource, const gfx3D while ((r = iter.Next())) { aDest.Or(aDest, TransformRect(*r, aTransform)); } - aDest.SimplifyOutward(20); } static void AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource) { aDest.Or(aDest, aSource); - aDest.SimplifyOutward(20); } static nsIntRegion diff --git a/gfx/layers/basic/BasicThebesLayer.h b/gfx/layers/basic/BasicThebesLayer.h index 04d7ff862a3..a4ba138a8cc 100644 --- a/gfx/layers/basic/BasicThebesLayer.h +++ b/gfx/layers/basic/BasicThebesLayer.h @@ -53,7 +53,6 @@ public: NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); mInvalidRegion.Or(mInvalidRegion, aRegion); - mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } diff --git a/gfx/layers/client/ClientThebesLayer.h b/gfx/layers/client/ClientThebesLayer.h index 098013167ac..7ee9b9c4c8c 100644 --- a/gfx/layers/client/ClientThebesLayer.h +++ b/gfx/layers/client/ClientThebesLayer.h @@ -60,7 +60,6 @@ public: NS_ASSERTION(ClientManager()->InConstruction(), "Can only set properties in construction phase"); mInvalidRegion.Or(mInvalidRegion, aRegion); - mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.cpp b/gfx/layers/d3d10/ThebesLayerD3D10.cpp index e2dcdb94b2b..47781cecfdf 100644 --- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp +++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp @@ -47,7 +47,7 @@ void ThebesLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion) { mInvalidRegion.Or(mInvalidRegion, aRegion); - mInvalidRegion.SimplifyOutward(20); + mInvalidRegion.SimplifyOutward(10); mValidRegion.Sub(mValidRegion, mInvalidRegion); } diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 296d2fb259f..f7cb25abdc6 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -50,7 +50,6 @@ void ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion) { mInvalidRegion.Or(mInvalidRegion, aRegion); - mInvalidRegion.SimplifyOutward(20); mValidRegion.Sub(mValidRegion, mInvalidRegion); } From 0f4e9d235392aa33e2e42d77ff4c72239fbe2793 Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Tue, 6 May 2014 08:33:12 -0400 Subject: [PATCH 34/50] Bug 1001234, disable arrow panel animation on linux, r=dao --- browser/base/content/browser.css | 10 ++++-- layout/xul/nsXULPopupManager.cpp | 6 +++- .../content/tests/chrome/test_arrowpanel.xul | 34 +++++++++++-------- toolkit/content/xul.css | 4 +++ 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index 2f8c195c409..d26cf7a71e0 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -935,13 +935,18 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar { -moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow"); background: transparent; border: none; + /* The popup inherits -moz-image-region from the button, must reset it */ + -moz-image-region: auto; +} + +%ifndef MOZ_WIDGET_GTK + +#BMB_bookmarksPopup { transform: scale(.7); opacity: 0; transition-property: transform, opacity; transition-duration: 0.15s; transition-timing-function: ease; - /* The popup inherits -moz-image-region from the button, must reset it */ - -moz-image-region: auto; } #BMB_bookmarksPopup[animate="open"] { @@ -975,6 +980,7 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar { transform: scale(.7) skew(-30deg, -20deg); } +%endif /* Customize mode */ #navigator-toolbox, diff --git a/layout/xul/nsXULPopupManager.cpp b/layout/xul/nsXULPopupManager.cpp index b18672dff82..fbfac96aa47 100644 --- a/layout/xul/nsXULPopupManager.cpp +++ b/layout/xul/nsXULPopupManager.cpp @@ -1380,7 +1380,10 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup, // able to see it. If there is a next popup, indicating that mutliple popups // are rolling up, don't wait and hide the popup right away since the effect // would likely be undesirable. This also does a quick check to see if the - // popup has a transition defined, and skips the wait if not. + // popup has a transition defined, and skips the wait if not. Transitions + // are currently disabled on Linux due to rendering issues on certain + // configurations. +#ifndef MOZ_WIDGET_GTK if (!aNextPopup && aPopup->HasAttr(kNameSpaceID_None, nsGkAtoms::animate) && popupFrame->StyleDisplay()->mTransitionPropertyCount > 0) { nsAutoString animate; @@ -1397,6 +1400,7 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup, return; } } +#endif HidePopupCallback(aPopup, popupFrame, aNextPopup, aLastPopup, aPopupType, aDeselectMenu); diff --git a/toolkit/content/tests/chrome/test_arrowpanel.xul b/toolkit/content/tests/chrome/test_arrowpanel.xul index f5df0ed9a9a..6f5d5a06b3c 100644 --- a/toolkit/content/tests/chrome/test_arrowpanel.xul +++ b/toolkit/content/tests/chrome/test_arrowpanel.xul @@ -176,23 +176,27 @@ function nextTest() $("bottomright").removeAttribute("right"); } - var transitions = 0; - function transitionEnded(event) { - transitions++; - // Two properties transition so continue on the second one finishing. - if (!(transitions % 2)) { - SimpleTest.executeSoon(() => runNextTest.next()); + // Test that a transition occurs when opening or closing the popup. The transition is + // disabled on Linux. + if (navigator.platform.indexOf("Linux") == -1) { + var transitions = 0; + function transitionEnded(event) { + transitions++; + // Two properties transition so continue on the second one finishing. + if (!(transitions % 2)) { + SimpleTest.executeSoon(() => runNextTest.next()); + } } - } - // Check that the transition occurs for an arrow panel with animate="true" - window.addEventListener("transitionend", transitionEnded, false); - $("animatepanel").openPopup($("topleft"), "after_start", 0, 0, false, false, null, "start"); - yield; - window.removeEventListener("transitionend", transitionEnded, false); - synthesizeKey("VK_ESCAPE", { }); - ok(!animatedPopupHidden, "animated popup not hidden yet"); - yield; + // Check that the transition occurs for an arrow panel with animate="true" + window.addEventListener("transitionend", transitionEnded, false); + $("animatepanel").openPopup($("topleft"), "after_start", 0, 0, false, false, null, "start"); + yield; + window.removeEventListener("transitionend", transitionEnded, false); + synthesizeKey("VK_ESCAPE", { }); + ok(!animatedPopupHidden, "animated popup not hidden yet"); + yield; + } SimpleTest.finish() yield; diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index 5040a1a6469..a28cb12290c 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -426,6 +426,8 @@ panel[type="arrow"] { -moz-binding: url("chrome://global/content/bindings/popup.xml#arrowpanel"); } +%ifndef MOZ_WIDGET_GTK + panel[type="arrow"]:not([animate="false"]) { transform: scale(.7); opacity: 0; @@ -485,6 +487,8 @@ panel[arrowposition="end_after"][animate="cancel"] { transform: scale(.7) skew(-10deg, -10deg); } +%endif + %ifdef XP_MACOSX .statusbar-resizerpanel { display: none; From 28ece2ba7d7969175f43ee9bc40223e3c0005767 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Tue, 6 May 2014 14:34:19 +0200 Subject: [PATCH 35/50] Bug 998130 - Add null checks in CairoImage::GetTextureClient. r=bjacob --- gfx/layers/ImageContainer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index 2927d4ff922..6c26b275ee7 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -613,6 +613,10 @@ CairoImage::~CairoImage() TextureClient* CairoImage::GetTextureClient(CompositableClient *aClient) { + if (!aClient) { + return nullptr; + } + CompositableForwarder* forwarder = aClient->GetForwarder(); RefPtr textureClient = mTextureClients.Get(forwarder->GetSerial()); if (textureClient) { @@ -621,12 +625,18 @@ CairoImage::GetTextureClient(CompositableClient *aClient) RefPtr surface = GetAsSourceSurface(); MOZ_ASSERT(surface); + if (!surface) { + return nullptr; + } // gfx::BackendType::NONE means default to content backend textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(), TextureFlags::DEFAULT, gfx::BackendType::NONE, surface->GetSize()); + if (!textureClient) { + return nullptr; + } MOZ_ASSERT(textureClient->CanExposeDrawTarget()); if (!textureClient->AllocateForSurface(surface->GetSize()) || !textureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) { From d70f075a1d3ea6933256c332b640f3a975287d9a Mon Sep 17 00:00:00 2001 From: Sean Lin Date: Tue, 6 May 2014 18:32:33 +0800 Subject: [PATCH 36/50] Bug 909001 - Update Registered Pages for System Message When App Gets Uninstalled. r=gene --- dom/messages/SystemMessageInternal.js | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/dom/messages/SystemMessageInternal.js b/dom/messages/SystemMessageInternal.js index 0d49cc85c5a..e312adf149f 100644 --- a/dom/messages/SystemMessageInternal.js +++ b/dom/messages/SystemMessageInternal.js @@ -25,6 +25,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "powerManagerService", "@mozilla.org/power/powermanagerservice;1", "nsIPowerManagerService"); +XPCOMUtils.defineLazyServiceGetter(this, "appsService", + "@mozilla.org/AppsService;1", + "nsIAppsService"); + // Limit the number of pending messages for a given page. let kMaxPendingMessages; try { @@ -83,6 +87,7 @@ function SystemMessageInternal() { Services.obs.addObserver(this, "xpcom-shutdown", false); Services.obs.addObserver(this, "webapps-registry-start", false); Services.obs.addObserver(this, "webapps-registry-ready", false); + Services.obs.addObserver(this, "webapps-clear-data", false); kMessages.forEach(function(aMsg) { ppmm.addMessageListener(aMsg, this); }, this); @@ -499,6 +504,7 @@ SystemMessageInternal.prototype = { Services.obs.removeObserver(this, "xpcom-shutdown"); Services.obs.removeObserver(this, "webapps-registry-start"); Services.obs.removeObserver(this, "webapps-registry-ready"); + Services.obs.removeObserver(this, "webapps-clear-data"); ppmm = null; this._pages = null; this._bufferedSysMsgs = null; @@ -524,6 +530,35 @@ SystemMessageInternal.prototype = { }, this); this._bufferedSysMsgs.length = 0; break; + case "webapps-clear-data": + let params = + aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams); + if (!params) { + debug("Error updating registered pages for an uninstalled app."); + return; + } + + // Only update registered pages for apps. + if (params.browserOnly) { + return; + } + + let manifestURL = appsService.getManifestURLByLocalId(params.appId); + if (!manifestURL) { + debug("Error updating registered pages for an uninstalled app."); + return; + } + + for (let i = this._pages.length - 1; i >= 0; i--) { + let page = this._pages[i]; + if (page.manifestURL === manifestURL) { + this._pages.splice(i, 1); + debug("Remove " + page.pageURL + " @ " + page.manifestURL + + " from registered pages due to app uninstallation."); + } + } + debug("Finish updating registered pages for an uninstalled app."); + break; } }, From 1810b4b59d1c5fef5d90a4eb804b7d9d552f2a6c Mon Sep 17 00:00:00 2001 From: Giovanni Sferro Date: Mon, 5 May 2014 18:21:00 -0400 Subject: [PATCH 37/50] Bug 1003741 - nsNumberControlFrame implements nsITextControlFrame. r=ehsan --- content/html/content/src/HTMLInputElement.h | 2 +- .../test/forms/test_set_range_text.html | 99 ++++++++++--------- layout/forms/nsNumberControlFrame.cpp | 86 ++++++++++++++++ layout/forms/nsNumberControlFrame.h | 35 +++++++ 4 files changed, 172 insertions(+), 50 deletions(-) diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index 73d1bd077af..cd2713de73f 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -1321,7 +1321,7 @@ private: bool SupportsSetRangeText() const { return mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_SEARCH || mType == NS_FORM_INPUT_URL || mType == NS_FORM_INPUT_TEL || - mType == NS_FORM_INPUT_PASSWORD; + mType == NS_FORM_INPUT_PASSWORD || mType == NS_FORM_INPUT_NUMBER; } static bool MayFireChangeOnBlur(uint8_t aType) { diff --git a/content/html/content/test/forms/test_set_range_text.html b/content/html/content/test/forms/test_set_range_text.html index e505eefb5a4..af58c3c8dec 100644 --- a/content/html/content/test/forms/test_set_range_text.html +++ b/content/html/content/test/forms/test_set_range_text.html @@ -20,6 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 + @@ -39,7 +40,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 /** Tests for Bug 850364 && Bug 918940**/ - var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea"]; + var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea", "number"]; var NonSupportedTypes = ["button", "submit", "image", "reset", "radio", "checkbox", "range", "file", "email"]; @@ -92,58 +93,58 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 }, false); var test = " setRange(replacement), shrink"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(1, 6); - elem.setRangeText("xyz"); - is(elem.value, "0xyz6789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "09996789123456", msg + test); is(elem.selectionStart, 1, msg + test); is(elem.selectionEnd, 4, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0mnk6789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "02226789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement), expand"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(1, 2); - elem.setRangeText("xyz"); - is(elem.value, "0xyz23456789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "099923456789123456", msg + test); is(elem.selectionStart, 1, msg + test); is(elem.selectionEnd, 4, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0mnk23456789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "022223456789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement) pure insertion at start"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(0, 0); - elem.setRangeText("xyz"); - is(elem.value, "xyz0123456789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "9990123456789123456", msg + test); is(elem.selectionStart, 0, msg + test); is(elem.selectionEnd, 0, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "mnkxyz0123456789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "2229990123456789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement) pure insertion in the middle"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(4, 4); - elem.setRangeText("xyz"); - is(elem.value, "0123xyz456789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "0123999456789123456", msg + test); is(elem.selectionStart, 4, msg + test); is(elem.selectionEnd, 4, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0123mnkxyz456789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "0123222999456789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement) pure insertion at the end"; - elem.value = "0123456789ABCDEF"; + elem.value = "1123456789123456"; elem.setSelectionRange(16, 16); - elem.setRangeText("xyz"); - is(elem.value, "0123456789ABCDEFxyz", msg + test); + elem.setRangeText("999"); + is(elem.value, "1123456789123456999", msg + test); is(elem.selectionStart, 16, msg + test); is(elem.selectionEnd, 16, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0123456789ABCDEFmnkxyz", msg + test); + elem.setRangeText("222"); + is(elem.value, "1123456789123456222999", msg + test); expectedNumOfSelectCalls += 3; //test SetRange(replacement, start, end, mode) with start > end @@ -155,43 +156,43 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 is(opThrows, true, msg + " should throw IndexSizeError"); //test SelectionMode 'select' - elem.value = "0123456789ABCDEF"; - elem.setRangeText("xyz", 4, 9, "select"); - is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + elem.value = "1023456789123456"; + elem.setRangeText("999", 4, 9, "select"); + is(elem.value, "10239999123456", msg + ".value == \"10239999123456\""); is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"select\""); is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"select\""); expectedNumOfSelectCalls += 1; - elem.setRangeText("pqm", 6, 25, "select"); - is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + elem.setRangeText("888", 6, 25, "select"); + is(elem.value, "102399888", msg + ".value == \"102399888\""); is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"select\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"select\""); expectedNumOfSelectCalls += 1; //test SelectionMode 'start' - elem.value = "0123456789ABCDEF"; - elem.setRangeText("xyz", 4, 9, "start"); - is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + elem.value = "0123456789123456"; + elem.setRangeText("999", 4, 9, "start"); + is(elem.value, "01239999123456", msg + ".value == \"01239999123456\""); is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"start\""); is(elem.selectionEnd, 4, msg + ".selectionEnd == 4, with \"start\""); expectedNumOfSelectCalls += 1; - elem.setRangeText("pqm", 6, 25, "start"); - is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + elem.setRangeText("888", 6, 25, "start"); + is(elem.value, "012399888", msg + ".value == \"012399888\""); is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"start\""); is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"start\""); expectedNumOfSelectCalls += 1; //test SelectionMode 'end' - elem.value = "0123456789ABCDEF"; - elem.setRangeText("xyz", 4, 9, "end"); - is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + elem.value = "1023456789123456"; + elem.setRangeText("999", 4, 9, "end"); + is(elem.value, "10239999123456", msg + ".value == \"10239999123456\""); is(elem.selectionStart, 7, msg + ".selectionStart == 7, with \"end\""); is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"end\""); expectedNumOfSelectCalls += 1; - elem.setRangeText("pqm", 6, 25, "end"); - is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + elem.setRangeText("888", 6, 25, "end"); + is(elem.value, "102399888", msg + ".value == \"102399888\""); is(elem.selectionStart, 9, msg + ".selectionStart == 9, with \"end\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"end\""); expectedNumOfSelectCalls += 1; @@ -201,8 +202,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selection{Start|End} > end elem.value = "0123456789"; elem.setSelectionRange(6, 9); - elem.setRangeText("Z", 1, 2, "preserve"); - is(elem.value, "0Z23456789", msg + ".value == \"0Z23456789\""); + elem.setRangeText("7", 1, 2, "preserve"); + is(elem.value, "0723456789", msg + ".value == \"0723456789\""); is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"preserve\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"preserve\""); expectedNumOfSelectCalls += 2; @@ -210,8 +211,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selection{Start|End} < end elem.value = "0123456789"; elem.setSelectionRange(4, 5); - elem.setRangeText("QRST", 2, 9, "preserve"); - is(elem.value, "01QRST9", msg + ".value == \"01QRST9\""); + elem.setRangeText("3456", 2, 9, "preserve"); + is(elem.value, "0134569", msg + ".value == \"0134569\""); is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"preserve\""); is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"preserve\""); expectedNumOfSelectCalls += 2; @@ -219,8 +220,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selectionStart > end, selectionEnd < end elem.value = "0123456789"; elem.setSelectionRange(8, 4); - elem.setRangeText("QRST", 1, 5); - is(elem.value, "0QRST56789", msg + ".value == \"0QRST56789\""); + elem.setRangeText("3456", 1, 5); + is(elem.value, "0345656789", msg + ".value == \"0345656789\""); is(elem.selectionStart, 1, msg + ".selectionStart == 1, with \"default\""); is(elem.selectionEnd, 5, msg + ".selectionEnd == 5, with \"default\""); expectedNumOfSelectCalls += 2; @@ -228,8 +229,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selectionStart < end, selectionEnd > end elem.value = "0123456789"; elem.setSelectionRange(4, 9); - elem.setRangeText("QRST", 2, 6); - is(elem.value, "01QRST6789", msg + ".value == \"01QRST6789\""); + elem.setRangeText("3456", 2, 6); + is(elem.value, "0134566789", msg + ".value == \"0134566789\""); is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"default\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"default\""); expectedNumOfSelectCalls += 2; diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index 0caed05e136..309fdc715f6 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -42,6 +42,8 @@ NS_IMPL_FRAMEARENA_HELPERS(nsNumberControlFrame) NS_QUERYFRAME_HEAD(nsNumberControlFrame) NS_QUERYFRAME_ENTRY(nsNumberControlFrame) NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) + NS_QUERYFRAME_ENTRY(nsITextControlFrame) + NS_QUERYFRAME_ENTRY(nsIFormControlFrame) NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) nsNumberControlFrame::nsNumberControlFrame(nsStyleContext* aContext) @@ -254,6 +256,12 @@ nsNumberControlFrame::ContentStatesChanged(EventStates aStates) } } +nsITextControlFrame* +nsNumberControlFrame::GetTextFieldFrame() +{ + return do_QueryFrame(GetAnonTextControl()->GetPrimaryFrame()); +} + nsresult nsNumberControlFrame::MakeAnonymousElement(Element** aResult, nsTArray& aElements, @@ -407,6 +415,84 @@ nsNumberControlFrame::GetType() const return nsGkAtoms::numberControlFrame; } +NS_IMETHODIMP +nsNumberControlFrame::GetEditor(nsIEditor **aEditor) +{ + return GetTextFieldFrame()->GetEditor(aEditor); +} + +NS_IMETHODIMP +nsNumberControlFrame::SetSelectionStart(int32_t aSelectionStart) +{ + return GetTextFieldFrame()->SetSelectionStart(aSelectionStart); +} + +NS_IMETHODIMP +nsNumberControlFrame::SetSelectionEnd(int32_t aSelectionEnd) +{ + return GetTextFieldFrame()->SetSelectionEnd(aSelectionEnd); +} + +NS_IMETHODIMP +nsNumberControlFrame::SetSelectionRange(int32_t aSelectionStart, + int32_t aSelectionEnd, + SelectionDirection aDirection) +{ + return GetTextFieldFrame()->SetSelectionRange(aSelectionStart, aSelectionEnd, + aDirection); +} + +NS_IMETHODIMP +nsNumberControlFrame::GetSelectionRange(int32_t* aSelectionStart, + int32_t* aSelectionEnd, + SelectionDirection* aDirection) +{ + return GetTextFieldFrame()->GetSelectionRange(aSelectionStart, aSelectionEnd, + aDirection); +} + +NS_IMETHODIMP +nsNumberControlFrame::GetOwnedSelectionController(nsISelectionController** aSelCon) +{ + return GetTextFieldFrame()->GetOwnedSelectionController(aSelCon); +} + +nsFrameSelection* +nsNumberControlFrame::GetOwnedFrameSelection() +{ + return GetTextFieldFrame()->GetOwnedFrameSelection(); +} + +nsresult +nsNumberControlFrame::GetPhonetic(nsAString& aPhonetic) +{ + return GetTextFieldFrame()->GetPhonetic(aPhonetic); +} + +nsresult +nsNumberControlFrame::EnsureEditorInitialized() +{ + return GetTextFieldFrame()->EnsureEditorInitialized(); +} + +nsresult +nsNumberControlFrame::ScrollSelectionIntoView() +{ + return GetTextFieldFrame()->ScrollSelectionIntoView(); +} + +void +nsNumberControlFrame::SetFocus(bool aOn, bool aRepaint) +{ + GetTextFieldFrame()->SetFocus(aOn, aRepaint); +} + +nsresult +nsNumberControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue) +{ + return GetTextFieldFrame()->SetFormProperty(aName, aValue); +} + HTMLInputElement* nsNumberControlFrame::GetAnonTextControl() { diff --git a/layout/forms/nsNumberControlFrame.h b/layout/forms/nsNumberControlFrame.h index a29c0ce1506..c2c555bb03e 100644 --- a/layout/forms/nsNumberControlFrame.h +++ b/layout/forms/nsNumberControlFrame.h @@ -9,6 +9,7 @@ #include "mozilla/Attributes.h" #include "nsContainerFrame.h" #include "nsIFormControlFrame.h" +#include "nsITextControlFrame.h" #include "nsIAnonymousContentCreator.h" #include "nsCOMPtr.h" @@ -27,6 +28,7 @@ class HTMLInputElement; */ class nsNumberControlFrame MOZ_FINAL : public nsContainerFrame , public nsIAnonymousContentCreator + , public nsITextControlFrame { friend nsIFrame* NS_NewNumberControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); @@ -83,6 +85,38 @@ public: ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); } + // nsITextControlFrame + NS_IMETHOD GetEditor(nsIEditor **aEditor) MOZ_OVERRIDE; + + NS_IMETHOD SetSelectionStart(int32_t aSelectionStart) MOZ_OVERRIDE; + NS_IMETHOD SetSelectionEnd(int32_t aSelectionEnd) MOZ_OVERRIDE; + + NS_IMETHOD SetSelectionRange(int32_t aSelectionStart, + int32_t aSelectionEnd, + SelectionDirection aDirection = eNone) MOZ_OVERRIDE; + + NS_IMETHOD GetSelectionRange(int32_t* aSelectionStart, + int32_t* aSelectionEnd, + SelectionDirection* aDirection = nullptr) MOZ_OVERRIDE; + + NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) MOZ_OVERRIDE; + virtual nsFrameSelection* GetOwnedFrameSelection() MOZ_OVERRIDE; + + virtual nsresult GetPhonetic(nsAString& aPhonetic) MOZ_OVERRIDE; + + /** + * Ensure mEditor is initialized with the proper flags and the default value. + * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created + * @throws various and sundry other things + */ + virtual nsresult EnsureEditorInitialized() MOZ_OVERRIDE; + + virtual nsresult ScrollSelectionIntoView() MOZ_OVERRIDE; + + // nsIFormControlFrame + virtual void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE; + virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; + /** * This method attempts to localizes aValue and then sets the result as the * value of our anonymous text control. It's called when our @@ -158,6 +192,7 @@ public: private: + nsITextControlFrame* GetTextFieldFrame(); nsresult MakeAnonymousElement(Element** aResult, nsTArray& aElements, nsIAtom* aTagName, From 0476f35f2bdfc4773b08a75dd89c4ffb697bc104 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Sat, 3 May 2014 03:59:00 -0400 Subject: [PATCH 38/50] Bug 1005456 - Stop generating an invalid package-manifest when only one d3dc version was found. r=ted --- browser/installer/Makefile.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in index 98ca791b27f..806a290999a 100644 --- a/browser/installer/Makefile.in +++ b/browser/installer/Makefile.in @@ -53,9 +53,13 @@ DEFINES += -DJAREXT= ifdef MOZ_ANGLE_RENDERER DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER) +ifdef MOZ_D3DCOMPILER_VISTA_DLL DEFINES += -DMOZ_D3DCOMPILER_VISTA_DLL=$(MOZ_D3DCOMPILER_VISTA_DLL) +endif +ifdef MOZ_D3DCOMPILER_XP_DLL DEFINES += -DMOZ_D3DCOMPILER_XP_DLL=$(MOZ_D3DCOMPILER_XP_DLL) endif +endif DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME) From 160103aa7f779e28a280e6184641a8197191131d Mon Sep 17 00:00:00 2001 From: Eugen Sawin Date: Mon, 5 May 2014 23:29:20 +0200 Subject: [PATCH 39/50] Bug 1002426 - Check restore status before overriding zoom. r=kats --- dom/base/nsDOMWindowUtils.cpp | 17 +++++++++++++++++ dom/interfaces/base/nsIDOMWindowUtils.idl | 11 ++++++++++- layout/generic/nsGfxScrollFrame.h | 4 ++-- layout/generic/nsIScrollableFrame.h | 2 +- mobile/android/chrome/content/browser.js | 20 +++++++++++++------- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 0f03158710a..a2a77402a94 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -576,6 +576,23 @@ nsDOMWindowUtils::GetResolution(float* aXResolution, float* aYResolution) return NS_OK; } +NS_IMETHODIMP +nsDOMWindowUtils::GetIsHistoryRestored(bool* aIsHistoryRestored) { + if (!nsContentUtils::IsCallerChrome()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsIPresShell* presShell = GetPresShell(); + if (!presShell) { + return NS_ERROR_FAILURE; + } + + const nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable(); + *aIsHistoryRestored = sf && sf->DidHistoryRestore(); + + return NS_OK; +} + NS_IMETHODIMP nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint) { diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 11cf774571b..67b436ee5e3 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -48,7 +48,7 @@ interface nsIRunnable; interface nsICompositionStringSynthesizer; interface nsITranslationNodeList; -[scriptable, uuid(d68ea9fa-b1ea-4744-a78e-bb0e6ef95f55)] +[scriptable, uuid(8489681a-7407-457e-b889-53d1ae999b30)] interface nsIDOMWindowUtils : nsISupports { /** @@ -230,6 +230,15 @@ interface nsIDOMWindowUtils : nsISupports { void getResolution(out float aXResolution, out float aYResolution); + /** + * Whether the current window has been restored from session history. + * This gives a way to check whether the provided resolution and scroll + * position are default values or restored from a previous session. + * + * Can only be accessed with chrome privileges. + */ + readonly attribute boolean isHistoryRestored; + /** * Whether the next paint should be flagged as the first paint for a document. * This gives a way to track the next paint that occurs after the flag is diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index c1cc1cd475f..70273eb204c 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -658,7 +658,7 @@ public: virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE { mHelper.ResetScrollPositionForLayerPixelAlignment(); } - virtual bool DidHistoryRestore() MOZ_OVERRIDE { + virtual bool DidHistoryRestore() const MOZ_OVERRIDE { return mHelper.mDidHistoryRestore; } virtual void ClearDidHistoryRestore() MOZ_OVERRIDE { @@ -972,7 +972,7 @@ public: virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE { mHelper.ResetScrollPositionForLayerPixelAlignment(); } - virtual bool DidHistoryRestore() MOZ_OVERRIDE { + virtual bool DidHistoryRestore() const MOZ_OVERRIDE { return mHelper.mDidHistoryRestore; } virtual void ClearDidHistoryRestore() MOZ_OVERRIDE { diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 50d14c9e6e9..f236568f4d7 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -270,7 +270,7 @@ public: /** * Was the current presentation state for this frame restored from history? */ - virtual bool DidHistoryRestore() = 0; + virtual bool DidHistoryRestore() const = 0; /** * Clear the flag so that DidHistoryRestore() returns false until the next * RestoreState call. diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index d30b37e5ca4..2ad9e53ab06 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -4204,20 +4204,26 @@ Tab.prototype = { sendMessageToJava(message); }, + _getGeckoZoom: function() { + let res = {x: {}, y: {}}; + let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + cwu.getResolution(res.x, res.y); + let zoom = res.x.value * window.devicePixelRatio; + return zoom; + }, + saveSessionZoom: function(aZoom) { let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); cwu.setResolution(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio); }, restoredSessionZoom: function() { - if (!this._restoreZoom) { - return null; - } - let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - let res = {x: {}, y: {}}; - cwu.getResolution(res.x, res.y); - return res.x.value * window.devicePixelRatio; + + if (this._restoreZoom && cwu.isHistoryRestored) { + return this._getGeckoZoom(); + } + return null; }, OnHistoryNewEntry: function(aUri) { From d3186c9035c7e9a3752667cf795b7e44c6d76a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= Date: Thu, 1 May 2014 16:59:16 +0200 Subject: [PATCH 40/50] Bug 1005652 - Replace a free with a delete in nptest.cpp to fix a minor warning found by scan-build, the LLVM/Clang static analyzer. r=bsmedberg --- dom/plugins/test/testplugin/nptest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugin/nptest.cpp index f129077aa1a..1cdf6f41da7 100644 --- a/dom/plugins/test/testplugin/nptest.cpp +++ b/dom/plugins/test/testplugin/nptest.cpp @@ -839,7 +839,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass); if (!scriptableObject) { printf("NPN_CreateObject failed to create an object, can't create a plugin instance\n"); - free(instanceData); + delete instanceData; return NPERR_GENERIC_ERROR; } scriptableObject->npp = instance; From d2af9270e27ca625459caf15ba5d452b5b00cb44 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 6 May 2014 16:23:08 +0200 Subject: [PATCH 41/50] Bug 997145 - Add a attribute in order to silent a Clang static analyzer check r=nfroyd --HG-- extra : amend_source : 9ef01d8df4e8797981f770621a3885d456db5801 --- mfbt/Assertions.h | 4 ++-- mfbt/Attributes.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/mfbt/Assertions.h b/mfbt/Assertions.h index c4acd7ca474..e4d0d2283cb 100644 --- a/mfbt/Assertions.h +++ b/mfbt/Assertions.h @@ -132,7 +132,7 @@ extern "C" { * for use in implementing release-build assertions. */ static MOZ_ALWAYS_INLINE void -MOZ_ReportAssertionFailure(const char* s, const char* file, int ln) +MOZ_ReportAssertionFailure(const char* s, const char* file, int ln) MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS { #ifdef ANDROID __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", @@ -147,7 +147,7 @@ MOZ_ReportAssertionFailure(const char* s, const char* file, int ln) } static MOZ_ALWAYS_INLINE void -MOZ_ReportCrash(const char* s, const char* file, int ln) +MOZ_ReportCrash(const char* s, const char* file, int ln) MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS { #ifdef ANDROID __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH", diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h index e4f92f3f385..1d4acd98e41 100644 --- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -111,6 +111,16 @@ // http://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug #endif +/* + * When built with clang analyzer (a.k.a scan-build), define MOZ_HAVE_NORETURN + * to mark some false positives + */ +#ifdef __clang_analyzer__ +# if __has_extension(attribute_analyzer_noreturn) +# define MOZ_HAVE_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) +# endif +#endif + /* * The MOZ_CONSTEXPR specifier declares that a C++11 compiler can evaluate a * function at compile time. A constexpr function cannot examine any values @@ -185,6 +195,27 @@ # define MOZ_NORETURN /* no support */ #endif +/* + * MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS, specified at the end of a function + * declaration, indicates that for the purposes of static analysis, this + * function does not return. (The function definition does not need to be + * annotated.) + * + * MOZ_ReportCrash(const char* s, const char* file, int ln) MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS + * + * Some static analyzers, like scan-build from clang, can use this information + * to eliminate false positives. From the upstream documentation of scan-build: + * "This attribute is useful for annotating assertion handlers that actually + * can return, but for the purpose of using the analyzer we want to pretend + * that such functions do not return." + * + */ +#if defined(MOZ_HAVE_ANALYZER_NORETURN) +# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS MOZ_HAVE_ANALYZER_NORETURN +#else +# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS /* no support */ +#endif + /* * MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time * instrumentation shipped with Clang and GCC) to not instrument the annotated From 30c541e8cd1965d7e83375f078bbfb82e05a239e Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 6 May 2014 11:24:17 -0400 Subject: [PATCH 42/50] Bug 1003228 - Remove gecko-side handling of some options that are being taken out. r=janx --- b2g/chrome/content/settings.js | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js index 783a46baabd..57bdb9f1c03 100644 --- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -600,38 +600,6 @@ SettingsListener.observe("accessibility.screenreader", false, function(value) { }); })(); -// =================== AsyncPanZoom ====================== -SettingsListener.observe('apz.displayport.heuristics', 'default', function(value) { - // first reset everything to default - Services.prefs.clearUserPref('apz.velocity_bias'); - Services.prefs.clearUserPref('apz.use_paint_duration'); - Services.prefs.clearUserPref('apz.x_skate_size_multiplier'); - Services.prefs.clearUserPref('apz.y_skate_size_multiplier'); - Services.prefs.clearUserPref('apz.allow-checkerboarding'); - // and then set the things that we want to change - switch (value) { - case 'default': - break; - case 'center-displayport': - Services.prefs.setCharPref('apz.velocity_bias', '0.0'); - break; - case 'perfect-paint-times': - Services.prefs.setBoolPref('apz.use_paint_duration', false); - Services.prefs.setCharPref('apz.velocity_bias', '0.32'); // 16/50 (assumes 16ms paint times instead of 50ms) - break; - case 'taller-displayport': - Services.prefs.setCharPref('apz.y_skate_size_multiplier', '3.5'); - break; - case 'faster-paint': - Services.prefs.setCharPref('apz.x_skate_size_multiplier', '1.0'); - Services.prefs.setCharPref('apz.y_skate_size_multiplier', '1.5'); - break; - case 'no-checkerboard': - Services.prefs.setBoolPref('apz.allow-checkerboarding', false); - break; - } -}); - // =================== Various simple mapping ====================== let settingsToObserve = { 'ril.mms.retrieval_mode': { @@ -666,7 +634,6 @@ let settingsToObserve = { }, 'layers.enable-tiles': true, 'layers.simple-tiles': false, - 'layers.progressive-paint': false, 'layers.draw-tile-borders': false, 'layers.dump': false, 'debug.fps.enabled': { From 273629b231d4e7660e88b8256eb70c381d5817f2 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 1 May 2014 09:26:17 -0700 Subject: [PATCH 43/50] Bug 989414 - Speed up the C++ side of write barriers fired from jitcode; r=jonco --- js/src/gc/StoreBuffer.h | 14 ++++++++++++-- js/src/jit/IonLinker.h | 2 +- js/src/jit/VMFunctions.cpp | 10 +++++----- js/src/jsiter.cpp | 2 +- js/src/vm/ArrayBufferObject.h | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index 21159ca7074..d348a7f70c9 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -399,6 +399,16 @@ class StoreBuffer buffer.unput(this, edge); } + template + void putFromMainThread(Buffer &buffer, const Edge &edge) { + if (!isEnabled()) + return; + JS_ASSERT(CurrentThreadCanAccessRuntime(runtime_)); + mozilla::ReentrancyGuard g(*this); + if (edge.maybeInRememberedSet(nursery_)) + buffer.put(this, edge); + } + MonoTypeBuffer bufferVal; MonoTypeBuffer bufferCell; MonoTypeBuffer bufferSlot; @@ -438,9 +448,9 @@ class StoreBuffer void putSlotFromAnyThread(JSObject *obj, int kind, int32_t start, int32_t count) { putFromAnyThread(bufferSlot, SlotsEdge(obj, kind, start, count)); } - void putWholeCell(Cell *cell) { + void putWholeCellFromMainThread(Cell *cell) { JS_ASSERT(cell->isTenured()); - putFromAnyThread(bufferWholeCell, WholeCellEdges(cell)); + putFromMainThread(bufferWholeCell, WholeCellEdges(cell)); } /* Insert or update a single edge in the Relocatable buffer. */ diff --git a/js/src/jit/IonLinker.h b/js/src/jit/IonLinker.h index d7371a9ad7b..8649e6cb854 100644 --- a/js/src/jit/IonLinker.h +++ b/js/src/jit/IonLinker.h @@ -67,7 +67,7 @@ class Linker masm.link(code); #ifdef JSGC_GENERATIONAL if (masm.embedsNurseryPointers()) - cx->runtime()->gc.storeBuffer.putWholeCell(code); + cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code); #endif return code; } diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 709ae84060a..3fb2f427895 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -553,8 +553,8 @@ NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot // The JIT creates call objects in the nursery, so elides barriers for // the initializing writes. The interpreter, however, may have allocated // the call object tenured, so barrier as needed before re-entering. - if (!IsInsideNursery(cx->runtime(), obj)) - cx->runtime()->gc.storeBuffer.putWholeCell(obj); + if (!IsInsideNursery(obj)) + cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); #endif return obj; @@ -571,9 +571,9 @@ NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots) // The JIT creates call objects in the nursery, so elides barriers for // the initializing writes. The interpreter, however, may have allocated // the call object tenured, so barrier as needed before re-entering. - MOZ_ASSERT(!IsInsideNursery(cx->runtime(), obj), + MOZ_ASSERT(!IsInsideNursery(obj), "singletons are created in the tenured heap"); - cx->runtime()->gc.storeBuffer.putWholeCell(obj); + cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); #endif return obj; @@ -714,7 +714,7 @@ void PostWriteBarrier(JSRuntime *rt, JSObject *obj) { JS_ASSERT(!IsInsideNursery(rt, obj)); - rt->gc.storeBuffer.putWholeCell(obj); + rt->gc.storeBuffer.putWholeCellFromMainThread(obj); } void diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index e3ce922a955..55ee8638548 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1503,7 +1503,7 @@ static void GeneratorWriteBarrierPost(JSContext *cx, JSGenerator *gen) { #ifdef JSGC_GENERATIONAL - cx->runtime()->gc.storeBuffer.putWholeCell(gen->obj); + cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(gen->obj); #endif } diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h index b81caa0cbc9..af5d8a6fdd8 100644 --- a/js/src/vm/ArrayBufferObject.h +++ b/js/src/vm/ArrayBufferObject.h @@ -276,7 +276,7 @@ PostBarrierTypedArrayObject(JSObject *obj) JS_ASSERT(obj); JSRuntime *rt = obj->runtimeFromMainThread(); if (!rt->isHeapBusy() && !IsInsideNursery(rt, obj)) - rt->gc.storeBuffer.putWholeCell(obj); + rt->gc.storeBuffer.putWholeCellFromMainThread(obj); #endif } From ba92902ebd6ebad92aeb81ee9edb8ce4a699703c Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Tue, 6 May 2014 12:18:10 +0200 Subject: [PATCH 44/50] Bug 992258 - Trigger a refresh of the experiments view in the addon manager when experiments change. r=irving --- browser/experiments/Experiments.jsm | 110 +++++++++++++----- .../test/xpcshell/test_previous_provider.js | 3 + .../test/browser/browser_experiments.js | 4 - 3 files changed, 84 insertions(+), 33 deletions(-) diff --git a/browser/experiments/Experiments.jsm b/browser/experiments/Experiments.jsm index 069b805ffa3..a41b7d17cef 100644 --- a/browser/experiments/Experiments.jsm +++ b/browser/experiments/Experiments.jsm @@ -49,7 +49,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter", "nsICrashReporter"); const FILE_CACHE = "experiments.json"; -const OBSERVER_TOPIC = "experiments-changed"; +const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed"; const MANIFEST_VERSION = 1; const CACHE_VERSION = 1; @@ -114,6 +114,7 @@ let gLogAppenderDump = null; let gPolicyCounter = 0; let gExperimentsCounter = 0; let gExperimentEntryCounter = 0; +let gPreviousProviderCounter = 0; // Tracks active AddonInstall we know about so we can deny external // installs. @@ -464,7 +465,7 @@ Experiments.Experiments.prototype = { this._log.info("Completed uninitialization."); }), - _registerWithAddonManager: function () { + _registerWithAddonManager: function (previousExperimentsProvider) { this._log.trace("Registering instance with Addon Manager."); AddonManager.addAddonListener(this); @@ -474,15 +475,15 @@ Experiments.Experiments.prototype = { // The properties of this AddonType should be kept in sync with the // experiment AddonType registered in XPIProvider. this._log.trace("Registering previous experiment add-on provider."); - gAddonProvider = new Experiments.PreviousExperimentProvider(this, [ + gAddonProvider = previousExperimentsProvider || new Experiments.PreviousExperimentProvider(this); + AddonManagerPrivate.registerProvider(gAddonProvider, [ new AddonManagerPrivate.AddonType("experiment", URI_EXTENSION_STRINGS, STRING_TYPE_NAME, AddonManager.VIEW_TYPE_LIST, 11000, AddonManager.TYPE_UI_HIDE_EMPTY), - ]); - AddonManagerPrivate.registerProvider(gAddonProvider); + ]); } }, @@ -500,6 +501,15 @@ Experiments.Experiments.prototype = { AddonManager.removeAddonListener(this); }, + /* + * Change the PreviousExperimentsProvider that this instance uses. + * For testing only. + */ + _setPreviousExperimentsProvider: function (provider) { + this._unregisterWithAddonManager(); + this._registerWithAddonManager(provider); + }, + /** * Throws an exception if we've already shut down. */ @@ -1151,7 +1161,7 @@ Experiments.Experiments.prototype = { gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null); if (activeChanged) { - Services.obs.notifyObservers(null, OBSERVER_TOPIC, null); + Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null); } if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) { @@ -1970,7 +1980,7 @@ ExperimentsProvider.prototype = Object.freeze({ ], _OBSERVERS: [ - OBSERVER_TOPIC, + EXPERIMENTS_CHANGED_TOPIC, ], postInit: function () { @@ -1991,7 +2001,7 @@ ExperimentsProvider.prototype = Object.freeze({ observe: function (subject, topic, data) { switch (topic) { - case OBSERVER_TOPIC: + case EXPERIMENTS_CHANGED_TOPIC: this.recordLastActiveExperiment(); break; } @@ -2040,26 +2050,40 @@ ExperimentsProvider.prototype = Object.freeze({ */ this.Experiments.PreviousExperimentProvider = function (experiments) { this._experiments = experiments; + this._experimentList = []; + this._log = Log.repository.getLoggerWithMessagePrefix( + "Browser.Experiments.Experiments", + "PreviousExperimentProvider #" + gPreviousProviderCounter++ + "::"); } this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({ - startup: function () {}, - shutdown: function () {}, + startup: function () { + this._log.trace("startup()"); + Services.obs.addObserver(this, EXPERIMENTS_CHANGED_TOPIC, false); + }, + + shutdown: function () { + this._log.trace("shutdown()"); + Services.obs.removeObserver(this, EXPERIMENTS_CHANGED_TOPIC); + }, + + observe: function (subject, topic, data) { + switch (topic) { + case EXPERIMENTS_CHANGED_TOPIC: + this._updateExperimentList(); + break; + } + }, getAddonByID: function (id, cb) { - this._getPreviousExperiments().then((experiments) => { - for (let experiment of experiments) { - if (experiment.id == id) { - cb(new PreviousExperimentAddon(experiment)); - return; - } + for (let experiment of this._experimentList) { + if (experiment.id == id) { + cb(new PreviousExperimentAddon(experiment)); + return; } + } - cb(null); - }, - (error) => { - cb(null); - }); + cb(null); }, getAddonsByTypes: function (types, cb) { @@ -2068,17 +2092,45 @@ this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({ return; } - this._getPreviousExperiments().then((experiments) => { - cb([new PreviousExperimentAddon(e) for (e of experiments)]); - }, - (error) => { - cb([]); - }); + cb([new PreviousExperimentAddon(e) for (e of this._experimentList)]); }, - _getPreviousExperiments: function () { + _updateExperimentList: function () { return this._experiments.getExperiments().then((experiments) => { - return Promise.resolve([e for (e of experiments) if (!e.active)]); + let list = [e for (e of experiments) if (!e.active)]; + + let newMap = new Map([[e.id, e] for (e of list)]); + let oldMap = new Map([[e.id, e] for (e of this._experimentList)]); + + let added = [e.id for (e of list) if (!oldMap.has(e.id))]; + let removed = [e.id for (e of this._experimentList) if (!newMap.has(e.id))]; + + for (let id of added) { + this._log.trace("updateExperimentList() - adding " + id); + let wrapper = new PreviousExperimentAddon(newMap.get(id)); + AddonManagerPrivate.callInstallListeners("onExternalInstall", null, wrapper, null, false); + AddonManagerPrivate.callAddonListeners("onInstalling", wrapper, false); + } + + for (let id of removed) { + this._log.trace("updateExperimentList() - removing " + id); + let wrapper = new PreviousExperimentAddon(oldMap.get(id)); + AddonManagerPrivate.callAddonListeners("onUninstalling", plugin, false); + } + + this._experimentList = list; + + for (let id of added) { + let wrapper = new PreviousExperimentAddon(newMap.get(id)); + AddonManagerPrivate.callAddonListeners("onInstalled", wrapper); + } + + for (let id of removed) { + let wrapper = new PreviousExperimentAddon(oldMap.get(id)); + AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper); + } + + return this._experimentList; }); }, }); diff --git a/browser/experiments/test/xpcshell/test_previous_provider.js b/browser/experiments/test/xpcshell/test_previous_provider.js index a5212ab6174..3585a93bad6 100644 --- a/browser/experiments/test/xpcshell/test_previous_provider.js +++ b/browser/experiments/test/xpcshell/test_previous_provider.js @@ -44,6 +44,8 @@ add_task(function* test_provider_basic() { let e = Experiments.instance(); let provider = new Experiments.PreviousExperimentProvider(e); + e._setPreviousExperimentsProvider(provider); + let deferred = Promise.defer(); provider.getAddonsByTypes(["experiment"], (addons) => { deferred.resolve(addons); @@ -124,6 +126,7 @@ add_task(function* test_active_and_previous() { // Building on the previous test, activate experiment 2. let e = Experiments.instance(); let provider = new Experiments.PreviousExperimentProvider(e); + e._setPreviousExperimentsProvider(provider); gManifestObject = { version: 1, diff --git a/toolkit/mozapps/extensions/test/browser/browser_experiments.js b/toolkit/mozapps/extensions/test/browser/browser_experiments.js index 852366eabff..400b855b4ed 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_experiments.js +++ b/toolkit/mozapps/extensions/test/browser/browser_experiments.js @@ -284,12 +284,8 @@ add_task(function testDeactivateExperiment() { Assert.equal(addons[0].id, "experiment-1", "Add-on ID matches expected."); // Verify the UI looks sane. - // TODO remove the pane cycle once the UI refreshes automatically. - yield gCategoryUtilities.openType("extension"); Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible."); - yield gCategoryUtilities.openType("experiment"); - let item = get_addon_element(gManagerWindow, "experiment-1"); Assert.ok(item, "Got add-on element."); Assert.ok(!item.active, "Element should not be active."); From 0c0ad80a26f93d65266eab1f68e392f9fa3dbc85 Mon Sep 17 00:00:00 2001 From: Mike de Boer Date: Tue, 6 May 2014 12:01:48 +0200 Subject: [PATCH 45/50] Bug 978861: disable prefillWithSelection on OSX by default, fix its semantics when enabled. r=ehsan --- modules/libpref/src/init/all.js | 4 ++++ .../content/tests/chrome/findbar_window.xul | 19 ++++++++++--------- toolkit/content/widgets/findbar.xml | 7 +++++++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index ddd42dfc655..f32dc479d8b 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -523,7 +523,11 @@ pref("accessibility.typeaheadfind.timeout", 4000); pref("accessibility.typeaheadfind.enabletimeout", true); pref("accessibility.typeaheadfind.soundURL", "beep"); pref("accessibility.typeaheadfind.enablesound", true); +#ifdef XP_MACOSX +pref("accessibility.typeaheadfind.prefillwithselection", false); +#else pref("accessibility.typeaheadfind.prefillwithselection", true); +#endif pref("accessibility.typeaheadfind.matchesCountTimeout", 250); pref("accessibility.typeaheadfind.matchesCountLimit", 100); diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul index d338c235717..9fb618f5b52 100644 --- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -33,6 +33,12 @@ var gClipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); var gHasFindClipboard = gClipboard.supportsFindClipboard(); + // Since bug 978861, this pref is set to `false` on OSX. For this test, we'll + // set it `true` to disable the find clipboard on OSX, which interferes with + // our tests. + let prefsvc = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + prefsvc.setBoolPref("accessibility.typeaheadfind.prefillwithselection", true); + var gStatusText; var gXULBrowserWindow = { QueryInterface: function(aIID) { @@ -359,12 +365,10 @@ highlightButton.click(); ok(highlightButton.checked, "testFindWithHighlight 3: Highlight All should be checked."); - if (!gHasFindClipboard) { - a = gFindBar._findField.value; - b = gFindBar._browser.finder._fastFind.searchString; - c = gFindBar._browser.finder.searchString; - ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + "."); - } + a = gFindBar._findField.value; + b = gFindBar._browser.finder._fastFind.searchString; + c = gFindBar._browser.finder.searchString; + ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + "."); gFindBar.onFindAgainCommand(); a = gFindBar._findField.value; @@ -489,9 +493,6 @@ } function testClipboardSearchString(aExpected) { - if (!gHasFindClipboard) - return; - if (!aExpected) aExpected = ""; var searchStr = gFindBar.browser.finder.clipboardSearchString; diff --git a/toolkit/content/widgets/findbar.xml b/toolkit/content/widgets/findbar.xml index 4b548765f41..64b4b86dfed 100644 --- a/toolkit/content/widgets/findbar.xml +++ b/toolkit/content/widgets/findbar.xml @@ -1198,6 +1198,13 @@ Date: Fri, 2 May 2014 17:00:06 +0200 Subject: [PATCH 46/50] Bug 1005038 - In-content preferences: open the links in a new tab. r=jaws --- browser/components/preferences/in-content/sync.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/browser/components/preferences/in-content/sync.js b/browser/components/preferences/in-content/sync.js index 637f8820c45..d6b60dc1e5e 100644 --- a/browser/components/preferences/in-content/sync.js +++ b/browser/components/preferences/in-content/sync.js @@ -259,9 +259,7 @@ let gSyncPane = { gSyncUtils._openLink(url); return; } - win.switchToTabHavingURI(url, true); - // seeing as we are doing this in a tab we close the prefs dialog. - window.close(); + win.openUILinkIn(url, "tab"); }, signUp: function() { From 62dcffa375925c9cdcddc6e42e15e8fe42f7809c Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Mon, 5 May 2014 15:06:28 -0400 Subject: [PATCH 47/50] Bug 1005378 - Have TabChild create a view ID for the document element if one doesn't already exist. r=kats --- dom/ipc/TabChild.cpp | 6 +++--- gfx/layers/apz/util/APZCCallbackHelper.cpp | 9 +++++---- gfx/layers/apz/util/APZCCallbackHelper.h | 12 +++++++----- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index aa0e03aa55b..6d73f030ef7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -196,7 +196,7 @@ TabChildBase::HandlePossibleViewportChange() nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize); uint32_t presShellId; mozilla::layers::FrameMetrics::ViewID viewId; - bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers( + bool scrollIdentifiersValid = APZCCallbackHelper::GetOrCreateScrollIdentifiers( document->GetDocumentElement(), &presShellId, &viewId); if (scrollIdentifiersValid) { ZoomConstraints constraints( @@ -726,8 +726,8 @@ TabChild::Observe(nsISupports *aSubject, nsCOMPtr doc(GetDocument()); uint32_t presShellId; ViewID viewId; - if (APZCCallbackHelper::GetScrollIdentifiers(doc->GetDocumentElement(), - &presShellId, &viewId)) { + if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(doc->GetDocumentElement(), + &presShellId, &viewId)) { CSSRect rect; sscanf(NS_ConvertUTF16toUTF8(aData).get(), "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}", diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index d9ca0388d38..73c0f974e36 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -329,13 +329,14 @@ APZCCallbackHelper::GetDOMWindowUtils(const nsIContent* aContent) } bool -APZCCallbackHelper::GetScrollIdentifiers(const nsIContent* aContent, - uint32_t* aPresShellIdOut, - FrameMetrics::ViewID* aViewIdOut) +APZCCallbackHelper::GetOrCreateScrollIdentifiers(nsIContent* aContent, + uint32_t* aPresShellIdOut, + FrameMetrics::ViewID* aViewIdOut) { - if (!aContent || !nsLayoutUtils::FindIDFor(aContent, aViewIdOut)) { + if (!aContent) { return false; } + *aViewIdOut = nsLayoutUtils::FindOrCreateIDFor(aContent); nsCOMPtr utils = GetDOMWindowUtils(aContent); return utils && (utils->GetPresShellId(aPresShellIdOut) == NS_OK); } diff --git a/gfx/layers/apz/util/APZCCallbackHelper.h b/gfx/layers/apz/util/APZCCallbackHelper.h index e5e0668c284..6024b614026 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.h +++ b/gfx/layers/apz/util/APZCCallbackHelper.h @@ -58,11 +58,13 @@ public: element. This might be an iframe inside the tab, for instance. */ static already_AddRefed GetDOMWindowUtils(const nsIContent* aContent); - /* Get the presShellId and view ID for the given content element, if they can be - found. Returns false if the values could not be found, true if they could. */ - static bool GetScrollIdentifiers(const nsIContent* aContent, - uint32_t* aPresShellIdOut, - FrameMetrics::ViewID* aViewIdOut); + /* Get the presShellId and view ID for the given content element. + * If the view ID does not exist, one is created. + * The pres shell ID should generally already exist; if it doesn't for some + * reason, false is returned. */ + static bool GetOrCreateScrollIdentifiers(nsIContent* aContent, + uint32_t* aPresShellIdOut, + FrameMetrics::ViewID* aViewIdOut); /* Tell layout that we received the scroll offset update for the given view ID, so that it accepts future scroll offset updates from APZ. */ From d1411b268cca58a33ae59e7067d4c2bd53d8e2d4 Mon Sep 17 00:00:00 2001 From: Mike de Boer Date: Tue, 6 May 2014 16:50:04 +0200 Subject: [PATCH 48/50] Backed out changeset df4ae5ba7d6e (bug 978861) due to m-o test failures. --- modules/libpref/src/init/all.js | 4 ---- .../content/tests/chrome/findbar_window.xul | 19 +++++++++---------- toolkit/content/widgets/findbar.xml | 7 ------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index f32dc479d8b..ddd42dfc655 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -523,11 +523,7 @@ pref("accessibility.typeaheadfind.timeout", 4000); pref("accessibility.typeaheadfind.enabletimeout", true); pref("accessibility.typeaheadfind.soundURL", "beep"); pref("accessibility.typeaheadfind.enablesound", true); -#ifdef XP_MACOSX -pref("accessibility.typeaheadfind.prefillwithselection", false); -#else pref("accessibility.typeaheadfind.prefillwithselection", true); -#endif pref("accessibility.typeaheadfind.matchesCountTimeout", 250); pref("accessibility.typeaheadfind.matchesCountLimit", 100); diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul index 9fb618f5b52..d338c235717 100644 --- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -33,12 +33,6 @@ var gClipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); var gHasFindClipboard = gClipboard.supportsFindClipboard(); - // Since bug 978861, this pref is set to `false` on OSX. For this test, we'll - // set it `true` to disable the find clipboard on OSX, which interferes with - // our tests. - let prefsvc = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); - prefsvc.setBoolPref("accessibility.typeaheadfind.prefillwithselection", true); - var gStatusText; var gXULBrowserWindow = { QueryInterface: function(aIID) { @@ -365,10 +359,12 @@ highlightButton.click(); ok(highlightButton.checked, "testFindWithHighlight 3: Highlight All should be checked."); - a = gFindBar._findField.value; - b = gFindBar._browser.finder._fastFind.searchString; - c = gFindBar._browser.finder.searchString; - ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + "."); + if (!gHasFindClipboard) { + a = gFindBar._findField.value; + b = gFindBar._browser.finder._fastFind.searchString; + c = gFindBar._browser.finder.searchString; + ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + "."); + } gFindBar.onFindAgainCommand(); a = gFindBar._findField.value; @@ -493,6 +489,9 @@ } function testClipboardSearchString(aExpected) { + if (!gHasFindClipboard) + return; + if (!aExpected) aExpected = ""; var searchStr = gFindBar.browser.finder.clipboardSearchString; diff --git a/toolkit/content/widgets/findbar.xml b/toolkit/content/widgets/findbar.xml index 64b4b86dfed..4b548765f41 100644 --- a/toolkit/content/widgets/findbar.xml +++ b/toolkit/content/widgets/findbar.xml @@ -1198,13 +1198,6 @@ Date: Tue, 6 May 2014 18:21:16 +0200 Subject: [PATCH 49/50] Bug 978861: disable prefillWithSelection on OSX by default, fix its semantics when enabled. r=ehsan --- modules/libpref/src/init/all.js | 4 ++++ toolkit/content/tests/chrome/findbar_window.xul | 10 ++++------ toolkit/content/tests/chrome/test_findbar.xul | 11 +++++++++-- toolkit/content/widgets/findbar.xml | 7 +++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index ddd42dfc655..f32dc479d8b 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -523,7 +523,11 @@ pref("accessibility.typeaheadfind.timeout", 4000); pref("accessibility.typeaheadfind.enabletimeout", true); pref("accessibility.typeaheadfind.soundURL", "beep"); pref("accessibility.typeaheadfind.enablesound", true); +#ifdef XP_MACOSX +pref("accessibility.typeaheadfind.prefillwithselection", false); +#else pref("accessibility.typeaheadfind.prefillwithselection", true); +#endif pref("accessibility.typeaheadfind.matchesCountTimeout", 250); pref("accessibility.typeaheadfind.matchesCountLimit", 100); diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul index d338c235717..1bff214b4c0 100644 --- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -359,12 +359,10 @@ highlightButton.click(); ok(highlightButton.checked, "testFindWithHighlight 3: Highlight All should be checked."); - if (!gHasFindClipboard) { - a = gFindBar._findField.value; - b = gFindBar._browser.finder._fastFind.searchString; - c = gFindBar._browser.finder.searchString; - ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + "."); - } + a = gFindBar._findField.value; + b = gFindBar._browser.finder._fastFind.searchString; + c = gFindBar._browser.finder.searchString; + ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + "."); gFindBar.onFindAgainCommand(); a = gFindBar._findField.value; diff --git a/toolkit/content/tests/chrome/test_findbar.xul b/toolkit/content/tests/chrome/test_findbar.xul index 069ce85236e..9cbe73c4754 100644 --- a/toolkit/content/tests/chrome/test_findbar.xul +++ b/toolkit/content/tests/chrome/test_findbar.xul @@ -31,8 +31,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=288254 /** Test for Bug 257061 and Bug 288254 **/ SimpleTest.waitForExplicitFinish(); -window.open("findbar_window.xul", "findbartest", - "chrome,width=600,height=600"); + +// Since bug 978861, this pref is set to `false` on OSX. For this test, we'll +// set it `true` to disable the find clipboard on OSX, which interferes with +// our tests. +SpecialPowers.pushPrefEnv({ + set: [["accessibility.typeaheadfind.prefillwithselection", true]] +}, () => { + window.open("findbar_window.xul", "findbartest", "chrome,width=600,height=600"); +}); ]]> diff --git a/toolkit/content/widgets/findbar.xml b/toolkit/content/widgets/findbar.xml index 4b548765f41..64b4b86dfed 100644 --- a/toolkit/content/widgets/findbar.xml +++ b/toolkit/content/widgets/findbar.xml @@ -1198,6 +1198,13 @@ Date: Tue, 6 May 2014 16:17:36 -0400 Subject: [PATCH 50/50] Backed out changeset 7b05ebf0a2d5 (bug 858787) for making bug 970728 nearly perma-fail. --- b2g/app/b2g.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 3cffc0f9daf..507cf4d1e4b 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -391,9 +391,6 @@ pref("content.ime.strict_policy", true); // $ adb shell start pref("browser.dom.window.dump.enabled", false); -// Turn on the CSP 1.0 parser for Content Security Policy headers -pref("security.csp.speccompliant", true); - // Default Content Security Policy to apply to privileged and certified apps pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"); // If you change this CSP, make sure to update the fast path in nsCSPService.cpp